Does this work with Starlink / CG-NAT / mobile hotspots?
Can I use this for site-to-site VPN?
Cloudflare Tunnel vs. Tailscale — which should I use?
References TL;DR: Cloudflare offers two free VPN solutions: WARP (consumer privacy VPN using WireGuard) and Cloudflare Tunnel + Zero Trust (self-hosted VPN replacement for accessing your home network). This guide covers both approaches step-by-step, with Docker Compose configs, split-tunnel setup, and security hardening. Zero Trust is free for up to 50 users — enough for any homelab or small team. Commercial VPN providers make bold promises about privacy, but their centralized architecture creates a fundamental trust problem. You’re routing all your traffic through servers you don’t control, operated by companies whose revenue model depends on subscriber volume — not security audits. ExpressVPN, NordVPN, and Surfshark have all faced scrutiny over logging practices, jurisdiction shopping, and opaque ownership structures. Cloudflare offers a different model. Instead of renting someone else’s VPN, you build your own using Cloudflare’s global Anycast network (330+ data centers in 120+ countries) as the transport layer. The result is a VPN that’s faster than most commercial alternatives, costs nothing, and gives you full control over access policies. There are two distinct approaches, and you might want both: Cloudflare WARP — A consumer VPN app that encrypts your device traffic using WireGuard. Install, toggle on, done. Best for: browsing privacy on public Wi-Fi. Cloudflare Tunnel + Zero Trust — A self-hosted VPN replacement that lets you access your home network (NAS, Proxmox, Pi-hole, Docker services) from anywhere without opening a single firewall port. Best for: homelabbers, remote workers, small teams. WARP is built on the WireGuard protocol — the same modern, lightweight VPN protocol that replaced IPSec and OpenVPN in most serious deployments. When you enable WARP, your device establishes an encrypted tunnel to the nearest Cloudflare data center. From there, your traffic exits onto the internet through Cloudflare’s network. Key technical details: Protocol: WireGuard (via Cloudflare’s BoringTun implementation in Rust) DNS: Queries routed through 1.1.1.1 (Cloudflare’s privacy-first DNS resolver, audited by KPMG) Encryption: ChaCha20-Poly1305 for data, Curve25519 for key exchange Latency impact: Typically 1-5ms added (vs. 20-50ms for most commercial VPNs) because traffic routes to the nearest Anycast PoP No IP selection: WARP doesn’t let you choose exit countries — it’s a privacy tool, not a geo-unblocking tool WARP runs on every major platform through the 1.1.1.1 app: Platform
Install Method Windowsone.one.one.one → Download macOSone.one.one.one → Download iOSApp Store → search “1.1.1.1” AndroidPlay Store → search “1.1.1.1” Linuxcurl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-archive-keyring.gpg && echo "deb [signed-by=/usr/share/keyrings/cloudflare-archive-keyring.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list && sudo apt update && sudo apt install cloudflare-warp After installing, launch the app and toggle WARP on. That’s it. Your DNS queries now go through 1.1.1.1 and your traffic is encrypted to Cloudflare’s edge. FeatureWARP (Free)WARP+ ($)Zero Trust WARP Price$0~$5/monthFree (50 users) EncryptionWireGuardWireGuardWireGuard Speed optimizationStandard routingArgo Smart RoutingStandard routing Private network accessNoNoYes Access policiesNoNoFull ZTNA DNS filteringNoNoGateway policies For most people, free WARP is sufficient for everyday privacy. If you need remote access to your homelab, keep reading — Part 2 is where it gets interesting. This is the setup that replaces WireGuard, OpenVPN, or Tailscale for accessing your home network. The architecture is elegant: a lightweight daemon called cloudflared runs inside your network and maintains an outbound-only encrypted tunnel to Cloudflare. Remote clients connect through Cloudflare’s network using the WARP client. No inbound ports. No dynamic DNS. No exposed IP address. javascript┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐│ Remote Device │ │ Cloudflare Edge │ │ Home Network ││ (WARP Client) │◄───────►│ 330+ PoPs globally │◄───────►│ (cloudflared) ││ │ WireGuard│ │ Outbound │ ││ Phone/Laptop │ Tunnel │ Zero Trust Policies │ Tunnel │ NAS/Docker/LAN │└─────────────────┘ └──────────────────────┘ └─────────────────┘ Create a .env file alongside it: Critical note: Use network_mode: host if you want to route traffic to your entire LAN subnet (192.168.x.0/24). Without it, cloudflared can only reach services within the Docker network. Back in the Zero Trust dashboard, under your tunnel’s Public Hostnames tab: Click Add a public hostname Set subdomain: nas, domain: yourdomain.com Service type: HTTP, URL: localhost:5000 (or wherever your service runs) Cloudflare automatically creates a DNS record. Your NAS is now accessible at https://nas.yourdomain.com — with automatic SSL, DDoS protection, and Cloudflare WAF. This is what turns a simple tunnel into a full VPN replacement. Instead of exposing individual services, you route an entire IP subnet through the tunnel. In Zero Trust dashboard → Networks → Tunnels → your tunnel → Private Networks Add your LAN CIDR: 10.0.0.x/24 (adjust to your subnet) Go to Settings → WARP Client → Split Tunnels Switch to Include mode and add 10.0.0.x/24 Now, any device running the WARP client (enrolled in your Zero Trust org) can access 192.168.1.x addresses as if they were on your home network. SSH into your server, access your NAS web UI, reach your Pi-hole dashboard — all without port forwarding. Install the 1.1.1.1 / WARP app on your phone or laptop Go to Settings → Account → Login to Cloudflare Zero Trust Enter your team name (set during Zero Trust setup) Authenticate with the method you configured (email OTP, Google SSO, GitHub, etc.) Enable Gateway with WARP mode Test it: connect to mobile data (not your home Wi-Fi) and try accessing a LAN IP like http://10.0.0.x. If the router admin page loads, your VPN is working. The “Zero Trust” part of this setup is what separates it from a traditional VPN. Instead of “anyone with the VPN key gets full network access,” you define granular policies: bash`Zero Trust Dashboard → Access → Applications → Add an Application Application type: Self-hostedApplication domain: nas.yourdomain.com Policy: AllowInclude: Emails ending in @yourdomain.com
Require: Country equals United States (optional geo-fence) Session duration: 24 hours` Map each service to a subdomain in the Zero Trust dashboard: grafana.yourdomain.com → http://nginx:3000, code.yourdomain.com → http://nginx:8443, etc. Check Docker logs: docker logs cloudflared-tunnel Verify your token hasn’t been rotated Ensure outbound HTTPS (port 443) isn’t blocked by your router/ISP If behind a corporate firewall, cloudflared also supports HTTP/2 over port 7844 Confirm network_mode: host in Docker Compose (or use macvlan) Check that the CIDR in “Private Networks” matches your actual subnet Verify Split Tunnels are set to Include mode (not Exclude) On the client, run warp-cli settings to verify the private routes are active Double-check your team name in Zero Trust → Settings → Custom Pages Ensure you’ve created a Device enrollment policy under Settings → WARP Client → Device enrollment permissions Allow email domains or specific emails that can enroll ☐ Enable Require Gateway in device enrollment — forces all enrolled devices through Cloudflare Gateway for DNS filtering ☐ Set session duration to 24h or less for sensitive services ☐ Require FIDO2/hardware keys for admin panels (Proxmox, router, etc.) ☐ Enable device posture checks: require screen lock, OS version, disk encryption ☐ Use Service Tokens (not user auth) for machine-to-machine tunnel access ☐ Monitor Access audit logs: Zero Trust → Logs → Access ☐ Never put your tunnel token in a public Git repository — use .env files and .gitignore ☐ Rotate tunnel tokens periodically via the dashboard Yes. Cloudflare Zero Trust offers a free plan that includes tunnels, access policies, and WARP client enrollment for up to 50 users. There are no bandwidth limits on the free tier. Paid plans (starting at $7/user/month) add features like logpush, extended session management, and dedicated egress IPs. Cloudflare terminates TLS at their edge, so they technically could inspect unencrypted HTTP traffic passing through the tunnel. For HTTPS services, end-to-end encryption between your browser and origin server means Cloudflare sees metadata (domain, timing) but not content. If this is a concern, use WireGuard for a fully self-hosted solution where no third party touches your packets. Yes — this is one of Cloudflare Tunnel’s biggest advantages. Since the tunnel is outbound-only, it works behind any NAT, including carrier-grade NAT (CG-NAT) used by Starlink, T-Mobile Home Internet, and most 4G/5G connections. No port forwarding needed. Yes, using WARP Connector (currently in beta). Install cloudflared with WARP Connector mode on a device at each site, and Cloudflare routes traffic between subnets. This replaces traditional IPSec site-to-site tunnels. Use Tailscale if your primary need is device-to-device mesh networking (see also our guide on home network segmentation with OPNsense) (accessing any device from any other device). Use Cloudflare Tunnel if you want to expose web services with automatic HTTPS and DDoS protection, or if you need granular ZTNA policies. Many homelabbers use both: Tailscale for device mesh, Cloudflare Tunnel for public-facing services. Cloudflare. “Connect private networks.” Cloudflare One Documentation, 2026. Cloudflare. “Cloudflare Tunnel setup guide.” Cloudflare Developers, 2026. Donenfeld, Jason A. “WireGuard: Next Generation Kernel Network Tunnel.” NDSS Symposium, 2017. Cloudflare. “Introducing WARP: Fixing Mobile Internet Performance and Security.” Cloudflare Blog, 2019. Ward, Brendan and Harris, Rustam. “BoringTun: a userspace WireGuard implementation in Rust.” Cloudflare Blog, 2019. Google. “BeyondCorp: A New Approach to Enterprise Security.” Google Cloud, 2014. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse
Command
Copy
$
Prerequisites - A **Cloudflare account** (free tier works) - A **domain name** with DNS managed by Cloudflare (required for tunnel management) - A server on your home network — any Linux box, Raspberry Pi, Synology NAS, or even a Docker container on TrueNAS - **Docker + Docker Compose** (recommended) or bare-metal `cloudflared` installation
Step 1: Create a Tunnel in the Zero Trust Dashboard - Go to [one.dash.cloudflare.com](https://one.dash.cloudflare.com/) → Networks → Tunnels - Click **Create a tunnel** - Select **Cloudflared** as the connector type - Name your tunnel (e.g., `homelab-tunnel`) - Copy the **tunnel token** — you’ll need this for the Docker config
Step 2: Deploy cloudflared with Docker Compose Create a `docker-compose.yml` on your home server:
Command
Copy
$
Prerequisites - A **Cloudflare account** (free tier works) - A **domain name** with DNS managed by Cloudflare (required for tunnel management) - A server on your home network — any Linux box, Raspberry Pi, Synology NAS, or even a Docker container on TrueNAS - **Docker + Docker Compose** (recommended) or bare-metal `cloudflared` installation
Step 1: Create a Tunnel in the Zero Trust Dashboard - Go to [one.dash.cloudflare.com](https://one.dash.cloudflare.com/) → Networks → Tunnels - Click **Create a tunnel** - Select **Cloudflared** as the connector type - Name your tunnel (e.g., `homelab-tunnel`) - Copy the **tunnel token** — you’ll need this for the Docker config
Step 2: Deploy cloudflared with Docker Compose Create a `docker-compose.yml` on your home server:
Command
Copy
$
Prerequisites - A **Cloudflare account** (free tier works) - A **domain name** with DNS managed by Cloudflare (required for tunnel management) - A server on your home network — any Linux box, Raspberry Pi, Synology NAS, or even a Docker container on TrueNAS - **Docker + Docker Compose** (recommended) or bare-metal `cloudflared` installation
Step 1: Create a Tunnel in the Zero Trust Dashboard - Go to [one.dash.cloudflare.com](https://one.dash.cloudflare.com/) → Networks → Tunnels - Click **Create a tunnel** - Select **Cloudflared** as the connector type - Name your tunnel (e.g., `homelab-tunnel`) - Copy the **tunnel token** — you’ll need this for the Docker config
Step 2: Deploy cloudflared with Docker Compose Create a `docker-compose.yml` on your home server:
Command
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
You can create different policies per service. Your Proxmox admin panel might require hardware key (FIDO2) authentication, while your Jellyfin media server only needs email OTP. This is **Zero Trust Network Access (ZTNA)** — the same architecture that Google BeyondCorp and Microsoft Entra use internally.
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
You can create different policies per service. Your Proxmox admin panel might require hardware key (FIDO2) authentication, while your Jellyfin media server only needs email OTP. This is **Zero Trust Network Access (ZTNA)** — the same architecture that Google BeyondCorp and Microsoft Entra use internally.
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel`
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel`
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel` - Cloudflare WARP — A consumer VPN app that encrypts your device traffic using WireGuard. Install, toggle on, done. Best for: browsing privacy on public Wi-Fi.
- Cloudflare Tunnel + Zero Trust — A self-hosted VPN replacement that lets you access your home network (NAS, Proxmox, Pi-hole, Docker services) from anywhere without opening a single firewall port. Best for: homelabbers, remote workers, small teams. - Protocol: WireGuard (via Cloudflare’s BoringTun implementation in Rust)
- DNS: Queries routed through 1.1.1.1 (Cloudflare’s privacy-first DNS resolver, audited by KPMG)
- Encryption: ChaCha20-Poly1305 for data, Curve25519 for key exchange
- Latency impact: Typically 1-5ms added (vs. 20-50ms for most commercial VPNs) because traffic routes to the nearest Anycast PoP
- No IP selection: WARP doesn’t let you choose exit countries — it’s a privacy tool, not a geo-unblocking tool - Click Add a public hostname
- Set subdomain: nas, domain: yourdomain.com
- Service type: HTTP, URL: localhost:5000 (or wherever your service runs) - In Zero Trust dashboard → Networks → Tunnels → your tunnel → Private Networks
- Add your LAN CIDR: 10.0.0.x/24 (adjust to your subnet)
- Go to Settings → WARP Client → Split Tunnels
- Switch to Include mode and add 10.0.0.x/24 - Install the 1.1.1.1 / WARP app on your phone or laptop
- Go to Settings → Account → Login to Cloudflare Zero Trust
- Enter your team name (set during Zero Trust setup)
- Authenticate with the method you configured (email OTP, Google SSO, GitHub, etc.)
- Enable Gateway with WARP mode - Check Docker logs: docker logs cloudflared-tunnel
- Verify your token hasn’t been rotated
- Ensure outbound HTTPS (port 443) isn’t blocked by your router/ISP
- If behind a corporate firewall, cloudflared also supports HTTP/2 over port 7844 - Confirm network_mode: host in Docker Compose (or use macvlan)
- Check that the CIDR in “Private Networks” matches your actual subnet
- Verify Split Tunnels are set to Include mode (not Exclude)
- On the client, run warp-cli settings to verify the private routes are active - Double-check your team name in Zero Trust → Settings → Custom Pages
- Ensure you’ve created a Device enrollment policy under Settings → WARP Client → Device enrollment permissions
- Allow email domains or specific emails that can enroll - ☐ Enable Require Gateway in device enrollment — forces all enrolled devices through Cloudflare Gateway for DNS filtering
- ☐ Set session duration to 24h or less for sensitive services
- ☐ Require FIDO2/hardware keys for admin panels (Proxmox, router, etc.)
- ☐ Enable device posture checks: require screen lock, OS version, disk encryption
- ☐ Use Service Tokens (not user auth) for machine-to-machine tunnel access
- ☐ Monitor Access audit logs: Zero Trust → Logs → Access
- ☐ Never put your tunnel token in a public Git repository — use .env files and .gitignore
- ☐ Rotate tunnel tokens periodically via the dashboard - Cloudflare. “Connect private networks.” Cloudflare One Documentation, 2026.
- Cloudflare. “Cloudflare Tunnel setup guide.” Cloudflare Developers, 2026.
- Donenfeld, Jason A. “WireGuard: Next Generation Kernel Network Tunnel.” NDSS Symposium, 2017.
- Cloudflare. “Introducing WARP: Fixing Mobile Internet Performance and Security.” Cloudflare Blog, 2019.
- Ward, Brendan and Harris, Rustam. “BoringTun: a userspace WireGuard implementation in Rust.” Cloudflare Blog, 2019.
- Google. “BeyondCorp: A New Approach to Enterprise Security.” Google Cloud, 2014." style="background: linear-gradient(135deg, #6a5acd 0%, #5a4abd 100%); color: #fff; border: none; padding: 6px 12px; border-radius: 8px; cursor: pointer; font-size: 12px; font-weight: 600; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); display: flex; align-items: center; gap: 8px; box-shadow: 0 4px 12px rgba(106, 90, 205, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1); position: relative; overflow: hidden;">Copy
$ `version: "3.8"
services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared-tunnel-weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} network_mode: host # Required for private network routing # Example: expose a local -weight: 500;">service whoami: image: traefik/whoami container_name: whoami ports: - "8080:80"`
`version: "3.8"
services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared-tunnel-weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} network_mode: host # Required for private network routing # Example: expose a local -weight: 500;">service whoami: image: traefik/whoami container_name: whoami ports: - "8080:80"`
`version: "3.8"
services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared-tunnel-weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} network_mode: host # Required for private network routing # Example: expose a local -weight: 500;">service whoami: image: traefik/whoami container_name: whoami ports: - "8080:80"`
`TUNNEL_TOKEN=eyJhIjoiYWJj...your-token-here`
`TUNNEL_TOKEN=eyJhIjoiYWJj...your-token-here`
`TUNNEL_TOKEN=eyJhIjoiYWJj...your-token-here`
`-weight: 500;">docker compose up -d-weight: 500;">docker logs cloudflared-tunnel # Should show "Connection registered"`
`-weight: 500;">docker compose up -d-weight: 500;">docker logs cloudflared-tunnel # Should show "Connection registered"`
`-weight: 500;">docker compose up -d-weight: 500;">docker logs cloudflared-tunnel # Should show "Connection registered"`
You can create different policies per -weight: 500;">service. Your Proxmox admin panel might require hardware key (FIDO2) authentication, while your Jellyfin media server only needs email OTP. This is **Zero Trust Network Access (ZTNA)** — the same architecture that Google BeyondCorp and Microsoft Entra use internally.
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
You can create different policies per -weight: 500;">service. Your Proxmox admin panel might require hardware key (FIDO2) authentication, while your Jellyfin media server only needs email OTP. This is **Zero Trust Network Access (ZTNA)** — the same architecture that Google BeyondCorp and Microsoft Entra use internally.
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
You can create different policies per -weight: 500;">service. Your Proxmox admin panel might require hardware key (FIDO2) authentication, while your Jellyfin media server only needs email OTP. This is **Zero Trust Network Access (ZTNA)** — the same architecture that Google BeyondCorp and Microsoft Entra use internally.
Cloudflare Tunnel vs. Alternatives: Honest Comparison Feature
Cloudflare Tunnel
WireGuard
Tailscale
OpenVPN Price
Free (50 users)
Free
Free (100 devices)
Free Open ports required
None
1 UDP port
None
1 UDP/TCP port Setup complexity
Medium
Medium-High
Low
High Works behind CG-NAT
Yes
Needs port forward
Yes
Needs port forward Access control
Full ZTNA policies
Key-based only
ACLs + SSO
Cert-based DDoS protection
Yes (Cloudflare)
No
No
No SSL/TLS termination
Automatic
N/A
N/A
Manual Trust model
Trust Cloudflare
Self-hosted
Trust Tailscale
Self-hosted Best for
Web services + LAN
Pure privacy
Mesh networking
Enterprise legacy **The honest tradeoff**: Cloudflare Tunnel routes your traffic through Cloudflare’s infrastructure. If you fundamentally distrust any third party touching your packets, self-hosted WireGuard is the purist choice. But for most homelabbers, the convenience of zero open ports + free DDoS protection + granular access policies makes Cloudflare Tunnel the pragmatic winner.
Advanced: Multi-Service Docker Stack Here’s a production-grade Docker Compose that exposes multiple services through a single tunnel:
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared -weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel`
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared -weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel`
`version: "3.8" services: cloudflared: image: cloudflare/cloudflared:latest container_name: cloudflared -weight: 500;">restart: unless-stopped command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN} networks: - tunnel depends_on: - nginx nginx: image: nginx:alpine container_name: nginx-proxy volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - tunnel # Add your services here — they just need to be on the 'tunnel' network # Configure public hostnames in the CF dashboard to point to nginx networks: tunnel: name: cf-tunnel` - Cloudflare WARP — A consumer VPN app that encrypts your device traffic using WireGuard. Install, toggle on, done. Best for: browsing privacy on public Wi-Fi.
- Cloudflare Tunnel + Zero Trust — A self-hosted VPN replacement that lets you access your home network (NAS, Proxmox, Pi-hole, Docker services) from anywhere without opening a single firewall port. Best for: homelabbers, remote workers, small teams. - Protocol: WireGuard (via Cloudflare’s BoringTun implementation in Rust)
- DNS: Queries routed through 1.1.1.1 (Cloudflare’s privacy-first DNS resolver, audited by KPMG)
- Encryption: ChaCha20-Poly1305 for data, Curve25519 for key exchange
- Latency impact: Typically 1-5ms added (vs. 20-50ms for most commercial VPNs) because traffic routes to the nearest Anycast PoP
- No IP selection: WARP doesn’t let you choose exit countries — it’s a privacy tool, not a geo-unblocking tool - Click Add a public hostname
- Set subdomain: nas, domain: yourdomain.com
- Service type: HTTP, URL: localhost:5000 (or wherever your -weight: 500;">service runs) - In Zero Trust dashboard → Networks → Tunnels → your tunnel → Private Networks
- Add your LAN CIDR: 10.0.0.x/24 (adjust to your subnet)
- Go to Settings → WARP Client → Split Tunnels
- Switch to Include mode and add 10.0.0.x/24 - Install the 1.1.1.1 / WARP app on your phone or laptop
- Go to Settings → Account → Login to Cloudflare Zero Trust
- Enter your team name (set during Zero Trust setup)
- Authenticate with the method you configured (email OTP, Google SSO, GitHub, etc.)
- Enable Gateway with WARP mode - Check Docker logs: -weight: 500;">docker logs cloudflared-tunnel
- Verify your token hasn’t been rotated
- Ensure outbound HTTPS (port 443) isn’t blocked by your router/ISP
- If behind a corporate firewall, cloudflared also supports HTTP/2 over port 7844 - Confirm network_mode: host in Docker Compose (or use macvlan)
- Check that the CIDR in “Private Networks” matches your actual subnet
- Verify Split Tunnels are set to Include mode (not Exclude)
- On the client, run warp-cli settings to verify the private routes are active - Double-check your team name in Zero Trust → Settings → Custom Pages
- Ensure you’ve created a Device enrollment policy under Settings → WARP Client → Device enrollment permissions
- Allow email domains or specific emails that can enroll - ☐ Enable Require Gateway in device enrollment — forces all enrolled devices through Cloudflare Gateway for DNS filtering
- ☐ Set session duration to 24h or less for sensitive services
- ☐ Require FIDO2/hardware keys for admin panels (Proxmox, router, etc.)
- ☐ Enable device posture checks: require screen lock, OS version, disk encryption
- ☐ Use Service Tokens (not user auth) for machine-to-machine tunnel access
- ☐ Monitor Access audit logs: Zero Trust → Logs → Access
- ☐ Never put your tunnel token in a public Git repository — use .env files and .gitignore
- ☐ Rotate tunnel tokens periodically via the dashboard - Cloudflare. “Connect private networks.” Cloudflare One Documentation, 2026.
- Cloudflare. “Cloudflare Tunnel setup guide.” Cloudflare Developers, 2026.
- Donenfeld, Jason A. “WireGuard: Next Generation Kernel Network Tunnel.” NDSS Symposium, 2017.
- Cloudflare. “Introducing WARP: Fixing Mobile Internet Performance and Security.” Cloudflare Blog, 2019.
- Ward, Brendan and Harris, Rustam. “BoringTun: a userspace WireGuard implementation in Rust.” Cloudflare Blog, 2019.
- Google. “BeyondCorp: A New Approach to Enterprise Security.” Google Cloud, 2014.