openstead
Guides

Deploy Django

Deploy a Django application with Gunicorn, private PostgreSQL, static assets, and release migrations.

Suggest a change

Deploy Django as a web service. Use a production WSGI or ASGI server, a managed database for durable data, and a separate strategy for static assets and user uploads.

Prepare production dependencies

Declare Django and a production server such as Gunicorn in your dependency manifest. For PostgreSQL, include a compatible PostgreSQL driver. You can use dj-database-url to parse a connection URL and WhiteNoise to serve collected static assets.

Commit the dependency manifest and lockfile used by your chosen package manager. Keep .env, virtual environments, and local SQLite database files out of the deployment repository.

Configure Django settings

Your settings module must read the variables you configure. For example:

import os
import dj_database_url

DEBUG = False
SECRET_KEY = os.environ["SECRET_KEY"]
ALLOWED_HOSTS = os.environ["ALLOWED_HOSTS"].split(",")
CSRF_TRUSTED_ORIGINS = os.environ.get("CSRF_TRUSTED_ORIGINS", "").split(",")
CSRF_TRUSTED_ORIGINS = [origin for origin in CSRF_TRUSTED_ORIGINS if origin]
DATABASES = {"default": dj_database_url.config(conn_max_age=60)}
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

This snippet assumes your settings already define BASE_DIR. Set ALLOWED_HOSTS to the generated hostname and any custom hostnames without schemes. Set CSRF_TRUSTED_ORIGINS to the HTTPS origins that submit browser requests to Django. Avoid using * for normal application host validation.

If you use WhiteNoise, add its middleware immediately after Django's security middleware and configure its static storage backend for your installed Django version.

Create the database and web service

Create PostgreSQL in the intended network scope. Put its private connection URL in DATABASE_URL on the web service, along with a strong, stable SECRET_KEY and the host settings above.

For a project whose WSGI module is config/wsgi.py:

SettingValue
Service typeWeb Service
Build methodRailpack
Build commandpython manage.py collectstatic --noinput
Pre-deploy commandpython manage.py migrate --noinput
Start commandgunicorn config.wsgi:application --bind 0.0.0.0:$PORT --access-logfile - --error-logfile -
Port8000

Replace config with your actual Python package. The builder prepares dependencies from the manifest. The pre-deploy command requires a paid instance and can reach the private database. Do not migrate the production database during image compilation.

Add a readiness endpoint

The platform's readiness probe reaches the instance directly. With strict host validation, implement a narrowly scoped health middleware before middleware that enforces host or HTTPS redirects. For example:

# config/health.py
from django.http import HttpResponse

class HealthCheckMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.path == "/health" and request.method == "GET":
            return HttpResponse("ok", content_type="text/plain")
        return self.get_response(request)

Add config.health.HealthCheckMiddleware at the beginning of the existing MIDDLEWARE list and set the service's health path to /health. This exposes only a minimal health response while normal routes keep their host and security checks. Add a fast bounded dependency check if your readiness requirements need more than application startup.

Handle media and background tasks

Collected static files are build output. User-uploaded media must use object storage or a persistent disk mounted at your configured MEDIA_ROOT. WhiteNoise is for static assets, not a complete user-media storage strategy.

Deploy Celery as a separate background worker with the same application code and appropriate variables. Use shared queue and result-store connections as required.

After deploying, run python manage.py check --deploy through a paid one-off job and verify login, forms, static assets, and database writes. Resolve its findings based on your actual proxy and application settings.

Need a hand? Contact Openstead support.

On this page