NGINX & Certbot

From NixNet

sudo apt install certbot nginx

Certbot

You should eventually read the official docs so you actually understand what’s going on and what these snippets mean.

Wildcard certs with DNS

(works with any subdomain)

sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory \
    --manual \
    --preferred-challenges dns \
    -d *.example.com -d example.com

Individual certs with webroot

(only works with the domains or subdomains you give it)

sudo certbot certonly --webroot -w /var/www/_certbot -d example.com

DH Params

More info at security.stackexchange.com

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

NGINX

You should eventually read the official docs so you actually understand what’s going on.

sudo mkdir /etc/nginx/snippets/ssl/
sudo mkdir /etc/nginx/sites-available/_utilities
sudo rm -rf /etc/nginx/sites-enabled/default

VHosts for wildcard certs

I like to save them as site.vhost though a lot of people use site.conf. It helps to differentiate between what functions more like a config and what’s meant to be a vhost (virtual host)

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

        server_name example.com;

        include snippets/ssl-params.conf;
        include snippets/ssl/example.com.conf;

        root /var/www/example.com;

        # Add index.php before the ; if you're using PHP
        index index.html;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

VHosts for reverse proxying a local server

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

	server_name example.com;

	include snippets/ssl-params.conf;
	include snippets/ssl/example.com.conf;

	location /
		proxy_pass http://localhost:PORT;
	}
}

snippets/ssl-params.conf

sudo -e /etc/nginx/snippets/ssl-params.conf

# generated 2020-03-04, Mozilla Guideline v5.4, nginx 1.14.2, OpenSSL 1.1.1d, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&guideline=5.4
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

# verify chain of trust of OCSP response using Root CA and Intermediate certs
# requires package "ca-certificates" on Debian
ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;

# replace with the IP address of your resolver (hint: see resolv.conf(5))
resolver 127.0.0.1;

snippets/ssl/example.com.conf

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

# HSTS for preloaded domains (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

# HSTS for non-preloaded domains (ngx_http_headers_module is required) (63072000 seconds)
# add_header Strict-Transport-Security "max-age=63072000" always;

After you generate the certs at the top of the page, Certbot will tell you where they’re located. If you don’t remember or can’t scroll back up or something, ls /etc/letsencrypt/live should help.

sites-available/_utilities/http-redirect

If you have wildcard certs, this is really useful because you won’t have to include them in every vhost. sudo vim /etc/nginx/sites-available/_utilities/http-redirect

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;

        access_log off;
        error_log off;

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

        location /.well-known/acme-challenge {
                root /var/www/_certbot/;

        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        }
}

sudo ln -s /etc/nginx/sites-available/_utilities/http-redirect /etc/nginx/sites-enabled/

/etc/nginx/nginx.conf

To make sure you're using secure ciphers for TLS, I recommend pasting this bit into your global NGINX config file. It's a portion of the config recommended by Mozilla. It goes under your global server { block.

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # generated with command in certbot section above
    ssl_dhparam /path/to/dhparam;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    # ONLY USE IF YOU'RE FAMILIAR WITH CERTBOT
    # it adds HSTS to all of your websites so they cannot be visited
    # without TLS encryption
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;