Introduction
For a couple of months, I had a low-grade nightmare running quietly in the background of my VPS setup: DNS Proxied (the little orange cloud in Cloudflare) just wouldn't behave. Sometimes it worked. Sometimes it threw redirect loops. Sometimes it just quietly served the wrong thing. I assumed I had a DNS problem, so I kept poking at DNS records, TTLs, and proxy toggles — none of which were the actual issue.
Turns out, the real culprit was sitting one menu over the whole time: SSL/TLS Encryption Mode. I didn't even know this setting existed as something I needed to actively manage — Cloudflare had quietly defaulted my zone to Flexible, and I had no idea that choice was fighting with my own infrastructure.
If you've been following the VPS migration post where I moved from Debian to AlmaLinux 10 and swapped Docker for Podman, you'll remember Caddy sitting at the center of that stack as my reverse proxy. That detail turns out to be exactly why Flexible mode was such a bad match for me — and why switching to Full (Strict) was the fix that finally made everything click.
This post walks through the two-connection model Cloudflare uses under the hood, why Flexible mode quietly sabotages a Caddy-based setup, and why Full (Strict) isn't just "more secure" — it's actually the correct mode for anyone running Caddy as their reverse proxy.
Core Concept: The Two-Connection Model (and Where Flexible Falls Apart)
Here's the mental model that would've saved me two months of confusion: when Cloudflare sits in front of your site, there are actually two separate connections, not one.
Visitor ◄──Connection 1──► Cloudflare ◄──Connection 2──► Origin Server (your VPS)
- Connection 1 is the visitor talking to Cloudflare's edge. This is always encrypted — Cloudflare handles that part for you.
- Connection 2 is Cloudflare talking to your origin server. This is the part your Encryption Mode setting actually controls.
The mode you pick doesn't change what the visitor sees in their browser (they'll get a padlock either way). What it changes is whether Cloudflare treats Connection 2 as encrypted, verified, or just... plain HTTP.
The five modes, quickly
| Mode | Cloudflare → Origin | Cert Required | Cert Validated |
|---|---|---|---|
| Off | HTTP | No | N/A |
| Flexible | HTTP | No | N/A |
| Full | HTTPS | Any (even self-signed) | No |
| Full (Strict) | HTTPS | Valid CA-issued | Yes |
| Automatic | Cloudflare decides | Varies | Varies |
Where my setup went wrong
Here's the part that got me: Caddy automatically provisions a real, valid HTTPS certificate for your domain via Let's Encrypt — that's basically Caddy's whole selling point as a reverse proxy. My origin server was already fully capable of proper HTTPS the moment Caddy started.
But Flexible mode doesn't care about any of that. It talks to the origin over plain HTTP, full stop — regardless of what Caddy is offering. So Caddy, seeing an incoming HTTP request, did what it's configured to do by default: redirect to HTTPS. Cloudflare, in Flexible mode, would follow that redirect... back to HTTP again. That's the classic ERR_TOO_MANY_REDIRECTS loop, and it's almost always a sign that your encryption mode and your origin server are disagreeing about what protocol to speak.
Switching to Full (Strict) solved this instantly, because:
- Caddy's cert is already valid, unexpired, and correctly matched to my hostname — exactly what Full (Strict) requires.
- Cloudflare now talks HTTPS to the origin and actually validates that cert instead of just trusting whatever's presented.
- There's no more protocol mismatch — both sides agree the connection should be HTTPS the whole way through.
In hindsight, Flexible mode is really meant for origins that can't do HTTPS at all — old legacy servers, providers without TLS support. If you're running Caddy (or honestly, any modern reverse proxy with auto-TLS like Traefik or nginx with certbot), Flexible is actively working against your setup rather than protecting it.
Best Practices
A few things I wish I'd locked in from day one, now that Full (Strict) is doing its job properly:
1. Enable "Always Use HTTPS" Under SSL/TLS → Edge Certificates, this forces all HTTP requests to HTTPS at Cloudflare's edge, before they even reach your origin. One less thing for Caddy to worry about.
2. Turn on "Automatic HTTPS Rewrites" This quietly fixes mixed-content issues by rewriting HTTP resource links to HTTPS. Handy if any part of your app still references old http:// URLs.
3. Set Minimum TLS Version to 1.2, and enable TLS 1.3 TLS 1.0/1.1 have known weaknesses (POODLE, BEAST). No reason to support them in 2026.
4. Let Caddy do what it's good at — don't fight it Since Caddy handles cert issuance and renewal automatically, there's no need to manually manage origin certificates in most cases. Full (Strict) plus Caddy's default behavior is a genuinely low-maintenance combo once it's set up correctly.
5. Confirm DNS Proxied status first, before chasing SSL settings Ironically, the orange cloud toggle wasn't my problem this time — but it's still worth checking early. If DNS Proxied is off, none of Cloudflare's edge protections apply at all, and you're troubleshooting the wrong layer entirely.
6. Test with SSL Labs After switching modes, run your domain through SSL Labs' Server Test. An A or A+ grade is a solid sanity check that Connection 2 is actually behaving the way you think it is.
Final Thoughts
The embarrassing part of this whole saga is that the fix was one dropdown menu away the entire time. I kept treating it as a DNS problem because "DNS Proxied" was the visible symptom — but the actual root cause was a mismatch between Cloudflare's encryption expectations and what my Caddy-fronted origin was already capable of.
If you're running a similar setup — Caddy or any reverse proxy with automatic TLS, sitting behind Cloudflare — do yourself a favor and check your encryption mode before you spend two months troubleshooting DNS like I did. Full (Strict) isn't just the "more secure" checkbox; for setups like mine, it's the mode that actually matches reality.