# Tailscale or Cloudflare Tunnel?

> I need to reach a private box or VPC, or put a service from it online. Is that Tailscale or Cloudflare Tunnel? Not competitors: they point in opposite directions. Tailscale brings your own machines into the private network; Cloudflare Tunnel publishes one service from it to the internet, on your domain, with no open port. Most boxes I run use both.

- A choice between tools from The Stack by Nicolas Dao (Cloudless Labs, Sydney): when to pick each, and when to run both
- Web page: https://cloudlesslabs.com/stack/guides/tailscale-or-tunnel/. The whole stack in one file: https://cloudlesslabs.com/stack/brief.md
- Tools: [Tailscale](https://cloudlesslabs.com/stack/tailscale/index.md) (My default), [Cloudflare Tunnel (cloudflared)](https://cloudlesslabs.com/stack/cloudflare-tunnel/index.md) (My default), [AWS Organizations + IAM Identity Center](https://cloudlesslabs.com/stack/aws-organizations-identity-center/index.md) (My default), [Hostinger VPS](https://cloudlesslabs.com/stack/hostinger-vps/index.md) (My default)

## When to pick which

Pick Tailscale when:

- Your laptops, CI runners or agent boxes need a private database or service in a VPC, with no public address on it.
- SSH to servers with no public port, with access decided by one policy file instead of copied keys.
- Reaching a VPS or a home machine from anywhere, behind any NAT, without opening ports.
- Two networks must talk privately (a VPC and a VPS, two clouds) without a site-to-site VPN.

Pick Cloudflare Tunnel when:

- A service on a private box must be public on your own domain, with no inbound port open.
- A client must see a preview or an internal tool on a real hostname, behind an Access login in the browser.
- Webhooks (Stripe, GitHub) must reach a box that has no public port.
- One server would otherwise need a load balancer and a public IP in front of it.

Both, when:

- On the same box, as the normal setup: services go out through a Tunnel, my machines come in through Tailscale, and no inbound port stays open except a locked-down SSH, or none.
- They don't overlap, so there's nothing to choose between inside one system: one is the way in for your team, the other the way out for the public.

Questions that change the answer:

- Who connects: your own machines and tools, or the public and a client's staff? Your machines means Tailscale; the public means Tunnel.
- Will the people connecting install an agent? Client staff who never will are better served by an Access login in a browser, through a Tunnel.
- Is it HTTP? SSH and databases through a Tunnel need cloudflared on every client, so they belong on Tailscale.
- Must it answer on your own domain? Tailscale Funnel only serves *.ts.net names, on three ports, and is in beta.
- Can a request take longer than 125 seconds, or upload more than 100 MB? Cloudflare cuts those off on the Free and Pro plans.

## The short version

| | Tailscale | Cloudflare Tunnel |
|---|---|---|
| Job | Your machines into the private network | One service out to the internet |
| Direction | Coming in | Going out |
| Who reaches it | Devices on your tailnet, allowed by the policy file | Anyone, or only people who pass an Access login |
| Needs on the client | The Tailscale agent | A browser (non-HTTP needs cloudflared on every client) |
| Protocols | Any: SSH, databases, internal services | HTTP: Cloudflare is the proxy |
| Your own domain | No: Funnel serves *.ts.net only, in beta | Yes |
| Limits to know | Device keys expire after 180 days by default | 125 seconds to answer; 100 MB per request on Free and Pro |
| Price | Standard $8 per user a month; Personal free for non-commercial use | Tunnel free; Access free up to 50 users, then $7 per user a month |
| Pulumi | Official: ACLs, auth keys, devices, DNS | Official: tunnel, routing rules, DNS records, token |
| When it breaks | An expired subnet router cuts everyone off from the VPC | A stopped tunnel leaves its DNS record, and visitors get error 1016 |

Price doesn't decide this one. They do different jobs, and both are cheap next to what they replace: AWS Client VPN in Sydney costs about $110 a month per subnet association before anyone connects.

## Why I run both

The question is which way the traffic goes. Tailscale puts my laptop inside the private network so I can reach a database as if it were local. Tunnel takes one service out of the private network and gives it a public name. Neither does the other's job well, so I don't make them compete.

My own [Hostinger VPS](https://cloudlesslabs.com/stack/hostinger-vps/index.md) is the example. Agents and previews run on it. Public things (a client preview, a webhook receiver) go out through [Cloudflare Tunnel](https://cloudlesslabs.com/stack/cloudflare-tunnel/index.md), with an Access login on anything that isn't for the public. I come in through [Tailscale](https://cloudlesslabs.com/stack/tailscale/index.md). The firewall drops all inbound traffic, so there's no public port to defend.

On AWS it's the same split. One small subnet router in the VPC advertises its range to the tailnet, and a developer, a CI runner or an agent box connects to a private Aurora endpoint. Nothing in the VPC gets a public address, and there's no bastion to patch. If a service from that network must be public, that's a Tunnel's job, not Tailscale's.

Neither one is AWS sign-in. Tailscale decides who can reach the network; [AWS Organizations + IAM Identity Center](https://cloudlesslabs.com/stack/aws-organizations-identity-center/index.md) decides who can touch the account. A client gets both.

## The traps

**A tunnel doesn't close anything.** If the service still listens on 0.0.0.0, it's reachable on the box's public IP, around Cloudflare and around your Access login. Bind every service to 127.0.0.1, drop all inbound traffic (keep your own SSH path first), and allow outbound port 7844 on TCP and UDP for cloudflared.

**A tunnel is an HTTP proxy with Cloudflare's limits.** Answer within 125 seconds or get error 524: return 202 and let the client poll, or stream. Bodies over 100 MB get a 413 on Free and Pro: upload big files straight to R2 or S3 with a presigned URL. Several replicas give failover, not load balancing.

**Keep cloudflared alive and current.** Run it as a system service that restarts on failure, and install it from Cloudflare's package repository: only releases from the past year are supported.

**Tailscale keys expire.** After 180 days a device's connections stop. Authenticate servers and subnet routers with a tagged auth key (tagged devices have expiry disabled by default), and declare the tags and keys in Pulumi.

**Routes and names need wiring.** Advertised routes do nothing until approved: add autoApprovers for the router's tag, and run `tailscale set --accept-routes` on Linux clients (not on the routers). Private hosted zones don't resolve on a laptop: add a split-DNS nameserver pointing at the VPC resolver, and allow port 53 to it.

**One router is one point of failure.** Run a second subnet router in another Availability Zone advertising the same routes.

**The free plan isn't for client work.** Put a client on a Standard plan in their own tailnet, signed in with their identity provider.

Sources, checked on 25 October 2026: [Tailscale pricing](https://tailscale.com/pricing), [subnet routers](https://tailscale.com/kb/1019/subnets), [Tailscale on AWS](https://tailscale.com/docs/reference/reference-architectures/aws), [key expiry](https://tailscale.com/kb/1028/key-expiry), [Cloudflare Tunnel docs](https://developers.cloudflare.com/tunnel/), [tunnel with a firewall](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-with-firewall/), [Zero Trust plans](https://www.cloudflare.com/plans/zero-trust-services/), [Cloudflare One account limits](https://developers.cloudflare.com/cloudflare-one/account-limits/).

## Related

- [Tailscale](https://cloudlesslabs.com/stack/tailscale/index.md): the full entry (verdict, pricing, gotchas)
- [Cloudflare Tunnel (cloudflared)](https://cloudlesslabs.com/stack/cloudflare-tunnel/index.md): the full entry (verdict, pricing, gotchas)
- [AWS Organizations + IAM Identity Center](https://cloudlesslabs.com/stack/aws-organizations-identity-center/index.md): the full entry (verdict, pricing, gotchas)
- [Hostinger VPS](https://cloudlesslabs.com/stack/hostinger-vps/index.md): the full entry (verdict, pricing, gotchas)
- [Every choice between tools](https://cloudlesslabs.com/stack/choices/index.md)
- [Map of every Markdown file on cloudlesslabs.com, with what each one answers](https://ask.cloudlesslabs.com)
