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)

Cloudflare DNS Dashboard

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

Cloudflare Tunnel Status

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.

Cloudflare Cache Functions

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.

Tunnel Domain Webapp

Resources