Blog
3 min read

Cloudflare Tunnel Explained: Put a Local App Online Without Opening Ports

Cloudflare Tunnel connects an app on your laptop, home server or private network to the internet through Cloudflare, with no public IP or open firewall ports. Quick tunnels for testing, named tunnels with your own domain, Access for protection, and when to use it instead of a server.

Normally, to put an app online you need a server with a public IP address and open ports. Cloudflare Tunnel flips that around: a small program called cloudflared runs next to your app and makes an outbound connection to Cloudflare. Visitors reach Cloudflare, and Cloudflare sends their requests down the tunnel to your app. (What is Cloudflare?)

Visitor → Cloudflare → (tunnel) → cloudflared → your app on localhost:3000

No public IP, no port forwarding on your router, no inbound firewall holes.

What it's good for

  • Showing someone your local dev app — a quick public URL for a demo.
  • Testing webhooks from Stripe, GitHub and others against your laptop. (Test webhooks locally)
  • Self-hosting from home — a Raspberry Pi, a home lab, Home Assistant — without exposing your home network.
  • Reaching internal tools (an admin panel, a dashboard) securely, combined with Cloudflare Access.
  • Servers behind restrictive networks that can't accept inbound connections.

Quick tunnel: a URL in one command

Install cloudflared (Homebrew, apt, winget or a download), then:

cloudflared tunnel --url http://localhost:3000

It prints a random https://something-random.trycloudflare.com address. Anyone can open it while the command runs. No account needed. Great for a quick test; the URL changes every time and it's not meant for production.

Named tunnel: your own domain

For something lasting, create a named tunnel tied to your Cloudflare account and a domain whose DNS is on Cloudflare. The easiest route is the dashboard (Zero Trust → Networks → Tunnels), which gives you a one-line install command with a token. Or from the CLI:

cloudflared tunnel login
cloudflared tunnel create myapp
cloudflared tunnel route dns myapp app.example.com

Then a config file:

# ~/.cloudflared/config.yml
tunnel: myapp
credentials-file: /home/you/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: app.example.com
    service: http://localhost:3000
  - hostname: grafana.example.com
    service: http://localhost:3001
  - service: http_status:404

Run it:

cloudflared tunnel run myapp

…and install it as a service so it starts on boot (cloudflared service install). HTTPS is handled by Cloudflare. (What is systemd?)

Protect private apps with Access

A tunnel makes an app reachable; it doesn't add a login. For internal tools, add Cloudflare Access in front: visitors must sign in (email code, Google, GitHub, your company's SSO) before Cloudflare lets the request through. Small teams can use it free.

Things to know

  • Your app is only up while your machine is. A tunnel from your laptop goes down when the lid closes. For something customers depend on, the app needs to run somewhere that's always on. (What is web hosting?)
  • Cloudflare sees the traffic. It terminates HTTPS, so it can inspect requests. Usually fine; worth knowing for sensitive data.
  • Bandwidth and terms. Cloudflare's terms limit using its network mainly for large media streaming on most plans.
  • Your app should still be secure. A tunnel isn't a substitute for authentication and input validation.

Cloudflare Tunnel vs ngrok vs a server

Cloudflare Tunnel ngrok A real server
Quick test URL Yes (quick tunnel) Yes —
Your own domain Free (domain on Cloudflare) Paid plans Yes
Login in front Cloudflare Access ngrok features You build it
Works when your laptop is off No No Yes
Best for Home labs, internal tools, webhooks Dev testing, webhook inspection Production

(What is ngrok?)


EasySpawn gives your app an always-on server with a public HTTPS address, so it stays online when your laptop doesn't. See how it works or join the waitlist.

Related: What Is ngrok? · What Is Cloudflare? · How to Test Webhooks Locally · What Is Localhost?

Keep reading