Published:
Updated:

Table of Contents

Intro

I enjoy an A+ Qualys TLS score. Here's my latest crypto playbook for yawnbox.is using Ubuntu Server 22.04. I use nginx-light, but you can use the heavier nginx if you need.

Preparation

Ubuntu 22.04 already has available nginx version 1.22.x. If you're using a prior version of Ubuntu Server, you need at least nginx version 1.19.7 to be able to prioritize the ChaCha20-Poly1305 cipher. If you need to upgrade you version of nginx, first add:

sudo add-apt-repository ppa:ondrej/nginx-mainline

Install nginx and certbot:

sudo apt update && sudo apt dist-upgrade -y && sudo apt install nginx certbot -V

Use EC-384 certs instead of the default RSA-2048

Obtain EC certs for your domain:

sudo certbot --nginx -d yawnbox.is --key-type ecdsa --elliptic-curve secp384r1 --redirect --hsts

nginx changes

Below are some important nginx changes.

sudo vim /etc/nginx/sites-available/default

First, Let's Encrypt didn't enable HTTP/2 for me, which is weird, so add that:

listen [::]:443 ssl;
listen 443 ssl;
http2 on;

I disable TLS 1.2, enable X25519 curve support, and prioritize ChaCha20-Poly1305 then AES-256-GCM while disabling AES-128-GCM:

ssl_protocols TLSv1.3;
ssl_ecdh_curve X25519:secp384r1;
ssl_conf_command Options PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;

If you want to support legacy platforms, you can add TLSv1.2 while maintaining the best AEAD suites:

ssl_protocols TLSv1.3 TLSv1.2;
ssl_ecdh_curve X25519:secp384r1;
ssl_conf_command Options PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384;

If you want to Enable Post-Quantum Key Agreements:

ssl_protocols TLSv1.3;
ssl_ecdh_curve x25519_kyber768:p384_kyber768:X25519:secp384r1;
ssl_conf_command Options PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;

Add HSTS-preload:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

Save and quit. Check your nginx config:

sudo nginx -t

I had some competing configs that certbot created:

sudo vim /etc/letsencrypt/options-ssl-nginx.conf

I moved these three lines, with some modifications, to the default nginx site:

ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;

I deleted the line referncing options-ssl-nginx.conf in the default nginx site.

Check your nginx config again:

sudo nginx -t

Restart nginx:

sudo service nginx restart

You can donate to Let's Encrypt here!

yawnbox