Nginx SSL – Fix ERR_TOO_MANY_REDIRECTS After Adding SSL

certbotlets-encryptnginxredirectssl

After i add Let's Encrypt certificate to my website with CertBot
i get ERR_TOO_MANY_REDIRECTS when i try to visit the domain of my website.

some info :

-mywebsite build with django, nginx and gunicorn.

server {
server_name www.example.com example.com;

location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
    root /home/myproject;
}

location / {
    include proxy_params;
    proxy_pass http://unix:/run/gunicorn.sock;
}


listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


if ($host = example.com) {
    return 301 https://$host$request_uri;
} # managed by Certbot

listen 80;
server_name www.example.com example.com;
return 404; # managed by Certbot

}

/etc/letsencrypt/options-ssl-nginx.conf :-

# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RS$

please tell me if you need any other code/info
thanks

Note : i have read all the questions with the same problem and i still can't know what is wrong

Best Answer

That's because you're redirecting all connections to https, even https connections, which means you create a redirect loop.

Change your config to

server {
    listen 80 default_server;
    server_name www.example.com example.com;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl default_server;
    server_name www.example.com example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


    location /favicon.ico { 
        access_log off; 
        log_not_found off; 
    }
    location /static/ {
        root /home/myproject;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Though it would be good to know what your /etc/letsencrypt/options-ssl-nginx.conf includes.

Explanation:

Basically you need two "server" sections, one for port 80 and one for port 443. The port 80 (http) section only has the redirect in it and the 443 section holds the actual settings for your site (locations, roots, etc.) and the SSL settings (certificates, supported protocols, ciphers, etc.).

So when a client connects via http the server tells him to go to https instead and then the https part handles everything from there.

It's also a good idea to use indentation in your configs for better readability and easier bug fixing.

Note: The config I posted only fixed your redirect issue, I don't know if the actual config you had was valid for your case (gunicorn etc.). Normally you should also define an index and a root for your server like this:

root /home/website/mywebsite/public;
index index.html index.htm index.php;