Installation
This walks you from a fresh clone to a live stack you can build on. It targets developers evaluating AnvilBase locally; production operators should also read Self-Hosting.
Prerequisites
- Docker 25+ and Docker Compose v2
openssl(to generate secrets)git- ~4 GB free RAM — the stack runs 10+ containers
- Optional: the Rust toolchain if you want to build the
anvilbaseCLI
Option A — the CLI (fastest)
If you have the CLI (cargo install --path cli, or a release binary), it
generates secrets and brings the stack up for you:
git clone https://github.com/paxtone-studio/anvilbase.gitcd anvilbaseanvilbase start # creates .env with fresh secrets on first run, waits for healthOn success it prints the local endpoints. Skip to Confirm health. Otherwise, use Option B.
Option B — Docker Compose by hand
1. Clone and configure secrets
git clone https://github.com/paxtone-studio/anvilbase.gitcd anvilbasecp .env.example .envOpen .env and fill every variable marked # Generate: …. This one-liner fills
the required secret material for you:
for k in POSTGRES_PASSWORD ANVILBASE_DB_PASSWORD MINIO_ROOT_PASSWORD \ VALKEY_PASSWORD IMGPROXY_SALT; do sed -i.bak -E "s|^${k}=.*|${k}=$(openssl rand -hex 24)|" .envdonefor k in CONTROL_PLANE_SECRET AUTH_SECRET IMGPROXY_KEY INTERNAL_SECRET; do sed -i.bak -E "s|^${k}=.*|${k}=$(openssl rand -hex 32)|" .envdone# Phoenix requires SECRET_KEY_BASE >= 64 charssed -i.bak -E "s|^SECRET_KEY_BASE=.*|SECRET_KEY_BASE=$(openssl rand -hex 64)|" .env# MinIO SSE-S3 KMS key (key-id:base64) — required for bucket encryptionsed -i.bak -E "s|^MINIO_KMS_SECRET_KEY=.*|MINIO_KMS_SECRET_KEY=anvilbase-dev:$(openssl rand -base64 32)|" .envrm -f .env.bakVerify nothing is left empty:
grep -E '^[A-Z_]+=$' .env && echo "STOP: empty required fields above" || echo "ok"The
MINIO_KMS_SECRET_KEYis required — project provisioning callsput_bucket_encryptionon every new bucket, and MinIO rejects it without a KMS key, rolling back project creation. The dev key above is fine locally; use an operator-managed key in production (Security Hardening).
2. (Optional) internal mTLS
Leave ANVILBASE_MTLS_ENABLED=false for local evaluation. For production, generate
certs with docker/mtls/generate-certs.sh and flip it to true — see
Network Security.
3. Bring up the stack
docker compose up -dFirst boot builds the Postgres image (installs wal-g) and the Rust services — expect 3–6 minutes on a warm cache, longer on first pull. Watch progress:
docker compose psdocker compose logs -f control-planeThe stack is ready when control-plane, postgres, auth, realtime,
console, and minio all report healthy.
4. Confirm health
curl -s http://localhost:39001/health | jq .curl -s http://localhost:39001/health/services | jq .Both should return "ok". A non-empty warnings[] is a soft signal (things still
work) — see Monitoring.
5. Open the console
The web console is at http://localhost:39004. The control-plane API is at http://localhost:39001.
Default ports
AnvilBase uses a dedicated 39xxx host-port block so it won’t collide with other
local services. Override any with *_PORT in .env; container-internal ports stay
at their conventional defaults.
| Service | Host port | Internal |
|---|---|---|
| Control plane (API) | 39001 | 3001 |
| Auth | 39002 | 3002 |
| Webhooks | 39003 | 3003 |
| Console | 39004 | 3004 |
| Realtime | 39040 | 4000 |
| Postgres | 39432 | 5432 |
| Valkey | 39637 | 6379 |
| Supavisor | 39654 | — |
| MinIO (S3 / console) | 39900 / 39901 | 9000 / 9001 |
| Traefik (http/https/dash) | 39080 / 39443 / 39081 | 80 / 443 / 8080 |
Full list: Reference → Ports.
Storage backend (MinIO vs RustFS)
AnvilBase runs MinIO by default. An opt-in overlay swaps in RustFS (an
S3-compatible server in Rust). Switch by editing .env:
# Default (MinIO):COMPOSE_FILE=docker-compose.yml# RustFS:COMPOSE_FILE=docker-compose.yml:docker-compose.rustfs.ymlThen docker compose down && docker compose up -d. The service name and hostname
stay minio, so nothing else changes. MinIO’s web console (:39901) is inactive
under RustFS; the S3 API (:39900) still works.
Tear down
docker compose down # stop containers, keep volumes (data preserved)docker compose down -v # ALSO wipe Postgres + MinIO data (destructive)Troubleshooting
uphangs on image pulls — check network / Docker Hub rate limits; isolate the build withdocker compose build postgres control-plane.- Control plane stuck
starting—docker compose logs control-plane; almost always a missing/misspelled env var. - Realtime: “SECRET_KEY_BASE must be at least 64 bytes” — regenerate with
openssl rand -hex 64. - Project creation rolls back — usually
MINIO_KMS_SECRET_KEYis unset (see step 1). - Port conflicts — override the relevant
*_PORTin.env.
Next: Quickstart.