TLS 1.3 was finalised in 2018. By 2026 it's the default in every browser, supported by every major CDN, and required by an increasing number of compliance frameworks. If you're still running TLS 1.2 only — or worse, leaving 1.0 and 1.1 enabled — you're carrying performance overhead, exposure to legacy attacks, and audit findings that get harder to defend every year.
The migration itself is short. On most modern web servers it's a few lines of configuration and a reload. The hard part is the audit before and after — confirming you actually rolled out 1.3 cleanly, that you've cut off the old protocols, and that nothing in your stack quietly downgraded a connection.
This guide covers why TLS 1.3 matters, the concrete differences from TLS 1.2 that affect your configuration, how to check what your server is currently negotiating, and step-by-step migration instructions for Nginx, Apache, and Cloudflare. We'll finish with the verification commands you should run after every TLS change.
Check your site right now: Free ZeriFlow scan in 60 seconds →
Why Migrate to TLS 1.3?
Three reasons, in order of business impact.
1. Faster Handshakes
TLS 1.3 cuts the handshake from two round trips to one. For repeat connections, 0-RTT mode reduces it to zero. On a 100ms RTT connection, that's 100-200ms shaved off every new connection. For sites with global audiences and lots of new visitors, that's a measurable conversion lift on the first paint.
2. Removed Legacy Crypto
TLS 1.3 strips out everything that turned out to be a bad idea: RSA key exchange (no forward secrecy), CBC-mode ciphers (Lucky 13, BEAST), MD5 and SHA-1 in signatures, static Diffie-Hellman, weak elliptic curves. The remaining cipher set is small, modern, and AEAD-only. There's no negotiation surface for an attacker to exploit, and no way to misconfigure yourself into a weak suite.
3. Compliance and Procurement
PCI-DSS 4.0, FedRAMP, and most enterprise procurement questionnaires now require TLS 1.2 minimum and prefer 1.3. Several browsers and CDNs have started issuing deprecation warnings for TLS 1.2-only configurations. Migrating now is cheap; migrating under audit pressure is not.
TLS 1.2 vs TLS 1.3: What Actually Changed
Three differences matter operationally:
Cipher suites are simpler. TLS 1.2 had hundreds of named suites combining key exchange, authentication, encryption, and MAC. TLS 1.3 has five total: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, and TLS_AES_128_CCM_8_SHA256. You don't pick — the protocol negotiates. The right move is to enable all five and let the client choose.
Configuration directives differ. Most servers separate TLS 1.3 cipher selection from TLS 1.2. In Nginx that's ssl_ciphers (1.2 and below) versus ssl_conf_command Ciphersuites (1.3). Get this wrong and you'll think you've configured something that the server is silently ignoring.
Session resumption is different. TLS 1.3 replaces session IDs and tickets with PSKs. If you've tuned session caches in 1.2, the equivalent settings in 1.3 are different and need separate consideration — particularly around 0-RTT, which has replay implications you should think through before enabling.
Step 1: Check Your Current TLS Configuration
Before changing anything, capture what you've got. Three commands:
# What protocols does the server actually accept?
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
# Detailed cipher and handshake info
testssl.sh --severity HIGH yourdomain.com
# Quick negotiation check
echo | openssl s_client -connect yourdomain.com:443 -tls1_3 2>/dev/null \
| grep -E "Protocol|Cipher"If openssl s_client -tls1_3 returns "no protocols available," your server isn't negotiating 1.3. If nmap shows TLS 1.0 or 1.1 in the supported list, you have legacy protocols enabled and need to disable them as part of this migration.
For a quick external view that you can hand to a non-technical stakeholder, run a ZeriFlow scan — the TLS section reports protocol versions, cipher suites, certificate chain, and HSTS status in plain English.
Step 2: Configure TLS 1.3 on Nginx
You need OpenSSL 1.1.1+ (1.1.1 added TLS 1.3 support) and Nginx 1.13.0+. Most distributions in 2026 ship with these by default.
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
http3 on;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Protocols: 1.2 minimum, 1.3 enabled
ssl_protocols TLSv1.2 TLSv1.3;
# TLS 1.2 ciphers (forward secrecy, AEAD only)
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;
# TLS 1.3 cipher selection (let client choose from the modern set)
ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
# Session settings
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}Reload with nginx -t && systemctl reload nginx. The -t is important — a syntax error in the SSL block will crash on reload otherwise.
Step 3: Configure TLS 1.3 on Apache
You need Apache 2.4.36+ and OpenSSL 1.1.1+.
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
# Protocols
SSLProtocol -all +TLSv1.2 +TLSv1.3
# TLS 1.2 ciphers
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
# TLS 1.3 cipher selection
SSLOpenSSLConfCmd Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
SSLHonorCipherOrder off
SSLSessionTickets off
# OCSP stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</VirtualHost>Reload with apachectl configtest && systemctl reload apache2.
Step 4: Configure TLS 1.3 on Cloudflare
Cloudflare is the easy case. In the dashboard:
- 1SSL/TLS → Edge Certificates → set Minimum TLS Version to 1.2.
- 2Toggle TLS 1.3 to On.
- 30-RTT Connection Resumption: leave off unless you've reviewed the replay implications for your application (anything non-idempotent should not use 0-RTT).
- 4Automatic HTTPS Rewrites: on. This handles mixed content for you at the edge.
- 5Always Use HTTPS: on.
Cloudflare handles the connection from the browser to its edge. The connection from Cloudflare to your origin is a separate setting under Edge Certificates → Origin Server. Set that to Full (strict) so Cloudflare validates your origin certificate.
Step 5: Disable TLS 1.0 and 1.1
If your config above explicitly lists TLSv1.2 TLSv1.3, you've already done this. To verify:
openssl s_client -connect yourdomain.com:443 -tls1 # should fail
openssl s_client -connect yourdomain.com:443 -tls1_1 # should fail
openssl s_client -connect yourdomain.com:443 -tls1_2 # should succeed
openssl s_client -connect yourdomain.com:443 -tls1_3 # should succeedThe first two should return "no protocols available" or a handshake error. If either succeeds, you have legacy protocol support enabled somewhere — check load balancers, CDN settings, and any reverse proxies in the path.
Step 6: Verify and Monitor
After deploying, run external verification:
- SSL Labs (`ssllabs.com/ssltest`): aim for an A+ grade with TLS 1.3 listed in supported protocols and TLS 1.0/1.1 absent.
- `testssl.sh --severity LOW yourdomain.com`: full local audit, no severity findings expected.
- ZeriFlow: continuous monitoring of TLS configuration, certificate expiry, and HSTS status. Catches regressions when someone reverts a config.
Set up alerts for two things: certificate expiry (30, 14, and 7 days) and TLS configuration changes (a diff against your last known-good scan).
For the broader configuration hardening that should sit alongside TLS, see our HTTP security headers guide.
FAQ
Q: Will enabling TLS 1.3 break old browsers or clients?
A: No, as long as you keep TLS 1.2 enabled in parallel. Every browser released since 2018 supports TLS 1.3, but plenty of older devices, IoT clients, and legacy software still negotiate 1.2. Drop 1.0 and 1.1 freely; keep 1.2 unless you have specific reason to require 1.3-only.
Q: Should I enable 0-RTT connection resumption?
A: Only after reviewing the replay implications. 0-RTT data can be replayed by an attacker — if any of your endpoints are non-idempotent (state-changing GETs, for example), an attacker could replay them. The safe default is off; enable selectively if you've audited your routes.
Q: How is TLS 1.3 different for performance?
A: TLS 1.3 reduces the handshake from two round trips (TLS 1.2) to one (TLS 1.3) or zero (0-RTT for resumed sessions). On a 100ms RTT, that's 100-200ms saved on every new connection. For high-latency regions and mobile users, the impact on time-to-first-byte is measurable.
Q: What's the right TLS configuration for a CDN-fronted site?
A: Configure TLS 1.2 + 1.3 at the CDN edge (where browsers connect) and TLS 1.2 minimum on the origin (where the CDN connects). Use Full (strict) origin validation so the CDN won't trust an unverified origin. Most CDNs handle the modern cipher set automatically.
Q: How often should I re-check my TLS configuration?
A: Continuously. TLS configurations regress through OS upgrades, control panel changes, CDN setting tweaks, and "temporary" debugging. An automated scanner that alerts on changes catches regressions in minutes instead of months.
Conclusion
TLS 1.3 migration in 2026 is short, well-documented, and supported by every relevant tool in your stack. The work is mostly verification — making sure you actually deployed what you intended to deploy, that legacy protocols are gone, and that nothing in the path quietly downgrades a connection.
Do the migration, drop TLS 1.0 and 1.1, run the verification commands, and set up continuous monitoring so you catch regressions when they happen rather than during your next compliance review.
Start your free security scan on ZeriFlow → — TLS audit, cipher inventory, certificate monitoring, and HSTS validation in 60 seconds. Free plan available, no credit card required.