NGINX redirect non-existent domains

Lets say I have the following domain:

example.com

with these subdomains:

test.example.com

prod.example.com

All only accessable through HTTPS. When someone enters https://test2.example.com or any other non-existent subdomain, they get served the standard NGINX index.html file. Instead, I want them to be redirected back to https://example.com.

This is what my server block /etc/nginx/nginx.conf looks like:

    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        server_name  example;
        root         /usr/share/nginx/html;
        index index.html
        ssl on;
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;


        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

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

I was hoping the line return 301 https://example.com$request_uri; would solve this problem, but it isn't working. Chrome displays following error:

ERR_TOO_MANY_REDIRECTS

What is working, is the URI int the address bar changes from test2.example.com to example.com. Im just having an issue with too many redirects. Or maybe there is a better way to do this?


You currently have one server block which is also the default server block.

You should separate that into two blocks. One block handles the named domains and another handles all of the non-existent domains:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout  10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

server {
    listen  443 ssl default_server;
    listen  [::]:443 ssl default_server;
    return  301 https://example.com$request_uri;
}

server {
    listen  443 ssl http2;
    listen  [::]:443 ssl http2;

    server_name  example.com test.example.com prod.example.com;

    root    /usr/share/nginx/html;
    index   index.html

    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

Many of the ssl_xxx directives can be placed above the server blocks (within the surrounding http block) so that they are inherited by both - or you can copy them into each server block (your choice).

See this document for more.