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
- The browser makes a request to port 80 on the load balancer
- The load balancer makes a request to port 80 on your web server
- Your web server sends a redirect to the user
- 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.