Futuristic developer desk scene with a glowing network tunnel leading from cloud icons to a laptop, with security and webhook-style symbols.

Cloudflare Tunnels for Local Dev

5 min read

If you’re anything like me, you’re juggling multiple projects at once.

And sooner or later, one of them hits the same wall:

You’ve finally got your SaaS behaving.
Routes. Auth. APIs. Services. The whole machine is humming.

Then you go to implement payments.

Stripe (usually), but it doesn’t really matter who it is—the problem is the same:

Webhooks need a public URL.

Even in sandbox mode, Stripe still needs somewhere to send callbacks so you can test the real-world flow:

  • payment succeeded / failed
  • subscription renewed / cancelled
  • customer updated details
  • invoice paid / payment method expired
  • out-of-band events your UI will never see coming

Same story with auth providers:

  • user deleted account → you want cleanup to run
  • email changed → you want your app to stay in sync
  • org removed → you want to revoke access

So you need a publicly reachable endpoint… pointed at your local machine… without punching holes in your firewall.

There are excellent tools for this.

I’ve used ngrok before. There’s Tailscale, Pinggy, and a bunch of others. No shade—they work, and they’re often plug-and-play.

But the catch is familiar:

They can get expensive fast once you want stable domains, multiple routes, longer sessions, higher limits, or team workflows. And if you’re also like me, you probably have random domains lying around that you’re not using.

That’s where Cloudflare Tunnel comes in. If you already have a domain on Cloudflare, it’s essentially the “free” option that just works.

What Cloudflare Tunnel Actually Gives You

Cloudflare Tunnel is not “exposing your machine to the internet” in the way people fear.

It’s not port forwarding.
It’s not opening inbound firewall rules.

Instead, cloudflared runs on your machine and creates an outbound connection to Cloudflare. Cloudflare then routes requests from your domain through that tunnel to your local service.

You get:

  • a real domain (and subdomains)
  • automatic HTTPS / SSL
  • a stable public URL for webhooks
  • no inbound firewall changes
  • the option to route multiple local apps if you want

This post walks you through the simple setup: domain → tunnel → localhost.

Note: depending on your framework/provider, you may need extra config (e.g. allowing dev origins in Next.js, updating OAuth callback URLs, etc.). This post focuses on the tunnel itself.

What You Need Before You Start

  • A domain added to Cloudflare (DNS managed by Cloudflare)
  • A local dev server running (Next.js / Vite / Astro / etc.)
  • cloudflared installed on your machine

1) Install cloudflared

Arch Linux

sudo pacman -S cloudflared

macOS (Homebrew)

brew install cloudflare/cloudflare/cloudflared

Debian / Ubuntu

sudo apt update
sudo apt install cloudflared

Package names can vary by distro—use your package manager if yours is different.

2) Create the Tunnel in Cloudflare Zero Trust

  1. Log into Cloudflare
  2. Open Zero Trust (sometimes shown as “Access” / “Zero Trust” depending on UI)
  3. Go to Networks → Tunnels (or Connectors)
  4. Click Create a tunnel
  5. Select cloudflared
  6. Name it (e.g. local-dev)
  7. Save

Cloudflare will show you installation/run instructions.

Scroll until you find the part with two commands:

  • one to install as a service (auto-start on reboot)
  • one to run manually (temporary / dev-only)

Important Warning about the Token

If you run it manually, the command includes a token.

That token is basically the key to the tunnel.

Don’t paste it into screenshots. Don’t commit it. Don’t drop it in public notes.

3) Confirm the Connector Is Connected

Once you run the connector command, the Cloudflare page should update and show your tunnel as:

Connected

Click Next.

4) Route a Hostname to Your Local Dev Server

In the routing step, you’ll see options like:

  • Published applications
  • Hostname routes
  • CIDR routes

For the basic domain → localhost dev server setup, you want a hostname/app route.

Create a route like:

  • Subdomain: dev (or whatever you want)
  • Domain: yourdomain.com
  • Service type: http
  • URL: localhost:3000 (or whatever your dev port is)

Common defaults:

  • Next.js dev server: localhost:3000
  • Astro dev server: localhost:4321
  • Vite dev server: localhost:5173

Click Complete setup.

Cloudflare will automatically create a proxied DNS record (usually a CNAME).

Now you should be able to visit:

https://dev.yourdomain.com

…and it should hit your local dev server.

5) Point Your Webhook Provider to the Tunnel URL

Now the whole reason we did this:

Set your webhook endpoint to something like:

https://dev.yourdomain.com/api/webhooks/stripe

…and test it.

Your local app should receive real callbacks over HTTPS, with a stable URL, without you opening your network.

Security Notes (Read This Once)

Your firewall can stay locked down, which is great—but be honest about what’s happening:

Your local dev server is now reachable via the public internet, through that domain.

That may be totally fine for webhook testing. Just don’t treat it like a private LAN service.

Practical tips:

  • Use a dedicated subdomain like webhooks.yourdomain.com or dev-webhooks.yourdomain.com
  • Keep the tunnel running only when you need it
  • Verify webhook signatures properly (Stripe signing secret, etc.)
  • If you want to lock down everything except the webhook endpoint:
    • put the app behind Cloudflare Access
    • keep the webhook route open (Stripe can’t pass an Access login page)

Troubleshooting

  • Cloudflare shows 502 / bad gateway → your local server isn’t running, wrong port, or bound to a different host.
  • Localhost works but tunnel doesn’t → some frameworks care about origin/host headers.
    • Next.js may need allowedDevOrigins
    • auth providers may need updated callback URLs / allowed origins
  • Webhooks hit your server but your app rejects them → check signature verification and raw body parsing rules.

Wrap-up

Cloudflare Tunnel is one of those tools that quietly removes an (annoying) class of local-dev friction: stable HTTPS URLs, real domains, and webhook testing—without opening inbound ports.

If you already have your domain on Cloudflare, it’s hard to beat.

Related posts

A fingertip hovering above a glowing surface as blue and orange energy-like lines and particles radiate outward, suggesting an invisible field between touch and contact.

The Interface of Reality

Contact feels like the simplest fact of life, yet physics suggests it’s an emergent interface: a boundary rendered by fields, constraints, and collective behavior. What we call touch is reality, compressed.

14 min read
© 2026 Valeon. All rights reserved.