fix: preserve original Host header in Caddy reverse proxy #452
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-platform!452
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/caddy-host-header"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
header_up Host {http.request.host}to the Caddy reverse proxy template so backends receive the original client hostname instead of the Tailscale proxy targetlandscaping-assistant.appredirect users to the internal Tailscale URL because the backend sees the wrong Host headerChanges
salt/states/caddy/Caddyfile.j2: Addedheader_up Host {http.request.host}inside thereverse_proxyblockTest Plan
salt state.apply caddyon edge proxy (178.156.129.142)landscaping-assistant.appno longer redirects to Tailscale URLpalinks.appcontinues to work (already working before this change)Review Checklist
Related Notes
ldraney/pal-e-platform #451— Caddy reverse proxy sends upstream hostname instead of original Host headerproject-dns-custom-domain-waves— Wave 2 Caddy configurationCloses #451
Adds header_up Host {http.request.host} so the backend sees the client's original hostname instead of the Tailscale proxy target. Without this, apps redirect to the internal Tailscale URL. Closes #451 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>PR #452 Review
DOMAIN REVIEW
Tech stack: Salt/Jinja2 template for Caddy reverse proxy configuration (infrastructure/IaC domain).
Change: Single line addition --
header_up Host {http.request.host}-- inside thereverse_proxyblock insalt/states/caddy/Caddyfile.j2.Correctness analysis:
Caddy syntax:
header_upis a valid sub-directive ofreverse_proxyin Caddy v2. Placement alongsidetransport httpinside thereverse_proxyblock is correct.Placeholder:
{http.request.host}is the correct Caddy placeholder for the original client Host header. This ensures the backend receiveslandscaping-assistant.appinstead oflandscaping-assistant.tail5b443a.ts.net.Root cause match: The bug described in #451 -- backends seeing the Tailscale hostname and redirecting users to internal URLs -- is precisely caused by Caddy forwarding the upstream target hostname. This
header_up Hostdirective is the canonical fix.Template scope: Because this is inside the Jinja2
forloop overpillar['caddy']['sites'], the fix applies to ALL sites (currentlypalinks.appandlandscaping-assistant.app). This is correct -- all reverse-proxied domains should preserve the original Host header.TLS interaction: The
transport http { tls_server_name }block handles TLS SNI for the upstream connection separately from the Host header. These are independent --tls_server_nametells Caddy what SNI to present to the upstream TLS handshake, whileheader_up Hostcontrols the HTTP-layer Host header. No conflict.Idempotency: Salt will render and deploy the updated Caddyfile on next
state.apply caddy. Caddy reload is graceful. No state drift risk.BLOCKERS
None.
NITS
None. The change is minimal, correctly scoped, and syntactically clean.
SOP COMPLIANCE
fix: preserve original Host header in Caddy reverse proxy)Closes #451present -- issue will auto-close on mergePROCESS OBSERVATIONS
header_up Hostdirective is documented Caddy behavior and widely used in reverse proxy configurations.salt state.apply caddyon edge-proxy post-merge. Test plan correctly identifies manual validation steps for both affected domains.project-dns-custom-domain-waves. Clean isolation from Wave 1 (DNS) and Wave 3 (app config).VERDICT: APPROVED