> ## Documentation Index
> Fetch the complete documentation index at: https://docs.octokraft.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker Compose Deployment

> Deploy Corbulo with Docker Compose

# Docker Compose Deployment

This guide walks through deploying Corbulo using Docker Compose. This is the recommended approach for small teams (under 50 developers) or evaluation environments.

***

## Prerequisites

* Linux server (Ubuntu 22.04+ recommended)
* Docker 24.x+ with Docker Compose v2
* A registered GitHub App (see [GitHub Integration](/integrations/github))
* A Clerk account for authentication
* Access to an OpenAI-compatible AI model API

***

## Quick Start

<Steps>
  <Step title="Get deployment files">
    Download the Corbulo deployment package, which includes `docker-compose.yml`, `.env.example`, and supporting configuration files.
  </Step>

  <Step title="Configure environment">
    Copy the example environment file and fill in your values:

    ```bash theme={null}
    cp .env.example .env
    ```

    Edit `.env` and set all required variables. See the [environment variables](#environment-variables) section below for the full list.
  </Step>

  <Step title="Start services">
    ```bash theme={null}
    docker compose up -d
    ```

    This starts Corbulo along with bundled infrastructure services (PostgreSQL, Redis, FalkorDB, Temporal). If you are using external managed services, remove the corresponding entries from `docker-compose.yml` and update the connection strings in your `.env` file.
  </Step>

  <Step title="Run database migrations">
    ```bash theme={null}
    docker compose exec api corbulo migrate up
    ```
  </Step>

  <Step title="Verify the deployment">
    ```bash theme={null}
    curl http://localhost:8080/healthz
    ```

    A successful response confirms the API server is running and connected to all infrastructure services.
  </Step>
</Steps>

***

## Environment Variables

These are the key variables you must configure. For the complete list, see the [Configuration Reference](/self-hosting/configuration).

### Required

| Variable                  | Description                                                                                   |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| `DATABASE_URL`            | PostgreSQL connection string (e.g., `postgres://user:pass@host:5432/corbulo?sslmode=disable`) |
| `REDIS_URL`               | Redis connection string (e.g., `redis://host:6379`)                                           |
| `TEMPORAL_ADDRESS`        | Temporal server address (e.g., `temporal:7233`)                                               |
| `FALKORDB_HOST`           | FalkorDB host address (e.g., `falkordb:6379`)                                                 |
| `SECRET_KEY`              | Encryption key for API tokens. Generate with `openssl rand -hex 32`.                          |
| `CLERK_SECRET_KEY`        | Your Clerk API secret key                                                                     |
| `CLERK_JWT_ISSUER`        | Your Clerk JWT issuer URL                                                                     |
| `GITHUB_APP_ID`           | Your GitHub App ID                                                                            |
| `GITHUB_PRIVATE_KEY_PATH` | Path to your GitHub App private key `.pem` file                                               |
| `GITHUB_WEBHOOK_SECRET`   | Secret used to verify GitHub webhook payloads                                                 |
| `CORS_ORIGINS`            | Allowed CORS origins (e.g., `https://corbulo.yourcompany.com`)                                |
| `FRONTEND_URL`            | Public URL of the frontend (e.g., `https://corbulo.yourcompany.com`)                          |

### AI Model Configuration

At minimum, configure the OpenAI large model slot. See [Configuration Reference](/self-hosting/configuration) for all 4 slots.

| Variable                    | Description                                           |
| --------------------------- | ----------------------------------------------------- |
| `LLM_OPENAI_LARGE_PROVIDER` | Provider name (e.g., `openai`, `azure`, `openrouter`) |
| `LLM_OPENAI_LARGE_MODEL`    | Model identifier (e.g., `gpt-4o`)                     |
| `LLM_OPENAI_LARGE_API_KEY`  | API key for the provider                              |
| `LLM_OPENAI_LARGE_BASE_URL` | API endpoint URL                                      |
| `LLM_OPENAI_SMALL_PROVIDER` | Provider for the small model slot                     |
| `LLM_OPENAI_SMALL_MODEL`    | Model identifier (e.g., `gpt-4o-mini`)                |
| `LLM_OPENAI_SMALL_API_KEY`  | API key                                               |
| `LLM_OPENAI_SMALL_BASE_URL` | API endpoint URL                                      |

***

## Docker Compose File

Below is a reference `docker-compose.yml` with all services. Adjust as needed -- if you use managed PostgreSQL or Redis, remove those services and update connection strings.

```yaml theme={null}
services:
  # Corbulo application
  api:
    image: ghcr.io/corbulo/corbulo-api:latest
    ports:
      - "8080:8080"
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      temporal:
        condition: service_started
    volumes:
      - github-keys:/keys:ro
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
      interval: 30s
      timeout: 5s
      retries: 3

  worker:
    image: ghcr.io/corbulo/corbulo-api:latest
    command: ["corbulo", "worker"]
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      temporal:
        condition: service_started
    volumes:
      - github-keys:/keys:ro
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

  frontend:
    image: ghcr.io/corbulo/corbulo-frontend:latest
    ports:
      - "3000:80"
    environment:
      - BACKEND_URL=http://api:8080
    depends_on:
      - api
    restart: unless-stopped

  # Infrastructure services
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: corbulo
      POSTGRES_PASSWORD: corbulo
      POSTGRES_DB: corbulo
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U corbulo"]
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped

  falkordb:
    image: falkordb/falkordb:latest
    volumes:
      - falkordata:/data
    restart: unless-stopped

  temporal:
    image: temporalio/auto-setup:latest
    environment:
      - DB=postgresql
      - DB_PORT=5432
      - POSTGRES_USER=corbulo
      - POSTGRES_PWD=corbulo
      - POSTGRES_SEEDS=postgres
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped

  temporal-ui:
    image: temporalio/ui:latest
    ports:
      - "8233:8080"
    environment:
      - TEMPORAL_ADDRESS=temporal:7233
    depends_on:
      - temporal
    restart: unless-stopped

volumes:
  pgdata:
  redisdata:
  falkordata:
  github-keys:
```

<Note>
  The `worker` service uses the same image as the `api` service with a different entrypoint. Workers process background tasks including code analysis, health assessments, and PR analysis.
</Note>

***

## Scaling

### Adding Workers

The analysis workers handle the compute-intensive tasks. To process more repositories or PRs concurrently, add more worker replicas:

```bash theme={null}
docker compose up -d --scale worker=3
```

### Resource Allocation

For a team of 20-30 developers with 10-20 repositories:

| Service         | CPU       | Memory |
| --------------- | --------- | ------ |
| `api`           | 2 cores   | 2 GB   |
| `worker` (each) | 2 cores   | 2 GB   |
| `frontend`      | 0.5 cores | 256 MB |
| `postgres`      | 2 cores   | 2 GB   |
| `redis`         | 0.5 cores | 512 MB |
| `falkordb`      | 1 core    | 1 GB   |
| `temporal`      | 1 core    | 1 GB   |

***

## TLS Configuration

For production deployments, terminate TLS in front of Corbulo using a reverse proxy such as Nginx, Caddy, or Traefik.

Example with Caddy:

```
corbulo.yourcompany.com {
    reverse_proxy localhost:3000
}

api.corbulo.yourcompany.com {
    reverse_proxy localhost:8080
}
```

Set `FRONTEND_URL` and `BACKEND_URL` to the public HTTPS URLs, and update `CORS_ORIGINS` accordingly.

***

## Operations

### Health Checks

```bash theme={null}
# Simple health check
curl http://localhost:8080/healthz

# Detailed health with component status
curl http://localhost:8080/health/detailed
```

### Logs

```bash theme={null}
# All services
docker compose logs -f

# Specific service
docker compose logs -f api
docker compose logs -f worker
```

### Upgrades

```bash theme={null}
# Pull latest images
docker compose pull

# Restart with new images
docker compose up -d

# Run any new migrations
docker compose exec api corbulo migrate up
```

### Backups

Back up the PostgreSQL database regularly. The other services (Redis, FalkorDB) contain derived data that can be rebuilt from a fresh analysis.

```bash theme={null}
docker compose exec postgres pg_dump -U corbulo corbulo > backup.sql
```

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="API server fails to start">
    Check the logs for missing environment variables:

    ```bash theme={null}
    docker compose logs api
    ```

    The API server will not start if any required variable is missing. The error message will indicate which variable is unset.
  </Accordion>

  <Accordion title="Cannot connect to database">
    Verify that PostgreSQL is running and the connection string is correct:

    ```bash theme={null}
    docker compose exec postgres pg_isready -U corbulo
    ```

    If using an external database, confirm that the `DATABASE_URL` is reachable from within the Docker network.
  </Accordion>

  <Accordion title="Workers not processing tasks">
    Verify the worker is running and connected to Temporal:

    ```bash theme={null}
    docker compose logs worker
    ```

    Check the Temporal UI at `http://localhost:8233` to see whether workflows are queued, running, or failing.
  </Accordion>

  <Accordion title="GitHub webhooks not arriving">
    Verify that your server is reachable from the internet on port 443 (or whichever port you expose). GitHub must be able to reach your webhook endpoint.

    Check webhook delivery status in your GitHub App settings under **Advanced > Recent Deliveries**.
  </Accordion>

  <Accordion title="Analysis running slowly">
    Scale the worker service to add more processing capacity:

    ```bash theme={null}
    docker compose up -d --scale worker=3
    ```

    Also confirm that the AI model API is responsive. Slow model responses are the most common cause of slow analysis.
  </Accordion>
</AccordionGroup>
