Org in a Box
Deployment

Docker Compose Deployment

Self-hosted deployment with Docker Compose for small teams and on-premises.

Compose Modes

The checked-in compose files now split cleanly into two modes:

  • docker-compose.yml: stable demo / self-hosted base stack using built containers for the API, worker, sandbox, platform admin app, tenant admin app, and the profile-gated web/docs UIs.
  • docker-compose.dev.yml: opt-in contributor overlay that swaps the API and Next.js surfaces to source-mounted dev servers.

If you want the contributor loop:

bun run compose:dev:up

For deployment-specific customization, use a user-owned override:

cp docker-compose.override.example.yml docker-compose.override.yml

Edit docker-compose.override.yml to:

  • Add resource limits
  • Configure restart policies
  • Pin images, ports, or secrets for your environment

Building Images

# From the repo root (context must be repo root for workspace deps)
docker build -f packages/core/Dockerfile -t orginabox-core:latest .
docker build -f packages/web/Dockerfile -t orginabox-web:latest .
docker build -f packages/platform-web/Dockerfile -t orginabox-platform-web:latest .
docker build -f packages/tenant-web/Dockerfile -t orginabox-tenant-web:latest .
docker build -f packages/docs/Dockerfile -t orginabox-docs:latest .
docker build -f packages/sandbox/Dockerfile -t orginabox/sandbox:latest .

Starting Production Stack

Set OPENCODE_SERVER_PASSWORD first, or run bun orginabox up once so the CLI can auto-provision it into .env.

docker compose \
  -f docker-compose.yml \
  --profile web \
  up -d

Add gateway profiles as needed:

docker compose \
  -f docker-compose.yml \
  --profile web \
  --profile docs \
  --profile slack \
  --profile teams \
  up -d

platform-web and tenant-web are part of the base stack and do not need a separate profile. The public docs UI remains opt-in behind the docs profile.

Backups

Back up the PostgreSQL volume regularly:

docker exec orginabox-postgres \
  pg_dump -U orginabox orginabox | gzip > backup-$(date +%Y%m%d).sql.gz

TLS

For HTTPS, put a reverse proxy (nginx, Caddy, Traefik) in front:

server {
  listen 443 ssl;
  server_name api.yourcompany.com;
  
  location / {
    proxy_pass http://localhost:8787;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Or use Caddy for automatic TLS:

api.yourcompany.com {
  reverse_proxy localhost:8787
}

On this page