
☝️ A quick word for everyone who just wanted to read a blog post: TLS is the reason your browser shows that little padlock. Every time you open a page here, it travels to you encrypted. Nobody in the same café Wi-Fi, at your internet provider or anywhere in between can read along or quietly swap a few words. And no, it is not called “SSL” any more, even if the test site below still insists on the old name. SSL was retired in 2015; we just never managed to retire the word. So when I brag about “TLS settings” below, I’m really bragging about how well the envelope around this very sentence is sealed. You’re welcome. 🤓
Every now and then I throw my own blog at Qualys SSL Labs, mostly to make sure nothing has quietly rotted since the last time. Tonight’s result made me smile: A+ on both endpoints, IPv4 and IPv6. No warnings, no “but”, no asterisk.

A grade is nice, but a grade alone tells you nothing. So here is what this server actually speaks, in plain words. Same workflow as always: I ask the questions and make the calls, my AI co-admin (Claude) pulled the raw scan data from the SSL Labs API and cross-checked it against the config.
🔐 What the blog supports (the short list)
| Feature | What we do | Why it matters |
|---|---|---|
| Protocols | TLS 1.3 and TLS 1.2 only | TLS 1.0/1.1 and every SSL version are gone, and so is their whole museum of attacks. |
| Cipher suites | 6 in total, all AEAD: AES-GCM and ChaCha20-Poly1305 | No CBC at all, so the padding-oracle family (POODLE, Lucky13, GOLDENDOODLE, Zombie POODLE …) has nothing to bite on. |
| Forward secrecy | ECDHE for every single connection | A stolen key tomorrow can’t decrypt traffic recorded today. Session tickets are off, so that stays true across resumptions. |
| Post-quantum key exchange | Hybrid X25519MLKEM768 offered first | Current Chrome and Firefox already use it. “Record now, decrypt later” gets a lot less attractive. |
| Certificate | ECDSA P-256 from Let’s Encrypt, fresh key on every renewal | Smaller and faster than RSA, and an old key never outlives its certificate. |
| HSTS | 1 year, includeSubDomains, preload – also on the apex redirect | After the first visit the browser refuses plain HTTP to this domain. This is what turns A into A+. |
| Extras | HTTP/2 via ALPN, TLS_FALLBACK_SCSV, no 0-RTT | Fast, downgrade-resistant, and no replayable early data. |
Every vulnerability test on the report comes back negative: Heartbleed, ROBOT, Ticketbleed, FREAK, Logjam, the lot. Not because of some clever patching, but because the vulnerable building blocks simply aren’t on offer any more.
🤓 Three details I found more interesting than the grade
- The post-quantum part came for free. I never configured
X25519MLKEM768. The ingress controller ships nginx built against OpenSSL 3.5, which puts the hybrid group first by default. Sometimes the best security feature is just keeping your images current. - No OCSP stapling – on purpose. SSL Labs lists it as “No”, which looks like a gap. It isn’t: Let’s Encrypt has retired OCSP, and the current certificates carry no OCSP URL at all. There is nothing to staple; revocation works via CRLs and short lifetimes now.
- The price of strictness. 46 of the 68 simulated clients connect fine. The 22 that fail are fossils: Internet Explorer up to version 10, Android up to 4.3, Safari up to 8, Java 6/7, OpenSSL 0.9.8, Chrome 49 on Windows XP and a Baidu crawler from 2015. I can live with that.
🛠️ Where the A+ lives: my Ansible code
None of this was clicked together on the server. The whole stack is deployed by my public Ansible repository aptupgrademe/www_k3s, and the scan above ran against the server exactly as a playbook run leaves it, with no manual tweaks on top. So consider this post a test report for the code. If you want to copy the settings, these are the two files to read:
roles/common_k3s/templates/ingress-nginx-values.yml.j2– protocols, cipher list, session cache, tickets off, and the comment explaining why OCSP stapling is deliberately missing.roles/blog_k3s_deploy/templates/ingress.yml.j2– the ECDSA certificate request for cert-manager, the HSTS header and the preload-ready apex redirect.
The heart of it fits on one screen:
# ingress controller (shared role, also in front of my Nextclouds)
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: "false"
ssl_session_tickets off;
# blog ingress: ECDSA certificate with a fresh key on every renewal
cert-manager.io/private-key-algorithm: "ECDSA"
cert-manager.io/private-key-size: "256"
cert-manager.io/private-key-rotation-policy: "Always"
# HSTS, even on the redirects
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;Because the TLS part lives in a shared role, the same settings protect my two Nextcloud instances as well. One fix, three servers.
📝 Still on the list
- HSTS preload submission: the header is preload-ready, but the domain isn’t on the browsers’ preload lists yet. That’s a one-way door, so I’m taking my time.
- CAA record: a DNS entry that says “only Let’s Encrypt may issue certificates for this domain”. Small, cheap, not there yet.
Want to check it yourself? The live SSL Labs report is one click away. And if your own server gets a B, the cipher list above is a good place to start.





