YTunnel
___ ___ _______ __
| | |_ _|.--.--.-----.-----.-----.| |
\ / | | | | | | | -__|| |
|___| |___| |_____|__|__|__|__|_____||__|
Cloudflare tunnels made easy!
A TUI-first CLI for managing Cloudflare Tunnels with custom domains. Think ngrok, but using your own Cloudflare domain with persistent URLs and a dashboard to manage them.
Supported Platforms: macOS and Linux
Features
- TUI Dashboard - Interactive interface to manage all your tunnels
- Live Metrics - Real-time request counts, error rates, and connection status
- Persistent tunnels - Tunnels run as background daemons (launchd on macOS, systemd on Linux)
- Automatic DNS management - Creates and updates CNAME records automatically
- Multi-zone support - Use different domains for different tunnels
- SSL/HTTPS - Automatic via Cloudflare
- Ephemeral mode - Quick one-off tunnels that stop when you exit
Prerequisites
-
cloudflared - Cloudflare's tunnel daemon
macOS:
Linux (Debian/Ubuntu):
| | &&Linux (other):
# Download the latest release from https://github.com/cloudflare/cloudflared/releasesNote: You only need to install cloudflared. Do NOT run it as a system service. YTunnel manages cloudflared processes directly.
-
Cloudflare API Token with these permissions:
- Zone:Read
- DNS:Edit
- Account > Cloudflare Tunnel:Edit
Create one at: https://dash.cloudflare.com/profile/api-tokens
-
A domain managed by Cloudflare (free tier works)
Installation
From crates.io (recommended)
From source
Pre-built binaries
Download from GitHub Releases.
Quick Start
# First-time setup
# Open the TUI dashboard
# Or add a tunnel directly from CLI
Architecture
How YTunnel Works
YTunnel is a management tool, not a daemon itself. Here's how the pieces fit together:
┌─────────────────────────────────────────────────────────────────┐
│ ytunnel (CLI/TUI) │
│ Management tool - runs only when you invoke it │
└─────────────────────────────────────────────────────────────────┘
│
Creates & manages configs for
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ launchd (macOS) / systemd (Linux) │
│ System service manager - always running │
│ │
│ macOS: ~/Library/LaunchAgents/com.ytunnel.<name>.plist │
│ Linux: ~/.config/systemd/user/ytunnel-<name>.service │
└─────────────────────────────────────────────────────────────────┘
│
Starts/stops/monitors
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cloudflared processes │
│ One process per tunnel - runs in background │
│ │
│ • cloudflared tunnel --config myapp.yml run │
│ • cloudflared tunnel --config api.yml run │
└─────────────────────────────────────────────────────────────────┘
│
Connects to
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Cloudflare Edge │
│ Routes traffic to your tunnels │
└─────────────────────────────────────────────────────────────────┘
Persistence Model
| Mode | How it runs | Survives reboot? | Use case |
|---|---|---|---|
Ephemeral (ytunnel run) |
Foreground process | No | Quick testing, one-off tunnels |
Persistent (ytunnel add --start) |
launchd/systemd | Yes* | Production, always-on services |
*Tunnels don't auto-start by default. They start when you run ytunnel start and keep running until you ytunnel stop or reboot. To auto-start on login, press A in the TUI to toggle auto-start (⟳ indicator shows when enabled).
What YTunnel Creates
When you run ytunnel add myapp localhost:3000 --start:
- Cloudflare Tunnel - Created via API, persists in your Cloudflare account
- DNS Record - CNAME pointing
myapp.yourdomain.com→ tunnel - Credentials - Tunnel credentials JSON file
- Config - cloudflared YAML config file
- Service - launchd plist (macOS) or systemd unit (Linux)
- State - Entry in
tunnels.toml
The service file tells launchd/systemd to run cloudflared with your config. Logs go to the logs directory.
TUI Dashboard
Run ytunnel with no arguments to open the interactive dashboard:
┌─ Tunnels (3) ─────────────────────┬─ Logs: myapp ─────────────────────────────────┐
│ ● myapp myapp.example.com │ 2024-01-20 10:30:15 INF Starting tunnel │
│ ● api api.example.com │ 2024-01-20 10:30:16 INF Connection registered │
│ ○ staging staging.example.com │ 2024-01-20 10:30:17 INF Tunnel connected │
│ │ 2024-01-20 10:30:18 INF Route propagated │
│ │ 2024-01-20 10:30:21 INF Request served GET / │
│ ├─ Metrics ─────────────────────────────────────┤
│ │ Requests: 1,247 Errors: 3 Active: 2 │
│ │ Health: ✓ healthy │
│ │ HA Connections: 4 Edge: dfw08, den01 │
│ │ Status Codes: 200:1198 304:42 404:3 500:4 │
│ │ Traffic: ▁▂▃▅▆▄▃▂▁▂▃▄▅▆▇█▆▅▄▃▂▁▂▃▄▅▆▇ │
├───────────────────────────────────┴───────────────────────────────────────────────┤
│ Started myapp │
│ [a]dd [s]tart [S]top [R]estart [c]opy [o]pen [h]ealth [d]elete [r]efresh [q]uit │
└───────────────────────────────────────────────────────────────────────────────────┘
Status indicators:
●Running (green)○Stopped (yellow)✗Error (red)⟳Auto-start enabled (cyan, shown after hostname)
Keyboard shortcuts:
| Key | Action |
|---|---|
a |
Add a new tunnel |
s |
Start selected tunnel |
S |
Stop selected tunnel |
R |
Restart tunnel (updates daemon config) |
c |
Copy tunnel URL to clipboard |
o |
Open tunnel URL in browser |
h |
Check tunnel health |
A |
Toggle auto-start on login (⟳ = enabled) |
d |
Delete selected tunnel |
m |
Import ephemeral tunnel as managed |
r |
Refresh status |
↑/↓ or j/k |
Navigate list |
q |
Quit |
Tunnels continue running in the background after you close the TUI.
Metrics Panel
For running tunnels, the TUI displays live metrics from cloudflared's Prometheus endpoint:
- Requests - Total requests handled by the tunnel
- Errors - Number of failed requests (red if > 0)
- Active - Currently in-flight concurrent requests
- Health - Whether the tunnel URL is reachable (✓ healthy / ✗ unreachable)
- HA Connections - Number of connections to Cloudflare edge (4 = healthy)
- Edge - Cloudflare edge locations (e.g.,
dfw08= Dallas) - Status Codes - Breakdown of HTTP response codes
- Traffic - Sparkline showing request rate over time
Metrics auto-refresh every 5 seconds. Health checks run every 30 seconds. Use h for immediate health check.
Notifications
When a tunnel goes down or comes back up, ytunnel sends a system notification. This helps you catch issues even when the TUI isn't visible.
- macOS: Uses
terminal-notifier(if installed) orosascript - Linux: Uses
notify-send(requireslibnotify)
Ephemeral Tunnels
Ephemeral tunnels (created with ytunnel run) also appear in the TUI marked as [ephemeral]. You can:
- View them alongside managed tunnels
- Delete them from Cloudflare
- Import them as managed tunnels (press
m) to add daemon control
CLI Commands
Persistent Tunnels
# Add a tunnel (doesn't start it)
# Add and start immediately
# Use a specific zone
# Start/stop/restart tunnels
# View logs
# List all tunnels with status
# Delete a tunnel
Ephemeral Tunnels
For quick one-off tunnels that stop when you press Ctrl+C:
# Auto-generated subdomain (ytunnel-abc123.example.com)
# Named subdomain (myapp.example.com)
# Different zone
Zone Management
# List available zones
# Change default zone
Configuration
File Locations
macOS:
| Path | Purpose |
|---|---|
~/Library/Application Support/ytunnel/config.toml |
API credentials and zones |
~/Library/Application Support/ytunnel/tunnels.toml |
Persistent tunnel state |
~/Library/Application Support/ytunnel/<tunnel-id>.json |
Cloudflare tunnel credentials |
~/Library/Application Support/ytunnel/tunnel-configs/<name>.yml |
cloudflared config files |
~/Library/Application Support/ytunnel/logs/<name>.log |
Tunnel daemon logs |
~/Library/LaunchAgents/com.ytunnel.<name>.plist |
launchd service files |
Linux:
| Path | Purpose |
|---|---|
~/.config/ytunnel/config.toml |
API credentials and zones |
~/.config/ytunnel/tunnels.toml |
Persistent tunnel state |
~/.config/ytunnel/<tunnel-id>.json |
Cloudflare tunnel credentials |
~/.config/ytunnel/tunnel-configs/<name>.yml |
cloudflared config files |
~/.config/ytunnel/logs/<name>.log |
Tunnel daemon logs |
~/.config/systemd/user/ytunnel-<name>.service |
systemd service files |
Main Config
Config file location: ~/Library/Application Support/ytunnel/config.toml (macOS) or ~/.config/ytunnel/config.toml (Linux):
= "your-token"
= "your-account-id"
= "zone-id"
= "example.com"
[[]]
= "zone-id"
= "example.com"
Tunnel State
tunnels.toml (same directory as config.toml):
[[]]
= "myapp"
= "localhost:3000"
= "abc123"
= "example.com"
= "myapp.example.com"
= "cf-tunnel-id"
= true
= false # Set to true to start on login
Troubleshooting
Check tunnel status
# Via ytunnel
# Via system service manager
|
View logs
# In TUI: select tunnel and view right pane
# Or directly
Tunnel won't start
- Check if cloudflared is installed:
cloudflared --version - Check the log file for errors
- Verify credentials exist in the config directory
- Try running manually:
cloudflared tunnel --config <config-path> run
Manually manage a tunnel
macOS:
# Stop
# Start
# Remove completely
Linux:
# Stop
# Start
# Remove completely
License
MIT