Snippets:Nginx universal port 80 redirect

server {
    listen [::]:80 ipv6only=off default_server;
    server_name www.example.com; # replace this with your primary website's
                                 # domain name; only used in the rare case when
                                 # no Host header is sent; the redirect will
                                 # otherwise always work regardless of what
                                 # domain name you put here.
    root /dev/null;
    location / {
        return 301 https://$host$request_uri;
    }
    location /.well-known/acme-challenge/ {
        root /var/www/acme-challenge/;
    }
}

The above configuration is one that I use on all of my servers. It basically creates a "universal" http -> https redirect that works on all virtual hosts defined on this web server.

The idea is that the port 80 configuration above is the same throughout the entire web server, whereas all virtual hosts are actually differentiated on port 443. Another way of seeing this is that the above configuration is a "generator" for every domain name that points to the server, in that it is equivalent to having a virtual host that performs this redirection for all domain names in existence.

You will only have one such server block throughout your entire web server. All other server blocks listen only on port 443, and there will only be one server block per virtual host instead of two.

In addition, it makes obtaining SSL certificates much easier. Just set /var/www/acme-challenge as the "webroot" for the purposes of Certbot's HTTP authenticator. This will be the "webroot" for all virtual hosts, even if the actual root directory for the secure site is different. You will be able to do this even if you don't have any port 443 virtual hosts.

The only disadvantage to this is that all sites on this web server will have to have an SSL certificate, but for our purposes, we don't have any insecure sites, so that doesn't really matter. After all, Let's Encrypt can provide SSL certificates for pretty much any site for free.

Example of some port 443 virtual server blocks, just to make this complete:

# The certificate file shown here should be a "multi-domain" or wildcard
# SSL certificate that covers all domain names that are not otherwise
# covered by server blocks that have their own ssl_certificate declaration.
ssl_certificate /path/to/main/ssl/certificate.crt;
ssl_certificate_key /path/to/main/ssl/certificate.key;

server {
    listen [::]:443 ssl http2 ipv6only=off default_server;
    server_name main-site.example.com;
    root /var/www/main-site;
}
server {
    listen [::]:443 ssl http2;
    server_name sub-site-1.example.com;
    root /var/www/sub-site-1;
}
server {
    listen [::]:443 ssl http2;
    server_name sub-site-2.example.com;
    ssl_certificate /path/to/sub-site-2/ssl/certificate.crt; # Use this ONLY if this domain name is not covered by the wildcard/multi-domain certificate.
    ssl_certificate_key /path/to/sub-site-2/ssl/certificate.key;
    root /var/www/sub-site-2;
}