cloudflare-tunnel-setup
npx skills add https://github.com/dawiddutoit/custom-claude --skill cloudflare-tunnel-setup
Agent 安装分布
Skill 文档
Cloudflare Tunnel Setup Skill
Interactive guide for setting up a new Cloudflare Tunnel from scratch.
Quick Start
Run this skill when you need to:
- Create a new Cloudflare Tunnel
- Replace an expired or invalid tunnel token
- Set up remote access for a fresh installation
Minimum requirements: Cloudflare account, domain on Cloudflare, Docker installed.
Table of Contents
- When to Use This Skill
- What This Skill Does
- Instructions
- 3.1 Check Prerequisites
- 3.2 Create Tunnel in Dashboard
- 3.3 Configure Token in .env
- 3.4 Restart Cloudflared Container
- 3.5 Configure Public Hostnames
- 3.6 Verify Connectivity
- Supporting Files
- Expected Outcomes
- Requirements
- Red Flags to Avoid
When to Use This Skill
Explicit Triggers:
- “Setup cloudflare tunnel”
- “Create a new tunnel”
- “Configure remote access”
- “Replace tunnel token”
- “Tunnel from scratch”
Implicit Triggers:
- Fresh installation of network infrastructure
- Tunnel token expired or invalid
- CLOUDFLARE_TUNNEL_TOKEN missing from .env
- Moving infrastructure to new hardware
Debugging Triggers:
- “Tunnel token not found”
- “cloudflared container won’t start”
- “No CLOUDFLARE_TUNNEL_TOKEN in .env”
What This Skill Does
- Checks Prerequisites – Verifies .env exists and cloudflared is in docker-compose
- Guides Tunnel Creation – Step-by-step instructions for Cloudflare dashboard
- Configures Token – Adds tunnel token to .env file
- Restarts Container – Restarts cloudflared to apply new token
- Guides Hostname Setup – Instructions for configuring public hostnames
- Verifies Connectivity – Confirms tunnel is connected and working
Instructions
3.1 Check Prerequisites
Step 1: Verify .env file exists
ls -la /home/dawiddutoit/projects/network/.env
If missing, create from example:
cp /home/dawiddutoit/projects/network/.env.example /home/dawiddutoit/projects/network/.env
Step 2: Check if CLOUDFLARE_TUNNEL_TOKEN exists
grep -E "^CLOUDFLARE_TUNNEL_TOKEN" /home/dawiddutoit/projects/network/.env
Possible outcomes:
- Line exists with value: Token already configured (check if valid)
- Line exists but empty/placeholder: Needs real token
- Line not found: Token needs to be added
Step 3: Verify docker-compose has cloudflared service
grep -A 10 "cloudflared:" /home/dawiddutoit/projects/network/docker-compose.yml
If cloudflared service is missing, it needs to be added. See references/reference.md for service definition.
3.2 Create Tunnel in Dashboard
Provide these instructions to the user:
- Go to: https://one.dash.cloudflare.com -> Access -> Tunnels
- Click “Create a tunnel” -> Select “Cloudflared” connector
- Name tunnel (e.g., “pi-home”) -> Choose “Docker” as connector type
- Copy the tunnel token (long base64 string after
--token) - Save token securely
Token format: Base64-encoded JSON containing Account ID, Tunnel ID, and Secret.
3.3 Configure Token in .env
Step 1: Check current token status
grep "CLOUDFLARE_TUNNEL_TOKEN" /home/dawiddutoit/projects/network/.env
Step 2: Add or update token
If line exists, update it. If not, add it.
# If line exists, use sed to replace
# If not, append to file
# The token should look like:
# CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoiYWJjZDEyMzQ...
Use the Edit tool to update .env:
- Look for existing
CLOUDFLARE_TUNNEL_TOKEN=line - Replace with new token value
- Or add new line if not present
Validate token format:
# Token should be base64 decodable
TUNNEL_TOKEN=$(grep "CLOUDFLARE_TUNNEL_TOKEN=" /home/dawiddutoit/projects/network/.env | cut -d'=' -f2)
echo "$TUNNEL_TOKEN" | base64 -d 2>/dev/null | python3 -c "import sys, json; d=json.load(sys.stdin); print('Valid token for account:', d.get('a', 'unknown'))"
3.4 Restart Cloudflared Container
Step 1: Restart the container
cd /home/dawiddutoit/projects/network && docker compose restart cloudflared
Or if container doesn’t exist yet:
cd /home/dawiddutoit/projects/network && docker compose up -d cloudflared
Step 2: Check container is running
docker ps | grep cloudflared
Expected output:
CONTAINER ID IMAGE STATUS NAMES
abc123... cloudflare/cloudflared:latest Up X seconds cloudflared
Step 3: Check logs for successful connection
docker logs cloudflared --tail 30
Look for these success indicators:
INF Registered tunnel connection connIndex=0 location=...
INF Registered tunnel connection connIndex=1 location=...
INF Registered tunnel connection connIndex=2 location=...
INF Registered tunnel connection connIndex=3 location=...
4 registered connections = healthy tunnel (2 connections per Cloudflare edge location)
If errors appear:
token is invalid: Token was copied incorrectly or expiredalready registered: Another instance using same token (stop other instances)network error: Check internet connectivity
3.5 Configure Public Hostnames
After tunnel is connected, configure services in Cloudflare dashboard:
- Go to: https://one.dash.cloudflare.com -> Access -> Tunnels
- Click tunnel name -> Configure -> Public Hostname -> Add
- For each service, enter subdomain, domain (temet.ai), Type (HTTP), and URL
Example hostnames:
| Service | Subdomain | URL |
|---|---|---|
| Pi-hole | pihole | pihole:80 |
| Webhook | webhook | webhook:9000 |
| Jaeger | jaeger | 192.168.68.135:16686 |
URL patterns:
- Docker container:
container:port(e.g., pihole:80) - Host service:
host-ip:port(e.g., 192.168.68.135:16686) - LAN device:
device-ip:port(e.g., 192.168.68.105:80)
Important: Use HTTP (not HTTPS) for backends. Do NOT use host.docker.internal on Linux.
3.6 Verify Connectivity
Step 1: Verify tunnel is registered
docker logs cloudflared 2>&1 | grep -E "Registered tunnel|connIndex"
Expected: 4 “Registered tunnel connection” messages
Step 2: Check tunnel status in dashboard
Go to: https://one.dash.cloudflare.com
Navigate to: Access -> Tunnels
Status should show: "HEALTHY" with green indicator
Step 3: Test external access (from mobile data or external network)
# From a device NOT on home network:
curl -I https://pihole.temet.ai
# Expected: HTTP 302 (redirect to Cloudflare Access) or HTTP 200 (if no auth)
Step 4: Run diagnostic script (optional)
./scripts/cf-tunnel-config.sh show
Supporting Files
| File | Purpose |
|---|---|
references/reference.md |
Docker-compose service definition, token format details |
examples/examples.md |
Example configurations for common setups |
Expected Outcomes
Success:
- CLOUDFLARE_TUNNEL_TOKEN in .env
- cloudflared container running
- 4 tunnel connections registered in logs
- Tunnel shows “HEALTHY” in dashboard
- Services accessible via *.temet.ai from external network
Partial Success:
- Token configured but hostnames not set up (user reminder provided)
- Tunnel connected but services return 502 (backend configuration issue)
Failure Indicators:
- “token is invalid” in logs -> Re-copy token from dashboard
- Container restart loop -> Check token format
- 0 registered connections -> Network/firewall issue
Requirements
Environment:
- Cloudflare account with domain
- Docker and Docker Compose installed
- Internet connectivity
.envfile in project root
Accounts/Access:
- Cloudflare dashboard access
- Zero Trust enabled (free tier works)
Tools needed:
- Read, Write, Edit (for .env configuration)
- Bash (for docker commands and verification)
- Grep (for checking existing configuration)
Red Flags to Avoid
- Do not commit tunnel token to git (keep in .env only)
- Do not use
host.docker.internalon Linux hosts - Do not use HTTPS URLs for internal service backends
- Do not share tunnel tokens between environments
- Do not skip the verification step (3.6)
- Do not forget to configure public hostnames after tunnel connects
- Do not leave placeholder token values in .env
Notes
- Tunnel tokens do not expire but can be revoked in dashboard
- Each tunnel can have multiple connectors (for redundancy)
- Tunnel configuration changes apply automatically (no restart needed)
- Use
./scripts/cf-tunnel-config.sh configureto update ingress via API - For authentication, use the
configure-google-oauthskill after tunnel setup - The existing
troubleshoot-tunnel-connectivityskill handles issues with running tunnels