Use this file to discover all available pages before exploring further.
Archon runs well on any Linux VPS — DigitalOcean, Linode, AWS EC2, Hetzner, Vultr, or any provider with Ubuntu 22.04 support. This guide walks through provisioning the server, creating a dedicated non-root deploy user (required for security), configuring the UFW firewall, setting up DNS, installing Docker, and starting Archon with automatic HTTPS via Caddy. If you prefer a fully automated approach, see the Cloud-Init section of the Docker guide.
This guide focuses on the server setup steps specific to cloud deployments. For the full Docker Compose reference — profiles, volume mounts, environment variables, and the Caddy Caddyfile — see the Docker guide.
Before creating your VPS, generate an SSH key pair on your local machine:
ssh-keygen -t ed25519 -C "archon"# Accept the default file location (~/.ssh/id_ed25519)# Copy your public key — you'll paste this during VPS creationcat ~/.ssh/id_ed25519.pub# Windows: type %USERPROFILE%\.ssh\id_ed25519.pub
Running Archon (and Claude Code) as root is not supported. You must create a non-root user. The container’s appuser (UID 1001) also runs as non-root for the same reason.
# Create user with sudo privilegesadduser deployusermod -aG sudo deploy# Copy root's SSH keys to the 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 the deploy user connection in a new terminal before proceeding:
curl -fsSL https://get.docker.com -o get-docker.shsudo sh get-docker.sh# Add deploy user to the docker groupsudo usermod -aG docker deploy# Log out and back in for group changes to take effectexitssh -i ~/.ssh/id_ed25519 deploy@your-server-ip
Point your domain to the server before starting Caddy — Let’s Encrypt requires DNS to resolve at certificate issuance time.Create an A record at your DNS provider:
Type
Name
Value
TTL
A
archon (or @ for root)
Your server IP
300
Cloudflare users: Set Proxy to DNS Only (grey cloud) — Caddy manages TLS directly and Cloudflare proxying will interfere with certificate issuance.Verify propagation before continuing:
dig archon.yourdomain.com# Should return your server IP
cd /opt/archoncp .env.example .envcp Caddyfile.example Caddyfilenano .env
Set these required variables:
.env
# AI credential — choose oneCLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxx# CLAUDE_API_KEY=sk-ant-xxxxx# Domain — must match your DNS A recordDOMAIN=archon.yourdomain.com# Database — use the local PostgreSQL containerDATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent# GitHub token (for repository access and webhooks)GH_TOKEN=ghp_your_token_hereGITHUB_TOKEN=ghp_your_token_here# Webhook secret — generate with: openssl rand -hex 32WEBHOOK_SECRET=your_generated_secret_here
For production, consider a managed PostgreSQL service (Supabase, Neon, AWS RDS) instead of the local container. Set DATABASE_URL to the managed connection string and omit --profile with-db. Managed databases handle backups, failover, and scaling automatically.
If you’re using an external database (Supabase, Neon, etc.), set DATABASE_URL and omit --profile with-db:
# Run the combined migration against the remote database firstpsql $DATABASE_URL < migrations/000_combined.sqldocker compose --profile cloud up -d --builddocker compose --profile cloud logs -f app
Press Ctrl+C to stop following logs — services keep running in the background.
# Health check via HTTPS (from your local machine)curl https://archon.yourdomain.com/api/health# Expected: {"status":"ok"}# Check all containers are runningdocker compose --profile with-db --profile cloud ps
Open https://archon.yourdomain.com in your browser. You should see the Archon Web UI with a green padlock and a Let’s Encrypt certificate.
By default, the Web UI is publicly accessible to anyone who knows the URL. If you want to restrict access, Caddy supports two auth methods.
Basic auth (simple)
Form auth (styled login page)
HTTP Basic Auth — browser shows a native credential dialog. No extra container.
# 1. Generate a bcrypt hashdocker run caddy caddy hash-password --plaintext 'YOUR_PASSWORD'# 2. Add to .env (use $$ to escape $ in hash values)# CADDY_BASIC_AUTH=basicauth @protected { admin $$2a$$14$$<hash> }# 3. Restart Caddydocker compose --profile cloud restart caddy
Webhook endpoints (/webhooks/*) and the health check (/api/health) automatically bypass auth.
A dark-mode HTML login page with 24-hour session cookies. Requires the auth-service container.See the form auth setup in the Docker guide for step-by-step instructions.Start with:
docker compose --profile with-db --profile cloud --profile auth up -d