HomeTechOps

Backups & Storage

Tailscale vs Cloudflare Tunnel for home remote access

Tailscale and Cloudflare Tunnel solve different problems even though both let you reach your home from outside without opening router ports. Tailscale is a mesh VPN — every device that needs to reach your home installs a client, and you get full LAN access with WireGuard-direct peer-to-peer connections. Cloudflare Tunnel is a reverse tunnel — your home server runs a `cloudflared` daemon that maintains an outbound connection to Cloudflare's edge, and your services become public HTTPS URLs that anyone with the link can reach. Most operators end up needing both: Tailscale for admin/SSH/SMB, Cloudflare Tunnel for anything you want a non-technical visitor to reach via a normal web link.

What a real Tailscale tailnet looks like in the admin console

Reference images and diagrams. Click any image to view full resolution.

Tailscale admin console at login.tailscale.com/admin/machines showing a real 5-device tailnet: a Linux Unraid NAS, two iOS devices, a Windows 11 desktop, and a macOS laptop. Each row shows the 100.x.y.z CGNAT address, the Tailscale client version, OS, and online/last-seen state. The desktop row has a 'Funnel' tag visible; the Unraid row has 'Expiry disabled' set.
Real Tailscale admin console (captured 2026-05-19 from a working home tailnet). Operator evidence visible: (1) the 100.64.0.0/10 CGNAT address space every Tailscale node lives in — these IPs are private to the tailnet, not internet-routable; (2) the per-row 'Funnel' tag on the Windows desktop, which is how you opt a single machine into public *.ts.net access without exposing the whole tailnet; (3) 'Expiry disabled' on the Unraid NAS — set for headless servers so the auth key doesn't expire mid-night and break remote access; (4) mixed-OS tailnet with Unraid + iOS + Windows + macOS clients all peering, which is the actual common shape for a home operator's mesh.

Who this is for

Home operators running services on a NAS (Synology / Unraid / TrueNAS Scale / QNAP) who need to reach them from outside — admin SSH, Home Assistant, Plex, SMB file shares, public dashboards, or family-shareable links. Choosing between Tailscale (mesh VPN), Cloudflare Tunnel (reverse proxy to CF edge), or both.

Outcome

A working remote-access setup using one or both tools, with the right tool serving the right service: Tailscale for admin/SSH/SMB/streaming, Cloudflare Tunnel for public-shareable web links. Failure modes catalogued and known by the operator before they hit them.

Required inputs

  • A NAS (or other always-on home server) that can install Tailscale and/or Cloudflared.
  • A free Tailscale account (tailscale.com) and/or a free Cloudflare account with a domain managed on Cloudflare DNS.
  • Outbound internet from the home (both tools work behind CGNAT — see /fix/cgnat-home-access-no-public-ip if unsure).
  • Decision on what services need public access vs admin-only access.
GuideFollow in order

Step-by-step procedure

1

Decide which tool fits each service before installing anything

Do: List every service you need remote access to. For each: is it admin-only (you only), small group (you + family with clients), or public-shareable (anyone with the link)? Admin-only → Tailscale. Public-shareable → Cloudflare Tunnel. Family group → either, with Cloudflare's 50-seat free tier being more generous than Tailscale's 6-user limit.

Expected result: A list with service name → recommended tool annotation.

If not: If you're unsure, default to Tailscale for the first install — it's easier to add Cloudflare Tunnel later than to remove Cloudflare Tunnel access from a public hostname after sharing the URL.

2

Install Tailscale on the NAS

Do: Synology: Package Center > Tailscale > Install + the boot-time `configure-host` Task Scheduler script. Unraid: Apps > Tailscale plugin > Settings > authenticate. TrueNAS Scale: Apps > Discover Apps > Tailscale > Install + paste auth key.

Expected result: `tailscale status` shows the NAS connected with a Tailscale IP in 100.x.y.z range. Other Tailscale clients can ping that IP.

If not: On Synology, the most common issue is the boot-time configure-host script not surviving package update — re-run from Task Scheduler if `tailscale status` shows degraded connectivity after a Tailscale upgrade.

3

Install Tailscale on every device that needs admin access

Do: Phone (iOS / Android app), laptop (Windows / macOS / Linux client), work computer. Sign in with the same account. Confirm each device appears in the admin console at login.tailscale.com.

Expected result: Tailnet shows all devices. SSH to NAS by Tailscale IP works from a phone on cellular.

If not: If devices show but can't reach each other, check ACLs in the admin console — the default policy allows full mesh but a custom ACL may have locked it down.

4

Tighten the Tailscale ACL before sharing with anyone else

Do: Admin console > Access Controls > edit the ACL JSON. Add tags for device groups (`tag:nas`, `tag:admin`), define users, restrict who can reach what. The default 'autogroup:member' allows full mesh — replace with least-privilege rules before adding family/external users.

Expected result: Family members added (via email invite) can only reach the services you specified, not the full LAN.

If not: Skip this only if you're the sole user and accept that any compromised device on your tailnet reaches everything.

5

Install Cloudflared on the NAS for public-shareable services

Do: Cloudflare Zero Trust dashboard > Networks > Tunnels > Create tunnel > Cloudflared. Choose Docker. Copy the docker run command (contains the tunnel token). Run on the NAS via Container Manager (Synology) / Community Apps (Unraid) / Apps catalog (TrueNAS Scale).

Expected result: Cloudflare Zero Trust dashboard shows the tunnel as 'Connected'. cloudflared logs show outbound TLS to CF edge.

If not: If tunnel won't connect, check outbound 443 isn't blocked by an upstream firewall — cloudflared has no listening port, only outbound TLS.

6

Create public hostnames in the Cloudflare Tunnel — with Access policies

Do: CF dashboard > tunnel > Public Hostname > add subdomain → service URL (e.g. `https://nas.local:5001` with noTLSVerify if self-signed). For each hostname, attach a Cloudflare Access policy (email allow-list, Google/GitHub SSO, OTP) before going live — without one, the subdomain is publicly reachable.

Expected result: `https://service.example.com` loads from a cellular connection; Access policy challenges unauthenticated visitors.

If not: If the subdomain returns 502 from CF edge, the tunnel is reaching CF but cloudflared can't reach the local service — verify the service is listening on the URL specified in the hostname config.

7

Test failure modes you'll hit later (so you know what to do)

Do: Test Nextcloud / Immich large-file upload through Cloudflare Tunnel — confirm the 100 MB cap is the bottleneck. Test SMB through Cloudflare Tunnel — confirm it doesn't work cleanly. Test Plex remote streaming through Cloudflare Tunnel — note quality/latency.

Expected result: Files over 100 MB fail through Cloudflare Tunnel (proxied HTTP path), and SMB is unreliable. These are expected. They're why you also installed Tailscale.

If not: If Cloudflare Tunnel handles large uploads fine, you're either on Business+ tier or your specific upload path bypasses the proxy — verify with the actual file sync you'll run in production.

Commands and settings paths

Verify Tailscale connectivity from the NAS

tailscale status

Where: SSH to NAS (or DSM Task Scheduler one-shot script).

Expected: All tailnet peers listed with relay status (`direct` is best; `relay` via DERP is acceptable but adds latency).

Failure means: If status shows the NAS as 'logged out', the tailscaled service isn't running.

Safe next step: Restart: `sudo systemctl restart tailscaled` (Linux) or via Tailscale package UI (DSM).

Verify Cloudflare Tunnel connection state

cloudflared tunnel info <tunnel-name>

Where: On a workstation with cloudflared CLI + auth, or in the Cloudflare Zero Trust dashboard > Networks > Tunnels.

Expected: Tunnel shows 'Connected' with at least one active connector. Dashboard shows recent requests if the hostname has been visited.

Failure means: Tunnel disconnected = cloudflared isn't reaching CF edge — usually outbound 443 blocked or the token is invalid.

Safe next step: Restart the cloudflared container; check container logs for auth errors; regenerate the tunnel token from CF dashboard if needed.

Evidence to record

  • Tailscale admin console screenshot showing all your devices listed with tags + ACL state.
  • Cloudflare Zero Trust dashboard screenshot showing tunnel status: Connected + list of public hostnames with Access policies.
  • Test result log: from cellular, can SSH to NAS via Tailscale IP; from cellular, can hit public hostname via Cloudflare Tunnel.
  • Capture of the failure modes for your reference: 100 MB upload limit hit, SMB-over-Tunnel attempt.

Common mistakes

  • Treating Cloudflare Tunnel as the one-tool solution and trying to route SMB/Plex/large uploads through it — both will frustrate. Cloudflare Tunnel is for HTTPS web UIs, not arbitrary protocols.
  • Forgetting to attach an Access policy to a Cloudflare Tunnel public hostname — the subdomain is then publicly reachable to anyone who finds it (Certificate Transparency logs make subdomains discoverable).
  • Leaving the default Tailscale 'full mesh' ACL in place after adding family/external users to the tailnet — they can reach every device, not just the ones you intend.
  • Trusting Cloudflare Tunnel for personal video streaming (Plex/Jellyfin) — Cloudflare's CDN terms restrict non-CF-hosted video; multiple operators report account warnings.

Stop points

  • Stop before exposing any home service via Cloudflare Tunnel without attaching an Access policy — even 'just a status page' becomes a public attack surface without authentication.
  • Stop before granting Tailscale tailnet access to a family member without first writing the ACL to limit what they can reach — the default policy is full mesh.
  • Stop before relying on Tailscale Funnel for free-tier use if your usage is bandwidth-heavy or pattern-public — Funnel availability on free is contested and Tailscale may rate-limit.

Last reviewed

2026-05-18

Source-backed checks

HomeTechOps turns official docs and conservative safety rules into a shorter runbook. These links are the source trail for the page direction.