Rather than hand-picking individual settings, generate a current, well-maintained configuration block and adjust from there — TLS best practices shift over time as new weaknesses are found.

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
Mozilla's SSL Configuration Generator produces a ready-to-use block for Nginx (with "modern," "intermediate," and "old" presets depending on how much legacy client compatibility you need) rather than requiring you to manually track which cipher suites are currently considered acceptable.
Confirming the result
After applying and reloading, run an SSL scan tool against your domain to confirm the intended protocol versions and cipher suites are in practice what's being served, and check the overall grade for anything unexpectedly flagged.
Picking the elliptic curve order explicitly
Nginx lets you set ssl_ecdh_curve X25519:prime256v1:secp384r1 to control which curves are offered for ECDHE key exchange and in what preference order — Mozilla's generator includes this for the modern and intermediate presets, but it's easy to lose if you're merging the output into an existing config by hand rather than dropping it in wholesale.
Validate before reloading, not after
Run nginx -t before every reload. A malformed cipher list or a missing semicolon fails the test cleanly, but a reload issued against a config that failed to parse leaves the previous configuration running — you won't notice anything's wrong until a scan turns up settings you thought you'd already changed.
Each server block needs its own certificate directives
Unlike a single shared vhost file, every server { } block serving TLS needs its own ssl_certificate and ssl_certificate_key lines — the protocol and cipher directives can live in one included snippet, but certificate paths can't, since each block is typically serving a different domain's certificate.
The listen-directive syntax changed in 1.25.1
Since nginx 1.25.1, HTTP/2 is enabled with a standalone http2 on; directive rather than as a flag on the listen 443 ssl http2; line — a config copied from an older tutorial that still uses the old combined syntax will load with a deprecation warning on current nginx, not a hard failure, so it's easy to miss.
Loading comments…