An SSL configuration (now TLS) is the server block that enables HTTPS — the cipher suites, protocols, certificates, and security headers that make the connection private, authenticated, and trusted. A weak configuration (TLS 1.0, RC4, no HSTS) still serves HTTPS but fails Qualys SSL Labs scans with a C or F, is vulnerable to POODLE, BEAST, and downgrade attacks, and is flagged by modern browsers. A TLS configuration generator that outputs copy-paste Nginx or Apache blocks with Mozilla's Intermediate compatibility (TLS 1.2+ with strong ciphers like ECDHE+AESGCM and CHACHA20), HSTS, OCSP stapling, and secure headers does the hardening without hand-editing openssl ciphers or memorizing the 20-line Mozilla template.
This expanded A-to-Z guide explains how to generate an SSL/TLS configuration for Nginx or Apache — what TLS, cipher suites, and HSTS are, the Mozilla Intermediate vs Modern vs Old profiles, step-by-step generation for the server's OpenSSL version, the directives for certificates, ciphers, protocols, HSTS, and OCSP, validation with SSL Labs, and the pitfalls that cause B grades — with references to Mozilla Server Side TLS (v5.7), RFC 8446 (TLS 1.3), RFC 6797 (HSTS), OWASP TLS Cheat Sheet, and Mozilla SSL Config Generator.
openssl version), and compatibility (Intermediate for broad clients — TLS 1.2+ with ECDHE+AESGCM, or Modern for TLS 1.3 only) in an SSL config generator to get a copy-paste server block with ssl_protocols, ssl_ciphers, ssl_prefer_server_ciphers, certificate paths (ssl_certificate, ssl_certificate_key), HSTS (Strict-Transport-Security), and OCSP stapling — ready for /etc/nginx/sites-available/default or httpd.conf after replacing the certificate paths with Let's Encrypt or commercial cert paths.
What Is SSL/TLS Configuration?
SSL (Secure Sockets Layer) is now TLS (Transport Layer Security) — SSL 3.0 is deprecated and insecure. The configuration is the set of directives that tells the web server how to negotiate HTTPS: which TLS versions to allow (1.2 and 1.3 per RFC 8446; 1.0 and 1.1 are deprecated per RFC 8996), which cipher suites to prefer (e.g., ECDHE-RSA-AES128-GCM-SHA256 for forward secrecy and AEAD), where the certificate and private key files are, whether to prefer server ciphers, and which security headers to send (HSTS per RFC 6797 and OCSP stapling per RFC 6961). Per Mozilla Server Side TLS v5.7, three profiles balance compatibility and security: Old (TLS 1.0+ for legacy), Intermediate (TLS 1.2+ for 5-year-old clients, recommended for public sites), and Modern (TLS 1.3 only, for modern clients). The generator lets you choose based on audience and OpenSSL version, since older OpenSSL lacks TLS 1.3 or CHACHA20.
Mozilla Profiles — Intermediate vs Modern vs Old
| Profile | Protocols | Ciphers | Compatibility |
|---|---|---|---|
| Old | TLS 1.0+ (with weak) | Includes 3DES, CBC | IE8, Java 6 — avoid unless legacy required |
| Intermediate ★ | TLS 1.2+ (and 1.3) | ECDHE+AESGCM, CHACHA20, no RC4/3DES | 5-year-old clients — recommended for public |
| Modern | TLS 1.3 only | TLS 1.3 ciphers only (AEAD) | Modern browsers only — strict, for internal |
For public sites, Intermediate is the default per Mozilla and OWASP — it negotiates TLS 1.3 with modern clients and falls back to 1.2 with strong ciphers for older, without weak RC4/3DES. Modern is for internal services where all clients are known to support 1.3. The generator tailors the cipher list to the OpenSSL version selected — older OpenSSL lacks CHACHA20 or TLS 1.3, so the list degrades gracefully rather than failing at reload.
How to Generate an SSL Configuration — 3 Steps (With Validation)
- Select server and OpenSSL version: Choose Nginx or Apache and run
openssl versionon the server (e.g., OpenSSL 1.1.1k vs 3.0.2). The generator includes only ciphers that that OpenSSL supports — selecting 1.1.1 but pasting a 3.0 cipher list causesnginx -tto fail with "unknown cipher." - Pick compatibility: Intermediate for broad clients (TLS 1.2+ with ECDHE+AESGCM and CHACHA20) or Modern for TLS 1.3 only. For public sites, Intermediate is recommended; for internal APIs where all clients are modern (e.g., Go 1.18+), Modern is stricter and simpler.
- Copy, adapt, and test: The output is a server block with
ssl_protocols TLSv1.2 TLSv1.3;,ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...,ssl_prefer_server_ciphers off;(for TLS 1.3 where client chooses, per Mozilla), certificate paths (ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;,ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;), HSTS (add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;), and OCSP stapling (ssl_stapling on;). Replace the certificate paths with the Let's Encrypt paths from Certbot or the commercial cert, place in/etc/nginx/sites-available/defaultorhttpd.conf, test withnginx -torapachectl configtest, reload (systemctl reload nginx), and scan at Qualys SSL Labs for an A+ (the generator's Intermediate typically scores A+ with the right cert chain).
Key Directives Explained — What Each Does
ssl_protocols: Allowed TLS versions —TLSv1.2 TLSv1.3for Intermediate; Modern isTLSv1.3only. Disables 1.0 and 1.1 (vulnerable to POODLE, BEAST).ssl_ciphers: Ordered list of AEAD ciphers with forward secrecy —ECDHE(ephemeral) for PFS,AES-GCMorCHACHA20-POLY1305for AEAD. The list excludes RC4, 3DES, EXPORT, and MEDIUM ciphers. Order matters forssl_prefer_server_ciphers on;(server chooses), but for TLS 1.3 the client chooses per RFC 8446, so Mozilla sets itofffor Modern.ssl_certificate/ssl_certificate_key: Full chain and private key paths — from Let's Encrypt (/etc/letsencrypt/live/) or commercial CA. The full chain includes intermediates; missing intermediates cause "incomplete chain" in SSL Labs.- HSTS (
Strict-Transport-Security): Tells browsers to use HTTPS for the max-age (63072000 = 2 years) and optionallyincludeSubDomainsandpreloadfor hstspreload.org submission per RFC 6797. Usealwaysin Nginx to send on all responses, not just 2xx. - OCSP Stapling: Server staples the OCSP response (
ssl_stapling on; ssl_stapling_verify on;plusssl_trusted_certificate) so clients don't contact the CA — faster handshake and better privacy than clients fetching OCSP. Requires the CA chain inssl_trusted_certificate.
Best Practices — Ciphers, HSTS, and Validation
- Ciphers: Prefer
ECDHE+AES-GCMorCHACHA20— forward secrecy (ephemeral keys) and AEAD (authenticated encryption). AvoidRC4(biased),3DES(64-bit, Sweet32), andEXPORT(40-bit). The generator's Intermediate list is Mozilla-vetted and ordered for PFS. - Protocols: TLS 1.2 and 1.3 only — 1.0 and 1.1 are deprecated per RFC 8996 and flagged by SSL Labs. The generator disables them.
- HSTS: Start with
max-age=63072000; includeSubDomainsand test thoroughly before addingpreload— preload is hard to revoke and requires submission tohstspreload.organd HTTPS on all subdomains, including internal. - OCSP Stapling: Enable stapling and verify with
openssl s_client -connect example.com:443 -status— look forOCSP Response Status: successful. Withoutssl_trusted_certificate, stapling silently fails. - Validation: After reload, run Qualys SSL Labs for a grade (A+ is achievable with Intermediate, a full chain, HSTS, and no weak ciphers) and
testssl.shlocally for cipher enumeration. Checkcurl -v https://example.comfor the negotiated protocol and cipher.
Common Pitfalls That Cause B/C Grades
- Incomplete chain:
ssl_certificatepoints to cert only, not fullchain — SSL Labs shows "Chain issues: Incomplete" → usefullchain.pemfrom Let's Encrypt. - Missing intermediate in
ssl_trusted_certificate: OCSP stapling fails silently — setssl_trusted_certificateto the chain or intermediate, not just the leaf. - Weak ciphers left enabled: Copy-pasting an old config with
RC4or3DES→ B grade — use the generator's current list, not a 2015 blog post. - HSTS without HTTPS everywhere: Enabling HSTS with
includeSubDomainswhile a subdomain is still HTTP → that subdomain breaks. Test HSTS on a single domain first, then addincludeSubDomainsand preload after auditing all subdomains. - Forgetting to reload: Editing the file without
nginx -t && systemctl reload nginxleaves the old config active — test and reload are required.
FAQs About SSL Configuration
How do I generate an SSL config for Nginx?
Choose Nginx and the server's OpenSSL version in an SSL config generator, pick Intermediate compatibility (TLS 1.2+), copy the server block, set ssl_certificate and ssl_certificate_key to the Let's Encrypt fullchain.pem and privkey.pem paths, test with nginx -t, reload, and scan at SSL Labs for A+.
What is the difference between Intermediate and Modern?
Intermediate supports TLS 1.2+ with strong ciphers for 5-year-old clients (recommended for public sites); Modern requires TLS 1.3 only and is stricter — use Intermediate for public, Modern for internal modern-only services where all clients support 1.3.
How do I enable HSTS?
Add add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; in the server block, test without preload first, then submit to hstspreload.org after verifying all subdomains are HTTPS.
What is OCSP stapling and should I enable it?
Yes — the server staples the OCSP response so clients don't contact the CA, speeding handshakes and improving privacy. Enable ssl_stapling on; ssl_stapling_verify on; and set ssl_trusted_certificate to the chain.
How do I get an A+ on SSL Labs?
Use the generator's Intermediate (TLS 1.2+ with strong ciphers, no weak), serve the full chain, enable HSTS and OCSP stapling, and ensure no 3DES/RC4. The generator's output typically scores A+ with a correct chain and HSTS.
Conclusion
Generating an SSL configuration is selecting the server, OpenSSL version, and compatibility, then copying a hardened block with TLS 1.2+, strong forward-secrecy ciphers, HSTS, and OCSP stapling — validated with nginx -t and SSL Labs for an A+. A generator that tracks Mozilla's intermediate recommendations and OpenSSL capabilities keeps the config current without hand-editing ciphers or memorizing the 20-line template.
Generate the next config for Nginx or Apache — select the version and compatibility, copy the block, set the fullchain and privkey paths, reload, and scan for A+.