Self-host quickstart (docker compose)#
See also: Self-hosting the control plane — production deployment patterns (Kubernetes, multi-region, TLS, hardening, ops). This page is the local-eval path; that page is the production guide. Both are linked from the main quickstart.
One command. CP + console + state, all on your machine. No image building, no cloning, no Python toolchain. Pulls private images from GHCR — you authenticate with your GitHub PAT.
Prerequisites#
- Docker Desktop or docker-ce + the Compose plugin (most installs include it).
- A GitHub PAT with
read:packagesscope, authorized for theairlockaiorg if you're behind SSO. Get one at https://github.com/settings/tokens. - ~5 GB free disk for images plus the persistent volume.
Install#
# 1. Authenticate to GHCR
echo $GITHUB_TOKEN | docker login ghcr.io -u <your-github-username> --password-stdin
# 2. Run the installer
curl -fsSL https://airlocklabs.ai/install.sh | bash
What it does (paraphrasing install.sh):
- Generates a fresh operator token.
- Writes a
.envto~/.airlock/.env. - Runs
docker compose up -dagainst the bundledcompose.yaml. - Polls
/healthuntil CP is up. - Prints the console URL plus the operator token.
You should see:
Console: http://localhost:3000/login
CP: http://localhost:8080
Token: <64 hex chars>
Open the console URL, paste the token, you're in.
What's running#
Three services in one compose stack:
cp— control plane on:8080(HTTP). Persistent volumeairlock_stateholdsstate.yaml, the audit log, and the CP's Ed25519 keypair (auto-generated on first boot).console— operator dashboard on:3000(HTTP). Talks tocpover the docker network.- state volume — persistent across restarts.
The worker is not in this stack. The worker runs in your VPC, near your Postgres. Once CP is up, follow Step 3 of the quickstart to mint an enrollment token and install the worker on whatever host has database access.
Customization#
The most-asked overrides:
Pin image versions#
AIRLOCK_CP_IMAGE_TAG=v0.1.0 ./install.sh
Use our hosted console#
Drop the console service from ~/.airlock/compose.yaml and visit
https://console.airlocklabs.ai?cp=http://your-cp.example.com.
Production with HTTPS#
Stick Caddy or Cloudflare in front of cp (port 8080); set
AIRLOCK_CP_PUBLIC_URL to the public HTTPS URL; restart the stack.
# Add to compose.yaml under cp.environment:
AIRLOCK_CP_PUBLIC_URL: https://cp.example.com
Override the operator token#
Edit ~/.airlock/.env and set a known value, then
cd ~/.airlock && docker compose up -d to apply.
Operations#
- Stop:
cd ~/.airlock && docker compose down - Restart:
cd ~/.airlock && docker compose restart - Upgrade:
cd ~/.airlock && docker compose pull && docker compose up -d— same compose, newer images. - Logs:
docker compose logs -f cpordocker compose logs -f console. - Volume backup:
docker run --rm -v airlock_state:/state -v $(pwd):/backup busybox tar czf /backup/airlock-state.tgz -C / state - Reset:
docker compose down -v(the-vremoves the state volume; you'll get a fresh CP keypair plus token on next startup).
When to use this vs self-hosting-cp.md#
Quick guide to whether you're on the wrong page:
| Use this page | Use self-hosting-cp.md |
|---|---|
| Local laptop / one-VM eval | Production deploy |
| Just want to see the console working | k8s, multi-region, multi-replica |
| OK with HTTP on localhost | Need TLS / signed images / cosign |
| Tear down + start over freely | Backed-up volume, monitoring, alerting |
| Single-tenant operator | Org-scoped operators with OIDC |
Troubleshooting#
A few common failure modes:
docker pullreturns "denied" — your PAT isn't authorized for the airlockai org. Re-authorize via Settings → Developer settings → PAT → "Configure SSO".- CP refuses to start — check
AIRLOCK_CP_ALLOW_LOCALHOST_PUBLIC_URL=trueis in.env(required whenAIRLOCK_CP_PUBLIC_URLishttp://localhost:*). - Console can't reach CP — make sure both are on the same compose
network (the bundled
compose.yamldoes this; if you split them onto different stacks, setAIRLOCK_CP_URLon the console explicitly). - Token forgot —
cat ~/.airlock/.env(it's there).