Skip to content

fix(deploy): pass the front proxy's scheme through the web tier - #77

Merged
mjunek merged 1 commit into
masterfrom
fix/forwarded-proto
Nov 15, 2026
Merged

mjunek merged 1 commit into
masterfrom
fix/forwarded-proto

Conversation

@mjunek

@mjunek mjunek commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

What and why

nginx in the web image set X-Forwarded-Proto to its own $scheme. It listens without TLS behind a proxy or load balancer, so that was always http, and the orchestrator took an HTTPS site to be plain HTTP:

  • OIDC redirect URIs were built as http://;
  • the CSRF origin check expected the http origin, which is why DV_CSRF_TRUSTED_ORIGINS was required;
  • the Flower cookie was issued without Secure.

docker/nginx.conf.template now passes on X-Forwarded-Proto: https when the proxy in front sent it and falls back to its own scheme otherwise. One mapped value feeds all three proxied locations (/api, the Flower proxy and the Flower auth check).

Things to be aware of:

  • nginx believes the header from whoever connects to it, not only from a known proxy. A client connecting directly can claim HTTPS, but that only changes how its own request is seen.
  • The front proxy must send X-Forwarded-Proto: https and pass Host through unchanged. docs/DEPLOYMENT.md (Users and access) now says so, with the nginx and HAProxy lines.

Independent of #75 and #76.

How it was tested

  • make check passes.
  • The template was run in a real nginx:1.30-alpine container against an echo upstream: https, HTTPS and https, http come through as https; no header, http, httpsx and ftp come through as http.
  • A new test covers the Django side: with the forwarded header the HTTPS origin passes CSRF, the HTTP one is refused, and absolute URLs are https://.
  • Nothing automated covers the nginx template itself.

Checklist

  • make check passes locally
  • Tests added or updated for the change
  • New DV_* variables are documented in docs/DEPLOYMENT.md and the relevant *.env.example (none added)
  • Model changes have generated migrations (makemigrations) (no model changes)
  • API changes keep api/serializers.py, api/views.py and frontend/src/api/types.ts / endpoints.ts in step (no API changes)
  • Docs (README.md, docs/) updated where behaviour changed

nginx set X-Forwarded-Proto to its own scheme, which is always http
since it listens without TLS behind a proxy or load balancer. The
orchestrator therefore took an HTTPS site to be plain HTTP: OIDC
redirect URIs were built as http://, the CSRF check expected the http
origin (hence DV_CSRF_TRUSTED_ORIGINS), and the Flower cookie was
issued without Secure.

nginx now passes on X-Forwarded-Proto: https when the proxy in front
sent it, and falls back to its own scheme otherwise. A client that
sends the header itself only changes how its own request is seen.

The front proxy must send X-Forwarded-Proto: https and pass Host
through unchanged; DEPLOYMENT.md says so.
@mjunek
mjunek requested a review from a team as a code owner November 15, 2026 04:30
@mjunek
mjunek merged commit d0be792 into master Nov 15, 2026
1 check passed
@mjunek
mjunek deleted the fix/forwarded-proto branch November 15, 2026 04:36
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