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

# Docker Compose

> Run Xitter and PostgreSQL with Docker Compose.

`compose.yaml` runs Xitter and PostgreSQL 18, with ffmpeg and `pg_dump` in the image. The client is downloaded into its volume on the first start.

## Start

```sh theme={null}
docker/env.sh                  # writes .env with fresh secrets
docker compose up -d --build
docker compose exec app bun scripts/create-user.ts <name> <password> "<display name>"
docker compose exec app bun scripts/make-admin.ts <name>
```

Edit `PUBLIC_ORIGIN`, `HOST_PORT` and the mail keys in `.env`. Any variable from [Configuration](/self-hosting/configuration) can be added there.

Other scripts run the same way, for example:

```sh theme={null}
docker compose exec app bun scripts/invite.ts
```

## Client builds

* `FETCH_CLIENT=0` skips the download on the first start.
* Re-pin the current build with:

```sh theme={null}
docker compose exec app bun scripts/fetch-client.ts --latest
```

## Chat key backup

Add `--profile keybackup` to `up` to also run the Juicebox realm used for chat passcode recovery. It is built from `deploy/juicebox` with its own PostgreSQL. Its realm ID and tenant secret come from `.env`. See [Encrypted chat](/self-hosting/encrypted-chat).

## Backups

Keep `.env` and back it up together with the volumes:

* `db`
* `client`
* `media`
* `data`
* `realm-db`

> [!WARNING]
>
> `data/` holds the instance's federation key. Other instances stop trusting you if you lose it.

## Health check

`/healthz` answers `ok` while the server runs and reaches its database. `docker compose ps` shows the app as `unhealthy` when it doesn't.

Docker doesn't restart unhealthy containers by itself. A watcher such as [autoheal](https://github.com/willfarrell/docker-autoheal) can.

## Connection pooling

For an optional PgBouncer pool, add these to `.env`:

```sh theme={null}
DB_HOST=pool
DB_PORT=6432
```

Then start with:

```sh theme={null}
docker compose --profile sqlpool up -d --build
```

PgBouncer uses session pooling, so Bun's prepared statements and the startup migration keep their connection semantics. `PGBOUNCER_POOL_SIZE` defaults to 20 server connections; tune it alongside `DB_POOL_MAX` for the number of app replicas. Backups use a direct PostgreSQL connection (`BACKUP_DATABASE_URL`).

The Compose PostgreSQL service uses conservative cache and autovacuum settings. Adjust them for the host's memory and workload.


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