modern nginx cryptography.
Table of Contents
Intro
This post simply aims to document the current best settings for nginx transport cryptograhy that I use for the many sites that I maintain.
Tested working on nginx 1.29.1
Tested working on Ubuntu 24.04 and Debian 13
Stronger Let's Encrypt certs
Instead of the default RSA-2048, choose RSA-4096 or EC-384:
RSA-4096
sudo certbot certonly -d yawnbox.eu --key-type rsa --rsa-key-size 4096
EC-384
sudo certbot certonly -d yawnbox.eu --key-type ecdsa --elliptic-curve secp384r1
Template config
sudo vim /etc/nginx/conf.d/default.conf
OpenSSL 3.0 - 3.4
server {
server_name yawnbox.eu;
root /var/www/public;
# no logs
access_log off;
# hsts and hsts-preload
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# certs
ssl_certificate /etc/letsencrypt/live/cyber.cafe/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cyber.cafe/privkey.pem;
# http/3
listen [::]:443 quic reuseport;
listen 443 quic reuseport;
http3 on;
http3_hq on;
quic_gso on;
quic_retry on;
ssl_early_data off;
add_header Alt-Svc 'h3=":443"; ma=86400';
# http/2 and http/1.1
listen [::]:443 ssl;
listen 443 ssl;
http2 on;
# ciphers - 1.3 only, no AES-128, good groups
ssl_protocols TLSv1.3;
ssl_conf_command Groups X25519:secp384r1;
ssl_conf_command Options +ServerPreference;
ssl_conf_command Options +PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
With OpenSSL 3.5
$ openssl version
OpenSSL 3.5.1 1 Jul 2025
# ciphers - 1.3 only, no AES-128, good groups w/ hybrid pcq
ssl_protocols TLSv1.3;
ssl_conf_command Groups X25519MLKEM768:SecP384r1MLKEM1024:SecP256r1MLKEM768:MLKEM1024:X25519:secp384r1;
ssl_conf_command Options +ServerPreference;
ssl_conf_command Options +PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
Security Headers
Don't forget these! see: https://securityheaders.com
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data:; font-src 'self'; style-src 'self'; script-src 'self'; connect-src 'self'; form-action 'self'; frame-src 'none'; manifest-src 'self'; worker-src 'self'; upgrade-insecure-requests" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=(), bluetooth=(), interest-cohort=()" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;