Skip to main content

SafariDesk Production Deployment

This page covers production deployment for the Docker Compose setup in the monorepo root. Use Installation first for the base install. Use this page before exposing SafariDesk to real users. Related pages:
Recommended:
In this model:
  • The host, cloud load balancer, or external reverse proxy terminates TLS.
  • The SafariDesk nginx service receives HTTP traffic from that trusted layer.
  • Internal services remain private inside Docker Compose.
The current root Compose file publishes only HTTP:
The HTTPS_PORT value exists in .env.example for future TLS deployment patterns, but the current root Compose file does not publish 443 by default.

Host Requirements

Minimum:
  • Linux server
  • Docker Engine
  • Docker Compose plugin
  • 4 GB RAM
  • 20 GB disk
  • Port 80 available
Recommended:
  • Ubuntu 22.04 or newer
  • 8 GB RAM
  • 4 CPU cores
  • 50 GB or more disk for database, uploads, logs, and backups
  • Domain name
  • TLS certificate
  • Automated backups
  • Monitoring for disk, memory, CPU, and container restarts

DNS

Same-domain deployment needs one DNS record. Example:
The public routes are:
Split-domain deployment is possible, but same-domain deployment is recommended for self-hosting.

Firewall Rules

Public inbound: Do not expose these service ports publicly: Check published ports:
Only safaridesk_nginx should show a host port by default.

Production Environment

Set production values in .env. Example same-domain values:
Use strong secrets:
Pin a release image:

Start Production Services

Pull images:
Start with the production override:
The production override sets restart policy to always for core services. Run migrations:
Collect static files:
Create the admin user:
Run optional bootstrap commands:

TLS

The current Compose setup does not terminate TLS inside the SafariDesk Nginx container. Use one of these production patterns:
  1. Host-level reverse proxy terminates TLS and forwards to localhost:${HTTP_PORT}.
  2. Cloud load balancer terminates TLS and forwards to the server.
  3. Future Compose TLS profile mounts certificates into Nginx.
Placeholder TLS links: When TLS is enabled, all public .env URLs should use https://.

Volumes and Persistence

Production data lives in Docker volumes: At minimum, back up:
  • PostgreSQL database
  • uploads volume
  • .env
Static files can be regenerated with:

Backup Before Real Usage

Create a first backup after installation:
Expected files:
Move production backups to durable storage outside the application server. See Backup and Restore.

Operational Checks

Check containers:
Check rendered config:
Check public health:
Check backend health directly from inside Compose:
Check logs:

WebSocket Verification

WebSockets are routed through:
The Nginx route forwards to:
If WebSockets fail in production, verify that the external proxy preserves upgrade headers:
See Troubleshooting.

Security Checklist

  • DEBUG=false
  • SECRET_KEY changed
  • SECRET_ENCRYPTION_KEY changed
  • DB_PASSWORD changed
  • SUPERUSER_PASSWORD changed
  • ALLOWED_HOSTS is not *
  • CORS_ALLOW_ALL_ORIGINS=false
  • CORS_ALLOWED_ORIGINS matches the public app URL
  • CSRF_TRUSTED_ORIGINS matches the public app URL
  • PostgreSQL is not publicly exposed
  • Redis is not publicly exposed
  • Backend port 8100 is not publicly exposed
  • Channels port 8101 is not publicly exposed
  • Docker socket is not mounted into backend containers
  • Image tag is pinned
  • Backups are configured

Production Deployment Checklist

  • DNS points to the deployment host.
  • TLS is configured.
  • .env contains production URLs.
  • .env contains production secrets.
  • docker compose config --quiet passes.
  • docker compose pull succeeds.
  • Containers start.
  • Migrations run.
  • Static files collect.
  • Admin user exists.
  • Frontend loads.
  • API health route works.
  • WebSockets work.
  • Uploads work.
  • Celery worker starts.
  • Celery Beat starts.
  • Email settings are tested.
  • Backup and restore have been tested.