Deployment

This section covers key considerations for deploying Django Cast in production.

Prerequisites

  • Python 3.11+

  • A database (PostgreSQL or SQLite)

  • A reverse proxy (e.g., Traefik, Nginx) with a WSGI server (e.g., Gunicorn)

Basic Configuration

Your production settings should include:

DEBUG = False
ALLOWED_HOSTS = ["your-domain.com"]
SECRET_KEY = os.environ["SECRET_KEY"]  # never hardcode

# Wagtail
WAGTAILADMIN_BASE_URL = "https://your-domain.com"

See Installation for the full INSTALLED_APPS, MIDDLEWARE, and URL configuration.

Keep dev-only routes disabled in production unless you explicitly need them:

CAST_ENABLE_DEV_TOOLS = False

Application Server

A typical production setup uses Gunicorn behind a reverse proxy:

gunicorn --workers 4 --timeout 600 --bind 127.0.0.1:8000 config.wsgi:application

Manage the process with systemd for automatic restarts and logging.

Transcript Worker

If the site enables Voxhelm transcript generation from Wagtail admin, run a Django Tasks database worker in addition to the web process. Install the optional transcript-worker extra first; it requires a Wagtail/django-tasks combination compatible with django-tasks-db 0.12. Wagtail 7.0 LTS uses django-tasks 0.7 and is not compatible with that database backend.

uv pip install "django-cast[transcript-worker]"
python manage.py db_worker --backend cast_transcripts --worker-id homepage-transcripts

Use a distinct --worker-id per deployed site, for example python-podcast-transcripts for a second site sharing the same codebase. The default task backend should remain immediate; only the cast_transcripts backend should point at django_tasks_db.DatabaseBackend. The web process and transcript worker must both receive the Voxhelm configuration used for job submission and artifact downloads. For deployment-managed secrets, set CAST_VOXHELM_API_BASE and CAST_VOXHELM_API_KEY in the shared process environment; the Wagtail Voxhelm settings token field can stay blank in that setup. If a site-level Wagtail value is set, it takes precedence for that site. If CAST_VOXHELM_DIARIZATION_ENABLED is enabled, make sure the Voxhelm backend has diarization support configured. Full-episode diarization can be slow and CPU-heavy, so keep it on the queued transcript worker path instead of waiting for completion in a Wagtail admin request.

Static Files

Django Cast ships pre-built JavaScript assets (image gallery, Podlove audio player). Collect all static files before deployment:

python manage.py collectstatic --noinput

Serve the STATIC_ROOT directory via your reverse proxy, a storage backend, or a CDN.

Media Storage

Uploaded media (images, audio, video) is stored via Django’s STORAGES["default"] backend. A common production setup uses an object store like AWS S3 with CloudFront as CDN.

See Using a CDN (AWS S3 + Cloudfront) in the Settings reference for S3 + CloudFront configuration details.

Important

Set DELETE_WAGTAIL_IMAGES = False when using S3. This prevents your development environment from accidentally deleting production images.

If you use automatic media processing features in production, make sure the required FFmpeg tools are installed on your application hosts:

  • ffprobe for audio duration extraction, chapter-mark import, and video dimension detection

  • ffmpeg for video poster generation

For backup and restore of media files, see Backup and the media management commands.

Database

Run migrations before starting the application:

python manage.py migrate

Both PostgreSQL and SQLite are supported. PostgreSQL is the more typical production choice, especially for multi-server deployments. SQLite can work for simpler single-server setups, but operational characteristics such as locking, backups, and write concurrency remain your responsibility.

Image Renditions

After initial deployment or after changing image slot dimension settings, generate image renditions:

python manage.py sync_renditions

This creates responsive image variants used by the gallery and post templates. See Management Commands for details.

Example: Ansible-Based Deployment

A production deployment typically involves:

  1. Sync source code to the server (rsync or git clone)

  2. Create/update a virtualenv and install dependencies (uv sync --frozen)

  3. Set environment variables (SECRET_KEY, DATABASE_URL, AWS credentials, etc.) via your deployment environment or an .env file

  4. Run python manage.py migrate

  5. Run python manage.py collectstatic --noinput

  6. Run python manage.py update_index (Wagtail search index)

  7. Restart the application service (e.g., systemctl restart mysite)

TLS certificates can be managed automatically via Let’s Encrypt with a reverse proxy like Traefik.

Checklist

  • [ ] DEBUG = False

  • [ ] SECRET_KEY set from environment variable

  • [ ] ALLOWED_HOSTS configured

  • [ ] WAGTAILADMIN_BASE_URL set to production domain

  • [ ] CAST_ENABLE_DEV_TOOLS = False unless explicitly required

  • [ ] Database configured and migrations applied

  • [ ] collectstatic run

  • [ ] Media storage configured (local filesystem or S3)

  • [ ] DELETE_WAGTAIL_IMAGES = False if using S3

  • [ ] ffprobe / ffmpeg installed if using audio/video processing features

  • [ ] Image renditions generated with sync_renditions

  • [ ] Reverse proxy with TLS configured

  • [ ] Application server (Gunicorn) managed by systemd