Skip to main content

Production Deployment

The reference production setup runs the app behind Caddy as the sole public-facing ingress, with PostgreSQL and (optionally) Redis as internal-only services — nothing but Caddy is exposed on ports 80/443.

What Caddy does

  • Terminates TLS automatically via Let's Encrypt (configured with an admin contact email for certificate notices).
  • Reverse-proxies all traffic to the app container.
  • Adds security headers on every response: HSTS, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin.

Bring the stack up

The compose files and configuration live under deploy/ in the repository. Clone the repo, cd deploy, and follow the operator's guide to provision secrets and environment files before running the commands below.

docker compose pull
docker compose up -d postgres
docker compose run --rm migrate
docker compose up -d

The migrate step runs schema migrations using a dedicated inboxui_migrator database role with DDL privileges. The app itself connects as inboxui_app, which can only read and write data — it cannot alter the schema. A third role, inboxui_backup, can read everything plus write backup status, for use by backup tooling. A break-glass superuser role exists but is never used by the running application.

DNS and health check

Point your domain's A record at the host, then verify:

curl -fsS https://your-domain.example.com/api/healthz

Next step

See Upgrading for how to roll out a new version safely.