Getting started
Put a service on your domain
Connect your Cloudflare account and route a hostname such as app.yourhost.com to a service on your computer with Cloudflare Tunnel, with the DNS record made for you.
A route sends a hostname on one of your Cloudflare domains, such as app.yourhost.com,
to a service on your computer, such as localhost:3000. Unlike a
Quick Share, its address never changes and it stays
until you remove it. It can require a login, and it can
keep running after you quit the app.
Use a route for anything that should last: a self-hosted app, a staging site, a webhook endpoint you set once, SSH to a home machine. For a link that should only live for a session, a share on your domain is quicker and cleans up after itself. Choose how to share compares every option.
Before you start
- A Cloudflare account. The free plan is enough, and Cloudflare Tunnel costs nothing on any plan. Sign up if you don't have one.
- A domain on Cloudflare. In the Cloudflare dashboard choose Add a domain, then change the nameservers at your registrar to the two Cloudflare gives you. Routes on a domain start working once Cloudflare says it's Active. Until then, Teitunnel lists the domain under Domains as Waiting for nameservers, with the nameservers to set.
- Teitunnel installed, and the service running on your
machine: open
http://localhost:3000in your browser to check.
Add the route
Connect your Cloudflare account
Open Settings ▸ Accounts and choose Connect an Account (or Use My Own Domain… on the Overview). Then either:
- Sign in with Cloudflare: your browser opens Cloudflare's consent page. Allow access, and every account the sign-in reaches is connected. Nothing to copy.
- Or connect with an API token: Open Cloudflare opens the dashboard's Create API token page with Teitunnel's permissions selected. Choose Continue to summary, then Create Token, copy the token and paste it under Paste it here, then Connect.
Either way the credential is checked with Cloudflare, stored in your system's keychain (Keychain on macOS, Credential Manager on Windows, the Secret Service on Linux), and only ever sent to Cloudflare. Accounts and permissions explains the two ways and what each permission is for.

Start a new route
Open Routes (⌘2 / Ctrl+2) and choose New Route (⌘N / Ctrl+N). Under Service,
pick a detected dev server or container, or type a port (3000) or an address
(http://localhost:8080, https://localhost:8443, ssh://localhost:22).

Choose the hostname
Under Public hostname, type the subdomain (app) and pick the domain
(yourhost.com). Leave the subdomain empty to use the domain itself. Teitunnel says
whether the name is Available before you go on.
Optionally, under Advanced: restrict the route to a Path (such as ^/api/),
Require a login, or change the origin settings. With more than one
tunnel on this computer, Tunnel picks which one serves it.
Review
Choose Review. Teitunnel shows exactly what will change in Cloudflare, and nothing changes until you apply: the tunnel for this machine (created with your first route), its routes, and the DNS record. If a record Teitunnel didn't create already uses the hostname, the plan says so, and you tick Replace the existing records or go back and pick another name.

Add the route
Choose Add Route. Each step is checked off as it runs; if one fails, the earlier ones
are undone. Teitunnel then requests https://app.yourhost.com through Cloudflare and
tells you whether It works (the connector can take a few seconds to connect the first
time). The route shows as Live in Routes.
From the terminal
teitunnel setup # once: store an API token in the keychain
teitunnel route add app.yourhost.com 3000The command prints the same plan and asks before applying:
$ teitunnel route add app.yourhost.com 3000
1. Create tunnel “laptop”
2. Update tunnel “laptop” to serve 1 route
3. Add DNS record app.yourhost.com → tunnel “laptop”
4. Check https://app.yourhost.com works
Apply? [y/N] y
https://app.yourhost.com works.teitunnel routes lists what's routed. --allow ana@yourhost.com adds a login, --path
limits the route to some paths, -y applies without asking, and --replace confirms
replacing a record Teitunnel didn't create. The command exits with status 1 if the check
fails. Every flag is in the command reference.
teitunnel route add runs from the terminal, but the route itself is served by a connector:
the app's while it runs, or teitunnel up, always-on or teitunnel serve.
What was created
In your Cloudflare account you'll now find:
- a tunnel named after this machine (Zero Trust ▸ Networks ▸ Tunnels), created with your first route and shared by every later one,
- a published application route on it:
app.yourhost.com→http://localhost:3000, - a proxied
CNAMErecordapp.yourhost.com→<tunnel-id>.cfargotunnel.com(DNS ▸ Records), with the commentteitunnel:route=…so Teitunnel knows it made it.
The change is recorded, step by step, in Activity, and the confirmation that appears right after applying has Undo to take it back. See routes and tunnels for how these fit together, and DNS ownership for which records Teitunnel will change.
What it needs
| Cloudflare plan | Free. Tunnels and their traffic cost nothing on any plan. |
| Permissions | Cloudflare Tunnel · Edit, DNS · Edit, Zone · Read and Account Settings · Read. A login adds Access: Apps and Policies · Edit. See permissions. |
| On this computer | The connector (the app, or teitunnel up) running while people use the route. |
Origin settings
Advanced ▸ Origin settings covers everything cloudflared can do when it talks to your service. Leave a field empty for cloudflared's default.
- HTTPS services: Accept self-signed certificates, a Certificate name when the certificate isn't for the hostname it's reached at (or Use the visitor's hostname as the certificate name), a Certificate authority file of your own, or Connect with HTTP/2.
- Requests: a different Host header (for dev servers that only answer to their own name, like some Vite and webpack setups; see dev servers), Don't use chunked encoding (some WSGI servers need this), or a SOCKS5 Proxy for TCP routes.
- Connection (seconds): connect, TLS handshake and idle connection timeouts, TCP keepalive, idle connections kept, and Don't fall back between IPv4 and IPv6.
Settings made in the Cloudflare dashboard are kept when you edit a route here, and ones
Teitunnel doesn't show are never removed. Importing a config.yml carries its settings
over, including the ones at the top of the file that apply to every route. In the terminal,
each setting has a flag (--no-tls-verify, --host-header, --connect-timeout…).
Keep it running
The route runs through this machine's connector while Teitunnel is open, including when its window is closed and it's only in the menu bar or tray. Quit the app and the route stops answering (visitors see Cloudflare's error 1033, or your offline page).
To keep it running after you quit and across restarts, turn on
Tunnels ▸ Keep running when Teitunnel quits (teitunnel always-on in the terminal). See
run modes.
If it doesn't work
- The check says 502, or "nothing is listening". Cloudflare reached your computer but the service didn't answer. Check the port, and that the service is running.
- Error 1033. No connector is running for the tunnel: open Teitunnel, or turn on Keep running when Teitunnel quits.
- The domain isn't in the list. It isn't on the connected account, or the credential can't reach it. Check Domains, and the account's Permissions in Settings ▸ Accounts.
- "This change replaces DNS records Teitunnel didn't create. Confirm it first." The name is in use. Tick Replace the existing records if you mean to, or choose another name.
- A dev server answers "Blocked request" or "Invalid Host header". Set the Host header under Origin settings; see dev servers.
The Doctor finds most of these by itself, and troubleshooting covers Cloudflare's error pages one by one.
Next
Last updated on
Share a local service
Get a free public HTTPS URL for anything running on your computer with Cloudflare Tunnel, in one click and without a Cloudflare account.
Find your way around
A tour of the Teitunnel app, section by section, with what each part is for, where its terminal equivalent is, the keyboard shortcuts, the command palette and Settings.


