Skip to content

Configure nginx TLS protocols and ciphers

Severity: highApplies to: nginx 1.25+Applies to: nginx 1.30 / 1.31Applies to: freenginx
The fix/etc/nginx/nginx.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
Terminal window
sudo nginx -t && sudo systemctl reload nginx

TLS 1.0 and 1.1 are obsolete, deprecated by the IETF, and rejected by current browsers. Leaving them enabled doesn’t help anyone reach your site — the clients that would need them can’t complete a modern handshake anyway — but it does keep you failing compliance scans and offering downgrade surface.

ssl_protocols TLSv1.2 TLSv1.3 is the whole control. The rest of this page is about not making things worse.

The same argument as SSH ciphers applies, for the same reason: cipher lists age badly, and a list pasted from a 2016 blog post encodes 2016’s opinions forever.

Use the Mozilla SSL Configuration Generator. It produces a current list for your nginx and OpenSSL versions, and it is maintained by people who track this full time. Pick the intermediate profile unless you have a specific reason — modern drops TLS 1.2 entirely, which is more compatibility loss than most sites can absorb.

If you inherit a config with a long ssl_ciphers line, the question isn’t whether the ciphers are bad — they’re probably fine. It’s whether anyone will revisit them when the next weakness lands. A generated config that you regenerate is more durable than a curated one that you won’t.

This surprises people who carefully craft a cipher list and then wonder why their scan still shows suites they didn’t list.

ssl_ciphers configures TLS 1.2 and below only. TLS 1.3 has its own separate cipher suite set, and nginx offers no directive for it — OpenSSL’s defaults apply and they are deliberately short and all strong. There is nothing to tune, and nothing you can break.

So a hand-written ssl_ciphers line governs a shrinking share of your traffic, which is another reason not to spend effort on it.

ssl_prefer_server_ciphers off is deliberate

Section titled “ssl_prefer_server_ciphers off is deliberate”

The old advice was on — let the server dictate the order. Current Mozilla guidance for the intermediate profile is off, because modern clients pick better than a fixed server-side ordering can. A phone with hardware AES and a laptop without it want different suites, and only the client knows which it is.

ssl_session_tickets off is the other non-obvious one: tickets can undermine forward secrecy unless the ticket key is rotated, and nginx has no built-in rotation.

  • Enable HSTS — TLS is only useful if the browser insists on it.
  • OCSP stapling — mostly moot now; read before enabling.