README
ΒΆ
cftunn
Zero-config Cloudflare Tunnels for Developers.
Expose localhost to the world in seconds with a custom domain.
cftunn is a lightweight CLI tool that automates the creation of Cloudflare Tunnels. It abstracts away the complexity of creating tunnels, routing DNS, and configuring ingress rules into a single command.
Designed for developers who want the ease of ngrok but with their own custom domains and the security/performance of Cloudflare.
β¨ Features
- One-Command Setup: No YAML configs, no UUID management. Just
cftunn <port> <domain>. - Automatic DNS: Automatically manages CNAME records for your domain.
- Smart Auth: seamlessly integrates with your existing
cloudflaredlogin or API tokens. - Self-Healing: Automatically cleans up or rotates credentials for existing named tunnels to ensure a successful connection.
- Safe: Prompts for confirmation before overwriting existing DNS records.
- Cross-Platform: Works on macOS and Linux.
π Installation
Homebrew (Recommended)
brew install thatjuan/tap/cftunn
Automatic
Install the latest binary for your OS/Arch:
curl -fsSL https://raw.githubusercontent.com/thatjuan/cftunn/main/install.sh | bash
From Source
You need Go 1.20+ installed.
go install github.com/thatjuan/cftunn@latest
Or clone the repo:
git clone https://github.com/thatjuan/cftunn.git
cd cftunn
make install
π Updating
To update to the latest version, simply run the installation command again.
Homebrew:
brew upgrade cftunn
Automatic:
curl -fsSL https://raw.githubusercontent.com/thatjuan/cftunn/main/install.sh | bash
From Source:
go install github.com/thatjuan/cftunn@latest
Prerequisites
1. cloudflared
This tool relies on the official Cloudflare Tunnel daemon.
- macOS:
brew install cloudflared - Linux: Installation Instructions
2. Authentication
You need to be authenticated with Cloudflare.
-
Method A: Interactive Login (Recommended)
Run this once to authorize your machine:cloudflared tunnel loginThis will open your browser and generate a
cert.pemfile. -
Method B: API Token (CI/CD friendly)
Set the environment variable:export CLOUDFLARE_API_TOKEN=your_api_tokenSee Creating an API Token below for the required permissions and step-by-step instructions.
π Creating an API Token
cftunn needs an API token with these permissions:
| Scope | Permission | Why |
|---|---|---|
| Account | Cloudflare Tunnel:Edit |
Create/delete tunnels and read account info. |
| Zone | DNS:Edit |
Create/update the CNAME pointing to your tunnel. |
| Zone | Zone:Read |
Look up the zone ID for your domain. |
Option 1: Cloudflare Dashboard (Recommended)
- Open https://dash.cloudflare.com/profile/api-tokens.
- Click Create Token β Create Custom Token β Get started.
- Set Token name (e.g.
cftunn). - Under Permissions, add the three rows above.
- Under Account Resources, select Include β <your account>.
- Under Zone Resources, select Include β All zones (or pin to a specific zone).
- Click Continue to summary β Create Token.
- Copy the token and export it:
export CLOUDFLARE_API_TOKEN=<paste-here> - Verify it works:
cftunn auth whoami
Option 2: Mint via cftunn auth create-token (Advanced)
If you already hold a bootstrap token with the API Tokens Write permission (created from the dashboard's Create Additional Tokens template), cftunn can mint a properly scoped token for itself:
# Export the bootstrap token first
export CLOUDFLARE_API_TOKEN=<bootstrap-token>
# Mint a cftunn-scoped token (uses first accessible account, all zones)
cftunn auth create-token
# Or pin to a specific zone and account
cftunn auth create-token --zone example.com --account <account-id> --name cftunn-prod
The new token's value is printed once. Export it for subsequent cftunn runs:
export CLOUDFLARE_API_TOKEN=<new-token>
Note: There is no fully zero-state automation path. Cloudflare's
POST /user/tokensrequires an existing privileged token, and there is no public OAuth flow orcloudflaredsubcommand for first-time token issuance β so the dashboard step (Option 1) is unavoidable for the very first token.
References: Create tokens via API, Permission groups.
π Usage
Basic Example
Expose your local server running on port 3000 to dev.example.com:
cftunn 3000 dev.example.com
Advanced Usage
Tunnel to a specific host (e.g., a container or VM):
cftunn 8080 dev.example.com --host 192.168.1.100
What happens next?
cftunnchecks for the tunnelcftunn-dev-example-com.- If it doesn't exist, it creates it.
- It checks if
dev.example.comexists in your DNS. - It routes the tunnel to that hostname (prompting if it needs to overwrite).
- It starts the tunnel, forwarding traffic to
localhost:3000.
Flags
Usage:
cftunn [PORT] [DOMAIN] [flags]
Flags:
-D, --debug Enable debug output for troubleshooting
-d, --domain string Domain to expose (e.g. dev.example.com)
-h, --help help for cftunn
-H, --host string Target host to tunnel to (default: localhost)
-p, --port int Local port to tunnel to
-v, --version version for cftunn
Troubleshooting
If you encounter issues during tunnel setup, use the --debug flag to get detailed output:
cftunn 3000 dev.example.com --debug
This will show:
- Authentication method detection (API token vs cert.pem)
- cloudflared commands being executed
- API calls and responses
- Zone and DNS record lookups
- Tunnel creation/deletion operations
π οΈ Development & Contributing
We welcome contributions!
Setup
- Fork the repository.
- Clone your fork:
git clone https://github.com/thatjuan/cftunn.git cd cftunn - Install dependencies:
go mod tidy
Building
Use the included Makefile:
make build
# Output binary is ./cftunn
Testing
Currently, manual testing is required due to the integration nature of the tool (requires real Cloudflare API).
- Mocking: Future improvements should include interfaces for the Cloudflare API to allow unit testing.
Reporting Bugs
Please open an issue on GitHub with:
- Your OS version.
- The command you ran.
- The error output (redacted of any tokens/secrets).
- Output of
cloudflared --version.
π License
MIT License. See LICENSE for details.
Disclaimer
This is a community project and is not affiliated with Cloudflare. Use it at your own risk.
Documentation
ΒΆ
There is no documentation for this package.