NGINX HTTP/NON-WWW to HTTPS caused too many redirects

nginxredirectssl

I want to 301 redirect all non-https and non-www to https://www.example.com using the following configuration I found in another thread as the accepted answer. But it's not working for me.

What works:

  • https://example.com -> https://www.example.com

  • http://example.com -> https://www.example.com

BUT…

  • http://www.example.com -> TOO MANY REDIRECTS… using curl I can see that this always redirects to itself…

Here is my nginx.conf:

server {

    # ports
    listen 80;
    listen [::]:80;

    # domain name
    server_name example.com www.example.com;

    # Redirect all non-https requests
    rewrite ^ https://www.example.com$request_uri? permanent;
}

server {

    if ($bad_referer) {
        return 444;
    }

    if ($bad_bot) {
        return 444;
    }

    # ports
    listen [::]:443 ssl http2;
    listen 443 ssl http2;

    # domain name
    server_name example.com www.example.com;

    if ($host = 'example.com') {
      return 301 https://www.example.com$request_uri;
    }

    # ssl certificate files
    ssl_certificate /etc/ssl/certs/domain.crt;
    ssl_certificate_key /etc/ssl/private/domain.key;

    include basic.conf;
}

Any ideas?

Update: It's getting even weirder…i've tried to make a general rule to route everything to ssl (as suggested on many blogs)…now www as well as non-www version are redirecting back to itself…

server {

    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

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

I have no idea how to debug this…btw…this is a docker swarm cluster…if this helps…

Best Answer

After testing this myself, I had to edit my original answer because it led to a conflicting server name error.

Sadly I cannot tell you why you still get this redirect loop - maybe the error comes from your include. But I can present you with a working (tested) configuration that accomplishes what you were asking for:

Generally: For rather simple redirecting it is recommended to use the return directive instead of redirect (https://www.nginx.com/blog/creating-nginx-rewrite-rules/)

Goal: Whatever combination

  • of scheme (http or https)
  • and domain (example.com or www.example.com)

you type into the browser, you will get redirected to https://www.example.com

Heres the configuration:

server {

listen 80;

server_name www.example.com redirecttest.de;

return 301 https://www.example.com$request_uri;

}

server {

listen 443 ssl http2;

server_name www.example.com;

root /var/www/example.com/http;

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

}
Related Topic