Short answer
For new systems where all clients support TLS 1.3: use Mozilla's modern profile — TLS 1.3 only with its three AEAD suites, no legacy configuration required. For anything that must serve older clients: use intermediate — TLS 1.2+1.3, ECDHE suites only with AES-GCM or ChaCha20-Poly1305, no CBC, RC4, 3DES or static RSA. Both give forward secrecy and top marks in scanners.
Mozilla modern — TLS 1.3 only
The simplest secure configuration. In TLS 1.3 the suites are chosen by the server from a fixed, secure list, and you normally do not need to specify them explicitly:
# nginx — modern (TLS 1.3 only) ssl_protocols TLSv1.3; ssl_prefer_server_ciphers off; # TLS 1.3 suites are fixed and not disabled individually: # TLS_AES_128_GCM_SHA256 # TLS_AES_256_GCM_SHA384 # TLS_CHACHA20_POLY1305_SHA256
Choose modern only if you know that no relevant client is stuck on TLS 1.2. Otherwise older browsers, old Java versions and some API clients will be unable to connect.
Mozilla intermediate — the recommended baseline
This is the right choice for the vast majority of public services in 2026. It allows TLS 1.2 and 1.3 and a curated list of strong ECDHE suites:
# nginx — intermediate (TLS 1.2 + 1.3) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off;
Note: in intermediate Mozilla deliberately sets ssl_prefer_server_ciphers off so the client may choose between AES-GCM and ChaCha20 according to whichever its hardware is fastest at. That is the right call — see AES-GCM vs ChaCha20.
The two profiles compared
| Modern | Intermediate | |
|---|---|---|
| Protocols | TLS 1.3 only | TLS 1.2 + 1.3 |
| Cipher types | AEAD only (fixed) | ECDHE + AEAD |
| Forward secrecy | Always | Always |
| Older clients | Rejected | Supported (TLS 1.2) |
| Choose when | Internal/modern clients | Public services |
The Apache equivalent
# Apache — intermediate SSLProtocol -all +TLSv1.2 +TLSv1.3 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 SSLHonorCipherOrder off SSLSessionTickets off
What you deliberately exclude
It is just as important to understand what is not on the list. Both profiles exclude: anything with RC4 (statistically breakable), 3DES (SWEET32), plain CBC suites without AEAD, static RSA key exchange (no forward secrecy), and any suite with MD5 or SHA1. This is not an arbitrary selection — each exclusion corresponds to a concrete, named attack. We walk through them in why RC4 and 3DES are dangerous. The point of allow-listing the good list rather than block-listing the bad one is that a new weak suite in a future OpenSSL version is never automatically permitted.
A note on server preference and ordering
In TLS 1.2, ssl_prefer_server_ciphers controls who chooses: with on the server's order wins, with off the client's wins. The old reflex was always to set on to force "the strongest" suite. That is outdated advice: when the list contains only strong AEAD suites, there is no bad option to protect against, and letting the client choose gives it the fastest cipher for its hardware. That is why Mozilla's intermediate sets off. Set on only if you have a specific reason to enforce a particular order.
Verify the result
A configuration is only good if the server actually enforces it. Confirm what is really offered:
nmap --script ssl-enum-ciphers -p 443 example.com # or in more detail: testssl.sh --protocols --ciphers example.com
If you still see TLS 1.0/1.1, CBC suites or a suite without ECDHE, an old include or a default image has overridden your configuration. The full testing arsenal is in how to test your TLS ciphers.
A good choice only stays good if it does not drift
The most common failure is not a bad choice — it is a good configuration quietly disappearing: a server is rebuilt from an older image, a load balancer default wins over your nginx config, or one host in twenty was never hardened. CertControl scans all of your endpoints, compares the suites actually offered against your baseline, and raises a finding when a server falls outside the profile. That is the difference between choosing correctly once and staying secure. Read what the names mean in what is a cipher suite.
Frequently asked questions
Should I use modern or intermediate?
Use intermediate unless you know for certain that all your clients support TLS 1.3. Intermediate covers practically every modern client while still excluding weak cryptography. Modern is only for internal or controlled environments.
Do I even need to specify cipher suites in TLS 1.3?
No. TLS 1.3 has only five fixed, secure suites, and most servers do not let you disable them individually. You specify ciphers only to control the TLS 1.2 part.
Should I set ssl_prefer_server_ciphers on or off?
For a modern intermediate configuration Mozilla recommends off, so the client can choose between AES-GCM and ChaCha20 according to its hardware. Set it on only if you deliberately want to force a particular order.
Are the DHE suites in the intermediate list necessary?
They are a fallback for clients without ECDHE support and are still secure, but slower. Many drop them entirely today. Keep them only if you have clients that genuinely need them.
How often should I review my cipher configuration?
At least once a year, and whenever Mozilla updates its profiles or a new weakness is published. Continuous scanning additionally catches the servers that drift away from baseline between reviews.