My home cloud sits behind a Cloudflare Tunnel, and the tunnel hands traffic to a Traefik reverse proxy. The day I wired the two together, the page would not load. The browser said it had been redirected too many times.
Nothing was down and every component answered. That made it slow to find: each piece was working, and the loop only existed in the way they were joined.
What the loop looked like
A redirect loop is a conversation where each side keeps giving the same answer. The first thing to establish is who is answering. The cheapest way to find out is to skip the browser and ask the origin directly, with a header that says which site you want:
curl -sI http://<origin>/ -H "Host: <your-hostname>"
The answer was not the page. It was a permanent redirect whose destination was the HTTPS version of the same hostname. The origin was telling the caller to go somewhere that, once it went through the tunnel again, led straight back to the same origin.
Why it looped
Traefik had a redirect from HTTP to HTTPS configured on its port 80 entrypoint. That setting applies at the entrypoint, before any router is matched. So it does not matter what a router would have done with a request: if the request arrives on port 80, it is redirected.
My tunnel route pointed at the origin over plain HTTP. The sequence went like this:
- A visitor opens the site over HTTPS. Cloudflare terminates that connection.
- Cloudflare sends the request down the tunnel, and cloudflared forwards it to Traefik on port 80, in plain HTTP.
- Traefik answers with a redirect to the HTTPS address of the same hostname.
- The browser follows it, goes back through Cloudflare, and arrives at step 2 again.
The visitor's connection was secure the whole time. The hop that mattered was the last one, between the tunnel and the proxy, and on that hop the redirect was an instruction to repeat the request forever.
What fixed it
Three changes, none of them clever:
- A real certificate for the public hostname on Traefik, issued with the DNS challenge, so the proxy could serve HTTPS for that name.
- The tunnel route moved to the HTTPS port, so requests never touch the redirecting entrypoint at all.
- One line of resolver config on the cloudflared container. cloudflared checks the origin certificate against the hostname in the route URL. The newer Cloudflare dashboard no longer exposes the origin server name or a skip-verification option on routes, so I made the container resolve the public hostname to the proxy's internal address with an
extra_hostsentry. The certificate name then matches the URL, and the traffic stays inside the house. Every public app added to that tunnel later needs the same one line.
What I check first now
- Does the origin answer with a redirect? One
curl -sIwith aHostheader, bypassing the browser and the tunnel. - Where is that redirect defined? In Traefik it can sit on the entrypoint or on a router, and the entrypoint wins.
- Is the hop into the origin HTTP or HTTPS? A redirect to HTTPS is right for a browser talking to the proxy and wrong for a tunnel that already terminated TLS upstream.
Same configuration, two meanings of "HTTP". The proxy was doing its job, and so was the tunnel. They just disagreed about which end was the front door.

