rewrite http to https with ngnix behind load balancer

sciurus is correct in that Rackspace's Cloud Load Balancers set the X-Forwarded-Proto to https when SSL is offloaded at the load balancer. In order to avoid a redirect loop in nginx, you should be able to add the following to the location section in the vhost configuration:

if ($http_x_forwarded_proto = "http") {
            rewrite  ^/(.*)$  https://mydomain.com/$1 permanent;
}

This should avoid the infinite redirect loop while redirecting non-https requests to https.


By using nginx's built-in server variables $request_uri and $server_name you can do this without using regular expressions at all. Add the following to your server's location block and you're done:

if ($http_x_forwarded_proto = "http") {
    return 301 https://$server_name$request_uri;
}

This assumes your load balancer is sending the $http_x_forwarded_proto header along with the request to your backend instance(s). Other common headers include $http_x_forwarded_scheme and also just $scheme.

More information can be found in the nginx Pitfalls and Common Mistakes documentation : https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#taxing-rewrites


The load balancer always talks to you over http. What is happening is

  1. The browser makes a request to port 80 on the load balancer
  2. The load balancer makes a request to port 80 on your web server
  3. Your web server sends a redirect to the user
  4. The user makes a request to port 443 on the load balancer

Steps 2-4 keep repeating until the browser detect the redirect loop and gives up.

EDIT: To resolve this, only perform the rewrite when the X-Forwarded-Proto header is set to http. That header is how Rackspace's load balancer tells your web server the protocol via which it received the request.