Best Open Source Alternatives to Cloudflare Tunnels 2026
TL;DR
Cloudflare Tunnels expose your local services to the internet without opening firewall ports — but they route all your traffic through Cloudflare's infrastructure. If you want the same capability without Cloudflare dependence, the best open source alternatives use a VPS as your public endpoint: frp (Fast Reverse Proxy, 85K stars) for the most features, rathole for the best performance (Rust, ~12K stars), or Chisel for HTTP-proxy-compatible tunnels. All require a VPS with a public IP.
Key Takeaways
- What Cloudflare Tunnels does: Exposes local services publicly without opening inbound ports
- Why you'd self-host: No Cloudflare dependency, data privacy, no traffic routing through third parties
- What you need: A VPS with a public IP acts as your "Cloudflare" — outbound-only tunnel from your local machine to the VPS
- frp: ~85K stars, Go, MIT — most feature-complete self-hosted tunnel
- rathole: ~12K stars, Rust — best performance, smallest resource footprint
- Chisel: ~12K stars, Go — works through HTTP proxies (useful in restricted networks)
- Use case: Home servers, local dev environments, bypassing CGNAT
How Tunnel Software Works
The pattern is the same for all alternatives:
Internet → VPS (public IP) → Tunnel → Your local machine → Service
Firewall state:
VPS: inbound port 80/443 open (your "edge")
Your machine: outbound only (no inbound ports needed)
Result: home server is publicly accessible without opening home router
This is how Cloudflare Tunnels works: cloudflared on your machine opens outbound-only connections to Cloudflare's edge. Self-hosted versions replace Cloudflare with your own VPS.
You need a VPS with a public IP. Hetzner CX22 at €4.35/month works perfectly.
Comparison
| Tool | Language | License | Stars | Protocol | Best For |
|---|---|---|---|---|---|
| frp | Go | Apache 2.0 | ~85K | TCP/UDP/HTTP | Most use cases |
| rathole | Rust | Apache 2.0 | ~12K | TCP/UDP | Performance-critical |
| Chisel | Go | MIT | ~12K | TCP over HTTP | HTTP proxy environments |
| WireGuard | C/Go | MIT | ~14K | UDP | Full network access |
| Cloudflare Tunnels | Go (cloudflared) | Apache 2.0 | — | QUIC | Managed (Cloudflare infra) |
frp: The Most Feature-Complete Alternative
frp (Fast Reverse Proxy) is the most popular self-hosted tunnel with ~85K GitHub stars. It supports TCP, UDP, HTTP, HTTPS, and STCP (secret TCP), with a built-in dashboard and extensive configuration options.
Architecture
Your local machine runs: frpc (client)
Your VPS runs: frps (server)
frpc → connects outbound to frps
frps → receives connections, routes to frpc
Install frp
# Download latest frp on both your VPS and local machine:
# Get version from: github.com/fatedier/frp/releases
FRP_VERSION="0.61.0"
wget https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz
tar xzf frp_${FRP_VERSION}_linux_amd64.tar.gz
cd frp_${FRP_VERSION}_linux_amd64
VPS: Server Config (frps.toml)
# /etc/frp/frps.toml (on your VPS)
bindPort = 7000 # Port frpc connects to
auth.token = "your-strong-secret-token"
# Optional: Web dashboard
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "your-dashboard-password"
# For HTTP/HTTPS tunnels: your VPS domain
vhostHTTPPort = 80
vhostHTTPSPort = 443
# Run frps as systemd service:
sudo cp frps /usr/local/bin/
sudo tee /etc/systemd/system/frps.service <<EOF
[Unit]
Description=frp Server
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable frps
sudo systemctl start frps
Local: Client Config (frpc.toml)
# ~/frp/frpc.toml (on your local machine)
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-strong-secret-token"
# Expose a local web server on HTTP:
[[proxies]]
name = "myapp-http"
type = "http"
localIP = "127.0.0.1"
localPort = 3000
customDomains = ["app.yourdomain.com"]
# Expose a local HTTPS app:
[[proxies]]
name = "myapp-https"
type = "https"
localIP = "127.0.0.1"
localPort = 3000
customDomains = ["app.yourdomain.com"]
# Expose a raw TCP port (database, SSH, etc.):
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000 # Access via: ssh user@your-vps -p 6000
# Expose a UDP port:
[[proxies]]
name = "game-udp"
type = "udp"
localIP = "127.0.0.1"
localPort = 7000
remotePort = 6001
# Run frpc:
./frpc -c ./frpc.toml
# As a systemd service (Linux) or launchd (macOS):
# See: https://github.com/fatedier/frp#configure-frpc-as-systemd-service
DNS Setup
Point your domain to the VPS:
A app.yourdomain.com → your-vps-ip
frps handles routing incoming requests to the correct frpc tunnel via customDomains.
rathole: Best Performance
rathole is a Rust-based tunnel with ~12K GitHub stars. It uses significantly less CPU and memory than frp, making it ideal for high-throughput scenarios or resource-constrained systems.
Key Differences from frp
- Written in Rust — better performance, lower resource usage
- No dashboard (simpler, but less visibility)
- TOML config only — clean and concise
- Transport options: TCP, TLS, Noise protocol
rathole Setup
Server (server.toml) on VPS:
[server]
bind_addr = "0.0.0.0:2333" # Client connects here
[server.services.myapp]
token = "your-secret-token"
bind_addr = "0.0.0.0:8080" # Public-facing port
Client (client.toml) on local machine:
[client]
remote_addr = "your-vps-ip:2333"
[client.services.myapp]
token = "your-secret-token"
local_addr = "127.0.0.1:3000" # Your local app
# Run:
./rathole server.toml # On VPS
./rathole client.toml # On local machine
With TLS (secure tunnel)
# server.toml
[server]
bind_addr = "0.0.0.0:2333"
[server.transport]
type = "tls"
[server.transport.tls]
pkcs12 = "/path/to/server.pfx"
pkcs12_password = "password"
Chisel: HTTP Proxy Compatible
Chisel (~12K stars) creates TCP tunnels over HTTP or HTTPS. Its superpower: it works through corporate HTTP proxies, making it useful when other tunneling tools are blocked.
# Server (VPS):
./chisel server --port 8080 --auth user:pass --reverse
# Client (local machine):
./chisel client --auth user:pass your-vps-ip:8080 R:0.0.0.0:8080:localhost:3000
# R: = reverse tunnel (public port 8080 → local port 3000)
# Multiple tunnels:
./chisel client --auth user:pass your-vps-ip:8080 \
R:0.0.0.0:80:localhost:3000 \
R:0.0.0.0:443:localhost:3001
WireGuard: Full Network Access
If you want to access your entire home/office network (not just specific services), WireGuard creates a proper VPN tunnel:
# Your local machine connects to VPS via WireGuard
# Traffic routing: local machine → WireGuard VPN → VPS → internet
# This gives the VPS a route to your local machine's private IP
# Useful for: accessing all LAN devices through the VPS, not just specific ports
See our WireGuard vs OpenVPN guide for full WireGuard setup.
Cloudflare Tunnels: When to Stay
Despite the self-hosting options, Cloudflare Tunnels makes sense when:
- Free tier is enough: Personal projects, hobby sites — Cloudflare Tunnels is genuinely free for basic use
- You already use Cloudflare: DNS on Cloudflare + tunnels = zero extra infrastructure cost
- DDoS protection needed: Cloudflare's edge absorbs attacks before they reach your origin
- You don't want to manage a VPS: One less server to maintain
The self-hosted alternatives require a VPS (€4.35–$10/month) that you maintain. The trade-off is control and privacy vs. convenience.
Docker Compose for frp Server
If your VPS already runs Docker:
# On your VPS: docker-compose.yml
services:
frps:
image: snowdreamtech/frps:latest
restart: unless-stopped
volumes:
- ./frps.toml:/etc/frp/frps.toml:ro
ports:
- "7000:7000" # Client connection port
- "7500:7500" # Dashboard
- "80:80" # HTTP tunnels
- "443:443" # HTTPS tunnels
Decision Guide
Use frp if:
→ You want the most features and documentation
→ You need HTTP/HTTPS subdomain routing
→ A web dashboard for visibility is helpful
→ Multiple local services to expose
Use rathole if:
→ Performance is critical
→ Resource-constrained environment
→ You prefer Rust-based tooling
→ Simpler config is preferred
Use Chisel if:
→ You're behind a corporate HTTP proxy
→ Standard VPN ports are blocked
→ HTTP-wrapped tunneling is required
Use WireGuard if:
→ You need access to your entire local network
→ Multiple devices need access, not just one service
→ A full VPN is more appropriate than a tunnel
Stay on Cloudflare Tunnels if:
→ Already using Cloudflare for DNS
→ Free tier covers your needs
→ No privacy concerns with Cloudflare traffic routing
→ DDoS protection from Cloudflare's edge is valuable
See all open source networking and infrastructure tools at OSSAlt.com/categories/networking.