Too many redirects error while trying to configure rails application as SSL using nginx and unicorn

apr picture apr · Feb 18, 2013 · Viewed 9.4k times · Source

I am trying to configure a Rails application with SSL, using Nginx and Unicorn. I am trying to set it up locally. For that I first created a self-signed certificate using OpenSSL for Nginx. I followed the document for creating self-signed certificates. After that I configured my nginx.conf as below, inside the http block:

upstream unicorn_myapp {
    # This is the socket we configured in unicorn.rb
    server unix:root_path/tmp/sockets/unicorn.sock fail_timeout=0;
}

server {
    listen 80;
    server_name dev.myapp.com;
    rewrite ^/(.*) http://dev.myapp.com/$1 permanent;
}

server {
    listen                80;
    listen                443 ssl;
    server_name           dev.myapp.com;
    ssl                   on;
    ssl_certificate       /etc/nginx/ssl/server.pem;
    ssl_certificate_key   /etc/nginx/ssl/server.key;
    ssl_protocols         SSLv3 TLSv1;
    ssl_ciphers           ALL:-ADH:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;
    ssl_session_cache     shared:SSL:10m;

    root root_path/public;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_myapp;
            break;
        }
    }
}

I tried to set it up locally, and started Unicorn locally. I mapped 127.0.0.1 to dev.myapp.com in /etc/hosts. But after starting the server, when I tried to ping the app, it gave the below error in Chrome:

This webpage has a redirect loop
Error 310 (net::ERR_TOO_MANY_REDIRECTS): There were too many redirects.

and the following error in Firefox:

The page isn't redirecting properly

The nginix.access.log shows the following result:

127.0.0.1 - - [18/Feb/2013:12:56:16 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11;        Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:16 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:16 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:16 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:16 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"
127.0.0.1 - - [18/Feb/2013:12:56:43 +0530] "-" 400 0 "-" "-"

Can any one please help me out to find the solution?

Answer

Eric Platon picture Eric Platon · Feb 15, 2014

You are missing a header:

proxy_set_header X-Forwarded-Proto https;

Let me cite a comprehensive post that explains nicely how Rails deals with HTTPS on Nginx:

force_ssl relies on the HTTP_X_FORWARDED_PROTO HTTP header to determine whether or not the request was an HTTPS request. If this setting isn't set to https then you will end up with an infinite redirect loop as force_ssl will always think the forwarded request isn't HTTPS.