2 Cloudflared Tunnel Setup Guide
How to securely expose local services to the world through Cloudflare tunnels โ no port forwarding, no static IP, no problem.
Table of Contents
- ๐ Overview
- โ๏ธ Step 0: Download Cloudflared
- ๐ช Step 1: Create & Route Your Tunnel
- ๐ช Step 2: Prepare Host Configuration
- ๐ช Step 3: Run Tunnel
- ๐ Complete Configuration Examples
- โ๏ธ Docker Compose Integration
- ๐ Tunnel Management Commands
- โ๏ธ Running as a Service
- ๐ Troubleshooting
- ๐ Security Best Practices
- ๐ Quick Reference
- ๐ Real-World Use Cases
- ๐ Additional Resources
๐ Overview
Cloudflared creates secure tunnels to expose your local services to the internet through Cloudflare's network. This guide covers installation, tunnel creation, and configuration.
โ๏ธ Step 0: Download Cloudflared
macOS
Install via Homebrew:
brew install cloudflared
Alternative: Download the latest release directly:
- Darwin arm64 release (for M1/M2/M3 Macs)
- Darwin amd64 release (for Intel Macs)
Windows
Install via winget:
winget install --id Cloudflare.cloudflared
Alternative: Download the latest release directly:
| Type | 32-bit | 64-bit |
|---|---|---|
| Executable | Download | Download |
Instances of cloudflared do not automatically update on Windows. You will need to perform manual updates.
Docker
A Docker image of cloudflared is available on DockerHub.
๐ช Step 1: Create & Route Your Tunnel
Important for Windows Users
Navigate to the cloudflared.exe directory and use it with .\cloudflared.exe instead of cloudflared:
cd path/to/cloudflared.exe
Tunnel Setup Commands
# Authenticate and obtain your cert.pem
cloudflared tunnel login
# Create a locally-managed tunnel named 'tunnel-name'
cloudflared tunnel create tunnel-name
# Check list of tunnels
cloudflared tunnel list
# Provision DNS CNAME for demo.kunj.dev โ your tunnel
cloudflared tunnel route dns tunnel-name demo.kunj.dev
What These Commands Do
cloudflared tunnel loginโ Opens browser for Cloudflare authentication and downloads cert.pemcloudflared tunnel create tunnel-nameโ Creates tunnel and generates credentials JSON filecloudflared tunnel listโ Shows all your created tunnelscloudflared tunnel route dns tunnel-name demo.kunj.devโ Automatically adds CNAME record in Cloudflare DNS
Storage Location:
- Your Tunnel UUID and credentials JSON are stored at:
~/.cloudflared/<UUID>.json - The tunnel automatically creates a CNAME record in Cloudflare DNS
๐ช Step 2: Prepare Host Configuration
Create Directory Structure
mkdir -p ./cloudflared
Copy Credentials File
Copy your <UUID>.json into ./cloudflared/ directory (you can rename it if desired).
Create Configuration File
Create ./cloudflared/config.yml with the following contents:
tunnel: <YOUR_TUNNEL_UUID>
credentials-file: /etc/cloudflared/<YOUR_TUNNEL_UUID>.json
ingress:
- hostname: demo.kunj.dev # Domain to route all traffic through tunnel
service: http://localhost:3000 # Your local running service URL
- service: http_status:404 # Return 404 for all other hosts
Configuration Explanation
tunnelโ Your unique tunnel UUID (from Step 1)credentials-fileโ Path to your tunnel credentials JSON fileingressโ Routing rules for incoming traffichostnameโ The domain that will route through the tunnelserviceโ Your local service URL (e.g., http://localhost:3000)- Last rule โ Catch-all rule (returns 404 for unmatched requests)
๐ช Step 3: Run Tunnel
Using Specific Config File
# To use specific tunnel config (e.g., tunnel-name.yml)
cloudflared tunnel --config /path/to/tunnel/tunnel-name.yml run
Using Default Config
# For default config (config.yml)
cloudflared tunnel run tunnel-name
๐ Complete Configuration Examples
Example 1: Single Service
File: ./cloudflared/config.yml
tunnel: abc123-def456-ghi789
credentials-file: /etc/cloudflared/abc123-def456-ghi789.json
ingress:
- hostname: app.kunj.dev
service: http://localhost:3000
- service: http_status:404
Example 2: Multiple Services
File: ./cloudflared/config.yml
tunnel: abc123-def456-ghi789
credentials-file: /etc/cloudflared/abc123-def456-ghi789.json
ingress:
- hostname: api.kunj.dev
service: http://localhost:5000
- hostname: app.kunj.dev
service: http://localhost:3000
- hostname: admin.kunj.dev
service: http://localhost:8080
- service: http_status:404
Example 3: Docker Service
File: ./cloudflared/config.yml
tunnel: abc123-def456-ghi789
credentials-file: /etc/cloudflared/abc123-def456-ghi789.json
ingress:
- hostname: n8n.kunj.dev
service: http://n8n:5678 # Docker service name
- service: http_status:404
โ๏ธ Docker Compose Integration
docker-compose.yml
version: '3.8'
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared-tunnel
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${TUNNEL_TOKEN}
restart: unless-stopped
networks:
- app-network
app:
image: your-app:latest
container_name: your-app
ports:
- "3000:3000"
networks:
- app-network
networks:
app-network:
driver: bridge
Alternative: Using Config File in Docker
version: '3.8'
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared-tunnel
command: tunnel --config /etc/cloudflared/config.yml run
volumes:
- ./cloudflared:/etc/cloudflared
restart: unless-stopped
networks:
- app-network
networks:
app-network:
driver: bridge
๐ Tunnel Management Commands
Essential Commands
# List all tunnels
cloudflared tunnel list
# Delete a tunnel
cloudflared tunnel delete tunnel-name
# Run tunnel with specific config
cloudflared tunnel --config /path/to/config.yml run
# Run tunnel in background (Linux/macOS)
nohup cloudflared tunnel run tunnel-name &
# Check tunnel info
cloudflared tunnel info tunnel-name
# Clean up tunnel connections
cloudflared tunnel cleanup tunnel-name
โ๏ธ Running as a Service
Linux (systemd)
Create service file: /etc/systemd/system/cloudflared.service
[Unit]
Description=Cloudflare Tunnel
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/cloudflared tunnel --config /root/.cloudflared/config.yml run
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Enable and start service:
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared
macOS (launchd)
Create plist file: ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.cloudflare.cloudflared</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/cloudflared</string>
<string>tunnel</string>
<string>run</string>
<string>tunnel-name</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Load the service:
launchctl load ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
launchctl start com.cloudflare.cloudflared
Windows (Service)
# Install as Windows service
cloudflared service install
# Start the service
cloudflared service start
# Stop the service
cloudflared service stop
# Uninstall the service
cloudflared service uninstall
๐ Troubleshooting
Common Issues
Issue: Tunnel not connecting
# Check tunnel status
cloudflared tunnel info tunnel-name
# View logs
cloudflared tunnel --loglevel debug run tunnel-name
Issue: DNS not resolving
# Verify DNS routing
cloudflared tunnel route dns tunnel-name demo.kunj.dev
# Check Cloudflare DNS settings in dashboard
Issue: Service not accessible
# Verify local service is running
curl http://localhost:3000
# Check config.yml ingress rules
# Ensure hostname and service URL are correct
Viewing Logs
# Basic logs
cloudflared tunnel run tunnel-name
# Debug logs
cloudflared tunnel --loglevel debug run tunnel-name
# For systemd (Linux)
sudo journalctl -u cloudflared -f
# For Docker
docker logs -f cloudflared-tunnel
๐ Security Best Practices
-
Protect credentials file โ Set proper permissions:
chmod 600 ~/.cloudflared/<UUID>.json -
Use specific hostnames โ Don't use wildcards unless necessary
-
Implement authentication โ Use Cloudflare Access for additional security layer
-
Regular updates โ Keep cloudflared updated (especially on Windows)
-
Monitor logs โ Regularly check tunnel logs for suspicious activity
๐ Quick Reference
Installation
# macOS
brew install cloudflared
# Windows
winget install --id Cloudflare.cloudflared
Setup
cloudflared tunnel login
cloudflared tunnel create tunnel-name
cloudflared tunnel route dns tunnel-name demo.kunj.dev
Run
cloudflared tunnel run tunnel-name
Management
cloudflared tunnel list
cloudflared tunnel info tunnel-name
cloudflared tunnel delete tunnel-name
๐ Real-World Use Cases
Use Case 1: Expose Local Development Server
Perfect for showing clients your work-in-progress without deploying.
ingress:
- hostname: dev.kunj.dev
service: http://localhost:3000
- service: http_status:404
Use Case 2: Self-Hosted Services (n8n, Grafana, etc.)
ingress:
- hostname: n8n.kunj.dev
service: http://localhost:5678
- hostname: grafana.kunj.dev
service: http://localhost:3001
- service: http_status:404
Use Case 3: IoT Device Access
ingress:
- hostname: homeassistant.kunj.dev
service: http://192.168.1.100:8123
- service: http_status:404
๐ Additional Resources
- Cloudflare Tunnel Docs: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps
- Community Forum: https://community.cloudflare.com
- GitHub Issues: https://github.com/cloudflare/cloudflared/issues