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

# Docker

> Run the gateway as a container, alone or with a PostgreSQL beside it.

## Pull the image

```bash theme={null}
docker pull ghcr.io/abhishek-mallick/warden:latest
```

Tags: `latest`, and `X.Y.Z` for each release. Images are multi-architecture (`linux/amd64`, `linux/arm64`), each built natively.

> [!NOTE]
>
> Published when a `vX.Y.Z` tag is pushed. Before the first release, build locally: `docker build -t warden:local .`
>
> The package is built from a private repository, so it inherits **private** visibility, and GitHub offers no API to change that — the setting exists only in the web UI. Make it public once, at
> `https://github.com/users/Abhishek-Mallick/packages/container/warden/settings`; every later release inherits the setting. Until then `docker pull` needs a `ghcr.io` login, and an anonymous pull reports that the package does not exist.

## Run it

```bash theme={null}
docker run --rm \
  -p 127.0.0.1:9470:9470 \
  -v "$PWD/warden.yaml:/etc/warden/warden.yaml:ro" \
  -v "$PWD/policies:/etc/warden/policies:ro" \
  -v warden-state:/var/lib/warden \
  ghcr.io/abhishek-mallick/warden:latest
```

| Path | Purpose |
| - | - |
| `/etc/warden/warden.yaml` | The configuration the default command reads |
| `/etc/warden/policies` | Whatever your connections' `policy:` fields point at |
| `/var/lib/warden` | State: audit chain, leases, idempotency keys. **Use a volume** |

The image runs as UID 65532 and contains no shell. A named volume mounted at the state directory inherits the right ownership on first use; a bind mount from the host does not, so `chown 65532:65532` it first.

## The whole stack, with a database beside it

> [!NOTE]
>
> The demo stack — Warden plus a seeded PostgreSQL, one command — lives in the source repository, which is private. With access to it:
>
> ```bash theme={null}
> git clone https://github.com/Abhishek-Mallick/Warden.git warden && cd warden
> docker compose up --build
> ```
>
> Without access, compose your own: the image above, a PostgreSQL service, and the configuration from [the quickstart](https://warden.buildlab.in/quickstart.md). The only thing the demo adds is seed data.

Whatever the source of the compose file, two properties are worth copying:

* **Do not publish the database port.** Agents reach it through Warden or not at all, which is the arrangement Warden exists to create.
* **Publish Warden's port to loopback** unless TLS is configured. Warden refuses a non-loopback listener without TLS unless told otherwise.

## Production notes

* **TLS.** Warden refuses a non-loopback listener without TLS unless `allow_insecure_listen: true` is set — appropriate only when something in front terminates TLS. Mount the certificate and key and set `tls.cert` / `tls.key`. See [TLS and state](https://warden.buildlab.in/configure/tls-and-state.md).
* **Secrets.** The configuration file holds a database DSN. Mount it from a secret store rather than baking it into an image, and prefer `key_hash` / `token_hash` over plaintext credentials — the gateway warns when it finds plaintext.
* **Health.** `GET /health` is unauthenticated and reports process liveness and how many connections are configured, and nothing about what it governs. Use it as the container health check.
* **Restarts.** With `data_dir` on a volume, the audit chain, leases, and idempotency keys survive. A pending async approval does not: it never ran, and the agent is told the outcome is unknown if it retries the same key.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.