Run manage.py check --deploy against your production settings and treat every warning as a to-do item. The four that matter most are a secret SECRET_KEY, DEBUG set to False, a real ALLOWED_HOSTS list, and secure cookies behind site-wide HTTPS. Everything else is tuning.
Run the check against the right settings
The Django deployment checklist tells you to run the deploy check with your production settings loaded, not your laptop settings. If you run it with development settings it will pass or fail for the wrong reasons. Point DJANGO_SETTINGS_MODULE at the production module, or run it inside the production container.
DJANGO_SETTINGS_MODULE=myproject.settings.production python manage.py check --deploy
Do this in CI too, so a regression in settings fails a build instead of surfacing after release.
The settings that leak the most
SECRET_KEY must be a large random value, kept secret and not reused elsewhere. The docs show loading it from the environment with os.environ["SECRET_KEY"]. Never commit it. If you need to rotate it, the docs point to SECRET_KEY_FALLBACKS, and they ask you to remove the old keys promptly so a leaked key stops working.
DEBUG must be False. The docs are blunt about why: with it on, Django leaks source excerpts, local variables and settings in error pages.
ALLOWED_HOSTS is required once DEBUG is off. Django validates the Host header against it. The docs add that you should configure your web server to reject unknown hosts as well, so you have two layers.
Do not use the development server
The checklist says not to run manage.py runserver in production. Use a WSGI or ASGI server. The development server is not built to face the internet.
HTTPS and cookies
Enforce HTTPS site wide and have the web server redirect HTTP to HTTPS. Then set CSRF_COOKIE_SECURE = True and SESSION_COOKIE_SECURE = True, so the CSRF and session cookies are never sent over plain HTTP. If you skip this, a user on a hostile network can have a session cookie read on the first HTTP request. See the full HTTPS settings walkthrough for the rest.
Things people forget
- Uploads: the docs say to treat
MEDIA_ROOTcontent as untrusted and make sure the web server never executes it. - Databases and caches: use production credentials, protect them like
SECRET_KEY, restrict network access, and keep cache servers reachable only from your application servers. - Email defaults:
DEFAULT_FROM_EMAILandSERVER_EMAILdefault to localhost addresses that are often rejected, so error mail may silently go nowhere. - Error reporting: set
ADMINSso you hear about 500 errors, and reviewLOGGINGonce real traffic arrives.
A short order of operations
- Run the check with production settings and save the output.
- Fix
SECRET_KEY,DEBUG,ALLOWED_HOSTS. - Turn on HTTPS redirect and secure cookies.
- Lock down database, cache and media access.
- Add the check to CI.
Safeguard can scan your Python dependencies for known vulnerabilities and flag which ones are reachable in your code, which covers the part of a Django launch that settings checks do not. The free scan is at gold.safeguard.sh/scan.
Quick check
Does a clean deploy check mean the app is secure?
No. It checks configuration, not your views, queries or dependencies. Treat it as a floor.
Is it fine to keep SECRET_KEY in settings.py if the repo is private?
The docs say to load it from the environment or a file. A private repo still leaks to every contractor, CI log and backup that touches it.
Sources
Last reviewed: 19 October 2026.