Docker Compose deploy
The production stack is two services: the hub (orchestrator plus web UI) and a co-located
agent that drives the local Docker daemon and runs the runner containers. The bundled agent
auto-enrolls on first boot, so a single-machine install is one docker compose command. The hub
builds from this repository’s Dockerfile; only the agent ships as a prebuilt image.
Get the repository
Section titled “Get the repository”git clone https://github.com/<owner>/runaway.gitcd runawayGenerate the secrets
Section titled “Generate the secrets”Generate three secrets into a .env file:
{ echo "RUNAWAY_MASTER_KEY=$(openssl rand -base64 32)" echo "BETTER_AUTH_SECRET=$(openssl rand -base64 32)" echo "RUNAWAY_LOCAL_AGENT_TOKEN=$(openssl rand -base64 32)"} >> .envRUNAWAY_MASTER_KEYencrypts your GitHub tokens at rest (AES-256-GCM).BETTER_AUTH_SECRETsigns your login session.RUNAWAY_LOCAL_AGENT_TOKENlets the bundled agent enroll itself on first boot.
The full list of variables, including the optional ones, is in the environment variables reference.
Start the stack
Section titled “Start the stack”docker compose -f docker-compose.example.yml up -dThis builds the hub and starts it alongside the agent. Open http://localhost:3000 to create your admin account. For the full first-run walkthrough — connecting an org, creating a scale set, running a workflow — follow the quickstart.
Persist the data volume
Section titled “Persist the data volume”All state lives in one volume mounted at /app/data:
Directory/app/data
- app.db SQLite database (with WAL)
Directorybackups/ pre-migration snapshots (last 5)
- …
Use a named volume so state survives upgrades. The entrypoint snapshots the database into
/app/data/backups/ before running migrations — those snapshots cover a migration failure, not
whole-volume loss, so keep an off-box backup for disaster recovery. See Backups and
recovery.
Run a single instance
Section titled “Run a single instance”SQLite is single-writer. Deploy one hub instance per data volume and use recreate, not rolling updates — two containers against the same volume is unsupported. The entrypoint holds a lock, so a second container on the same volume exits cleanly rather than corrupting state.
To upgrade, pull and recreate; the entrypoint runs database migrations on boot before serving traffic:
docker compose -f docker-compose.example.yml pulldocker compose -f docker-compose.example.yml up -d