Docker 가이드
Docker로 server에 Archon을 배포합니다. 자동 HTTPS, PostgreSQL, Web UI 구성이 포함됩니다. HarnessLab은 Archon fork이므로 같은 Docker 배포 방식을 그대로 사용할 수 있습니다.
Claude Code는 image에 미리 설치되어 있습니다. 공식
ghcr.io/coleam00/archonimage에는 npm으로 설치된 Claude Code와 미리 설정된CLAUDE_BIN_PATH가 포함되어 있어 추가 설정이 필요 없습니다. npm install을 생략한 custom image를 build하는 경우에는 mountedcli.js를 가리키도록CLAUDE_BIN_PATH를 직접 설정하세요(AI Assistants → Binary path configuration 참고).
Cloud-Init(가장 빠른 설정)
Section titled “Cloud-Init(가장 빠른 설정)”가장 빠른 배포 방법입니다. server를 만들 때 VPS provider의 User Data field에 cloud-init config를 붙여 넣으면 필요한 항목이 자동으로 설치됩니다.
File: deploy/cloud-init.yml
- DigitalOcean, AWS, Linode, Hetzner 등에서 VPS를 생성합니다(Ubuntu 22.04+ 권장).
deploy/cloud-init.yml내용을 “User Data” / “Cloud-Init” field에 붙여 넣습니다.- provider UI에서 SSH key를 추가합니다.
- server를 생성하고 setup이 끝날 때까지 약 5-8분 기다립니다.
설치되는 항목
Section titled “설치되는 항목”- Docker + Docker Compose
- UFW firewall(port 22, 80, 443)
- repo를
/opt/archon에 clone .env.example->.env,Caddyfile.example->Caddyfile복사- PostgreSQL 및 Caddy image pre-pull
- Archon Docker image build
Boot 이후
Section titled “Boot 이후”server에 SSH로 접속해 설정을 마무리합니다.
# Check setup completedcat /opt/archon/SETUP_COMPLETE
# Edit credentials and domainnano /opt/archon/.env
# Set at minimum:# CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...# DOMAIN=archon.example.com# DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent
# (Optional) Set up basic auth to protect Web UI:# docker run caddy caddy hash-password --plaintext 'YOUR_PASSWORD'# Add to .env: CADDY_BASIC_AUTH=basicauth @protected { admin $$2a$$14$$<hash> }
# Startcd /opt/archondocker compose --profile with-db --profile cloud up -dDNS를 잊지 마세요. 시작하기 전에 domain의 A record가 server IP를 가리키도록 설정해야 합니다.
Provider별 참고 사항
Section titled “Provider별 참고 사항”| Provider | cloud-init 붙여넣는 위치 |
|---|---|
| DigitalOcean | Create Droplet -> Advanced Options -> User Data |
| AWS EC2 | Launch Instance -> Advanced Details -> User Data |
| Linode | Create Linode -> Add Tags -> Metadata (User Data) |
| Hetzner | Create Server -> Cloud config -> User Data |
| Vultr | Deploy -> Additional Features -> Cloud-Init User-Data |
Local Docker Desktop(Windows / macOS)
Section titled “Local Docker Desktop(Windows / macOS)”Docker Desktop으로 Archon을 로컬에서 실행합니다. domain이나 VPS가 필요 없으며, SQLite와 Web UI만 사용합니다.
git clone https://github.com/coleam00/Archon.gitcd Archoncp .env.example .env# Edit .env: set CLAUDE_CODE_OAUTH_TOKEN or CLAUDE_API_KEYdocker compose up -dWeb UI는 **http://localhost:3000**에서 열 수 있습니다.
Windows 참고 사항
Section titled “Windows 참고 사항”PowerShell이 아니라 WSL에서 build하세요. Windows의 Docker Desktop은 build context transfer 중 Bun workspace symlink를 따라가지 못합니다. The file cannot be accessed by the system이 보이면 WSL terminal을 열고 실행하세요.
cd /mnt/c/Users/YourName/path/to/Archondocker compose up -dLine endings: 이 repo는 shell script에 LF ending을 강제하도록 .gitattributes를 사용합니다. 이 설정이 추가되기 전에 clone했고 exec docker-entrypoint.sh: no such file or directory가 보이면 다시 clone하거나 다음을 실행하세요.
git rm --cached -r .git reset --hard실행 후 제공되는 것
Section titled “실행 후 제공되는 것”| Feature | Status |
|---|---|
| Web UI | http://localhost:3000 |
| Database | SQLite(자동, zero setup) |
| HTTPS / Caddy | 로컬에서는 필요 없음 |
| Auth | 없음(single-user, localhost only) |
| Platform adapters | 선택 사항(Telegram, Slack 등) |
로컬에서 PostgreSQL 사용(선택)
Section titled “로컬에서 PostgreSQL 사용(선택)”docker compose --profile with-db up -d그다음 .env에 추가합니다.
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agentManual server 설정
Section titled “Manual server 설정”cloud-init을 사용하지 않거나 더 세밀하게 제어하고 싶을 때 쓰는 단계별 대안입니다.
1. Docker 설치
Section titled “1. Docker 설치”# On Ubuntu/Debiancurl -fsSL https://get.docker.com | shsudo usermod -aG docker $USER
# Log out and back in for group change to take effectexit# ssh back in
# Verifydocker --versiondocker compose version2. Repo clone
Section titled “2. Repo clone”git clone https://github.com/coleam00/Archon.gitcd Archon3. Environment 설정
Section titled “3. Environment 설정”cp .env.example .envcp Caddyfile.example Caddyfilenano .env.env에 다음 값을 설정합니다.
# AI Assistant — at least one is required# Option A: Claude OAuth token (run `claude setup-token` on your local machine to get one)CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxx# Option B: Claude API key (from console.anthropic.com/settings/keys)# CLAUDE_API_KEY=sk-ant-xxxxx
# Domain — your domain or subdomain pointing to this serverDOMAIN=archon.example.com
# Database — connect to the Docker PostgreSQL container# Without this, the app uses SQLite (fine for getting started, but PostgreSQL recommended)DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent
# Basic Auth (optional) — protects Web UI when exposed to the internet# Skip if using IP-based firewall rules instead.# Generate hash: docker run caddy caddy hash-password --plaintext 'YOUR_PASSWORD'# CADDY_BASIC_AUTH=basicauth @protected { admin $$2a$$14$$... }
# Platform tokens (set the ones you use)# TELEGRAM_BOT_TOKEN=123456789:ABCdef...# SLACK_BOT_TOKEN=xoxb-...# SLACK_APP_TOKEN=xapp-...# GH_TOKEN=ghp_...# GITHUB_TOKEN=ghp_...Docker는
CLAUDE_USE_GLOBAL_AUTH=true를 지원하지 않습니다. container 안에는 localclaudeCLI가 없습니다.CLAUDE_CODE_OAUTH_TOKEN또는CLAUDE_API_KEY를 명시적으로 제공해야 합니다.
DATABASE_URL없이--profile with-db를 사용하면, app은 SQLite로 fallback하고 warning을 log에 남깁니다. PostgreSQL container는 실행되지만 사용되지 않습니다.
4. Domain을 server에 연결
Section titled “4. Domain을 server에 연결”domain registrar에서 DNS A record를 생성합니다.
| Type | Name | Value |
|---|---|---|
| A | archon(root domain이면 @) | server의 public IP |
DNS propagation을 기다립니다(보통 5-60분). dig archon.example.com으로 확인합니다.
5. Firewall port 열기
Section titled “5. Firewall port 열기”sudo ufw allow 22/tcpsudo ufw allow 80/tcpsudo ufw allow 443sudo ufw --force enabledocker compose --profile with-db --profile cloud up -d세 개의 container가 시작됩니다.
- app — Archon server + Web UI
- postgres — PostgreSQL 17 database(자동 초기화)
- caddy — 자동 HTTPS를 제공하는 reverse proxy(Let’s Encrypt)
# Check all containers are runningdocker compose --profile with-db --profile cloud ps
# Watch logsdocker compose logs -f appdocker compose logs -f caddy
# Test HTTPS (from your local machine)curl https://archon.example.com/api/healthbrowser에서 **https://archon.example.com**을 열면 Archon Web UI가 보여야 합니다.
Profile
Section titled “Profile”Archon은 Docker Compose profile로 PostgreSQL 또는 HTTPS를 선택적으로 추가합니다. 필요에 따라 조합해서 사용합니다.
| Command | What runs |
|---|---|
docker compose up -d | SQLite를 사용하는 App |
docker compose --profile with-db up -d | App + PostgreSQL |
docker compose --profile cloud up -d | App + Caddy(HTTPS) |
docker compose --profile with-db --profile cloud up -d | App + PostgreSQL + Caddy |
No profile(SQLite)
Section titled “No profile(SQLite)”zero-config 기본값입니다. database container가 필요 없으며, SQLite file은 archon_data volume에 저장됩니다.
--profile with-db(PostgreSQL)
Section titled “--profile with-db(PostgreSQL)”PostgreSQL 17 container를 시작합니다. .env에 connection URL을 설정합니다.
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agentschema는 첫 startup 때 자동으로 초기화됩니다. PostgreSQL은 외부 tool에서 접근할 수 있도록 ${POSTGRES_PORT:-5432}에 노출됩니다.
--profile cloud(Caddy HTTPS)
Section titled “--profile cloud(Caddy HTTPS)”Let’s Encrypt에서 TLS certificate을 자동으로 발급하는 Caddy reverse proxy를 추가합니다.
시작 전 필요 항목:
Caddyfile생성:cp Caddyfile.example Caddyfile.env에DOMAIN설정- server IP를 가리키는 DNS A record
- port 80 및 443 open
Caddy는 HTTPS certificate, HTTP->HTTPS redirect, HTTP/3, SSE streaming을 처리합니다.
Authentication(Optional Basic Auth)
Section titled “Authentication(Optional Basic Auth)”Caddy는 webhook(/webhooks/*)과 health check(/api/health)를 제외한 모든 route에 HTTP Basic Auth를 적용할 수 있습니다. 선택 사항이므로 IP 기반 firewall rule 또는 다른 network-level access control을 사용한다면 생략해도 됩니다.
활성화 방법:
-
bcrypt password hash를 생성합니다.
Terminal window docker run caddy caddy hash-password --plaintext 'YOUR_PASSWORD' -
.env에CADDY_BASIC_AUTH를 설정합니다(bcrypt hash의$는$$로 escape).CADDY_BASIC_AUTH=basicauth @protected { admin $$2a$$14$$abc123... } -
restart합니다:
docker compose --profile cloud restart caddy
Archon URL에 접근하면 browser가 username/password를 요청합니다. Webhook endpoint는 HMAC signature verification을 사용하므로 auth를 우회합니다.
비활성화하려면 CADDY_BASIC_AUTH를 비우거나 설정하지 않습니다. Caddyfile은 이를 빈 값으로 확장합니다.
중요: hash 생성에는 항상
docker run caddy caddy hash-passwordcommand를 사용하세요..env에 plaintext password를 넣지 마세요.
Form-Based Authentication(HTML Login Page)
Section titled “Form-Based Authentication(HTML Login Page)”browser의 credential popup 대신 styled HTML login form을 제공하는 basic auth의 대안입니다. lightweight auth-service sidecar와 Caddy의 forward_auth directive를 사용합니다.
form auth와 basic auth 중 선택 기준:
- Form auth: styled dark-mode login page, 24h session cookie, logout support가 필요할 때. 추가 container가 필요합니다.
- Basic auth: 추가 container 없이 더 단순한 설정. browser가 native credential dialog를 표시합니다.
설정:
-
bcrypt password hash를 생성합니다.
Terminal window docker compose --profile auth run --rm auth-service \node -e "require('bcryptjs').hash('YOUR_PASSWORD', 12).then(h => console.log(h))"첫 실행에서는 auth-service image를 build합니다. 출력된 hash(
$2b$12$...로 시작)를 저장해 둡니다. -
random cookie signing secret을 생성합니다.
Terminal window docker run --rm node:22-alpine \node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" -
.env에 다음을 설정합니다.AUTH_USERNAME=adminAUTH_PASSWORD_HASH=$2b$12$REPLACE_WITH_YOUR_HASHCOOKIE_SECRET=REPLACE_WITH_64_HEX_CHARS -
Caddyfile을 update합니다(아직 복사하지 않았다면Caddyfile.example에서 복사).- “Option A” form auth block(
handle /login,handle /logout,handle { forward_auth ... }block)을 uncomment합니다. - “No auth” default
handleblock(site block 하단 근처의 마지막handle { ... }block)을 comment out합니다.
- “Option A” form auth block(
-
cloud와authprofile을 함께 사용해 시작합니다.Terminal window docker compose --profile with-db --profile cloud --profile auth up -d -
domain에 방문하면
/login으로 redirect되어야 합니다.
Logout: /logout으로 이동하면 session cookie가 지워지고 login form으로 돌아갑니다.
Session duration: 기본값은 24시간(COOKIE_MAX_AGE=86400)입니다. .env에서 override할 수 있습니다.
COOKIE_MAX_AGE=3600 # 1 hour참고: form auth와 basic auth를 동시에 사용하지 마세요. 둘 중 하나만 선택하고 다른 방식은 disabled 상태로 두세요(
CADDY_BASIC_AUTH를 비우거나 Caddyfile에서 basic auth@protectedblock 제거).
Port Defaults
Section titled “Port Defaults”Docker healthcheck는 /health가 아니라 /api/health를 사용합니다.
# Inside Dockercurl http://localhost:3000/api/health
# Local development (both work)curl http://localhost:3090/healthcurl http://localhost:3090/api/healthAI Credentials(필수)
Section titled “AI Credentials(필수)”Docker container는 CLAUDE_USE_GLOBAL_AUTH=true를 사용할 수 없습니다. container 안에는 local claude CLI가 없습니다. .env에 credential을 명시적으로 설정해야 합니다.
Claude(하나 선택):
# OAuth token — run `claude setup-token` on your local machine, copy the tokenCLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxx
# Or API key — from console.anthropic.com/settings/keysCLAUDE_API_KEY=sk-ant-xxxxxCodex(대안):
CODEX_ID_TOKEN=eyJhbGc...CODEX_ACCESS_TOKEN=eyJhbGc...CODEX_REFRESH_TOKEN=rt_...CODEX_ACCOUNT_ID=6a6a7ba6-...Platform Tokens(선택)
Section titled “Platform Tokens(선택)”TELEGRAM_BOT_TOKEN=123456789:ABCdef...SLACK_BOT_TOKEN=xoxb-...SLACK_APP_TOKEN=xapp-...DISCORD_BOT_TOKEN=...GH_TOKEN=ghp_...GITHUB_TOKEN=ghp_...WEBHOOK_SECRET=...Server Settings(선택)
Section titled “Server Settings(선택)”PORT=3000 # Default: 3000DOMAIN=archon.example.com # Required for --profile cloudLOG_LEVEL=info # fatal|error|warn|info|debug|traceMAX_CONCURRENT_CONVERSATIONS=10전체 목록과 설명은 .env.example을 참고하세요.
Data Directory
Section titled “Data Directory”container는 모든 data를 /.archon/에 저장합니다(workspaces, worktrees, artifacts, logs, SQLite DB).
기본값은 Docker-managed volume입니다. host의 특정 위치에 data를 저장하려면 .env에 ARCHON_DATA를 설정합니다.
# Store Archon data at a specific host pathARCHON_DATA=/opt/archon-datadirectory는 자동으로 생성됩니다. container user인 UID 1001이 쓸 수 있는지 확인하세요.
mkdir -p /opt/archon-datasudo chown -R 1001:1001 /opt/archon-dataARCHON_DATA가 설정되어 있지 않으면 Docker가 volume(archon_data)을 자동으로 관리합니다. data는 restart와 rebuild 이후에도 유지되지만 Docker storage 안에 저장됩니다.
GitHub CLI Authentication
Section titled “GitHub CLI Authentication”.env의 GH_TOKEN은 자동으로 사용됩니다. 또는 다음을 실행할 수 있습니다.
docker compose exec app gh auth loginGitHub Webhook
Section titled “GitHub Webhook”server가 HTTPS로 접근 가능해진 뒤 설정합니다.
https://github.com/<owner>/<repo>/settings/hooks로 이동합니다.- webhook을 추가합니다.
- Payload URL:
https://archon.example.com/webhooks/github - Content type:
application/json - Secret:
.env의WEBHOOK_SECRET - Events: Issues, Issue comments, Pull requests
- Payload URL:
Pre-built image
Section titled “Pre-built image”source에서 build할 필요가 없는 사용자를 위한 방식입니다.
mkdir archon && cd archoncurl -O https://raw.githubusercontent.com/coleam00/Archon/main/deploy/docker-compose.ymlcurl -O https://raw.githubusercontent.com/coleam00/Archon/main/.env.example
cp .env.example .env# Edit .env — set AI credentials, DOMAIN, etc.
docker compose up -dghcr.io/coleam00/archon:latest를 사용합니다. PostgreSQL을 추가하려면 compose file에서 postgres service를 uncomment하고 .env에 DATABASE_URL을 설정하세요.
pre-built image 위에 custom tool을 추가하려면 Customizing the Image를 참고하세요.
Image build
Section titled “Image build”Dockerfile은 세 단계로 구성됩니다.
- deps — 모든 dependency 설치(web build용 devDependencies 포함)
- web-build — Vite로 React web UI build
- production — production dependency와 pre-built web asset만 포함한 production image
docker build -t archon .docker run --env-file .env -p 3000:3000 archonimage에 포함되는 것:
- Runtime: Bun 1.2(TypeScript를 직접 실행, compile step 없음)
- System deps: git, curl, gh(GitHub CLI), postgresql-client, Chromium
- Browser tooling: agent-browser(Vercel Labs) — CDP를 통한 E2E testing workflow를 활성화합니다. system Chromium(
AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium)을 사용합니다. - App: 모든 10개 workspace package(source), pre-built web UI
- User: non-root
appuser(UID 1001) — Claude Code SDK에 필요 - Archon dirs:
/.archon/workspaces,/.archon/worktrees
multi-stage build는 image를 가볍게 유지합니다. devDependencies, test file, docs, .git/은 포함하지 않습니다.
Image 커스터마이징
Section titled “Image 커스터마이징”tracked Dockerfile을 수정하지 않고 추가 tool을 넣으려면:
- 예시 file을 복사합니다.
- Local/dev:
cp Dockerfile.user.example Dockerfile.user - Server/deploy:
cp deploy/Dockerfile.user.example Dockerfile.user
- Local/dev:
Dockerfile.user를 편집합니다. 필요한 예시를 uncomment하고 확장합니다.- override file을 복사합니다.
- Local/dev:
cp docker-compose.override.example.yml docker-compose.override.yml - Server/deploy:
cp deploy/docker-compose.override.example.yml docker-compose.override.yml
- Local/dev:
docker compose up -d를 실행합니다. Compose가 override를 자동으로 merge합니다.
Dockerfile.user와 docker-compose.override.yml은 gitignored 상태이므로 custom 설정은 로컬에만 남습니다.
Log 보기
Section titled “Log 보기”docker compose logs -f # All servicesdocker compose logs -f app # App onlydocker compose logs --tail=100 app # Last 100 linesgit pulldocker compose --profile with-db --profile cloud up -d --buildRestart
Section titled “Restart”docker compose restart # Alldocker compose restart app # App onlydocker compose down # Stop containers (data preserved)docker compose down -v # Stop + delete volumes (destructive!)Database Migrations(PostgreSQL)
Section titled “Database Migrations(PostgreSQL)”첫 startup에서는 000_combined.sql을 통해 migration이 자동으로 실행됩니다. database table을 추가하는 새 version으로 upgrade할 때는 incremental migration을 수동으로 적용해야 합니다.
# Example: apply the env vars migration (required when upgrading to v0.3.x)docker compose exec postgres psql -U postgres -d remote_coding_agent -f /migrations/020_codebase_env_vars.sqlmigrations/ directory는 postgres container에 read-only로 mounted됩니다. update를 pull한 뒤 새 migration file이 있는지 확인하세요.
Docker Resource 정리
Section titled “Docker Resource 정리”docker system prune -a # Remove unused images/containersdocker volume prune # Remove unused volumes (caution!)docker system df # Check disk usageApp이 시작되지 않음: “no_ai_credentials”
Section titled “App이 시작되지 않음: “no_ai_credentials””AI assistant가 설정되지 않았습니다. Docker는 CLAUDE_USE_GLOBAL_AUTH=true를 지원하지 않습니다. .env에 다음 중 하나를 설정하세요.
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...(로컬에서claude setup-token실행)CLAUDE_API_KEY=sk-ant-...(console.anthropic.com에서 발급)- 또는 Codex credential(
CODEX_ID_TOKEN,CODEX_ACCESS_TOKEN등)
Caddy 시작 실패: “not a directory”
Section titled “Caddy 시작 실패: “not a directory””error mounting "Caddyfile": not a directoryCaddyfile이 없습니다. Docker가 그 자리에 directory를 만들었습니다. 다음처럼 수정합니다.
rm -rf Caddyfilecp Caddyfile.example Caddyfiledocker compose --profile cloud up -dCaddy가 SSL certificate을 받지 못함
Section titled “Caddy가 SSL certificate을 받지 못함”# Check DNS propagationdig archon.example.com# Should return your server IP
# Check Caddy logsdocker compose logs caddy
# Check firewallsudo ufw status# Ports 80 and 443 must be open흔한 원인: DNS propagation 미완료(5-60분 대기), firewall이 80/443 차단, .env의 domain typo.
Health check 실패
Section titled “Health check 실패”Docker healthcheck는 /health가 아니라 /api/health를 사용합니다.
curl http://localhost:3000/api/healthPostgreSQL connection refused
Section titled “PostgreSQL connection refused”--profile with-db를 사용할 때 다음을 확인합니다.
DATABASE_URL의 hostname은localhost가 아니라 Docker service name인postgres여야 합니다.DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remote_coding_agent- postgres container가 healthy 상태인지 확인합니다:
docker compose ps postgres - migration이 실행되었는지 확인합니다: init script output은
docker compose logs postgres에서 볼 수 있습니다.
/.archon/ permission error
Section titled “/.archon/ permission error”container는 appuser(UID 1001)로 실행됩니다. Docker volume 대신 bind mount를 사용하는 경우:
sudo chown -R 1001:1001 /path/to/archon-dataPort conflicts
Section titled “Port conflicts”Docker 기본 port는 3000입니다(local dev는 3090). .env에서 변경합니다.
PORT=3001Container가 계속 restart됨
Section titled “Container가 계속 restart됨”docker compose psdocker compose logs --tail=50 app흔한 원인: .env file 누락, invalid credential, database 접근 불가.