I'm chainging my setup from

nginx > apache/php


haproxy > nginx > apache/php

(using haproxy 1.5-dev18 with ssl support compiled in)

Both nginx and haproxy are setup correctly to set the HTTP_X_FORWARDED_PROTO header. However, when nginx gets the ssl traffic from haproxy, it sees the connection as http and sets the header as so.

How can I set nginx to forward the HTTP_X_FORWARDED_PROTO header if it exists, but otherwise continue setting it based on the connection?


I figured out how to solve this. The problem was that nginx was overwriting the header set by haproxy on this line of my config:

proxy_set_header X-Forwarded-Proto $scheme;

I fixed it by adding in this:

map $http_x_forwarded_proto $thescheme {
     default $scheme;
     https https;

and changing the proxy_set_header line to use the new scheme:

proxy_set_header X-Forwarded-Proto $thescheme;
  • Unless I'm missing something, your before and after proxy_set_header lines are the same. – Wilfred Hughes Sep 26 '13 at 17:39
  • 2
    $scheme vs $thescheme. – Arlen Beiler Jul 2 '15 at 13:30
  • Isn't this in some rare cases insecure? If a web browser sends a HTTP request to haproxy, and haproxy then sends a HTTPS request to Nginx — then the default $scheme case will happen, setting $thescheme to HTTPS although in fact the request (to haproxy) is insecure HTTP. — To avoid that, what about: default $http_x_forwarded_proto; '' $scheme;, so if haproxy says HTTP it'll be respected. – KajMagnus May 8 '18 at 14:28
  • That is suggested here: stackoverflow.com/a/21911864/694469 (i.e. default $http_x_forwarded_proto;). – KajMagnus May 8 '18 at 14:41

I had the same need with AWS ELB

Here is my solving line:

proxy_set_header        X-Forwarded-Proto $http_x_forwarded_proto;
  • Should I bet setting $http_x_forwarded_proto somewhere? What is that? – Jonathan May 23 '18 at 23:55
  • developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… $http_x_forwarded_proto is the NGINX implementation – jobwat Jun 11 '18 at 20:46
  • 2
    You answer just solved an issue I've been hammering at for 3 days! Every other post on the subject of aws load balancers with https advocate proxy_set_header X-Forwarded-Proto $scheme;, which doesn't work – MikeMarsian Jan 23 '19 at 7:42
  • $http_x_forwarded_proto is the way nginx exposes the X-Forwarded-Proto header. See the docs for "$http_name" in nginx.org/en/docs/http/ngx_http_core_module.html#variables – RobSiklos Dec 17 '20 at 21:53
  • Doesn't this just copy the header value from the upstream request? Shouldn't nginx do this automatically? – Migwell Jan 4 at 4:10

I can't just comment so I post this as an answer : Could you give us part or all of your nginx configuration so we can see what's wrong with it ? Possibly your HAProxy config too ?

The first problem I can think of is that your HAProxy is doing ssl termination. To sum it up, to offload your backend servers, a load balancer can be configured to do all the ssl thing, and then communicate with your backend servers in HTTP. Like the scheme here : http://blog.exceliance.fr/2012/09/10/how-to-get-ssl-with-haproxy-getting-rid-of-stunnel-stud-nginx-or-pound/

To give you a good answer to your question, could you check you don't have any loopback problem in your http<>https config ? Maybe then you could redirect http to http, https to https, and then force http to be redirected to https.

Could you check too that you have enabled ssl passthrough in your HAProxy config ?

  • Did you resolve your problem ? – Yannovitch Jun 15 '13 at 12:53
  • 1
    I figured it out. Your answer didn't help directly, but that second link helped me figure out a way to solve it. Thanks. – Echo says Reinstate Monica Jun 17 '13 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.