Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/coleam00/Archon/llms.txt

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.

Prerequisites

Cloud VPS account

Any provider that offers Ubuntu 22.04 LTS (DigitalOcean, Linode, AWS EC2, Hetzner, Vultr).

Domain name

A domain or subdomain you control (e.g. archon.yourdomain.com) — required for HTTPS.

SSH key

An ed25519 SSH key pair on your local machine. Generate one below if needed.

AI credentials

A Claude OAuth token or API key. Run claude setup-token locally to generate one.
ResourceMinimumRecommended
vCPUs12
RAM2 GB4 GB
Storage20 GB SSD40 GB SSD
OSUbuntu 22.04 LTSUbuntu 22.04 LTS

Generate an SSH key

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 creation
cat ~/.ssh/id_ed25519.pub
# Windows: type %USERPROFILE%\.ssh\id_ed25519.pub

Step 1 — Provision the server

  1. Log in and click Create → Droplets
  2. Select Ubuntu 22.04 LTS
  3. Choose Basic → 2 GB RAM ($12/month)
  4. Under Authentication, click New SSH Key and paste your public key
  5. Click Create Droplet and note the public IP

Step 2 — Initial server configuration

Connect to your new server as root:
ssh -i ~/.ssh/id_ed25519 root@your-server-ip

Create a non-root deploy user

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 privileges
adduser deploy
usermod -aG sudo deploy

# Copy root's SSH keys to the deploy user
mkdir -p /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
Test the deploy user connection in a new terminal before proceeding:
ssh -i ~/.ssh/id_ed25519 deploy@your-server-ip

Disable password authentication

nano /etc/ssh/sshd_config
Find and set:
PasswordAuthentication no
Save with Ctrl+X → Y → Enter, then restart SSH:
systemctl restart ssh
su - deploy

Configure the firewall

sudo ufw allow 22/tcp     # SSH
sudo ufw allow 80/tcp     # HTTP (required by Caddy/Let's Encrypt)
sudo ufw allow 443        # HTTPS (TCP + UDP for HTTP/3)
sudo ufw --force enable
sudo ufw status

Step 3 — Install Docker

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add deploy user to the docker group
sudo usermod -aG docker deploy

# Log out and back in for group changes to take effect
exit
ssh -i ~/.ssh/id_ed25519 deploy@your-server-ip
Install supporting packages:
sudo apt update
sudo apt install -y docker-compose-plugin git postgresql-client

# Verify
docker --version
docker compose version
git --version

Step 4 — Configure DNS

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:
TypeNameValueTTL
Aarchon (or @ for root)Your server IP300
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

Step 5 — Clone and configure Archon

sudo mkdir -p /opt/archon
sudo chown deploy:deploy /opt/archon
git clone https://github.com/coleam00/Archon /opt/archon
Copy and edit the environment file:
cd /opt/archon
cp .env.example .env
cp Caddyfile.example Caddyfile
nano .env
Set these required variables:
.env
# AI credential — choose one
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxx
# CLAUDE_API_KEY=sk-ant-xxxxx

# Domain — must match your DNS A record
DOMAIN=archon.yourdomain.com

# Database — use the local PostgreSQL container
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent

# GitHub token (for repository access and webhooks)
GH_TOKEN=ghp_your_token_here
GITHUB_TOKEN=ghp_your_token_here

# Webhook secret — generate with: openssl rand -hex 32
WEBHOOK_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.

AI credentials

Run this on your local machine (not the server):
claude setup-token
# Copy the token starting with sk-ant-oat01-...
Add to .env on the server:
.env
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxx

Step 6 — Set workspace permissions

The app container runs as UID 1001. Create and permission the workspace directory:
mkdir -p /opt/archon/workspace
sudo chown -R 1001:1001 /opt/archon/workspace

Step 7 — Start services

Press Ctrl+C to stop following logs — services keep running in the background.

Step 8 — Verify deployment

# Health check via HTTPS (from your local machine)
curl https://archon.yourdomain.com/api/health
# Expected: {"status":"ok"}

# Check all containers are running
docker 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.

Step 9 — Configure GitHub webhooks

Now that your app has a public URL, register the webhook in GitHub:
  1. Go to https://github.com/owner/repo/settings/hooks
  2. Click Add webhook
FieldValue
Payload URLhttps://archon.yourdomain.com/webhooks/github
Content typeapplication/json
SecretYour WEBHOOK_SECRET from .env
SSL verificationEnabled
EventsIssues, Issue comments, Pull requests
  1. Click Add webhook and check Recent Deliveries for a green checkmark.

Protecting the Web UI

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.
HTTP Basic Auth — browser shows a native credential dialog. No extra container.
# 1. Generate a bcrypt hash
docker 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 Caddy
docker compose --profile cloud restart caddy
Webhook endpoints (/webhooks/*) and the health check (/api/health) automatically bypass auth.

Maintenance and operations

View logs

docker compose --profile cloud logs -f              # All services
docker compose --profile cloud logs -f app          # App only
docker compose --profile cloud logs --tail=100 app  # Last 100 lines

Update Archon

cd /opt/archon
git pull
docker compose --profile with-db --profile cloud up -d --build
docker compose --profile with-db --profile cloud logs -f app

Restart services

docker compose --profile cloud restart           # All services
docker compose --profile cloud restart app       # App only
docker compose --profile cloud restart caddy     # Caddy only

Stop services

docker compose --profile cloud down              # Stop (data preserved)
docker compose --profile cloud down -v           # Stop and delete volumes — destructive!

Troubleshooting

dig archon.yourdomain.com     # Must return your server IP
sudo ufw status               # Ports 80 and 443 must be open
docker compose --profile cloud logs caddy
Common causes: DNS not propagated yet (wait 5–60 min), firewall blocking 80/443, domain typo in .env, Cloudflare proxy enabled (must be DNS-only).
docker compose --profile cloud ps
curl http://localhost:3000/api/health     # Tests app directly, bypasses Caddy
docker compose --profile cloud logs -f app
# Test connection directly
psql $DATABASE_URL -c "SELECT 1"

# Run migrations if tables are missing
psql $DATABASE_URL < migrations/000_combined.sql
  1. Go to the webhook settings page and check Recent Deliveries
  2. Verify WEBHOOK_SECRET in .env matches the secret in GitHub
  3. Test reachability:
    curl https://archon.yourdomain.com/webhooks/github
    # Should return 400 (missing signature) — endpoint is reachable
    
df -h
docker system df
docker system prune -a      # Remove unused images and containers
docker volume prune         # Remove unused volumes (check first)

Next steps

Docker reference

Full Docker Compose reference — profiles, volumes, Caddyfile, and all configuration options.

Local development

Run Archon from source with Bun for hot-reload development.

Configuration reference

Full list of environment variables and config options.

Troubleshooting

Diagnose common startup and runtime issues.

Build docs developers (and LLMs) love