Forge ships two Compose files: a hardened single-node production stack and a lighter local-development stack. This guide explains the production topology, the hardening applied, and how to operate it. To get running quickly first, see quickstart.md.
| File | Purpose |
|---|---|
| ../../deploy/docker-compose.yml | Production single-node stack |
| ../../deploy/docker-compose.dev.yml | Local development stack (make dev) |
| ../../deploy/caddy/Caddyfile | Edge reverse proxy + automatic HTTPS |
| Service | Image | Role |
|---|---|---|
db |
pgvector/pgvector:pg16 |
Postgres with the pgvector extension |
redis |
redis:7.4-alpine |
Queue, cache, and session store |
minio |
quay.io/minio/minio |
S3-compatible object storage for artifacts (quay.io is MinIO's public registry — the Docker Hub repo is no longer anonymously pullable) |
api |
built from deploy/docker/api.Dockerfile |
FastAPI application |
worker |
built from deploy/docker/worker.Dockerfile |
Celery worker (indexer, syncer, agent runner) |
mcp-gateway |
built from deploy/docker/mcp-gateway.Dockerfile |
MCP client manager |
web |
built from deploy/docker/web.Dockerfile |
Next.js frontend |
caddy |
caddy:2.8-alpine |
TLS termination and reverse proxy |
autoheal |
willfarrell/autoheal |
Restarts containers that fail their healthcheck |
docker-proxy |
tecnativa/docker-socket-proxy:0.3.0 |
Read-only-socket, verb-restricted Docker API proxy — the only component near the raw Docker socket, used by worker to create/exec/inspect per-task sandbox containers |
sandbox-proxy |
ubuntu/squid:6.6-24.04_edge |
Allow-listing forward proxy (squid) — the only egress route for sandboxed agent containers on the network: egress sandbox mode |
The production file follows the spec's "Production Docker Compose Requirements":
-
Pinned images — every image uses an explicit version tag.
-
Healthchecks on every long-running service.
-
Autoheal sidecar restarts any container labelled
autoheal=truethat goes unhealthy. -
Resource limits — CPU and memory limits on every container.
-
Named volumes for all stateful data (
db-data,redis-data,minio-data,caddy-data,caddy-config) — never bind mounts. -
Segmented networks — seven networks:
edge,backend,data,mcp,sandbox_ctl,sandbox_egress, andobservability.data,sandbox_ctl,sandbox_egress, andobservabilityare markedinternal(no route to the public internet):dataisolates the database from the edge;sandbox_ctlisworker's private route todocker-proxy;sandbox_egressis the only route out for sandboxed agent containers, bridged bysandbox-proxy.observabilityis only populated when theobservabilityCompose profile is enabled (otel-collector,prometheus,grafana,loki,tempo,alertmanager);temporal,temporal-ui, andtemporal-workersimilarly only start under thetemporalprofile.minio-data,forge-specs,forge_repos,caddy-data,caddy-config) — never bind mounts.forge-specsis the spec engine's document store, mounted intoapi,workerandmcp-gatewayso all three read the same specs; without it each container keeps its own copy on its writable layer and loses every spec on redeploy. It is a separate store from Postgres and must be in your backups — see backup.md. -
Segmented networks —
edge,backend,data,mcp; thedatanetwork is markedinternal, so the database is unreachable from the edge. -
Non-root app containers (
user: "1000:1000"). -
Log rotation —
json-filedriver capped atmax-size: 100m,max-file: 5per container.
# Start (detached)
docker compose -f deploy/docker-compose.yml up -d --remove-orphans
# Status and health
docker compose -f deploy/docker-compose.yml ps
# Tail logs for one service
docker compose -f deploy/docker-compose.yml logs -f api
# Stop (containers removed, named volumes preserved)
docker compose -f deploy/docker-compose.yml down
# Validate the file without starting anything
docker compose -f deploy/docker-compose.yml configAll services read configuration from environment variables, sourced from .env
in the repo root. Compose substitutes them at up time. See
../../.env.example for the full list and
security.md for which values must be treated as secrets.
- Image digests: images are pinned to version tags, not immutable
@sha256digests. Resolving digests needs registry network access; pin by digest before a production rollout. - Building images:
docker compose -f deploy/docker-compose.yml buildbuilds the four application images from thedeploy/docker/Dockerfiles. Run it on a host with network access to fetch base images.