A pattern I settled on after hitting redirect loops one too many times while deploying demos and services behind Cloudflare: serve the origin over plain HTTP and let Cloudflare own TLS at the edge.
The loop happens when the two layers disagree about who handles HTTPS. Cloudflare terminates TLS and talks to your origin; if Cloudflare’s SSL mode and the origin’s own redirect behavior are mismatched — the classic case being an origin that redirects HTTP to HTTPS while Cloudflare is configured to reach it over HTTP — the visitor bounces between the edge and the origin forever: browser asks for HTTPS, edge fetches over HTTP, origin answers “redirect to HTTPS,” edge passes it back, repeat until the browser gives up with too-many-redirects.
There are two coherent ways to set it up:
- HTTP-only origin, Cloudflare-managed SSL. The origin never redirects, never holds a certificate, and firewalls itself so only tunnel/proxied traffic reaches it. This is what I use for anything behind Cloudflare Tunnel — the tunnel connection itself is already encrypted outbound, and the origin stays dumb and simple.
- Full end-to-end TLS, where the origin has its own certificate and Cloudflare’s SSL mode is explicitly set to match. Right choice when the path between edge and origin crosses networks you don’t control.
Either is fine. The loop comes from being half in each — an origin that thinks it’s public and an edge that thinks it owns TLS.
The convention pays off most on quick client demos: one Coolify deploy, HTTP only, tunnel it, and TLS is nobody’s job. I haven’t debugged a certificate or a redirect loop on that setup since.