Overview
Cloudflare Tunnel (via cloudflared) creates an encrypted tunnel from your machine to Cloudflare’s edge. No open ports, no firewall changes, free with unlimited bandwidth.
| Best for | Production deployments, free persistent URLs |
| TLS | Automatic (Cloudflare edge) |
| Persistent URL | Yes (your domain) |
| Auth layer | None (add Cloudflare Zero Trust) |
Prerequisites
- A Cloudflare account (free plan works)
- A domain added to Cloudflare (DNS managed by Cloudflare)
Install
macOS:
brew install cloudflaredDebian/Ubuntu:
sudo mkdir -p --mode=0755 /usr/share/keyringscurl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg \ | sudo tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/nullecho "deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.gpg] https://pkg.cloudflare.com/cloudflared any main" \ | sudo tee /etc/apt/sources.list.d/cloudflared.listsudo apt-get update && sudo apt-get install cloudflaredRHEL/CentOS:
curl -fsSl https://pkg.cloudflare.com/cloudflared.repo \ | sudo tee /etc/yum.repos.d/cloudflared.reposudo yum update && sudo yum install cloudflaredSetup
Step 1: Authenticate with Cloudflare
cloudflared tunnel loginThis opens a browser to log in. On success, it writes a certificate to ~/.cloudflared/cert.pem.
Step 2: Create a Tunnel
cloudflared tunnel create codepiperNote the tunnel UUID from the output (e.g., a1b2c3d4-e5f6-7890-abcd-ef1234567890).
Step 3: Create DNS Records
cloudflared tunnel route dns codepiper codepiper.yourdomain.comcloudflared tunnel route dns codepiper codepiper-ws.yourdomain.comThis creates CNAME records in Cloudflare DNS pointing to your tunnel.
Step 4: Create the Config File
Create ~/.cloudflared/config.yml:
tunnel: a1b2c3d4-e5f6-7890-abcd-ef1234567890credentials-file: /home/youruser/.cloudflared/a1b2c3d4-e5f6-7890-abcd-ef1234567890.json
ingress: # Web dashboard - hostname: codepiper.yourdomain.com service: http://localhost:3000
# WebSocket endpoint - hostname: codepiper-ws.yourdomain.com service: http://localhost:9999
# Catch-all (required — must be last) - service: http_status:404Step 5: Run the Tunnel
cloudflared tunnel run codepiperStep 6: Verify
cloudflared tunnel info codepiperOpen https://codepiper.yourdomain.com in your browser. The dashboard should load with full WebSocket connectivity.
Validate Your Config
# Check config syntaxcloudflared tunnel ingress validate
# Test which rule matches a URLcloudflared tunnel ingress rule https://codepiper-ws.yourdomain.com/wsWebSocket Support
Cloudflare Tunnel supports WebSocket connections transparently. Use http:// (not ws://) as the service scheme in your config — the WebSocket upgrade handshake passes through automatically. Clients connect using wss:// since Cloudflare terminates TLS.
Run as a System Service
# Linux (systemd)sudo cloudflared service installsudo systemctl enable --now cloudflared
# macOS (launchd)sudo cloudflared service installsudo launchctl start com.cloudflare.cloudflaredDaemon Environment
TRUST_PROXY_HEADERS=true \FORCE_SECURE_COOKIES=true \ALLOWED_ORIGINS=https://codepiper.yourdomain.com \codepiper daemon --webWhen to Use Something Else
Cloudflare Tunnel is excellent for production with custom domains. Consider adding Cloudflare Zero Trust for identity-aware access control on top. If you don’t want to manage a domain, consider Tailscale for private access or ngrok for quick sharing.
See the Remote Access overview for a comparison of all methods.