Skip to content

chore(deploy): harden Heroku production settings#224

Merged
matrixise merged 1 commit into
masterfrom
chore/harden-heroku-deploy
Jun 11, 2026
Merged

chore(deploy): harden Heroku production settings#224
matrixise merged 1 commit into
masterfrom
chore/harden-heroku-deploy

Conversation

@matrixise

Copy link
Copy Markdown
Contributor

Summary

Hardens the Heroku production deployment. Resolves every issue reported by python manage.py check --deploy (went from 5 issues → 0 real findings) and applies Heroku-specific best practices.

Changes

Security / HTTPS

  • Add django.middleware.security.SecurityMiddleware — it was missing entirely, so none of the SECURE_* settings had any effect (security.W001). WhiteNoise is moved directly after it as recommended.
  • Enable in production.py: SECURE_SSL_REDIRECT, HSTS (1 year, subdomains, preload), SESSION_COOKIE_SECURE (security.W012), CSRF_COOKIE_SECURE (security.W016).
  • SECURE_PROXY_SSL_HEADER — Heroku terminates TLS at the router and forwards plain HTTP to the dyno. Django must trust X-Forwarded-Proto, otherwise SECURE_SSL_REDIRECT causes an infinite redirect loop.

Storage

  • AWS_S3_FILE_OVERWRITE = False — prevents silently overwriting/deleting user-uploaded files that share a name (wagtailadmin.W004).

Database

  • Persistent, TLS-required connections for Heroku Postgres: conn_max_age=600, conn_health_checks=True, ssl_require=True. Avoids a new TCP+TLS connection on every request. Scoped to production.py (dev/tests keep SQLite).

Tooling

  • Replace deprecated runtime.txt with .python-version (Heroku's current mechanism).

Validation

  • check --deploy now reports 0 real issues (only the SECRET_KEY warning remains, a false positive from the dummy key used during the check; the real DJANGO_SECRET_KEY is long and random).
  • ✅ 7/7 tests pass with the reordered middleware.
  • ruff check passes.
  • ✅ No remaining references to runtime.txt in Dockerfile/Taskfile/compose.

Deploy note

After this is live, SECURE_SSL_REDIRECT + HSTS take effect. HSTS preload is a strong commitment (browsers will refuse plain HTTP for python.ie and subdomains for 1 year) — appropriate here since the site is already HTTPS-only.

Address all issues reported by `manage.py check --deploy` and apply
Heroku-specific best practices:

- Add `SecurityMiddleware` (was missing, so all SECURE_* settings had no
  effect) and move WhiteNoise directly after it.
- Enable HTTPS hardening in production: SECURE_SSL_REDIRECT, HSTS (1y,
  subdomains, preload), SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE, and
  SECURE_PROXY_SSL_HEADER so Django trusts Heroku's X-Forwarded-Proto
  (prevents an infinite redirect loop).
- Set AWS_S3_FILE_OVERWRITE = False to avoid silently overwriting
  user-uploaded files (wagtailadmin.W004).
- Use persistent, TLS-required database connections for Heroku Postgres
  (conn_max_age=600, conn_health_checks=True, ssl_require=True).
- Replace deprecated runtime.txt with .python-version.
@matrixise matrixise merged commit 6990b97 into master Jun 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant