← Blog

Cloudflare Tunnels and Tailscale, and when each one wins

Contents
  1. What each thing actually is
  2. Why Cloudflare wins for me
  3. Where I still use Tailscale
  4. The trade-off I didn't see at first

I have both Cloudflare Tunnels and Tailscale running on the Mac Mini under my desk. The two tools overlap a lot in the "reach my hardware from anywhere" space, and I see them confused often. They actually solve different problems. Once I'd been running both for a few months it stopped being close.

For my personal infra, Cloudflare Tunnels does almost all the work.

#What each thing actually is

Tailscale is a mesh VPN. It installs a client on every device you own, gives each one a static private IP on your tailnet, and routes encrypted traffic between them. Apple laptop, Mac Mini, phone, work machine, all on the same flat network as if they were in the same room. Great for "my devices reach my devices."

Cloudflare Tunnels are the opposite shape. The Mac Mini opens an outbound connection to Cloudflare's edge. Cloudflare gets a public hostname (yash.voltade.com) and routes anything hitting it back down the tunnel to localhost:3000 on the Mini. No client on the requester's end. Just a browser. With Cloudflare Access bolted on top, you also get email-based SSO in front of it for free.

So: Tailscale equals my devices ↔ my devices. Cloudflare Tunnels equals the whole internet (gated by SSO) β†’ my devices.

#Why Cloudflare wins for me

Most of what I want to do from outside my flat falls into the second shape, not the first.

I want to use Open WebUI on my phone in a cafe. I want a friend to be able to hit a tool I'm running on the Mini without installing anything. I want the URL I shared yesterday to keep working when my laptop is closed. None of that is "my devices ↔ my devices." All of it is "browser β†’ my hardware, gated by SSO."

A few specific things I keep coming back to:

  1. Zero client install on the requester side. My phone, my browser, a friend's laptop, none of them need anything. Just navigate to the URL, do the email code, you're in.
  2. No exposed ports. The Mini connects out. My router never opens a port. This is also true for the SSH tunnel I run, ssh mini goes through ssh-yash.voltade.com, not a port I forwarded.
  3. DNS, TLS, and SSO in one place. Cloudflare already manages voltade.com. Adding a subdomain, a cert, and an Access policy is a few clicks. Tailscale's MagicDNS is great but the auth model is "you're on my tailnet or you're not."
  4. Friends and teammates can be added by email. Granting access to someone outside my devices on Tailscale means inviting them onto my tailnet, which is more sharing than I want for one demo.

#Where I still use Tailscale

Tailscale isn't off my machines. It still wins for two things:

  • SSH between my own machines without thinking about it. When I'm on home Wi-Fi I can ssh mini.local over the LAN. When I'm not, Tailscale's mini hostname just works. I could do this entirely over the Cloudflare tunnel and in fact I have mini-remote configured in ~/.ssh/config for exactly that, but Tailscale is one fewer hop.
  • Anything that should never have a public URL. Internal experiments, a database I haven't put auth on yet, a port that should only ever be reachable from a device I own. Tailscale's default-deny mesh is the right shape for that.

#The trade-off I didn't see at first

The reason I lean Cloudflare-first now isn't speed or features. It's that a public URL with SSO is a different kind of artefact than a private IP. The URL is something I can drop into a message. I can revoke it. I can add a teammate by email in two clicks. The private IP only exists on a network I curate.

For personal infrastructure I want to actually use, share, and revoke, the public-URL-with-SSO shape is the right default. Tailscale stays installed for the cases where the answer to "should this exist on a public URL?" is no.

That distinction matters more than the protocol details.