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 cloudflared

On Linux:

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared

2. 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 login

This opens a browser window. Pick your domain. A certificate gets saved to ~/.cloudflared/cert.pem.

4. Create a Named Tunnel

cloudflared tunnel create my-site

This generates a tunnel ID and credentials file. One tunnel can serve multiple domains.

5. Route Your Domain

cloudflared tunnel route dns my-site example.com

This 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:404

Then run it:

cloudflared tunnel run my-site

That’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:404

Each 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.