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

# Single-container deploy

> Run Qodex with one Docker container, an external Postgres database, and a persistent volume for artifacts.

# Single-container deploy

Use the single-container deployment when you want the smallest self-hosted Qodex setup.

You provide Postgres, secrets, an LLM key, and a persistent `/data` volume. The container runs the web server, UI, scheduler, agent runner, Playwright, Chromium, and bundled skills.

## Prerequisites

* Docker, Podman, or another OCI container runtime.
* Postgres 16 or 17 reachable from the container.
* An OpenAI API key for the platform default model.
* A 32-character or longer `QODECLAW_SECRET_KEY`.
* A random `JWT_SECRET`.
* A persistent volume mounted at `/data`.

## 1. Pull the image

```bash theme={null}
docker pull ghcr.io/flinket/qodeclaw:latest
```

Use a pinned release tag or SHA for production so deploys are reproducible.

## 2. Set environment variables

At minimum, the container needs:

```bash theme={null}
OPENAI_API_KEY=sk-...
DATABASE_URL=postgres://qodeclaw:password@postgres.host:5432/qodeclaw
QODECLAW_SECRET_KEY=<32-or-more-char-random-string>
JWT_SECRET=<random-string>
PORT=3000
```

Recommended for non-development deploys:

```bash theme={null}
NODE_ENV=production
APP_URL=https://qodex.your-domain.com
APP_VERSION=<release-sha>
```

See [Environment variables](/self-hosted-environment-variables) for the full list.

## 3. Mount storage

Mount `/data` so screenshots, videos, DOM snapshots, logs, and attachments survive container restarts.

```bash theme={null}
-v qodex-data:/data
```

Optionally mount your source repository read-only at `/project` if you want the agent to inspect local code for context.

## 4. Start Qodex

```bash theme={null}
docker run -d \
  --name qodex \
  -p 3000:3000 \
  -e OPENAI_API_KEY=sk-... \
  -e DATABASE_URL=postgres://qodeclaw:password@db:5432/qodeclaw \
  -e QODECLAW_SECRET_KEY=<random-32-plus-chars> \
  -e JWT_SECRET=<random-string> \
  -e NODE_ENV=production \
  -e APP_URL=https://qodex.your-domain.com \
  -v qodex-data:/data \
  ghcr.io/flinket/qodeclaw:latest
```

## 5. Verify the server

```bash theme={null}
curl http://localhost:3000/api/health
```

The boot log prints which critical environment variables are present, without printing their values. This helps confirm wiring without leaking secrets.

Without `REDIS_URL`, Qodex runs the scheduler and agent runner in the same container. That is fine for a small single-container deploy.

## Next steps

<CardGroup cols={2}>
  <Card title="Docker Compose" icon="layers" href="/self-hosted-docker-compose">
    Add Postgres in the same local stack.
  </Card>

  <Card title="Storage backends" icon="hard-drive" href="/self-hosted-storage-backends">
    Switch artifacts from local disk to S3.
  </Card>

  <Card title="Environment variables" icon="settings" href="/self-hosted-environment-variables">
    Review every setting Qodex reads at boot.
  </Card>

  <Card title="Secret management" icon="key" href="/self-hosted-secret-management">
    Understand the encryption key before production.
  </Card>
</CardGroup>
