nginx redirect loop with ssl

stoves picture stoves · Apr 17, 2014 · Viewed 13.9k times · Source

This is a very similar problem to Nginx configuration leads to endless redirect loop but that discussion has not led me to an answer yet. I'm learning how to work with nginx and ssl and everything works perfectly on the regular http:// example.com side of things, but when routing to the https:// example.com/admin I instead see:

This webpage has a redirect loop

Here is my config file:

map $uri $example_org_preferred_proto {
        default "http";
        ~^/(images|css|javascript)/ "none";
        ~^/admin/ "https";
}

server {
    listen 80;
    root /usr/share/nginx/www/example.com/blog;

    server_name example.com;
        if ($example_org_preferred_proto = "https")
            return 301 https://example.com$request_uri;
        }

    location ~ / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:2368;
    }

}

server {
    listen 443;
    ssl on;
    root /usr/share/nginx/www/example.com/blog;

    server_name example.com;
    ssl_certificate /usr/share/nginx/<redacted>.crt;
    ssl_certificate_key /usr/share/nginx/<redacted>.key;
    if ($example_org_preferred_proto = "http") {
        return 301 http://example.com$request_uri;
    }

    location ~ / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:2368;
    }


}

Basically what I want to accomplish is having a site that normally runs unencrypted, but when I point to my admin page the browser redirects to https and encrypts my login.

Note: the mapping idea came from http://www.redant.com.au/ruby-on-rails-devops/manage-ssl-redirection-in-nginx-using-maps-and-save-the-universe/ and seems like a much better approach than using rewrite

Answer

John picture John · Apr 17, 2014

When nginx encounters a https protocol it thinks it is still using http as the protocol and is not being forwarded with the rest of the headers, try adding:

proxy_set_header        X-Forwarded-Proto $scheme;

in your location blocks to fix it.