{{ message }}
fix(nginx): preserve upstream X-Forwarded-Proto when behind another TLS proxy#3793
Open
ajayr wants to merge 1 commit into
Open
fix(nginx): preserve upstream X-Forwarded-Proto when behind another TLS proxy#3793ajayr wants to merge 1 commit into
ajayr wants to merge 1 commit into
Conversation
…LS proxy When DeerFlow's nginx runs behind another TLS-terminating reverse proxy (Pangolin/Traefik, Cloudflare, Caddy), every location block overwrote the already-correct X-Forwarded-Proto with $scheme (= http on the private hop). The Gateway then treated HTTPS browser traffic as HTTP: the auth-origin check rejected the login POST with 403 "Cross-site auth request denied", and session cookies lost the Secure flag and max-age. Preserve an upstream X-Forwarded-Proto via a map that falls back to $scheme when nginx is itself the TLS edge, so standalone `make dev` / Docker is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why
When DeerFlow's bundled nginx runs behind another TLS-terminating reverse proxy (e.g. Pangolin/Traefik, Cloudflare, Caddy) — a common way to expose a self-hosted DeerFlow publicly over HTTPS — login silently fails. The user submits valid credentials and is bounced straight back to the login screen with no session established.
Root cause: every
locationblock hardcodesproxy_set_header X-Forwarded-Proto $scheme. The front proxy terminates TLS and reaches nginx over plain HTTP on the private hop, so$schemeishttp, overwriting thehttpsthe front proxy already set. The Gateway then treats HTTPS browser traffic as HTTP, and:CSRFMiddleware.is_allowed_auth_origincomputes the expected origin ashttp://<host>, which no longer matches the browser'sOrigin: https://<host>, so the login POST is rejected with 403 "Cross-site auth request denied" (backend/app/gateway/csrf_middleware.py).is_secure_request()returns false, so theaccess_tokensession cookie is set withoutSecureand withoutmax-age(session-only).What changed
nginx now preserves an upstream proxy's
X-Forwarded-Protoinstead of unconditionally overwriting it, via amapthat falls back to$schemewhen there is no upstream value:All
proxy_set_header X-Forwarded-Protolines now use$forwarded_proto.make dev/ Docker (nginx is the TLS edge): no incomingX-Forwarded-Proto→ falls back to$scheme→ behavior unchanged.httpsscheme reaches the Gateway → the login origin check passes and session cookies regainSecure+max-age.Note: this trusts an incoming
X-Forwarded-Proto, which is the intended behavior when nginx sits behind a trusted front proxy. Operators who expose nginx's port directly to untrusted clients should terminate TLS at nginx (the$schemefallback covers that) or restrict the trusted-proxy source.Surface area
docker/or sandboxed execution (reverse-proxy config underdocker/nginx/)$schemefallback)Bug fix verification
nginx config is not exercised by the unit/E2E suites, so verified manually against the running stack (requests reaching the Gateway through nginx):
The standalone case (no
X-Forwarded-Proto) returns the same result as before via the$schemefallback.Validation
nginx -tpasses on the modified config.Secureflag restored on session cookies).frontend/changes, so E2E is unaffected.🤖 Generated with Claude Code