Docker Deployment
Deploy QUESTPIE Autopilot with Docker and docker-compose for production use.
Run the Autopilot orchestrator as a Docker container. One image, two ports, one volume.
Quick Start
1. Create a company directory
mkdir -p ~/autopilot-data
cd ~/autopilot-data
# Option A: Use the CLI to scaffold
bun add -g @questpie/autopilot
autopilot init my-company
# Option B: Use Docker to scaffold (no Bun needed on host)
docker run --rm -v $(pwd):/out questpie/autopilot:latest \
autopilot init my-company --output /out/my-company2. Create docker-compose.yml
services:
autopilot:
image: questpie/autopilot:latest
container_name: autopilot
restart: unless-stopped
ports:
- "7778:7778" # API + Dashboard
- "7777:7777" # Webhooks
volumes:
- ./my-company:/data/company
environment:
COMPANY_ROOT: /data/company
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
AUTOPILOT_MASTER_KEY: ${AUTOPILOT_MASTER_KEY}
NODE_ENV: production
CORS_ORIGIN: ${CORS_ORIGIN:-}
healthcheck:
test: ["CMD", "bun", "-e", "fetch('http://localhost:7778/api/health').then(r => r.ok ? process.exit(0) : process.exit(1)).catch(() => process.exit(1))"]
interval: 30s
timeout: 5s
start_period: 15s
retries: 33. Configure environment
# Generate a master key for secrets encryption
export AUTOPILOT_MASTER_KEY=$(openssl rand -base64 32)
# Authenticate (choose one):
# Option A (recommended): autopilot provider set openrouter --api-key sk-or-...
# Works on headless VPS — prints a URL to open on any device.
# Option B: Set API key in .env
# OPENROUTER_API_KEY=sk-or-...
# Save to .env for docker-compose
cat > .env << 'EOF'
AUTOPILOT_MASTER_KEY=your-generated-key-here
# Uncomment if using API key instead of subscription login:
# OPENROUTER_API_KEY=sk-or-your-key-here
EOF4. Start
docker compose up -dThe orchestrator is now running at http://localhost:7778.
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
OPENROUTER_API_KEY | No | — | Claude API key (alternative to autopilot provider set openrouter --api-key sk-or-...) |
COMPANY_ROOT | Yes | — | Path to company data inside the container |
AUTOPILOT_MASTER_KEY | Recommended | Auto-generated file | 256-bit base64 key for secrets encryption |
NODE_ENV | Recommended | development | Set production for secure cookies and HTTPS |
PORT | No | 7778 | API server port |
WEBHOOK_PORT | No | 7777 | Webhook server port |
MAX_CONCURRENT_AGENTS | No | 5 | Max simultaneous agent sessions |
CORS_ORIGIN | No | — | Allowed CORS origin. Set to your domain when using a reverse proxy. |
Volume Mounting
The company directory is the single source of truth. Mount it as a Docker volume so data persists across container restarts.
volumes:
- ./my-company:/data/companyThe volume contains:
company.yaml— company configurationteam/— agents, humans, workflows, schedulestasks/— task lifecycle directoriesknowledge/— company brainsecrets/— encrypted credentials.data/autopilot.db— SQLite database (auto-rebuilt if deleted)logs/— activity and session logs
Do not mount .data/ separately. It must live inside the company directory.
First-Time Setup
After starting the container, enable authentication and create an owner account:
1. Enable auth in company.yaml
settings:
auth:
enabled: true2. Create the owner account
# Using the CLI (if installed on host)
cd my-company
autopilot auth setup
# Or exec into the container
docker exec -it autopilot autopilot auth setupThis prompts for name, email, and password, then saves credentials to ~/.autopilot/credentials.json.
For full auth setup details, see Authentication.
Health Checks
The container includes a built-in health check that polls /api/health every 30 seconds.
# Check container health
docker inspect --format='{{.State.Health.Status}}' autopilot
# Manual health check
curl http://localhost:7778/api/healthViewing Logs
# Follow container logs
docker logs -f autopilot
# View last 100 lines
docker logs --tail 100 autopilot
# Audit logs (on host filesystem)
cat my-company/logs/audit/$(date +%Y-%m-%d).jsonlUpdating
# Pull the latest image
docker compose pull
# Restart with the new image
docker compose up -d
# Verify
docker logs autopilot | head -20The SQLite database (.data/autopilot.db) is rebuilt automatically on startup from YAML/Markdown files. No migrations needed.
Backup
Back up the mounted company directory. That's it — it contains everything.
# Stop the container to ensure consistent state
docker compose stop
# Backup
tar -czf autopilot-backup-$(date +%Y%m%d).tar.gz my-company/
# Restart
docker compose startExclude from backups:
.data/autopilot.db— rebuilt automaticallylogs/sessions/*.jsonl— large, append-only session streamssecrets/.master-key— useAUTOPILOT_MASTER_KEYenv var instead
Debugging
Container won't start
# Check logs for startup errors
docker logs autopilot
# Common issues:
# - "failed to load company.yaml" → COMPANY_ROOT path is wrong or volume not mounted
# - "EADDRINUSE" → port conflict, change PORT/WEBHOOK_PORT
# - "missing authentication" → run: autopilot provider set openrouter --api-key sk-or-..., or set OPENROUTER_API_KEYPort conflicts
# Change ports in docker-compose.yml
ports:
- "8080:7778" # Map API to host port 8080
- "8081:7777" # Map webhooks to host port 8081Exec into the container
docker exec -it autopilot shProduction Stack with TLS
For a complete production deployment with automatic TLS, use the ready-made stack in the deploy/ directory:
# On your server
git clone https://github.com/questpie/autopilot.git
cd autopilot/deploy
# Configure
cp .env.example .env
nano .env # Set DOMAIN and OPENROUTER_API_KEY
# Initialize and start
docker compose run --rm autopilot autopilot init /data/company
docker compose up -d
docker compose exec autopilot autopilot auth setupThis stack includes:
- Caddy reverse proxy with automatic Let's Encrypt TLS
- Autopilot orchestrator + dashboard (no ports exposed directly)
- Single domain routing (
/api/*,/artifacts/*,/fs/*to API;/*to dashboard)
See deploy/README.md for the full guide, including webhooks, auto-updates, and troubleshooting.
Production Checklist
-
AUTOPILOT_MASTER_KEYset as env var (not auto-generated file) -
NODE_ENV=production -
CORS_ORIGINset to your domain URL (e.g.,https://autopilot.yourdomain.com) - Authentication enabled in
company.yaml - Owner account created via
autopilot auth setup -
.envfile has restrictive permissions (chmod 600 .env) - Reverse proxy with TLS in front (see Networking)
- API port (7778) not directly exposed to the internet
- Webhook port (7777) reachable only by services that need it
- Regular backups of the company directory