Is this re-formulation of the recommended Let's Encrypt NGINX configuration correct?

Apologies if this is off-topic here, but I previously asked on NGINX sub-reddit (no replies) and on Serverfault stackexchange (got deleted).

I'm using NGINX by generating a config file to a non-standard location and call it via nginx -c <path/to/nginx.conf> (see NixOS Discourse thread for details), therefore I have to figure out what the nginx.conf should contain, and keep the Let's Encrypt / certbot part updated manually.

The only difference in behaviour between the original and the re-written config should be that the re-written version is more strict, returning 400 when the Host header is missing. As for the syntactic changes, I took inspiration from the Improve Certbot nginx config generate thread to remove the conditionals.

Thank you!

The original

... from the Let's Encrypt forum's Security issue with redirects added by Certbot's Nginx plugin post:

server {
    root /var/www/html;
    index index.html;
    server_name example.com example.org;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    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 = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


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

    server_name example.com example.org;
    listen 80;
    listen [::]:80;
    return 404; # managed by Certbot
}

The re-written version

... using 3 server blocks:

  1. Explicit default server block catching requests without a Host header.

    server {
        server_name "";
        listen 80 default_server;
        return 400;
    }
    

    Returning 400 (Bad Request) according to RFC 9112 "HTTP/1.1", section "3.2 Request Target".

  2. Redirect HTTP to HTTPS.

    server {
        server_name example.com example.org;
        listen 80;
        listen [::]:80;
        return 301 https://$host$request_uri;
    }
    

    I think the if blocks can be omitted because the explicit default server block in 1. (See also this thread.)

  3. Handle TLS connections.

    server {
        root /var/www/html;
        index index.html;
        server_name example.com example.org;
    
        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        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
    }
    

I don't see anything wrong with it, it looks like a simple, straight forward nginx configuration to me.

2 Likes

The concept is fine with your new plan. A couple things ...

You are missing a listen for IPv6 in the above block. All server blocks should listen in the same way. Right now your default block won't ever get selected for IPv6 requests

Also, an HTTP Challenge will get redirected from HTTP to HTTPS (using Certbot --webroot). Which works and is not terrible. But, a better way to handle this if you even use HTTP Challenge and --webroot is like this

server {
    listen 80;
    listen [::]:80;    
    server_name example.com example.org;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;          # set to the folder you want
    }
    location / {
       return 301 https://$host$request_uri;
    }
}
7 Likes

EDITED: Please don't repost things from accounts that have been removed.

QUESTION-1: ... and how would one know if the removal was done by the admins and not by the user on their own volition? This same thing happened to me on another discourse forum, except it was the latter scenario.

QUESTION-2: Why was it removed? It didn't seem like spam. If it was a technical reason, then I would definitely benefit from knowing as I didn't catch it when I was editing it... Thanks.

I removed the post because it was off-topic: although related to nginx, it was offering a very broad and general set of advice on nginx config that didn’t address anything in this thread.

6 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.