Skip to main content

Cloudflare Tunnel

Expose CodePiper through Cloudflare's edge network with automatic TLS, no open ports, and unlimited bandwidth.

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 forProduction deployments, free persistent URLs
TLSAutomatic (Cloudflare edge)
Persistent URLYes (your domain)
Auth layerNone (add Cloudflare Zero Trust)

Prerequisites

  • A Cloudflare account (free plan works)
  • A domain added to Cloudflare (DNS managed by Cloudflare)

Install

macOS:

Terminal window
brew install cloudflared

Debian/Ubuntu:

Terminal window
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg \
| sudo tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null
echo "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.list
sudo apt-get update && sudo apt-get install cloudflared

RHEL/CentOS:

Terminal window
curl -fsSl https://pkg.cloudflare.com/cloudflared.repo \
| sudo tee /etc/yum.repos.d/cloudflared.repo
sudo yum update && sudo yum install cloudflared

Setup

Step 1: Authenticate with Cloudflare

Terminal window
cloudflared tunnel login

This opens a browser to log in. On success, it writes a certificate to ~/.cloudflared/cert.pem.

Step 2: Create a Tunnel

Terminal window
cloudflared tunnel create codepiper

Note the tunnel UUID from the output (e.g., a1b2c3d4-e5f6-7890-abcd-ef1234567890).

Step 3: Create DNS Records

Terminal window
cloudflared tunnel route dns codepiper codepiper.yourdomain.com
cloudflared tunnel route dns codepiper codepiper-ws.yourdomain.com

This 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-ef1234567890
credentials-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:404

Step 5: Run the Tunnel

Terminal window
cloudflared tunnel run codepiper

Step 6: Verify

Terminal window
cloudflared tunnel info codepiper

Open https://codepiper.yourdomain.com in your browser. The dashboard should load with full WebSocket connectivity.

Validate Your Config

Terminal window
# Check config syntax
cloudflared tunnel ingress validate
# Test which rule matches a URL
cloudflared tunnel ingress rule https://codepiper-ws.yourdomain.com/ws

WebSocket 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

Terminal window
# Linux (systemd)
sudo cloudflared service install
sudo systemctl enable --now cloudflared
# macOS (launchd)
sudo cloudflared service install
sudo launchctl start com.cloudflare.cloudflared

Daemon Environment

Terminal window
TRUST_PROXY_HEADERS=true \
FORCE_SECURE_COOKIES=true \
ALLOWED_ORIGINS=https://codepiper.yourdomain.com \
codepiper daemon --web

When 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.