From b432d3f6b6359a1e39b8dcab39c50f473c7ab7ec Mon Sep 17 00:00:00 2001 From: Klaas van Schelven Date: Fri, 25 Jul 2025 16:30:34 +0200 Subject: [PATCH] Docker: BEHIND_HTTPS and BEHIND_PROXY Fix #164 --- bsmain/__init__.py | 18 ++++++++++++++++++ bugsink/conf_templates/docker.py.template | 14 +++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/bsmain/__init__.py b/bsmain/__init__.py index aadfb10..5d473fe 100644 --- a/bsmain/__init__.py +++ b/bsmain/__init__.py @@ -1,3 +1,4 @@ +import os import urllib.parse from django.core.checks import Warning, register @@ -58,3 +59,20 @@ def check_base_url_is_url(app_configs, **kwargs): )] return [] + + +@register("bsmain") +def check_proxy_env_vars_consistency(app_configs, **kwargs): + # in this check we straight-up check the os.environ: we can't rely on settings.BEHIND_HTTPS_PROXY to have been set + # since it's Docker-only. + + if ( + os.getenv("BEHIND_HTTPS_PROXY", "False").lower() in ("true", "1", "yes") and + os.getenv("BEHIND_PLAIN_HTTP_PROXY", "False").lower() in ("true", "1", "yes") + ): + return [Warning( + "BEHIND_HTTPS_PROXY and BEHIND_PLAIN_HTTP_PROXY are mutually exclusive.", + id="bsmain.W004", + )] + + return [] diff --git a/bugsink/conf_templates/docker.py.template b/bugsink/conf_templates/docker.py.template index f134ee7..c7c4760 100644 --- a/bugsink/conf_templates/docker.py.template +++ b/bugsink/conf_templates/docker.py.template @@ -20,14 +20,17 @@ DEBUG_CSRF = "USE_DEBUG" if os.getenv("DEBUG_CSRF") == "USE_DEBUG" else os.geten SECRET_KEY = os.getenv("SECRET_KEY") -if os.getenv("BEHIND_HTTPS_PROXY", "False").lower() in ("true", "1", "yes"): - # We hard-tie the ideas of "behind a proxy" and "use https" together: there is no reason to go through the trouble - # of setting up a proxy if you're not using https. We also hard-code some choices of proxy headers; which means you - # have to match those on the proxy side (but that's easy enough). +BEHIND_HTTPS_PROXY = os.getenv("BEHIND_HTTPS_PROXY", "False").lower() in ("true", "1", "yes") +BEHIND_PLAIN_HTTP_PROXY = os.getenv("BEHIND_PLAIN_HTTP_PROXY", "False").lower() in ("true", "1", "yes") + +if BEHIND_HTTPS_PROXY or BEHIND_PLAIN_HTTP_PROXY: + # We hard-code the choice of proxy headers; which means you have to match those on the proxy side (easy enough). SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # Note: slightly redundant, Gunicorn also does this. + USE_X_REAL_IP = True + +if BEHIND_HTTPS_PROXY: SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True - USE_X_REAL_IP = True else: # We don't warn about SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE; we can't set them to True because some browsers # interpret that as "use https for cookies, even on localhost", and there is no https (BEHIND_HTTPS_PROXY is False). @@ -38,6 +41,7 @@ else: ] + # The time-zone here is the default for display purposes (when no project/user configuration is used). # https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-TIME_ZONE TIME_ZONE = os.getenv("TIME_ZONE", "UTC")