Self-hosted deployment using Docker Compose.
- Docker + Docker Compose
- TLS certificates (for HTTPS)
- A domain name pointing to your server
cp .env.example .env
# Edit .env with your valuesRequired variables:
POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB- Database credentialsGITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET- OAuth (for dashboard login)JWT_ACCESS_SECRET/JWT_REFRESH_SECRET- Auth tokens (>= 32 chars each)POSTGATE_SYSTEM_TOKEN_SECRET- System token HMAC secret (>= 32 chars)HTTP_TLS_CERTIFICATE/HTTP_TLS_KEY- TLS cert paths
docker compose up -d postgres
# Wait for it to be healthy
docker compose psow alias set infra --db postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost/$POSTGRES_DBOr using Docker if you don't have the CLI installed locally:
docker run --rm --network host \
-v ~/.openworkers:/root/.openworkers \
ghcr.io/openworkers/openworkers-cli \
alias set infra --db postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost/$POSTGRES_DBow infra migrate status
ow infra migrate runThe system user (00000000-...) owns shared resources (the platform database config, etc.). Claim it with your admin identity.
The username must match exactly how you will log in:
- GitHub OAuth → use your GitHub username (e.g.
max-lt) - Email/password (headless) → use your email (e.g.
admin@example.com)
Important: Anyone who signs up or logs in with this username gets admin access to platform resources. Double-check it before proceeding.
# GitHub login
ow infra users create my-github-handle --system
# Or email/password login (headless, no GitHub)
ow infra users create admin@example.com --system --passwordUpdate the alias to reference the admin user:
ow alias set infra --db postgres://... --user my-github-handle --forceThe migrations created a database config for the API. Start Postgate and generate a token:
docker compose up -d postgate
docker compose exec postgate postgate gen-token \
00000000-0000-0000-0000-000000000000 api \
--permissions SELECT,INSERT,UPDATE,DELETECopy the generated token (pg_xxx...) to .env as POSTGATE_TOKEN.
docker compose up -ddocker compose ps
docker compose logs -fDashboard should be available at https://your-domain/.
You can now manage workers via CLI:
ow infra workers create my-worker
ow infra workers deploy my-worker script.tsThe API and Dashboard can also run as workers on the platform itself instead of as Docker containers. See openworkers-api/DEPLOY.md for instructions.
In this mode, Postgate HTTP is optional too — the workerized API uses runtime database bindings directly.
# Pull latest images
docker compose pull
# Apply new migrations
ow infra migrate run
# Restart with new images
docker compose up -d# View logs
docker compose logs -f openworkers-api
docker compose logs -f openworkers-runner
# Restart a service
docker compose restart openworkers-api
# Shell into postgres
docker compose exec postgres psql -U $POSTGRES_USER -d $POSTGRES_DB
# Stop all services
docker compose down
# Stop all + remove volumes (DANGER: deletes data)
docker compose down -v# Check migration status
ow infra migrate status
# Run pending migrations
ow infra migrate run
# Baseline (mark all as applied without running)
ow infra migrate baseline
# User management
ow infra users list
ow infra users create username # GitHub login
ow infra users create email --password # Email/password login
ow infra users delete usernameUsing the database.sh script:
./database.sh backup
./database.sh restore ~/backups/openworkers/openworkers-2025-01-10.dump
./database.sh psql