
September 12, 2026
10 min read
By Kokil Thapa | Last reviewed: September 2026
Choosing between TLS 1.2 vs TLS 1.3 is no longer a theoretical debate on most production stacks. Browsers, payment gateways, and API clients already prefer 1.3. Your job is to understand what changed, what breaks, and how to configure Apache or Nginx without leaving older clients stranded. This guide walks through handshake mechanics, cipher policy, and copy-paste server config grounded in real Linux server administration work on client sites in Nepal and abroad.
What is the difference between TLS 1.2 and TLS 1.3?
Both versions encrypt HTTP, API traffic, and database tunnels. The practical gap is how they negotiate keys and which algorithms they allow. TLS 1.2, defined in RFC 5246, supports many cipher suites. Some are strong. Some are obsolete today.
TLS 1.3, defined in RFC 8446, trims the cipher list aggressively. It drops RSA key transport, static Diffie-Hellman, CBC-mode bulk ciphers, and several legacy MAC constructions. Forward secrecy becomes the default path, not an optional upgrade.
On legal-tech portals and eCommerce sites I maintain, the shift matters beyond benchmarks. Faster handshakes reduce time-to-first-byte on mobile networks in Kathmandu. Stricter ciphers reduce the attack surface PCI assessors and security scanners flag during audits. For background on certificates themselves, see the guide on SSL/TLS certificates explained.
Core protocol changes at a glance
- Cipher suites: TLS 1.3 defines five mandatory suites. TLS 1.2 allows dozens, including weak ones if you misconfigure the server.
- Key exchange: 1.3 requires (EC)DHE. RSA encryption of premaster secrets is gone.
- Handshake shape: 1.3 sends encrypted extensions earlier. More of the negotiation is confidential.
- 0-RTT: Only 1.3 supports early data resumption. Useful for speed, risky if replay is possible.
- Session resumption: 1.3 uses PSK-based tickets instead of older session-ID patterns in many stacks.
How does the TLS 1.3 handshake compare to TLS 1.2?
Latency is where engineers feel the difference first. A full TLS 1.2 handshake needs two round trips before application data flows. TLS 1.3 completes the full handshake in one round trip under normal conditions. On high-latency mobile links, that single RTT saving often beats shaving kilobytes off HTML.
The detailed message flow is covered in the TLS 1.3 handshake explained. Here is the operational summary you need when tuning production servers.
When 0-RTT helps and when it hurts
0-RTT lets repeat visitors send HTTP requests before the handshake finishes. That sounds ideal for static assets and read-heavy pages. It is a poor fit for anything that changes state. Payment callbacks, login forms, and booking endpoints on sites like Adventure Third Pole Trek must treat 0-RTT as unsafe unless the application layer implements anti-replay logic.
Most small Laravel and WordPress stacks simply disable 0-RTT at the web server. The speed gain from 1-RTT full handshakes is already meaningful. You avoid a whole class of replay bugs.
Which cipher suites should you allow in TLS 1.2 vs TLS 1.3?
Cipher policy is the second place TLS 1.2 vs TLS 1.3 diverges in production config files. With 1.3, the server advertises a short list. OpenSSL and Nginx map them to names like TLS_AES_256_GCM_SHA384 and TLS_CHACHA20_POLY1305_SHA256. You mostly choose order, not membership.
With 1.2, you own the full allowlist. A permissive string like HIGH:!aNULL still lets through configurations that fail modern audits. I standardise on ECDHE key exchange, AEAD bulk encryption, and disable CBC where possible.
| Criterion | TLS 1.2 | TLS 1.3 |
|---|---|---|
| Typical bulk cipher | AES-GCM, ChaCha20-Poly1305 (if configured) | AES-128/256-GCM, ChaCha20-Poly1305 only |
| Key exchange | RSA, DHE, ECDHE (config-dependent) | (EC)DHE only — forward secrecy by default |
| Hash for PRF/MAC | SHA-256, SHA-384, legacy SHA-1 in old suites | SHA-256 / SHA-384 built into AEAD suites |
| Misconfiguration risk | High — many obsolete suites remain available | Low — small fixed set |
| PCI / scanner posture | Requires tight cipher string discipline | Passes most checks with version enabled |
| Interop with old Android | Required for Android 4.x–6.x without patches | Android 10+ native; older need 1.2 fallback |
For password and key material handling in adjacent workflows, pair transport security with strong secrets generated via a password generator tool. TLS protects data in motion. It does not fix weak credentials at rest.
How do you configure Nginx and Apache for TLS 1.2 and TLS 1.3?
Your OpenSSL build must support 1.3. On Ubuntu 22.04 and 24.04 with system OpenSSL 3.x, it does. Verify with:
openssl version -a
nginx -V 2>&1 | grep -i openssl
Full Nginx guidance lives in TLS 1.3 vs 1.2 configuration for Nginx. Below is a baseline I deploy on Apache + PHP-FPM stacks serving Laravel 12 and WordPress 7.1 sites.
Nginx example (dual-stack, 1.3 preferred)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
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_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000" always;
}
Note ssl_prefer_server_ciphers off with TLS 1.3. Clients pick AEAD suites correctly. For 1.2-only clients, the cipher string still enforces ECDHE and GCM.
Apache example (mod_ssl on Ubuntu)
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>
After any SSL change, reload the daemon and verify live negotiation. I use Qualys SSL Labs for external perspective and openssl s_client locally:
openssl s_client -connect example.com:443 -tls1_3 </dev/null 2>/dev/null | grep "Protocol"
openssl s_client -connect example.com:443 -tls1_2 </dev/null 2>/dev/null | grep "Cipher"
Sister sites on shared EC2 infrastructure — notary portals, translation services — share a Deployer 7 pipeline. Certbot renews certificates on schedule. PHP-FPM reload follows symlink swaps so opcache picks up code changes. TLS config lives in the web server layer and rarely changes per deploy. Details sit in Ansible playbooks for PHP server provisioning when I automate new hosts.
Should you disable TLS 1.2 and run TLS 1.3 only?
For most public websites in 2026, keep both enabled for now. Disable SSLv3, TLS 1.0, and TLS 1.1 unconditionally. Those versions fail compliance and browser trust policies.
TLS 1.3-only makes sense in controlled environments: internal gRPC meshes, service-to-service APIs where you own every client, or greenfield mobile apps with modern SDKs. Public law-firm portals and WooCommerce stores still see occasional 1.2-only clients. Disabling 1.2 without analytics to back the decision generates support tickets.
Decision checklist before dropping TLS 1.2
- Pull thirty days of access logs and tag TLS version if your edge logs
ssl_protocolor equivalent. - Check payment gateway and bank API requirements. Some specify minimum TLS versions but not maximum.
- Run SSL Labs and fix 1.2 cipher weaknesses first. A tight 1.2 stack beats a sloppy 1.3-only headline.
- Schedule the change outside Dashain/Tihar peaks if you serve Nepal retail traffic.
- Document rollback: keep the previous config snippet in your support and maintenance runbook.
Load-balanced setups add another layer. HAProxy and Kubernetes ingress controllers each expose protocol knobs differently. See HAProxy load balancing config and TLS and Kubernetes ingress and TLS with cert-manager when TLS terminates before your PHP workers.
Sites handling sensitive documents — client portals like Mijar Law Associates or Notary Nepal — benefit from HSTS preload and modern TLS together. Transport security is one layer. Application auth, rate limiting, and upload validation still matter. Read API rate limiting and abuse prevention for the next layer up.
What performance and SEO impact does TLS 1.3 have?
Search engines rank on Core Web Vitals, not TLS version directly. Indirect effects are real. Faster handshakes improve TTFB on cold connections. Mobile users on 4G in Nepal feel one fewer RTT on first visit. HTTP/2 and HTTP/3 adoption also pairs naturally with modern TLS stacks configured during speed optimization work.
Certificate overhead dominates on asset-heavy pages with many third-party domains. Each new origin may negotiate TLS separately. Keep asset domains on the same cert where possible. Use session tickets consistently. For greenfield apps, consider web development patterns that consolidate static delivery behind one edge hostname.
Testing belongs in staging before production cutover. A mis-ordered cipher string or missing intermediate certificate breaks more traffic than upgrading from 1.2 to 1.3. Fold SSL checks into your testing and optimization checklist alongside PHP 8.3+ and Laravel 13 readiness reviews.
Key Takeaways
- Prefer TLS 1.3 everywhere; keep TLS 1.2 as a fallback on public sites until logs prove zero legacy clients.
- Disable TLS 1.0 and 1.1 today — they carry no upside and fail audits.
- Lock TLS 1.2 to ECDHE + AEAD ciphers; let TLS 1.3 handle its own short suite list.
- Disable 0-RTT on state-changing routes unless you implement explicit anti-replay controls.
- Verify with
openssl s_clientand SSL Labs after every config change, not just at launch. - Terminate TLS at a maintained edge (Nginx/Apache/HAProxy) and automate cert renewal with Certbot or cert-manager.
People Also Ask
Is TLS 1.3 backward compatible with TLS 1.2?
Clients and servers negotiate the highest mutually supported version. A browser that speaks 1.3 connects with 1.3. An older client falls back to 1.2 if the server still allows it. They do not share cipher suites — 1.3 suites are version-specific.
Does Let's Encrypt support TLS 1.3?
Let's Encrypt issues certificates, not protocol versions. Your web server chooses TLS versions. Certbot-managed certs work with both 1.2 and 1.3 once OpenSSL and Nginx or Apache are current.
Which browsers require TLS 1.2 minimum?
All mainstream browsers in 2026 require at least TLS 1.2. Chrome, Firefox, Safari, and Edge have supported TLS 1.3 for years. Legacy Internet Explorer and unpatched Android WebViews are the usual reasons to keep 1.2 fallback.
Is TLS 1.2 still secure in 2026?
TLS 1.2 remains acceptable when weak ciphers and RSA key transport are disabled. PCI DSS and industry guidance treat 1.2 as minimum for compatibility. TLS 1.3 is the recommended target for new deployments because the protocol removes risky options by design.
Deploy modern TLS with confidence
The TLS 1.2 vs TLS 1.3 choice is really about defaults: enable 1.3, tighten 1.2, and retire everything below. Measure before you disable fallback. Automate certificate renewal. Reload your web server after every change.
If you want help auditing SSL on a live Laravel, WordPress, or WooCommerce stack — including Certbot, HSTS, and cipher hardening on Ubuntu — see domain registration and hosting or reach out via contact us. For broader context on how I approach production systems, visit about me or browse the portfolio of deployed sites.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

