A surprising number of production web applications are still running TLS configurations from 2018 — TLS 1.0 or 1.1 enabled, weak cipher suites accepted, certificates renewed manually, HSTS not set. These aren't edge cases; they're common findings in infrastructure audits. The consequences range from failed PCI DSS compliance to actively exploitable downgrade attacks.
Here is a current, practical guide to TLS configuration that reflects 2026 standards and threat landscape.
Protocol Versions: TLS 1.3 Only (Almost)
TLS 1.2 remains acceptable. TLS 1.0 and 1.1 must be disabled — they are vulnerable to BEAST, POODLE, and SLOTH attacks and have been deprecated by every major standards body. PCI DSS 4.0, which became mandatory in 2024, prohibits TLS 1.0 and 1.1 outright for cardholder data environments.
TLS 1.3 is the target. It removes the entire renegotiation mechanism that enabled many historical attacks, cuts the handshake to one round trip (versus two for TLS 1.2), and supports only forward-secret cipher suites. On Nginx:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
Setting ssl_prefer_server_ciphers off with TLS 1.3 lets the client choose from the supported cipher suite list — all of which are secure — while allowing modern clients to use their most optimized implementation.
Cipher Suites: Prioritize Forward Secrecy
Forward secrecy (Perfect Forward Secrecy, PFS) ensures that a future compromise of your private key cannot decrypt past recorded traffic. It works by using ephemeral session keys that are never written to disk. TLS 1.3 mandates forward secrecy — all its cipher suites use ephemeral Diffie-Hellman. For TLS 1.2, enforce it explicitly:
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;
Every cipher in this list starts with ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) — that's your forward secrecy guarantee. Exclude anything with RC4, DES, 3DES, NULL, EXPORT, or MD5.
Certificate Management: Automate Everything
Manual certificate renewal is a liability. Expiry incidents — production sites serving certificate errors to real users — are almost always the result of manual processes that someone forgot. The 2024 industry shift to 90-day maximum certificate lifetimes (following Apple and Google's CA/Browser Forum proposal) makes automation mandatory.
Let's Encrypt + Certbot remains the standard for most deployments. Install certbot, run certbot --nginx once, and it configures auto-renewal via a systemd timer or cron job:
# Install and issue
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Test renewal
sudo certbot renew --dry-run
For Docker/Traefik environments, Traefik handles ACME certificate issuance and renewal automatically via its Let's Encrypt integration — no manual certbot needed. Certificates are stored in a JSON file that persists across container restarts.
Certificate monitoring is still necessary even with automation. Tools like cert-expiry-check or Grafana alerting on certificate expiry metrics catch failures in renewal automation before users do. Set alerts at 30-day and 7-day thresholds.
HSTS: Tell Browsers to Always Use HTTPS
HTTP Strict Transport Security (HSTS) instructs browsers to refuse HTTP connections to your domain and always upgrade to HTTPS — even before the server can redirect. This eliminates the window for SSL stripping attacks on users who type your domain without https://.
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
The max-age of 63072000 seconds (2 years) is the minimum required for HSTS preloading. includeSubDomains extends coverage to all subdomains — make sure every subdomain has a valid certificate before enabling this. preload opts into the browser-maintained HSTS preload list, meaning users who have never visited your site are still protected.
Submit your domain to the preload list at hstspreload.org once you have a stable configuration. Removal takes months, so only enable preload when you're committed to HTTPS-only operation.
OCSP Stapling: Faster Certificate Validation
When a browser connects to your server, it checks whether your certificate has been revoked — a round trip to the Certificate Authority's OCSP responder. This adds 50–200ms to the TLS handshake and creates a dependency on a third-party service. OCSP stapling eliminates this: your server pre-fetches the OCSP response and "staples" it to the TLS handshake.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 8.8.8.8 1.1.1.1 valid=300s;
resolver_timeout 5s;
Testing Your Configuration
Two tools cover most of what you need:
SSL Labs Server Test (ssllabs.com/ssltest) — comprehensive grading of your TLS configuration against current best practices. Aim for A+. Common reasons for failing A+: missing HSTS header, TLS 1.0/1.1 still enabled, weak cipher suites in the supported list.
testssl.sh — open-source command-line tool for testing any server without sending data to a third party. Useful for internal services, staging environments, and CI pipeline integration:
./testssl.sh --full yourdomain.com
Configuration Checklist
- TLS 1.0 and 1.1 disabled
- TLS 1.3 enabled; TLS 1.2 with forward-secret cipher suites only
- Certificate auto-renewal configured and tested
- Certificate monitoring alerts set at 30 days and 7 days
- HSTS header with
max-age=63072000andincludeSubDomains - OCSP stapling enabled
- HTTP to HTTPS redirect on port 80
- SSL Labs score: A or A+
- No mixed content warnings (all sub-resources loaded over HTTPS)
TLS configuration is not set-and-forget. New vulnerabilities are discovered, cipher suite recommendations evolve, and CA policies change. Schedule a quarterly review of your TLS posture against current Mozilla SSL Configuration Generator recommendations, and run SSL Labs after every major Nginx or certificate infrastructure change.