Cloud Deployment
See also: Docker Guide for the complete Docker reference (profiles, building, configuration, troubleshooting).
Deploy Archon to a cloud VPS for 24/7 operation with automatic HTTPS and persistent uptime.
Navigation: Prerequisites | Server Setup | DNS Configuration | Repository Setup | Environment Config | Database Migration | Caddy Setup | Start Services | Verify
Prerequisites
Section titled “Prerequisites”Required:
- Cloud VPS account (DigitalOcean, Linode, AWS EC2, Vultr, etc.)
- Domain name or subdomain (e.g.,
archon.yourdomain.com) - SSH client installed on your local machine
- Basic command-line familiarity
Recommended Specs:
- CPU: 1-2 vCPUs
- RAM: 2GB minimum (4GB recommended)
- Storage: 20GB SSD
- OS: Ubuntu 22.04 LTS
Generate SSH Key (Required)
Section titled “Generate SSH Key (Required)”Before creating your VPS, generate an SSH key pair on your local machine:
# Generate SSH key (ed25519 recommended)ssh-keygen -t ed25519 -C "archon"
# When prompted:# - File location: Press Enter (uses default ~/.ssh/id_ed25519)# - Passphrase: Optional but recommended
# View your public key (you'll need this for VPS setup)cat ~/.ssh/id_ed25519.pub# Windows: type %USERPROFILE%\.ssh\id_ed25519.pubCopy the public key output - you’ll add this to your VPS during creation.
1. Server Provisioning & Initial Setup
Section titled “1. Server Provisioning & Initial Setup”Create VPS Instance (Examples)
Section titled “Create VPS Instance (Examples)”DigitalOcean Droplet
- Log in to DigitalOcean
- Click “Create” -> “Droplets”
- Choose:
- Image: Ubuntu 22.04 LTS
- Plan: Basic ($12/month - 2GB RAM recommended)
- Datacenter: Choose closest to your users
- Authentication: SSH keys -> “New SSH Key” -> Paste your public key from Prerequisites
- Click “Create Droplet”
- Note the public IP address
AWS EC2 Instance
- Log in to AWS Console
- Navigate to EC2 -> Launch Instance
- Choose:
- AMI: Ubuntu Server 22.04 LTS
- Instance Type: t3.small (2GB RAM)
- Key Pair: “Create new key pair” or import your public key from Prerequisites
- Security Group: Allow SSH (22), HTTP (80), HTTPS (443)
- Launch instance
- Note the public IP address
Linode Instance
- Log in to Linode
- Click “Create” -> “Linode”
- Choose:
- Image: Ubuntu 22.04 LTS
- Region: Choose closest to your users
- Plan: Nanode 2GB ($12/month)
- SSH Keys: Add your public key from Prerequisites
- Root Password: Set strong password (backup access)
- Click “Create Linode”
- Note the public IP address
Initial Server Configuration
Section titled “Initial Server Configuration”Connect to your server:
# Replace with your server IP (uses SSH key from Prerequisites)ssh -i ~/.ssh/id_ed25519 root@your-server-ipCreate deployment user:
# Create user with sudo privilegesadduser deployusermod -aG sudo deploy
# Copy root's SSH authorized keys to deploy usermkdir -p /home/deploy/.sshcp /root/.ssh/authorized_keys /home/deploy/.ssh/chown -R deploy:deploy /home/deploy/.sshchmod 700 /home/deploy/.sshchmod 600 /home/deploy/.ssh/authorized_keys
# Test connection in a new terminal before proceeding:# ssh -i ~/.ssh/id_ed25519 deploy@your-server-ipDisable password authentication for security:
# Edit SSH confignano /etc/ssh/sshd_configFind and change:
PasswordAuthentication noTo get out of Nano after making changes, press: Ctrl + X -> Y -> enter
Restart SSH:
systemctl restart ssh
# Switch to deploy user for remaining stepssu - deployConfigure firewall:
# Allow SSH, HTTP, HTTPS (including HTTP/3)sudo ufw allow 22/tcpsudo ufw allow 80/tcpsudo ufw allow 443
# Enable firewallsudo ufw --force enable
# Check statussudo ufw statusInstall Dependencies
Section titled “Install Dependencies”Install Docker:
# Install Dockercurl -fsSL https://get.docker.com -o get-docker.shsudo sh get-docker.sh
# Add deploy user to docker groupsudo usermod -aG docker deploy
# Log out and back in for group changes to take effectexitssh -i ~/.ssh/id_ed25519 deploy@your-server-ipInstall Docker Compose, Git, and PostgreSQL Client:
# Update package listsudo apt update
# Install required packagessudo apt install -y docker-compose-plugin git postgresql-client
# Verify installationsdocker --versiondocker compose versiongit --versionpsql --version2. DNS Configuration
Section titled “2. DNS Configuration”Point your domain to your server’s IP address.
A Record Setup:
- Go to your domain registrar or DNS provider (Cloudflare, Namecheap, etc.)
- Create an A Record:
- Name:
archon(forarchon.yourdomain.com) or@(foryourdomain.com) - Value: Your server’s public IP address
- TTL: 300 (5 minutes) or default
- Name:
Example (Cloudflare):
Type: AName: archonContent: 123.45.67.89Proxy: Off (DNS Only)TTL: Auto3. Clone Repository
Section titled “3. Clone Repository”On your server:
# Create application directorysudo mkdir -p /opt/archonsudo chown deploy:deploy /opt/archon
# Clone repository into the directorycd /opt/archongit clone https://github.com/coleam00/Archon .4. Environment Configuration
Section titled “4. Environment Configuration”Create Environment File
Section titled “Create Environment File”# Copy example filecp .env.example .env
# Edit with nanonano .env4.1 Core Configuration
Section titled “4.1 Core Configuration”Set these required variables:
# Database - Use remote managed PostgreSQLDATABASE_URL=postgresql://user:password@host:5432/dbname
# GitHub tokens (same value for both)GH_TOKEN=ghp_your_token_hereGITHUB_TOKEN=ghp_your_token_here
# Server settingsPORT=3090ARCHON_HOME=/tmp/archon # Override base directory (optional)GitHub Token Setup:
- Visit GitHub Settings > Tokens
- Click “Generate new token (classic)”
- Select scope:
repo - Copy token (starts with
ghp_...) - Set both
GH_TOKENandGITHUB_TOKENin.env
Database Options:
Note: SQLite is the default for local development and requires zero setup. For cloud deployments, PostgreSQL is recommended for reliability and network accessibility.
Recommended for Cloud: Remote Managed PostgreSQL
Use a managed database service for easier backups and scaling.
Supabase (Free tier available):
- Create project at supabase.com
- Go to Settings -> Database
- Copy connection string (Transaction pooler recommended)
- Set as
DATABASE_URL
Neon:
- Create project at neon.tech
- Copy connection string from dashboard
- Set as
DATABASE_URL
Alternative: Local PostgreSQL (with-db profile)
To run PostgreSQL in Docker alongside the app:
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agentUse the with-db profile when starting services (see Section 7).
4.2 AI Assistant Setup
Section titled “4.2 AI Assistant Setup”Configure at least one AI assistant.
Claude Code
On your local machine:
# Install Claude Code CLI (if not already installed)# Visit: https://docs.claude.com/claude-code/installation
# Generate OAuth tokenclaude setup-token
# Copy the token (starts with sk-ant-oat01-...)On your server:
nano .envAdd:
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxxAlternative: API Key
If you prefer pay-per-use:
- Visit console.anthropic.com/settings/keys
- Create key (starts with
sk-ant-) - Set in
.env:
CLAUDE_API_KEY=sk-ant-xxxxxSet as default (optional):
DEFAULT_AI_ASSISTANT=claudeCodex
On your local machine:
# Install Codex CLI (if not already installed)# Visit: https://docs.codex.com/installation
# Authenticatecodex login
# Extract credentialscat ~/.codex/auth.json# On Windows: type %USERPROFILE%\.codex\auth.json
# Copy all four valuesOn your server:
nano .envAdd all four credentials:
CODEX_ID_TOKEN=eyJhbGc...CODEX_ACCESS_TOKEN=eyJhbGc...CODEX_REFRESH_TOKEN=rt_...CODEX_ACCOUNT_ID=6a6a7ba6-...Set as default (optional):
DEFAULT_AI_ASSISTANT=codex4.3 Platform Adapter Setup
Section titled “4.3 Platform Adapter Setup”Configure at least one platform.
Telegram
Create bot:
- Message @BotFather on Telegram
- Send
/newbotand follow prompts - Copy bot token (format:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
On your server:
nano .envAdd:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHI...TELEGRAM_STREAMING_MODE=stream # stream (default) | batchGitHub Webhooks
You’ll configure this AFTER deployment (need public URL first).
For now, just generate the webhook secret:
# Generate secretopenssl rand -hex 32
# Copy the outputAdd to .env:
WEBHOOK_SECRET=your_generated_secret_hereGitHub webhook configuration happens in Section 9 after services are running.
Save and exit nano: Ctrl+X, then Y, then Enter
5. Database Migration
Section titled “5. Database Migration”IMPORTANT: Run this BEFORE starting the application.
Initialize the database schema with required tables:
# For remote database (Supabase, Neon, etc.)psql $DATABASE_URL < migrations/000_combined.sql
# Verify tables were createdpsql $DATABASE_URL -c "\dt"# Should show: codebases, conversations, sessions, isolation_environments,# workflow_runs, workflow_events, messagesIf using local PostgreSQL with with-db profile:
You’ll run migrations after starting the database in Section 7.
6. Caddy Configuration
Section titled “6. Caddy Configuration”Caddy provides automatic HTTPS with Let’s Encrypt certificates.
Create Caddyfile
Section titled “Create Caddyfile”# Copy the example — no manual editing neededcp Caddyfile.example CaddyfileThe Caddyfile reads {$DOMAIN} and {$PORT} from your .env automatically. Make sure DOMAIN is set:
DOMAIN=archon.yourdomain.comHow Caddy Works
Section titled “How Caddy Works”- Automatically obtains SSL certificates from Let’s Encrypt
- Handles HTTPS (443) and HTTP (80) -> HTTPS redirect
- Proxies requests to app container on port 3090
- Renews certificates automatically
7. Start Services
Section titled “7. Start Services”Setup Workspace Permissions (Linux Only)
Section titled “Setup Workspace Permissions (Linux Only)”# Create workspace directory and set permissions for container user (UID 1001)mkdir -p workspacesudo chown -R 1001:1001 workspaceOption A: With Remote PostgreSQL (Recommended)
Section titled “Option A: With Remote PostgreSQL (Recommended)”If using managed database:
# Start app with Caddy reverse proxydocker compose --profile cloud up -d --build
# View logsdocker compose --profile cloud logs -f appOption B: With Local PostgreSQL
Section titled “Option B: With Local PostgreSQL”If using with-db profile:
# Start app, postgres, and Caddydocker compose --profile with-db --profile cloud up -d --build
# View logsdocker compose --profile with-db --profile cloud logs -f appdocker compose --profile with-db --profile cloud logs -f postgresMonitor Startup
Section titled “Monitor Startup”# Watch logs for successful startup (use --profile with-db for local PostgreSQL)docker compose --profile cloud logs -f app
# Look for:# [App] Starting Archon# [Database] Connected successfully# [App] Archon is ready!Press Ctrl+C to exit logs (services keep running).
8. Verify Deployment
Section titled “8. Verify Deployment”Check Health Endpoints
Section titled “Check Health Endpoints”From your local machine:
# Basic health checkcurl https://archon.yourdomain.com/api/health# Expected: {"status":"ok"}
# Database connectivitycurl https://archon.yourdomain.com/api/health/db# Expected: {"status":"ok","database":"connected"}
# Concurrency statuscurl https://archon.yourdomain.com/api/health/concurrency# Expected: {"status":"ok","active":0,"queued":0,"maxConcurrent":10}Check SSL Certificate
Section titled “Check SSL Certificate”Visit https://archon.yourdomain.com/api/health in your browser:
- Should show green padlock
- Certificate issued by “Let’s Encrypt”
- Auto-redirect from HTTP to HTTPS
Check Telegram (if configured)
Section titled “Check Telegram (if configured)”Message your bot on Telegram:
/helpShould receive bot response with available commands.
9. Configure GitHub Webhooks
Section titled “9. Configure GitHub Webhooks”Now that your app has a public URL, configure GitHub webhooks.
Generate Webhook Secret (if not done earlier)
Section titled “Generate Webhook Secret (if not done earlier)”# On serveropenssl rand -hex 32
# Copy output to .env as WEBHOOK_SECRET if not already setAdd Webhook to Repository
Section titled “Add Webhook to Repository”- Go to:
https://github.com/owner/repo/settings/hooks - Click “Add webhook”
Webhook Configuration:
| Field | Value |
|---|---|
| Payload URL | https://archon.yourdomain.com/webhooks/github |
| Content type | application/json |
| Secret | Your WEBHOOK_SECRET from .env |
| SSL verification | Enable SSL verification |
| Events | Select individual events: Issues, Issue comments, Pull requests |
- Click “Add webhook”
- Check “Recent Deliveries” tab for successful delivery (green checkmark)
Test webhook:
Comment on an issue:
@your-bot-name can you analyze this issue?Bot should respond with analysis.
10. Maintenance & Operations
Section titled “10. Maintenance & Operations”View Logs
Section titled “View Logs”# All servicesdocker compose --profile cloud logs -f
# Specific servicedocker compose --profile cloud logs -f appdocker compose --profile cloud logs -f caddy
# Last 100 linesdocker compose --profile cloud logs --tail=100 appUpdate Application
Section titled “Update Application”# Pull latest changescd /opt/archongit pull
# Rebuild and restartdocker compose --profile cloud up -d --build
# Check logsdocker compose --profile cloud logs -f appRestart Services
Section titled “Restart Services”# Restart all servicesdocker compose --profile cloud restart
# Restart specific servicedocker compose --profile cloud restart appdocker compose --profile cloud restart caddyStop Services
Section titled “Stop Services”# Stop all servicesdocker compose --profile cloud down
# Stop and remove volumes (caution: deletes data)docker compose --profile cloud down -vTroubleshooting
Section titled “Troubleshooting”Caddy Not Getting SSL Certificate
Section titled “Caddy Not Getting SSL Certificate”Check DNS:
dig archon.yourdomain.com# Should return your server IPCheck firewall:
sudo ufw status# Should allow ports 80 and 443Check Caddy logs:
docker compose --profile cloud logs caddy# Look for certificate issuance attemptsCommon issues:
- DNS not propagated yet (wait 5-60 minutes)
- Firewall blocking ports 80/443
- Domain typo in Caddyfile
- A record not pointing to correct IP
App Not Responding
Section titled “App Not Responding”Check if running:
docker compose --profile cloud ps# Should show 'app' and 'caddy' with state 'Up'Check health endpoint:
curl http://localhost:3000/api/health# Tests app directly (bypasses Caddy)Check logs:
docker compose --profile cloud logs -f appDatabase Connection Errors
Section titled “Database Connection Errors”For remote database:
# Test connection from serverpsql $DATABASE_URL -c "SELECT 1"Check environment variable:
cat .env | grep DATABASE_URLRun migrations if tables missing:
psql $DATABASE_URL < migrations/000_combined.sqlGitHub Webhook Not Working
Section titled “GitHub Webhook Not Working”Check webhook deliveries:
- Go to webhook settings in GitHub
- Click “Recent Deliveries”
- Look for error messages
Verify webhook secret:
cat .env | grep WEBHOOK_SECRET# Must match GitHub webhook configurationTest webhook endpoint:
curl https://archon.yourdomain.com/webhooks/github# Should return 400 (missing signature) - means endpoint is reachableOut of Disk Space
Section titled “Out of Disk Space”Check disk usage:
df -hdocker system dfClean up Docker:
# Remove unused images and containersdocker system prune -a
# Remove unused volumes (caution)docker volume prune