Skip to main content
This section describes the recommended development workflow now that the full stack is available in self-hosting/docker-compose.
If you don’t need to run services locally, use the Docker Compose self-hosting guide instead. To run only selected services locally, skip to Core services below.
Start with Docker Compose for everything, then move a single service to host runtime when you need faster iteration.
# from repo root
make -C self-hosting/docker-compose all-up

# or run from the compose directory
# cd self-hosting/docker-compose
# make all-up
Use ngrok on the UI port (3030) when testing WorkOS and GitHub callbacks.

Core services

  • Backend (backend/, port 3000 by default) – orchestrator + REST APIs for repos/orgs/jobs.
  • Statesman (taco/cmd/statesman, port 8080) – state storage API and Terraform Cloud-compatible endpoints.
  • UI (ui/, port 3030) – TanStack Start frontend that talks to both services and WorkOS. When tunneling (e.g., ngrok), expose the UI host; WorkOS and GitHub callbacks should point to the UI domain.

Prerequisites

  • Go toolchain for backend + statesman, Node 18+ for UI (pnpm or npm).
  • A WorkOS project with User Management enabled and at least one organization + member (needed for UI auth and org IDs).
  • Optional: GitHub App for repo onboarding (the backend can help you create one via /github/setup).

Shared secrets and ports

  • Pick two secrets and reuse them across components:
    • ORCHESTRATOR_BACKEND_SECRET ≑ DIGGER_INTERNAL_SECRET (backend) ≑ UI env.
    • STATESMAN_BACKEND_WEBHOOK_SECRET ≑ OPENTACO_ENABLE_INTERNAL_ENDPOINTS (statesman) ≑ UI env.
  • Default ports: backend 3000, statesman 8080, UI 3030.

Hybrid mode: run one service outside Docker

1

Start Compose baseline

# from repo root
make -C self-hosting/docker-compose all-up

# or from self-hosting/docker-compose
make all-up
2

Stop the service you want to run locally

docker compose -f self-hosting/docker-compose/docker-compose.yml stop <service>
4

Update service URLs so callers can still reach it

Service running on hostIf UI is in DockerIf UI is on host
Backend (:3000)In ui container config, set ORCHESTRATOR_BACKEND_URL=http://host.docker.internal:3000In ui/.env.local, set ORCHESTRATOR_BACKEND_URL=http://localhost:3000
Statesman (:8080)In ui container config, set STATESMAN_BACKEND_URL=http://host.docker.internal:8080In ui/.env.local, set STATESMAN_BACKEND_URL=http://localhost:8080
Token service (:8081)In ui container config, set TOKENS_SERVICE_BACKEND_URL=http://host.docker.internal:8081In ui/.env.local, set TOKENS_SERVICE_BACKEND_URL=http://localhost:8081
Drift (:3001, optional)In ui container config, set DRIFT_REPORTING_BACKEND_URL=http://host.docker.internal:3001In ui/.env.local, set DRIFT_REPORTING_BACKEND_URL=http://localhost:3001
UI (:3030)Not applicableIn ui/.env.local, keep backend/statesman URLs on localhost
On Linux, host.docker.internal may require host-gateway mapping. If unavailable, use your host IP reachable from containers.
Treat self-hosting/docker-compose/docker-compose.yml ports: mappings as the source of truth for host ports.

What is superseded

  • Manually creating per-service local databases as the default first step.
  • Treating ngrok as backend-only; UI tunnel is now the primary callback endpoint.
  • Repeating full setup steps independently on each service page.

What remains important

  • Shared secret alignment across backend, statesman, and UI.
  • WorkOS organization/user sync into backend and statesman for authenticated UI flows.
  • GitHub App callback/webhook URLs pointing to the public UI domain.

Troubleshooting cheatsheet

  • Backend /api/ returns 404*: DIGGER_ENABLE_API_ENDPOINTS not true or org not upserted.
  • Statesman 403: webhook secret mismatch. Statesman 404/500 resolving org: org not synced (missing external_org_id).
  • UI WorkOS auth succeeds but org is empty: add membership in WorkOS and resync org/user to services.
  • GitHub connect opens 404: set ORCHESTRATOR_GITHUB_APP_URL to a valid install/setup URL.
Continue with the per-service pages for commands and env examples.