docker-compose.yml that runs three services on one box:
This single-box setup is suitable for most early-stage and growth-stage deployments. For high-availability requirements, move Postgres to a managed provider (Neon, RDS, Cloud SQL) and deploy the API container to a managed compute platform.
Dockerfile
The image uses a two-stage build to minimize the final image size. The runtime stage runs as a non-root user (appuser) for security.
docker-compose.yml
Caddyfile
EditCaddyfile and replace api.yourdomain.com with your real subdomain before starting:
Deploying the stack
1
Provision your server and point DNS
Create an Ubuntu 22.04 / Debian 12 VM (Hetzner CX22 is ~€5/month). Add an A record pointing
api.yourdomain.com to the server’s public IP. Let the record propagate before starting Caddy.2
Install Docker
3
Clone the repository
4
Configure secrets
.env — at minimum set:5
Edit the Caddyfile
Replace
api.yourdomain.com in Caddyfile with your actual subdomain.6
Start the stack
db initialises, then api starts once the database health check passes, then caddy begins serving HTTPS.7
Load the database schema
After the stack is running, load the schema into the Postgres container:Then apply migrations:See Database setup for the full guide, including the required
causeloop_app role.8
Verify
Kubernetes
The Docker image works on any Kubernetes cluster. Use the/health and /ready endpoints as probes:
Secret (for JWT_SECRET, CAUSELOOP_MASTER_KEY, DATABASE_URL) and a ConfigMap (for PORT, CORS_ORIGINS, LLM_PROVIDER_ORDER).