Cloudflare Tunnel: The Free Tool That Killed My Hosting Bill
I spent three months paying for VPS hosting before discovering that Cloudflare will connect any machine to the internet for free. No public IP required. No port forwarding. No dynamic DNS hacks. Just a daemon that runs on your box and a five-line config file.
This is the most underutilized tool in the solo builder stack.
What Cloudflare Tunnel Actually Does
Your home internet doesn’t give you a public IP. Your ISP uses CGNAT – carrier-grade NAT – which means a hundred households share one public address. No one on the internet can reach your machine. Every self-hosting guide stops here and says “get a VPS.”
Cloudflare Tunnel solves this by flipping the connection. Instead of the internet reaching in to your machine, your machine reaches out to Cloudflare. The tunnel daemon (cloudflared) establishes persistent outbound QUIC connections to Cloudflare’s edge network. When traffic arrives for your domain, Cloudflare routes it through the tunnel to your machine.
From the outside, it’s indistinguishable from a server in a data center. Your visitors get Cloudflare’s global CDN, automatic HTTPS, and DDoS protection. You get to run your server on whatever hardware you want, wherever you want.
The Setup (Ten Minutes, No Tricks)
1. Install cloudflared
On Mac:
brew install cloudflaredOn Linux:
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared2. Add Your Domain to Cloudflare
Go to dash.cloudflare.com, add your domain, and change its nameservers to the ones Cloudflare gives you. This takes a few minutes to propagate.
3. Authenticate
cloudflared tunnel loginThis opens a browser window. Pick your domain. A certificate gets saved to ~/.cloudflared/cert.pem.
4. Create a Named Tunnel
cloudflared tunnel create my-siteThis generates a tunnel ID and credentials file. One tunnel can serve multiple domains.
5. Route Your Domain
cloudflared tunnel route dns my-site example.comThis creates a CNAME record in Cloudflare DNS pointing your domain to the tunnel.
6. Configure and Run
Create ~/.cloudflared/config.yml:
tunnel: YOUR-TUNNEL-ID
credentials-file: /path/to/credentials.json
ingress:
- hostname: example.com
service: http://localhost:2368
- hostname: www.example.com
service: http://localhost:2368
- service: http_status:404Then run it:
cloudflared tunnel run my-siteThat’s it. Your domain now serves whatever is running on localhost:2368.
Making It Survive Reboots
On Linux, cloudflared has a built-in service installer. On Mac, create a LaunchAgent:
Save this as ~/Library/LaunchAgents/com.cloudflare.tunnel.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.cloudflare.tunnel</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/cloudflared</string>
<string>tunnel</string>
<string>run</string>
<string>my-site</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>Load it: launchctl load ~/Library/LaunchAgents/com.cloudflare.tunnel.plist
KeepAlive means macOS restarts the tunnel automatically if it crashes. I tested this – killed the process, and it was back in under five seconds.
Performance: 150ms From My Living Room
I was skeptical about latency. Satellite internet (Starlink) already adds 30-50ms. A tunnel adds overhead. How bad could it get?
Measured TTFB (time to first byte) over multiple requests: - Average: 250-300ms - Best: 146ms - Worst: 360ms
For a content site, this is fine. Cloudflare caches static assets at the edge, so repeat visitors get sub-50ms responses from the CDN without even hitting your machine.
For comparison, a typical cheap VPS serves pages in 100-200ms. You’re giving up maybe 100ms of latency in exchange for owning your infrastructure and paying zero monthly hosting fees.
What You Can’t Do (The Honest Limits)
Cloudflare Tunnel on the free tier does not proxy: - SMTP (port 25) – No self-hosted email behind a tunnel - Raw TCP/UDP – No game servers, no custom protocols - SIP/RTP – No VoIP telephony
For email, you still need a machine with a public IP. A $3/month VPS handles this fine.
For everything else – web apps, APIs, databases, dashboards, CMS platforms, static sites, webhooks – the tunnel works perfectly.
Multiple Sites, One Tunnel
A single tunnel can serve unlimited domains. Just add more ingress rules:
ingress:
- hostname: blog.example.com
service: http://localhost:2368
- hostname: analytics.example.com
service: http://localhost:3001
- hostname: app.example.com
service: http://localhost:3000
- service: http_status:404Each domain runs on a different port locally. The tunnel routes based on hostname. Add a new site by adding three lines to the config and restarting the tunnel.
Why This Matters for Solo Builders
The hosting tax is real. $20-50/month for a VPS, $10-20/month for managed hosting, $5-15/month for DNS and SSL. It adds up before you’ve earned a dollar.
Cloudflare Tunnel makes self-hosting practical for anyone with a spare computer and an internet connection. Not practical in the “it technically works if you babysit it” sense. Practical in the “I set it up once and forgot about it” sense.
The tunnel runs. The site serves. The bill doesn’t come.
That’s the stack.