Cloudflare Tunnel is a secure way to expose local services to the public internet without opening any ports on your network or exposing your IP address. It works by creating an outbound connection from your machine to Cloudflare’s edge network, which then proxies requests to your local server.
This post documents how to configure and use a Cloudflare Tunnel with your own domain name (example.com), using a local config.yml
file for setup. The tunnel is not permanently running as a service, but instead started manually when needed – e.g. for temporary access, controlled deployments, or personal use.
All configurations remain under your control and are stored locally. You’ll learn how to log in, create the tunnel, configure DNS, run it in foreground or background, and manage the cache.
💡 In this example, I’m using a domain that I manage through Cloudflare.
Cloudflared Tunnel
Install cloudflared
brew install cloudflared
Set up the tunnel
Login and certificate creation
First, you need to generate the certificate and configuration file.
# one-time login
cloudflared login
→ Opens your default browser.
→ You select your Cloudflare account and the zone.
→ The certificate ~/.cloudflared/cert.pem
is created.
The cert.pem
file is the foundation for being able to create a tunnel at all.
So if you ever clear the ~/.cloudflared
directory, you must run cloudflared login
again before creating anything new.
Create the tunnel
cloudflared tunnel create my-tunnel
This will automatically create the configuration file ~/.cloudflared/<TUNNEL-ID>.json
.
In this file, we can later configure individual settings via config.yml
.
Create config.yml
tunnel: my-tunnel
credentials-file: /home/<user>/.cloudflared/<TUNNEL-ID>.json
ingress:
- hostname: my-tunnel.example.com
service: http://localhost:8080
- service: http_status:404
Explanation:
- tunnel: Your tunnel name
- credentials-file: Path to the .json file (automatically created)
- ingress: Controls what Cloudflare should route to where
- service: Target on your local machine
The tunnel in this example connects to the local address http://localhost:8080.
Connect the tunnel with Cloudflare DNS
# one-time login
cloudflared tunnel route dns my-tunnel example.com
If a DNS entry for this tunnel name already exists, the action will fail.
In that case, you need to remove the existing DNS configuration manually in the Cloudflare dashboard.
In the Cloudflare dashboard → DNS:
→ Go to the DNS tab in your domain
→ Remove the existing entry for the tunnel (e.g. my-tunnel
)

Run the tunnel
cloudflared tunnel run
This will start the tunnel using your config.yml
.
Run in background with log
nohup cloudflared tunnel run > ~/.cloudflared/tunnel.log 2>&1 &
# end with
pkill cloudflared
Run with helper script (ZSH)
#!/bin/zsh
LOGFILE="${HOME}/.cloudflared/tunnel.log"
if [[ "$1" == "-b" ]]; then
echo "Start tunnel in background – log to ${LOGFILE}"
nohup cloudflared tunnel run > "$LOGFILE" 2>&1 &
echo "PID: $!"
else
echo "Start tunnel in foreground..."
cloudflared tunnel run
fi
./tunnel.sh # Starts tunnel in foreground
./tunnel.sh -b # Startes in background + writes in ~/.cloudflared/tunnel.log
Tunnel dashboard
You can check the status of your tunnel in Cloudflare:
Cloudflare dashboard → Zero Trust → Networks → Tunnels

Cache configuration
Cloudflare creates a cache when you access your website through the tunnel. This can sometimes interfere with development if you want to see recent changes. In Cloudflare, you can configure caching behavior or manually clear the cache.
Dashboard → Select domain → Configure Caching → Purge Everything.

Test
If everything worked, you should be able to access the local web app at http://localhost:8080 via the tunnel using the domain name.
