Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Tunnels create encrypted outbound connections from your infrastructure to Cloudflare's edge, eliminating the need to open inbound ports.
Create and Configure a Tunnel
# Authenticate with Cloudflare
cloudflared tunnel login
# Create a named tunnel
cloudflared tunnel create internal-apps
# This creates credentials at ~/.cloudflared/<TUNNEL_ID>.json# List tunnels
cloudflared tunnel list
# Route DNS to the tunnel (creates a CNAME record)
cloudflared tunnel route dns internal-apps grafana.example.com
cloudflared tunnel route dns internal-apps wiki.example.com
cloudflared tunnel route dns internal-apps ssh.example.com
Tunnel Configuration File
# ~/.cloudflared/config.ymltunnel:<TUNNEL_ID>credentials-file:/home/deploy/.cloudflared/<TUNNEL_ID>.jsoningress:# Grafana dashboard-hostname:grafana.example.comservice:http://localhost:3000# Internal wiki-hostname:wiki.example.comservice:http://localhost:8080originRequest:noTLSVerify:true# SSH access via browser-hostname:ssh.example.comservice:ssh://localhost:22# Private network access (CIDR routing)-hostname:internal.example.comservice:http://10.0.0.0/24# Catch-all — required as the last rule-service:http_status:404
Run the Tunnel
# Run in foreground (for testing)
cloudflared tunnel run internal-apps
# Install as a systemd servicesudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
# Or run via Docker
docker run -d --name cloudflared \
--restart unless-stopped \
-v /home/deploy/.cloudflared:/etc/cloudflared \
cloudflare/cloudflared:latest \
tunnel run internal-apps
# Create a service token for CI/CD
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/service_tokens" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "github-actions-deploy"}'# Response includes Client ID and Client Secret# Use in CI with headers:# CF-Access-Client-Id: <CLIENT_ID># CF-Access-Client-Secret: <CLIENT_SECRET>
# Use service token in CI/CD
curl -H "CF-Access-Client-Id: $CF_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_CLIENT_SECRET" \
https://grafana.example.com/api/health
Device Posture Checks
Enforce endpoint requirements before granting access.
Configure Posture Checks (Dashboard)
Go to Settings > WARP Client > Device posture.
Add checks:
Disk encryption: Require FileVault (macOS) or BitLocker (Windows).
OS version: Minimum macOS 14.0 or Windows 11.
Firewall: Ensure host firewall is enabled.
Crowdstrike/SentinelOne: Verify EDR agent is running.
Reference posture checks in Access policies under Require rules.
Gateway DNS Filtering
Block malicious domains and enforce acceptable use policies at the DNS level.
DNS Locations
# Configure DNS endpoints for offices or networks# Dashboard: Gateway > DNS Locations > Add a location# Assign the Gateway DNS IPs to your network's DNS resolver:# IPv4: 172.64.36.1, 172.64.36.2# IPv6: 2606:4700:4700::1111# DoH: https://<UNIQUE_ID>.cloudflare-gateway.com/dns-query
DNS Policies
# Create a DNS policy to block malware and phishing
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Block Security Threats",
"enabled": true,
"action": "block",
"traffic": "any(dns.security_category[*] in {80 83 131 134 151 153})",
"filters": ["dns"]
}'
Common DNS Policy Rules
Rule Name
Traffic Expression
Action
Block malware
any(dns.security_category[*] in {80 83})
Block
Block phishing
any(dns.security_category[*] in {131 134})
Block
Block social media
any(dns.content_category[*] in {75})
Block
Allow exceptions
dns.fqdn == "allowed.example.com"
Allow
WARP Client Deployment
Deploy the Cloudflare WARP client to route traffic through Gateway.
# MDM deployment — macOS configuration profile# Use Cloudflare's managed deployment:# Dashboard: Settings > WARP Client > Device enrollment# Manual enrollment# 1. Install WARP client from https://1.1.1.1# 2. Click gear icon > Account > Login with Cloudflare Zero Trust# 3. Enter your team name (from Settings > General)# Verify WARP is connected
curl https://connectivity.cloudflare.com/cdn-cgi/trace
# Look for: warp=on
WARP Split Tunnels
# Configure split tunnels to exclude certain traffic from WARP# Dashboard: Settings > WARP Client > Device settings > Split Tunnels# Exclude mode (default): WARP handles everything except listed IPs# Include mode: WARP only handles listed IPs/domains# Common exclusions:# - Local network: 192.168.0.0/16, 10.0.0.0/8# - Video conferencing: zoom.us, *.teams.microsoft.com# - Printer subnets
SSH and Browser-Based Terminal
# In cloudflared config.yml — expose SSH via browser renderingingress:-hostname:ssh.example.comservice:ssh://localhost:22
# Users access ssh.example.com in their browser# Cloudflare renders an in-browser terminal after Access authentication# Or use cloudflared on the client side for native SSH
cloudflared access ssh --hostname ssh.example.com
# Add to SSH config for seamless access# ~/.ssh/config# Host ssh.example.com# ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
Troubleshooting
Symptom
Cause
Fix
Tunnel shows ERR in dashboard
cloudflared not running or config error
Check systemctl status cloudflared; validate config YAML
Access returns 403 despite correct identity
Policy order or missing require rule
Policies are evaluated top-to-bottom; ensure Allow is above Block
WARP shows "Unable to connect"
Team name wrong or enrollment disabled
Verify team name in Settings > General; check enrollment permissions
Service token auth fails
Token expired or wrong headers
Regenerate token; use both CF-Access-Client-Id and CF-Access-Client-Secret
DNS filtering not blocking
Client not using Gateway DNS resolvers
Verify DNS is set to 172.64.36.1; check WARP is connected
Tunnel latency spikes
Tunnel running on overloaded host
Monitor cloudflared resource usage; run on dedicated infra
"No healthy origins" error
Backend service is down
Check the service at the configured ingress port; review cloudflared logs