TLS Configuration Best Practices for Modern Web Apps
TLS 1.0 and 1.1 are formally deprecated. Here's what production-grade looks like for your protocol versions, certificate chain and HSTS header — and how to verify it from outside.
By ShipReady · Updated
HTTPS is table stakes, but "has a padlock" and "configured correctly" are different things. Weak protocols, an incomplete certificate chain, or a missing HSTS header will all show a padlock while leaving real gaps. Here is what production-grade TLS looks like.
Protocols and ciphers
- Disable TLS 1.0 and 1.1. RFC 8996 formally deprecated both in 2021; every major browser had already removed support. PCI DSS has required at least TLS 1.1 since 2018, and TLS 1.2 is the practical floor.
- Require TLS 1.2 as a minimum and prefer TLS 1.3, which is faster and drops legacy cipher baggage.
- Disable weak cipher suites (RC4, 3DES, anything export-grade).
Turn on HSTS
HTTP Strict Transport Security (RFC 6797) tells browsers to only ever connect to your host over HTTPS, closing the downgrade window from the first visit onward. Add it once you are confident everything — every subdomain included — is served over HTTPS.
Two cautions. includeSubDomains applies the rule to every subdomain, so a legacy HTTP-only subdomain will break; ShipReady reports HSTS without it as a gap, not as a reason to add it blindly. And preload is close to irreversible — removal from the browser preload list takes months — so treat it as a deliberate commitment rather than a line you copy.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadRedirect HTTP, then keep it redirected
HSTS only protects a browser that has already seen the header once, which it can only do over HTTPS. So the first request still has to get there: http://yourdomain.com must return a 301 to the HTTPS URL, and ShipReady reports a missing HTTPS redirect when it does not.
Then watch for the page that undoes it. A single asset loaded over http:// on an HTTPS page is mixed content: browsers block active mixed content outright and the request is either broken or downgraded. ShipReady reports mixed content as its own finding, because it is usually a hardcoded URL in a template rather than a server misconfiguration.
Certificate hygiene
- Serve the full chain, not just the leaf certificate — a missing intermediate breaks some clients.
- Automate renewal so a cert never expires by surprise.
- Monitor expiry and get alerted well before the deadline.
The incomplete-chain problem deserves a word, because it is the classic "works in my browser" failure. Browsers often paper over a missing intermediate certificate by fetching it themselves; many non-browser clients — a payment provider calling your webhook, a mobile app, curl on an older system — do not. The symptom is an integration that fails for one partner while your site looks fine to everyone.
What TLS does not do
TLS protects data in transit between the browser and your server. That is all it does. It does not make the application behind it secure, it does not validate who is running the site beyond the domain name, and a padlock on a phishing page is exactly as green as a padlock on a bank. Everything in the security headers guide sits on top of it and does a different job.
How to verify it
From a terminal, openssl s_client -connect yourdomain.com:443 -tls1_1 should fail; the same command with -tls1_2 should succeed. curl -sI https://yourdomain.com | grep -i strict shows the HSTS header your server really sends, which is not always the one in your config.
ShipReady checks the same things from outside: whether the host still accepts a deprecated TLS version, whether the certificate is close to expiry, whether HTTP redirects to HTTPS, and whether the HSTS header is present with a sensible max-age. It does not enumerate cipher suites — for that, a dedicated TLS analyser is the better tool, and we say so.