Configuring Cloudflare Tunnel to Expose Servers for Local Development, Webhooks etc
I needed a way to expose local dev servers to the internet for webhook testing. ngrok works, but Cloudflare Tunnel is free and lets you use your own domain whereas ngrok is free, but you pay $10 (as of 20251201) per custom domain.
Prerequisite: Cloudflare must already be managing DNS for your domain.
Install and Login
brew install cloudflared
cloudflared tunnel login
The login command opens your browser to authenticate with Cloudflare.
Create a Tunnel
You only need one tunnel. You can route multiple subdomains through the same tunnel. I’ll use dev as the tunnel name in these examples:
cloudflared tunnel create dev
This creates the tunnel and stores credentials at ~/.cloudflared/<tunnel-id>.json.
Create DNS Routes
This creates CNAME records pointing your subdomains to the tunnel:
cloudflared tunnel route dns dev dev.yourdomain.com
cloudflared tunnel route dns dev dev-backend.yourdomain.com
To remove a route, delete the CNAME record from the Cloudflare dashboard.
Configure and Run
Create ~/.cloudflared/config.yml:
tunnel: <tunnel-id>
credentials-file: /Users/you/.cloudflared/<tunnel-id>.json
ingress:
- hostname: dev.yourdomain.com
service: http://localhost:5174
- hostname: dev-backend.yourdomain.com
service: http://localhost:4002
- service: http_status:404
The last rule is a required catch-all for unmatched requests.
Then normally, you’d just run:
cloudflared tunnel run dev
Both subdomains now route to their respective local ports.