QUESTPIE Autopilot
Self-Hosting

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

terminal
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-company

2. Create docker-compose.yml

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: 3

3. Configure environment

terminal
# 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
EOF

4. Start

terminal
docker compose up -d

The orchestrator is now running at http://localhost:7778.

Environment Variables

VariableRequiredDefaultDescription
OPENROUTER_API_KEYNoClaude API key (alternative to autopilot provider set openrouter --api-key sk-or-...)
COMPANY_ROOTYesPath to company data inside the container
AUTOPILOT_MASTER_KEYRecommendedAuto-generated file256-bit base64 key for secrets encryption
NODE_ENVRecommendeddevelopmentSet production for secure cookies and HTTPS
PORTNo7778API server port
WEBHOOK_PORTNo7777Webhook server port
MAX_CONCURRENT_AGENTSNo5Max simultaneous agent sessions
CORS_ORIGINNoAllowed 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.

docker-compose.yml (volumes section)
volumes:
  - ./my-company:/data/company

The volume contains:

  • company.yaml — company configuration
  • team/ — agents, humans, workflows, schedules
  • tasks/ — task lifecycle directories
  • knowledge/ — company brain
  • secrets/ — 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

my-company/company.yaml
settings:
  auth:
    enabled: true

2. Create the owner account

terminal
# Using the CLI (if installed on host)
cd my-company
autopilot auth setup

# Or exec into the container
docker exec -it autopilot autopilot auth setup

This 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.

terminal
# Check container health
docker inspect --format='{{.State.Health.Status}}' autopilot

# Manual health check
curl http://localhost:7778/api/health

Viewing Logs

terminal
# 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).jsonl

Updating

terminal
# Pull the latest image
docker compose pull

# Restart with the new image
docker compose up -d

# Verify
docker logs autopilot | head -20

The 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.

terminal
# 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 start

Exclude from backups:

  • .data/autopilot.db — rebuilt automatically
  • logs/sessions/*.jsonl — large, append-only session streams
  • secrets/.master-key — use AUTOPILOT_MASTER_KEY env var instead

Debugging

Container won't start

terminal
# 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_KEY

Port conflicts

terminal
# Change ports in docker-compose.yml
ports:
  - "8080:7778"   # Map API to host port 8080
  - "8081:7777"   # Map webhooks to host port 8081

Exec into the container

terminal
docker exec -it autopilot sh

Production Stack with TLS

For a complete production deployment with automatic TLS, use the ready-made stack in the deploy/ directory:

terminal
# 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 setup

This 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_KEY set as env var (not auto-generated file)
  • NODE_ENV=production
  • CORS_ORIGIN set to your domain URL (e.g., https://autopilot.yourdomain.com)
  • Authentication enabled in company.yaml
  • Owner account created via autopilot auth setup
  • .env file 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

On this page