Cloudflare Tunnel as the Indie Developer's Public IP

There is a specific moment in a solo developer's life when you build something on your laptop or your home server and realize you want other people to use it. A friend wants to try the demo. A client wants to see the prototype. You want a webhook to land on your machine. You want to expose your local Streamlit app at a real URL.

Historically, this has been a terrible experience. NAT, dynamic IPs, port forwarding, dynamic DNS, SSL certificates, firewall rules — six things that all have to work simultaneously, and that all break in different ways. Most solo developers respond to this by deploying somewhere else, paying for a VPS or a managed platform, even when their local machine has 10x the compute they actually need.

Cloudflare Tunnel ended that. This post is the working guide — what it is, how it differs from the older options, the setup, and the operational patterns that make it usable as production infrastructure for a personal stack.

The broader picture of how this fits with the rest of the solo-builder toolchain is in Why Snowflake's Bet on Streamlit Just Works.

What the old options actually cost

Before getting to Cloudflare Tunnel, it's worth being specific about what the alternatives looked like, because the contrast is what makes the value clear.

Port forwarding on your router. Conceptually straightforward, operationally fragile. You open port 443 on your router, point it at your machine's local IP, and pray nothing changes. Your ISP might block inbound traffic on common ports. Your local IP might shift if your DHCP lease renews and the static reservation didn't take. Your public IP might rotate if you have a dynamic-IP plan, which most residential ISPs do.

Dynamic DNS. Solves the public-IP rotation. Doesn't solve the inbound-blocking, the IPv6 confusion, the SSL certificate problem, or the fact that you are now serving your home network's IP address publicly to anyone who can resolve your DNS. The cheapest IP-camera scanner on the internet now has your address.

SSH reverse tunnel to a VPS. Works, but you need a VPS, you need to manage the SSH process (autossh, systemd, supervisord), and you need to terminate SSL somewhere. You're now paying for a server whose only job is to be the public face of another server.

ngrok and similar. The easiest of the older options. Free tier is enough for development; paid tiers handle production. But you're paying per month for what is essentially "a TCP tunnel with a domain in front," and the free tier rotates URLs in a way that breaks any persistent client.

Each of these works. None of them is what you actually want, which is "expose a local port on a stable domain with HTTPS, with no inbound firewall changes, for free."

What Cloudflare Tunnel actually is

Cloudflare Tunnel (also called cloudflared) is a daemon that runs on your machine and maintains an outbound persistent connection to Cloudflare's edge network. When traffic arrives at Cloudflare for your domain, it's routed through that outbound connection to your local service. From your machine's perspective, no inbound port is ever opened. The connection is initiated by you, going out, and traffic flows back through the established pipe.

Operationally this means:

- No port forwarding. You don't touch your router.
- No public IP exposure. Cloudflare's IPs are what the internet sees. Your home IP stays private.
- HTTPS is automatic. Cloudflare terminates TLS at their edge with their own certificates. You serve plain HTTP locally; the encryption layer is theirs.
- DDoS protection comes free. Cloudflare's normal edge protections apply.
- It's free for the standard use case. You need a domain on Cloudflare (which is also free — just transfer your DNS to them, no charge), but the tunnel itself has no per-tunnel cost for individuals.

The conceptual model is "an outbound WebSocket from your machine to Cloudflare's edge, with HTTP traffic multiplexed over it." The actual protocol is more sophisticated (HTTP/2, QUIC, several layers of resilience), but that's the mental model.

Setup, end to end

The minimum viable setup, assuming you have a domain on Cloudflare:

# 1. Install cloudflared
brew install cloudflared        # macOS
# or: apt install cloudflared   # Debian/Ubuntu

# 2. Authenticate (opens a browser)
cloudflared tunnel login

# 3. Create a named tunnel
cloudflared tunnel create my-app

# 4. Route a hostname through it
cloudflared tunnel route dns my-app app.example.com

# 5. Configure the tunnel
mkdir -p ~/.cloudflared
cat > ~/.cloudflared/config.yml <<EOF
tunnel: my-app
credentials-file: /home/you/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: app.example.com
    service: http://localhost:8501  # your Streamlit port
  - service: http_status:404
EOF

# 6. Run it
cloudflared tunnel run my-app

After step 6, your locally-running Streamlit app is reachable at https://app.example.com from anywhere on the internet, with valid HTTPS, behind Cloudflare's DDoS protection, without touching your firewall.

Make it a systemd service so it survives reboots:

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared

That's the whole setup. The conceptual leap from the older options is large; the operational complexity is genuinely small.

What you can usefully expose

The ingress block is the interesting part — you can route multiple hostnames through the same tunnel to different local services:

ingress:
  - hostname: app.example.com
    service: http://localhost:8501       # Streamlit
  - hostname: api.example.com
    service: http://localhost:8000       # FastAPI
  - hostname: ollama.example.com
    service: http://localhost:11434      # Ollama
  - hostname: jupyter.example.com
    service: http://localhost:8888       # Jupyter
  - service: http_status:404

One cloudflared process, one outbound connection, multiple public hostnames mapped to different local ports. For a developer running several services on one machine, this collapses what would otherwise be several reverse-proxy configurations into one YAML block.

The pattern is especially valuable for:

- AI/LLM services. Exposing a local Ollama or vLLM instance on a stable URL so other apps you write — including ones running on phones, tablets, or other machines — can use it without VPN setup.
- RAG backends. Personal search systems built on the SQLite + FTS5 + sqlite-vec stack from Building a Hybrid RAG in 200 Lines can be exposed as HTTP services with the same tunnel.
- Webhook receivers. GitHub, Stripe, Twilio — anything that needs to call your machine on a stable URL. The tunnel makes this trivial.
- Demo apps for clients. Run a Streamlit prototype locally, expose it on demo-yourclient.example.com, send the link. They click, they see the app, they give feedback. No cloud deployment needed for the demo stage.

High availability with two tunnels

For services you actually depend on, you want resilience. cloudflared supports running multiple replicas of the same tunnel from different machines — Cloudflare load-balances across them, and if one drops, traffic shifts to the others automatically.

The pattern for a personal infrastructure stack:

Primary host (always on)  →  cloudflared replica 1  →  Cloudflare edge
Backup host (always on)   →  cloudflared replica 2  →  Cloudflare edge

Both replicas advertise the same tunnel ID. Both have access to the same local services (either by being the actual service host, or by reverse-proxying to a shared backend). Cloudflare distributes traffic; if either machine goes offline, the other handles 100% until it comes back.

For a solo developer, this means you can have meaningful high availability without renting a load balancer or a managed Kubernetes cluster. Two cheap machines (or one machine and one Raspberry Pi) plus Cloudflare's edge equals an architecture that quietly stays up through power outages and reboots.

Security considerations worth taking seriously

Cloudflare Tunnel is convenient, but it is convenience that needs respect.

Anything you expose is exposed. A tunnel makes your local service publicly reachable. If that service has no authentication, it has no authentication on the public internet. Streamlit apps in particular default to "anyone with the URL can use them." Add authentication before exposing anything sensitive — Cloudflare Access (free for small teams) is the path-of-least-resistance option.

The credentials file matters. The <tunnel-id>.json file under ~/.cloudflared/ is the keys to your tunnel. Treat it like an SSH key. Don't commit it. Don't share it. If you're running on a shared machine, lock down its permissions.

Cloudflare Access for anything internal. For tools you only want yourself or a small team to access, put them behind Cloudflare Access. You define which Google or GitHub accounts can reach the hostname; Cloudflare handles the auth flow. The local service doesn't need to know anything about authentication — it just sees authenticated requests through the tunnel.

Audit what's in the ingress block. Every hostname-to-service mapping is a public endpoint. If a Jupyter kernel is on the list and you forgot to add a password, anyone on the internet can run code on your machine. Review the config when you add things.

When this stops being enough

Cloudflare Tunnel is excellent for personal use, demos, internal tools, and small-scale production. It is not infinite.

The free tier has rate limits that you will eventually hit if you're serving meaningful traffic. They are generous for hobbyist use and not designed for consumer-scale apps. If your tunnel is serving millions of requests a month, you are in a different conversation about pricing.

The tunnel is dependent on Cloudflare's edge being up. Cloudflare has had outages — rare, but real. For anything where downtime has business impact, you need a fallback, which means either a second tunnel through a different provider or a real cloud deployment alongside.

The local-host paradigm has limits. A residential ISP that doesn't notice you serving a small Streamlit app will absolutely notice you serving 50 GB of video a day. Read your ISP's terms of service before assuming the tunnel makes you invisible.

The shape of personal infrastructure in 2026

Step back from the specifics and Cloudflare Tunnel is one piece of a broader pattern: the components needed to run a serious personal infrastructure stack are now free or nearly free.

A laptop or small home server runs the compute. SQLite handles the data. sqlite-vec handles the vectors. Streamlit handles the UI. uv handles the Python environment. Cloudflare Tunnel handles the public endpoint. Cloudflare's DNS handles the routing. Cloudflare Access handles the auth.

For most personal projects, internal tools, and surprisingly many commercial applications, this stack delivers what would have cost $200–500/month in cloud infrastructure five years ago, for the price of a domain name and the electricity to run a small machine. The infrastructure-as-a-service industry has trained a generation of developers to reach for cloud platforms by default. The personal-infrastructure tier is much better than that habit assumes, and Cloudflare Tunnel is the piece that makes it work without requiring you to become a network engineer.

---

For the broader strategic context on solo-builder stacks, see Why Snowflake's Bet on Streamlit Just Works. For the practical RAG layer that pairs naturally with this networking setup, see Building a Hybrid RAG in 200 Lines.