# Clawmates on Docker Compose A single-node deployment of the whole platform — the same images the Kubernetes/Helm path uses, with the same §15 security topology. This is the air-gapped appliance route; it is equally usable as a simple self-host. ## What runs | Service | Role | |---|---| | `postgres` | database (named volume `pgdata`) | | `broker` | the secret broker — credentials never leave it; reachable only over a private socket volume shared with the server | | `socket-proxy` | allow-listed Docker API so the server can spawn agent sandboxes and **nothing else** | | `server` | API + streaming gateway + agent runtime + scheduler | | `frontend` | the Next.js web app | Networks `core`, `secrets_net`, `sandbox_net`, and `engine_net` are all `internal: true`; only `edge` is published. Agent sandboxes run with no network at all (egress is the browser container's alone). ## Quick start ```bash cd deploy/compose cp .env.example .env # Edit .env: set POSTGRES_PASSWORD and CLAWMATES_BOOTSTRAP_OWNER_PASSWORD. # Either build the images locally... docker compose build # ...or load them from a signed release bundle (see deploy/airgapped/install.sh). docker compose up -d ``` The server **self-migrates** on boot and, if `CLAWMATES_BOOTSTRAP_OWNER_PASSWORD` is set, provisions the first Owner + workspace once (a no-op on every later boot). Then open: - **App** → http://localhost:3000 - Sign in with `CLAWMATES_BOOTSTRAP_OWNER_EMAIL` / `…_PASSWORD`. - API health → http://localhost:8080/healthz ## Configuration Host- and secret-specific values come from `.env` (overlaid onto `clawmates.toml` at runtime — `CLAWMATES_*` env always wins). The knobs: | Concern | Where | Notes | |---|---|---| | DB password | `.env` `POSTGRES_PASSWORD` | also forms the server/broker DSN | | Image tag | `.env` `CLAWMATES_VERSION` | `latest` after a local build, or a release version | | First owner | `.env` `CLAWMATES_BOOTSTRAP_*` | password set = bootstrap on first boot | | LLM | `clawmates.toml` `[llm]` | `openai_compat` (default, point `base_url` at vLLM/Ollama/llama.cpp) or `anthropic` (+ `ANTHROPIC_API_KEY` in `.env`) | | Auth | `clawmates.toml` `[auth]` + `.env` `AUTH_MODE` | `local` (default) or `clerk` (see [docs/clerk.md](../../docs/clerk.md)) | | Tracing | `.env` `CLAWMATES_TELEMETRY__OTLP_ENDPOINT` | unset = logs only, no egress | ### Using Anthropic instead of a local model In `clawmates.toml`: ```toml [llm] provider = "anthropic" model = "claude-sonnet-4-6" ``` and set `ANTHROPIC_API_KEY` in `.env`. ## The broker master key — back it up On first boot the broker generates its encryption key into the `broker_key` volume and logs a reminder. **Every stored credential is unrecoverable without it.** Back it up: ```bash docker compose cp broker:/etc/clawmates-broker/broker.key ./broker.key.backup ``` ## Operations ```bash docker compose ps # status docker compose logs -f server # follow server logs docker compose pull && docker compose up -d # upgrade to a new CLAWMATES_VERSION docker compose down # stop (keeps volumes/data) docker compose down -v # stop AND delete all data ``` ## Production notes - Put a TLS-terminating reverse proxy in front of ports 3000/8080; the SSE gateway needs response buffering **off** (the Helm ingress sets this; nginx: `proxy_buffering off;` with long read timeouts). - `socket-proxy` mounts the Docker socket read-only and exposes only the container lifecycle verbs — verified by `crates/cm-sandbox/tests/socket_proxy.rs`. - The full bring-up is exercised end to end by `scripts/rehearse-install.sh` (verify a signed bundle → `docker load` → `compose up` → assert the login page serves), which also runs in the release pipeline.