Skip to main content
DevOps6 min readMarch 3, 2026

SSL/TLS Configuration Best Practices in 2026

Configure SSL/TLS correctly in 2026 — modern cipher suites, HSTS, certificate management, OCSP stapling, and avoiding common misconfigurations that weaken HTTPS.

James Ross Jr.

James Ross Jr.

Strategic Systems Architect & Enterprise Software Developer

SSL/TLS Configuration Best Practices in 2026

Getting an SSL certificate installed is table stakes. Configuring TLS correctly is where teams actually differ. I regularly see production systems with valid HTTPS that would receive a C or D grade from SSL Labs — weak cipher suites still enabled, TLS 1.0 and 1.1 still accepted, HSTS not configured, certificates that will expire in a week because nobody set up auto-renewal.

This is the TLS configuration guide I follow, with the reasoning behind each decision.

TLS Version: 1.2 and 1.3 Only

TLS 1.0 and 1.1 are deprecated. They have known vulnerabilities (BEAST, POODLE, CRIME), they use outdated cryptographic primitives, and the standards bodies officially deprecated them in 2021. There is no justification for enabling them in 2026.

Configure your server to accept TLS 1.2 and 1.3 only. In Nginx:

ssl_protocols TLSv1.2 TLSv1.3;

TLS 1.3 is faster — it reduces the handshake to one round trip instead of two — and more secure. It eliminates weak cipher suites entirely at the protocol level. Most modern browsers support it. Enable it and let clients that support it use it.

Cipher Suites

TLS 1.3 handles cipher suite selection automatically — the protocol defines only strong ciphers. For TLS 1.2 compatibility, you need to specify acceptable cipher suites 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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

These cipher suites have several properties in common: ECDHE or DHE key exchange (providing forward secrecy), AES-GCM or ChaCha20 authenticated encryption, and no RC4, 3DES, or CBC mode ciphers. Forward secrecy means that if your private key is compromised in the future, past sessions cannot be decrypted because each session used a unique session key.

ssl_prefer_server_ciphers off lets the client choose the cipher suite from your allowed list. Modern clients will select TLS 1.3 with its automatically strong ciphers, or the strongest TLS 1.2 cipher they support. Forcing server preference is mainly useful when you have legacy clients that might choose weak ciphers — if you have enforced the strong cipher list above, this is not needed.

HSTS: Force HTTPS

HTTP Strict Transport Security tells browsers that your site should only be accessed over HTTPS for a defined period. Once a browser has seen your HSTS header, it will refuse to make HTTP requests to your domain — it upgrades them to HTTPS automatically, without a round trip.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

max-age=31536000 is one year. Browsers remember this for a year after each visit. includeSubDomains extends the policy to all subdomains — essential if you want subdomain HTTPS to be enforced. preload signals that you want to be included in browser HSTS preload lists.

Submit your domain to the HSTS preload list at hstspreload.org after you are confident in your HTTPS setup. Preloaded domains get HTTPS enforcement before the first visit — the browser ships with your domain on the list.

One caution: set a short max-age first (300 seconds is fine) and verify your entire site works over HTTPS before increasing it. HSTS with a year max-age and a broken HTTPS setup means users cannot reach your site.

Certificate Management with Let's Encrypt

Manual certificate management is error-prone. Certificates expire. Renewal reminders get buried. I have seen production outages caused by expired certificates that nobody noticed until users started reporting "not secure" warnings.

Let's Encrypt provides free certificates with 90-day validity. Use Certbot with auto-renewal:

# Install Certbot
sudo apt install certbot python3-certbot-nginx

# Obtain and install certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Verify auto-renewal works
sudo certbot renew --dry-run

Certbot installs a systemd timer that runs renewal twice daily. Certificates renew automatically when they are 30 days from expiry. Set up a monitoring check that alerts if any certificate is within 14 days of expiry as a backup — use a service like Checkly or write a simple script that runs in CI on a schedule.

For containerized deployments, acme.sh or the Caddy web server (which handles TLS automatically) are good alternatives. Caddy obtains and renews Let's Encrypt certificates automatically with zero configuration.

OCSP Stapling

When a browser connects to your server, it needs to verify your certificate has not been revoked. Without OCSP stapling, the browser makes a separate request to the certificate authority's OCSP server to check revocation status. This adds latency and exposes your users' browsing to the CA.

OCSP stapling has your server fetch the OCSP response from the CA and include it in the TLS handshake. The browser gets the revocation status information from your server without a separate CA request.

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

This is a small performance and privacy improvement with essentially no downside. Enable it.

Perfect Forward Secrecy with DH Parameters

For DHE cipher suites, Nginx uses default Diffie-Hellman parameters that may be weak. Generate strong parameters:

openssl dhparam -out /etc/nginx/dhparam.pem 2048

Then reference in your Nginx config:

ssl_dhparam /etc/nginx/dhparam.pem;

This is only necessary for DHE cipher suites. If you are exclusively using ECDHE (which is preferable), DHE parameters are not needed. The cipher suite list above includes some DHE suites for broad compatibility — the DH parameter file covers those.

Full Nginx TLS Configuration

Here is the complete, production-ready TLS block for Nginx:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;

    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;
    ssl_prefer_server_ciphers off;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header Referrer-Policy strict-origin-when-cross-origin always;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://yourdomain.com$request_uri;
}

ssl_session_tickets off disables TLS session tickets, which can compromise forward secrecy because the ticket encryption key is long-lived. ssl_session_cache with ssl_session_timeout provides session resumption through a server-side cache instead.

Testing Your Configuration

After configuring TLS, test it. The SSL Labs server test at ssllabs.com/ssltest gives you a detailed grade with specific findings. Aim for A+. A score below A indicates specific configuration problems to address.

Mozilla's Observatory at observatory.mozilla.org checks security headers alongside TLS configuration. Both tools are free and give you actionable findings.

Run these tests after any significant configuration change and quarterly as baseline checks.


If you want help auditing and hardening the TLS configuration on your production servers, book a session at https://calendly.com/jamesrossjr.


Keep Reading