Skip to main content
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

Edit PUBLIC_ORIGIN, HOST_PORT and the mail keys in .env. Any variable from Configuration can be added there. Other scripts run the same way, for example:

Client builds

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

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.

Backups

Keep .env and back it up together with the volumes:
  • db
  • client
  • media
  • data
  • realm-db
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 can.

Connection pooling

For an optional PgBouncer pool, add these to .env:
Then start with:
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.