Production Deployment
Deploy AnswerLoops to a production server.
This assumes you've already worked through the self-host quickstart locally and know your setup works — production is the same app, just with real secrets, a real domain, and docker-compose.prod.yml instead of the dev compose file.
Recommended stack
- Server: Any Linux VPS (Ubuntu 22.04+)
- Reverse proxy: Caddy (auto SSL) or nginx
- Process: Docker Compose
- Database: Docker Postgres with named volume, or managed Postgres (Neon, Supabase, Railway)
Get the code onto the server
Clone the repo on your server the same way you did locally, then create a production .env (not .env.local — that's the dev-only file):
git clone https://github.com/AnswerLoops/AnswerLoops.git
cd AnswerLoops
cp .env.local.example .envFill in .env with your production values — the checklist below covers what has to be different from your dev setup.
Environment checklist
Before going live, verify these are set in your production .env:
-
AUTH_URLset to your production domain (e.g.https://app.yourdomain.com) -
AUTH_SECRET— unique 32-byte hex, not the same as dev -
ENCRYPTION_KEY— unique 32-byte hex, not the same as dev -
DATABASE_URLpointing to production database - OAuth callback URLs updated in GitHub/Google dashboards
-
OPENAI_API_KEYset
Caddy (recommended — auto SSL)
app.yourdomain.com {
reverse_proxy localhost:3000
}Run: caddy run --config Caddyfile
nginx
server {
listen 443 ssl;
server_name app.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Start in production
Use docker-compose.prod.yml, not the plain docker-compose.yml from local dev — it builds the multi-stage production image and runs the bot in bot:start mode instead of the dev watch mode:
docker compose -f docker-compose.prod.yml up -d --buildDrizzle migrations run automatically against your production database on first start, same as local dev — no separate migration step.
Health check
curl https://app.yourdomain.com/api/health
# → {"ok":true}Alternative: Railway or another PaaS
If you'd rather not manage a VPS, reverse proxy, and TLS certs yourself, push the repo to Railway (or Fly.io) — it builds straight from the Dockerfile, handles HTTPS automatically, and you skip the Caddy/nginx section above entirely. You'll still need to set the same environment variables, and a managed Postgres (Neon, Railway's own Postgres) instead of the Docker-volume one.