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

# Docker Compose

> Run the full Cognisafe stack locally or on a VM.

Docker Compose is the fastest way to get the full stack running. All six services start with a single command.

## Prerequisites

* Docker Engine 24+ and Docker Compose v2
* Git

## Steps

<Steps>
  <Step title="Clone the repository">
    ```bash theme={null}
    git clone https://github.com/cognisafe/cognisafe.git
    cd cognisafe
    ```
  </Step>

  <Step title="Configure environment variables">
    ```bash theme={null}
    cp .env.example .env
    ```

    Open `.env` and fill in the required values:

    ```bash theme={null}
    # Required
    PROXY_API_KEY=csk_your_key_here          # auth key for the proxy
    OPENAI_API_KEY=sk-...                    # used by PyRIT safety scorers
    STRIPE_SECRET_KEY=sk_live_...            # Stripe API key
    STRIPE_WEBHOOK_SECRET=whsec_...          # Stripe webhook signing secret
    STRIPE_PRICE_PRO=price_...               # Stripe price ID for Pro tier
    STRIPE_PRICE_TEAM=price_...              # Stripe price ID for Team tier

    # Pre-filled with sensible defaults — change if needed
    POSTGRES_URL=postgresql+asyncpg://postgres:postgres@postgres:5432/cognisafe
    REDIS_URL=redis://redis:6379
    ```

    For local development without Stripe, leave the Stripe vars blank — billing routes will return errors but all other functionality works.
  </Step>

  <Step title="Start the stack">
    ```bash theme={null}
    docker compose -f infra/docker-compose.yml up
    ```

    On first run, Docker pulls the images and the `migrate` service runs `alembic upgrade head` to initialise the database schema before the API starts.

    <Note>
      The `migrate` service is a one-shot container. It runs database migrations and exits with code 0. If you see it listed as "exited" in `docker compose ps`, that is expected — it completed successfully.
    </Note>
  </Step>

  <Step title="Open the dashboard">
    Navigate to [http://localhost:3000](http://localhost:3000).

    The proxy is available at [http://localhost:8080](http://localhost:8080) and the API at [http://localhost:8000](http://localhost:8000).
  </Step>

  <Step title="Point your SDK at the local stack">
    ```python theme={null}
    import cognisafe

    cognisafe.configure(
        api_key="csk_your_key_here",  # same as PROXY_API_KEY in .env
        project_id="my-app",
        proxy_url="http://localhost:8080",
        api_url="http://localhost:8000",
    )
    cognisafe.patch_openai()
    ```
  </Step>
</Steps>

## Services

| Service         | Port | Role                                            |
| --------------- | ---- | ----------------------------------------------- |
| `postgres`      | 5432 | TimescaleDB — primary datastore                 |
| `redis`         | 6379 | Job queue (`safety_score_jobs`)                 |
| `migrate`       | —    | One-shot: runs `alembic upgrade head` and exits |
| `api`           | 8000 | FastAPI backend — REST API and Stripe webhooks  |
| `safety_worker` | —    | PyRIT scoring worker                            |
| `proxy`         | 8080 | Go LLM reverse proxy                            |
| `web`           | 3000 | Next.js dashboard                               |

## Scaling safety workers

The `safety_worker` is stateless and horizontally scalable. Increase throughput by running multiple instances:

```bash theme={null}
docker compose -f infra/docker-compose.yml up --scale safety_worker=3
```

Each worker independently reads from the Redis queue. Three workers process three scoring jobs concurrently.

## Updating

```bash theme={null}
git pull
docker compose -f infra/docker-compose.yml up --build
```

Database migrations run automatically via the `migrate` service on startup.

## Stripe local webhook forwarding

To test billing flows locally, forward Stripe webhooks to your local API:

```bash theme={null}
stripe listen --forward-to localhost:8000/webhook/stripe
```

Copy the webhook signing secret printed by the CLI into `STRIPE_WEBHOOK_SECRET` in `.env`, then restart the API service.

## Running in detached mode

```bash theme={null}
docker compose -f infra/docker-compose.yml up -d
docker compose -f infra/docker-compose.yml logs -f api safety_worker
```
