Reverse Proxy vs Cloudflare Tunnel vs Tailscale: What Does Each One Actually Do?
Jesse Cole
September 27, 2026
Last spring a former colleague sent me a screenshot of his homelab dashboard and one question: “Why does everything break when I restart anything?” He’d been self-hosting for about six weeks. On one old laptop he was running Nginx Proxy Manager, a Cloudflare Tunnel container, and Tailscale. Cloudflare pointed at the proxy. The proxy pointed at his services by their Tailscale addresses. His phone reached them through Tailscale, except for one service, which it reached through Cloudflare, which went to the proxy, which went back out to a Tailscale address on the same laptop.
He’d followed three good tutorials. Each one solved a real problem. Nobody had told him that the three tools solve different problems, so he’d installed all three to solve one: “I want to open Jellyfin on my phone.”
I’ve run infrastructure for a living and I still remember being confused by this exact trio. So here’s the map I drew for him on a napkin, more or less. Not a feature comparison. Just what each one does, what question it answers, and when you need it.
Three questions, not three competitors
Every remote-access setup has to answer three separate questions:
- How does a request get from the outside world to my house?
- Who is allowed to send that request?
- Once it arrives, which of my services should get it?
A reverse proxy answers question three. Cloudflare Tunnel answers question one for the public internet. Tailscale answers questions one and two together, for a private group of devices. They overlap a bit at the edges, which is why tutorials treat them as rivals. But at the core, they’re different tools, and once you see which question each one answers, most of the confusion goes away.
The reverse proxy: a front desk for your services
Picture an apartment building lobby. Parcels arrive at one front door, and the concierge reads the name on each one and puts it in the right cubby. A reverse proxy is that concierge.
Your server probably runs several web apps, each listening on its own port: Jellyfin on 8096, Nextcloud on 8080, Home Assistant on 8123. Without a proxy, you’d reach them as 192.168.1.50:8096 and so on, which is ugly and doesn’t work well with HTTPS. With a proxy, everything arrives on the normal HTTPS port, 443. The proxy looks at the hostname in the request, say jellyfin.example.com, and passes it to port 8096 behind the scenes.
That’s the core job. Most proxies also handle the HTTPS certificates for you, which is a huge part of why people install them: Caddy, Traefik, and Nginx Proxy Manager can all request and renew Let’s Encrypt certificates on their own. Some add logins, rate limits, or header tweaks on top.
Here’s what a reverse proxy does not do: it does not make your server reachable from outside. It sits at the door and sorts what comes in. Whether anything can come in depends on your network. If you want the proxy reachable from the internet, you still have to forward port 443 on your router, and your ISP has to give you a public address that makes forwarding possible.
If you’re only using services at home, a reverse proxy is still nice: readable names and valid HTTPS certificates on your LAN. If you’re choosing between the popular ones, the difference that matters most for beginners is how Caddy and Traefik each hold up when you rewrite your Compose files, because that’s the moment the proxy config tends to break.

Cloudflare Tunnel: a public entrance without an open door
Cloudflare Tunnel answers the first question for the public internet: how does a stranger’s browser reach something in my house?
The traditional answer is port forwarding. You open 443 on your router, point your domain at your home IP, and let the internet knock. That works if you have a public IP and you’re comfortable with your home address being directly exposed. It doesn’t work at all if your ISP puts you behind carrier-grade NAT, which is increasingly common on newer fiber, mobile, and 5G plans. If you’ve set up a port forward correctly and nothing gets in, that’s the first thing to check, and how to tell whether your ISP has you behind CGNAT takes about five minutes.
Cloudflare Tunnel flips the direction. You run a small program, cloudflared, on your server. It opens an outbound connection to Cloudflare’s network and keeps it open. When someone visits blog.example.com, Cloudflare receives the request at its own data center and sends it down that existing connection to your server. Nothing is ever forwarded on your router. Your home IP never appears in DNS.
What you get: a public HTTPS URL that anyone can open, no port forwarding, and it works behind CGNAT. What you give up: Cloudflare terminates TLS, so it can see the traffic passing through; your domain has to use Cloudflare for DNS; and the free service is meant for websites, not for streaming large video libraries or arbitrary game traffic. Check their terms before you pipe a 4K movie collection through it.
Notice what Cloudflare Tunnel doesn’t do. It doesn’t decide who’s allowed in. By default, anyone with the URL reaches your service, and your service’s own login page is the only lock. Cloudflare sells an add-on, Cloudflare Access, that puts a login in front, but that’s a separate thing you have to set up. It also doesn’t care about your phone specifically. Your phone reaches the service the same way a stranger does: over the public internet.
Tailscale: a private network that follows your devices
Tailscale answers questions one and two together, for a small, known group: how do my devices reach each other, and nobody else’s?
You install Tailscale on your server, your phone, and your laptop, and sign each one into the same account. They form a private network, called a tailnet, on top of whatever internet connection each device happens to have. Your phone on hotel Wi-Fi can reach your server at home using a private address like 100.101.102.103, as if they were on the same LAN. Under the hood, it’s WireGuard encryption plus a coordination service that helps devices find each other and punch through NAT, falling back to relays if a direct path isn’t possible.
What you get: every service on the server is reachable from your devices, from anywhere, with nothing exposed to the public internet. Strangers can’t even see that the service exists. It works behind CGNAT. The login question is handled by the fact that only devices on your tailnet can connect.
What you give up: every device that needs access has to run Tailscale. That’s fine for you and your partner. It’s a problem for your aunt who wants to see the holiday photos, the school committee using a shared calendar from locked-down laptops, or a webhook from GitHub. Tailscale is a private club. It isn’t a public entrance.

Where they overlap, and why that confuses people
The overlap is why beginners end up running all three. Tailscale has a feature called Funnel that publishes one service to the public internet, which is Cloudflare Tunnel’s job. Cloudflare has a VPN-ish client called WARP plus Access policies that can restrict who gets in, which starts to look like Tailscale’s job. And Tailscale has a feature called Serve that gives a service a tidy HTTPS name inside your tailnet, which sounds like a reverse proxy.
These overlaps are real, but they’re edges. For a beginner, it’s much easier to think about the core purpose of each tool:
- Reverse proxy: sorts incoming requests to the right service, handles certificates. Doesn’t make anything reachable.
- Cloudflare Tunnel: makes a service reachable by anyone on the internet, without opening ports. Doesn’t decide who’s allowed.
- Tailscale: makes every service reachable by your own devices, and only them. Doesn’t serve the public.
Common setups that actually make sense
Here’s the part I wish someone had drawn for my colleague. Pick the row that matches who needs access.
Just you, maybe a partner
Tailscale alone. Install it on the server and your devices. Reach services by their Tailscale address or the MagicDNS name. Add a reverse proxy only if you want nicer names and HTTPS, and it can listen purely on the tailnet. No Cloudflare, no port forwarding. This covers most people and it’s what I run for about 90% of my own services.
You plus a public website or two
Tailscale for your private stuff, Cloudflare Tunnel for the public bits. The blog and the shared calendar go through the tunnel. Everything else stays on the tailnet. You can put a reverse proxy behind the tunnel if you have several public services, but with one or two, cloudflared can route by hostname on its own.
Several public services on a line with a real public IP
A reverse proxy with port 443 forwarded, possibly with Tailscale on the side for admin panels. This is the classic setup. You own the whole path, no third party sees your traffic, and you have to take security seriously because your home IP is the front door.
What my colleague actually needed
Jellyfin on his own phone. That’s row one. We removed the tunnel entirely, took the proxy off the path for Jellyfin, and pointed his phone at the Tailscale address. The “everything breaks when I restart anything” problem disappeared, because there was no longer a chain of three services that each had to be up, in order, for one video to play.
The mistake to avoid
The pattern I see most is people stacking tools because each tutorial adds one. You end up with Cloudflare in front of a proxy that points at Tailscale addresses on the same machine. Each hop is another thing to restart, another set of logs, another place for an expired token or a changed IP to break the chain.
Before adding any of these, ask the three questions. Who needs to reach this service? How will their request get to my house? Which service should it land on? If the answer to the first question is “only me,” you probably don’t need a public entrance at all. If the answer is “anyone,” you need either a port forward or a tunnel, and you need to think about who’s allowed in, because neither one decides that for you.
Draw it on a napkin first. It’s a lot easier to erase a line on a napkin than to untangle three containers at midnight.