Skip to content

maxuru ~ % cat nginx/tls-protocols-and-ciphers

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

Check your version first — that first line may already be the default

Section titled “Check your version first — that first line may already be the default”

ssl_protocols TLSv1.2 TLSv1.3; is now nginx’s own default, so on a current build the first line of the block above changes nothing. It is worth writing anyway — an explicit protocol line survives a distro that patches defaults, and it documents intent — but you should know which of these you are doing.

nginx moved to that default in two steps, and its own changelog dates both:

Release Change
1.23.4 (28 Mar 2023) TLSv1.3 enabled by default
1.27.3 (26 Nov 2024) TLSv1 and TLSv1.1 disabled by default

So:

  • nginx 1.27.3 or newer — the default is already TLSv1.2 TLSv1.3. Setting it is a verify, not a fix.
  • anything older — TLS 1.0 and 1.1 are still enabled by default and the line is a real change.

That second case is not hypothetical. nginx’s legacy branches are 1.28.x and 1.26.x, and distribution packages sit further back still, so a long-term server is exactly where the line does work. Check before assuming:

Terminal window
nginx -v

The rest of the block is not a no-op on any version. ssl_session_tickets off; differs from the default, and the two ssl_ciphers facts below — that it does not control TLS 1.3, and that a hand-written list ages badly — are the parts of this page that actually change outcomes.

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.