Production Deployment Security Checklist
Before deploying Patrimoine to production, verify each item below.
Application Configuration
Section titled “Application Configuration”- Set
DEBUG=falseinbackend/container/.env— disables error trace display. CookieSecureflag is protocol-aware (not controlled byDEBUG). - Set
E2E_TEST_MODE=false(or leave unset) inbackend/container/.env— prevents auth bypass. - Set
REGISTRATION_ENABLED=false(default) — only enable during initial setup, then disable. - Make sure you have an admin account, so you can invite additional users without re-enabling public registration. With OIDC, set
ADMIN_EMAILS(orADMIN_SUBS) to your own account. With local auth those variables do not apply: the first account registered on an empty instance becomes admin — see Troubleshooting. - Generate a strong
JWT_SECRET(the app refuses to start below 32 characters, but that floor is a minimum, not a target — use the full 48-byte generator):Terminal window python -c "import secrets; print(secrets.token_urlsafe(48))" - Leave
EXPOSE_API_DOCSunset (defaultfalse) so the interactive API docs and/openapi.jsonare not published. - If you enable
/metrics, generateMETRICS_TOKENwith the 48-byte generator and do not publish the backend port; Prometheus must scrape the backend on the container network. - If the backend is reachable by anything other than the frontend’s nginx (separate hosts, published port), set
TRUSTED_PROXIES; behind your own proxy setFRONTEND_TRUSTED_PROXIESto its address; firewall the backend port. - Once all pre-upgrade sessions have expired, set
JWT_ACCEPT_LEGACY_KEY=false. - If you use Redis, keep it on a private network (the
podman.shmanaged Redis listens on the pod loopback only) and set a password inREDIS_URLotherwise. - Review
LOGIN_MAX_ATTEMPTS(default 5) andLOGIN_LOCKOUT_MINUTES(default 15) — local-auth login/TOTP lockout thresholds. The defaults are reasonable for most deployments; tightenLOGIN_LOCKOUT_MINUTESif you want failed attempts to cost an attacker more time.
TLS & Reverse Proxy
Section titled “TLS & Reverse Proxy”- Use HTTPS — terminate TLS at a reverse proxy (Traefik, Caddy, or nginx).
- Set
FRONTEND_URLandOIDC_REDIRECT_URIto HTTPS URLs. - Ensure Uvicorn runs with
--proxy-headers(default in the backendContainerfile) soX-Forwarded-Proto/X-Forwarded-Hostfrom the reverse proxy are trusted. CookieSecure/SameSiteattributes depend on this header for HTTPS detection. - If using Traefik: disable the
compressmiddleware for/auth/paths — it can stripSet-Cookieheaders from 302 redirect responses, breaking the OIDC callback.
OIDC Provider
Section titled “OIDC Provider”- Use a strong, unique
OIDC_CLIENT_SECRET. - Restrict the OIDC provider to your organization (e.g., Authentik application access policy).
Backups
Section titled “Backups”- Set up regular SQLite database backups (
backup-db.shwith cron). - Configure offsite backup sync (WebDAV or S3) if using
backup-db.sh. - On PostgreSQL, schedule
pg_dumpinstead:backup-db.shis SQLite-only. - Keep
data/backups/(internalAUTO_BACKUPfiles) pruned: the app never deletes them. - Consider filesystem-level encryption for the
data/volume.
Dependencies
Section titled “Dependencies”- Keep Python dependencies updated (
uv lock --upgrade). - Keep frontend dependencies updated (
npm update).
- Configure CI secrets for image builds:
PRIVATE_REGISTRY_USERNAME,PRIVATE_REGISTRY_PASSWORD,NTFY_TOKEN(secret) +NTFY_URL(variable). - Verify Forgejo repository settings restrict the
GITHUB_TOKENto read-only (Settings → Actions → Token permissions). - Verify the
rockyrunner image is up to date (quay.io/rockylinux/rockylinux:9-minimal— includespython3-pip,git,buildah,podman,sudo).
Related Documentation
Section titled “Related Documentation”- Security Overview — Security measures summary
- Podman & Compose — Container deployment configuration
- Reverse Proxy — nginx, Traefik, and Caddy configuration