How to Use Cloudflare Tunnel: The Beginner's Guide

CodexFuse Team · 2026-11-02T22:45:59.164Z · 18 min read min read

What Is Cloudflare Tunnel, Exactly?

Learning how to use Cloudflare Tunnel means learning how to expose a service running on your own machine to the internet without opening a single inbound port. A tiny daemon called cloudflared makes outbound-only connections to Cloudflare's network, Cloudflare publishes the hostname you choose, and visitors reach your app over HTTPS as if it were hosted in a datacenter — no port forwarding on your router, no dynamic-DNS workaround, no exposed SSH port. The tunnel itself is free on every Cloudflare plan, and a first setup takes about fifteen minutes. This guide walks you through it beginner-style: the dashboard path for your first named tunnel, the one config file that controls everything (the ingress rule), multiple services on one tunnel, the Docker setup, SSH over the tunnel, and the one-command quick tunnel for throwaway tests. If you are weighing this against a mesh VPN instead, our Tailscale beginner guide covers that lane — a tunnel needs no client installed on any device, while Tailscale puts every device on one private network. And once your first hostname is live, run it through an SSL certificate checker to confirm HTTPS is serving correctly.

One disambiguation before anything else, because the names collide: Cloudflare Tunnel is the tunneling product (the one Cloudflare renamed from "Argo Tunnel" in 2021); the daemon you install is called cloudflared. WARP is a different product — the consumer 1.1.1.1 app — and this guide is not about it.

How Does a Cloudflare Tunnel Actually Work?

A tunnel is a persistent object, identified by a UUID, whose connectors dial out from your machine to Cloudflare — your firewall can block every inbound port and the tunnel still works. You run one or more cloudflared processes ("connectors") on the origin machine; each attaches to the nearest Cloudflare data center, and Cloudflare routes public traffic for your hostnames down those outbound connections. Within one tunnel you can run as many connectors as you like, which is how the setup survives a connector dying. That is Cloudflare's own description of the model (their docs), and it is the whole trick: nothing ever dials in to you.

Two field notes from people who tested it independently: indie testers report that a tunnel keeps four long-lived connections to two data centers for redundancy, and that cloudflared needs outbound access on port 7844 (UDP and TCP) — so if your network has a strict egress firewall, that port must be open out. Flavio Copes verified the port requirement on his own Mac in September 2026 with cloudflared 2026.9.1.

What Do You Need Before You Start?

Your Cloudflare Tunnel setup needs three things: a free Cloudflare account, a domain whose DNS is on Cloudflare, and a machine that stays on. The free plan is enough — say it once and stop worrying: tunnels, DNS, and the Access login feature below all work on the free tier. The domain requirement is the one people trip on: a named tunnel publishes hostnames on your domain, so the domain's nameservers must point at Cloudflare (the free plan includes this). The machine can be anything always-on — a Raspberry Pi, a home server, or a VPS if you would rather rent the box than run one.

The last beginner trap is the free-plan limits, so here is what I actually verified at write time instead of guessing: quick tunnels cap at 200 in-flight requests (extras get a 429), they carry no uptime guarantee and support no Server-Sent Events; uploads through the proxy are capped at 100 MB on Free and Pro plans; and Cloudflare publishes no stated limit on concurrent named tunnels or tunnel bandwidth — any round number you see quoted for those in a forum thread is invented. The "Is it free?" section below has the receipts.

How Do You Create Your First Tunnel in the Dashboard?

The dashboard path needs no config file: you name a tunnel, install one command on your machine, wait for it to report Healthy, then add a route that maps a hostname to your local service. This is the remotely-managed (dashboard) flow from Cloudflare's own get-started docs, and it is the one beginners should use first. Follow it exactly:

  1. Install the latest cloudflared first. Step zero, not step five: grab the current release from Cloudflare's downloads page for your OS. In October 2026 Cloudflare issued an advisory asking everyone to run cloudflared 2026.10.2 or newer (compromised certificates), so do not install from a stale tutorial's link — check the version on the downloads page at write time.
  2. Open the Zero Trust dashboard and create the tunnel. Log in at one.dash.cloudflare.com, go to Networks → Tunnels, and choose "Create a tunnel". Give it a name you will recognize later, like homelab.
  3. Pick your origin OS and copy the install command. The dashboard shows a connector command for your platform. Run it on the machine where your service lives — this is the step that generates the tunnel token.
  4. Run the connector and wait for Healthy. Start cloudflared on the origin with the token. Back in the dashboard, the tunnel's status should flip to Healthy — that is your proof the outbound connection reached Cloudflare.
  5. Add your first route. Open the tunnel, go to the Routes tab, choose "Add route", then "Published application". Enter a subdomain (say app), pick your domain, and set the Service URL to where the app actually listens — for example http://localhost:8000.
  6. Open your new hostname. Visit https://app.example.com in a browser. Your local service is now public, with Cloudflare's HTTPS in front of it, and your router still has zero open ports.
  7. Lock it down next. Right now anyone on the internet can reach the route you just published. The "lock a route behind a login" section below adds a Cloudflare Access application in front of it — do this before you publish anything you would not show a stranger.

This dashboard flow is also where the "cloudflare zero trust tunnel" keyword lives in practice: the tunnel connector is managed under Zero Trust → Networks, while the login gate (Access) is managed under Zero Trust → Access. Two different tabs, two different jobs.

What Goes in the Ingress Rule?

The Cloudflare Tunnel ingress rule is a short YAML config file that maps hostnames to local services: rules are evaluated top to bottom, the first match wins, and a catch-all rule with no hostname is mandatory at the very end. You need this file when you manage the tunnel locally (the CLI path) instead of purely through the dashboard. Cloudflare's configuration docs give the shape:

tunnel: YOUR-TUNNEL-UUID
credentials-file: /root/.cloudflared/YOUR-TUNNEL-UUID.json
ingress:
  - hostname: app.example.com
    service: http://localhost:80
  - hostname: ssh.example.com
    service: ssh://localhost:22
  - service: http_status:404

Read it like a routing table. A request for app.example.com goes to the web server on port 80; a request for ssh.example.com goes to SSH on port 22; anything else hits the catch-all, which returns a 404 instead of leaking some default service. Delete that last rule and the config is invalid — the catch-all is not optional.

Two indie gotchas worth knowing before you fight the file: validate the rules before you run with cloudflared tunnel ingress validate, and when you install cloudflared as a system service it snapshots whatever config it finds and hard-codes the path — ssdnodes' field notes put that path at /etc/cloudflared/config.yml, not the home directory, so edit the file the service actually reads.

How Do You Expose Multiple Services on One Tunnel?

Running Cloudflare Tunnel multiple services means adding one ingress entry per hostname — web apps, SSH, anything — and they all ride the same tunnel UUID, with the catch-all still last. One tunnel is not one service; it is one pipe with a routing table. A homelab example: app.example.com → http://localhost:8000, files.example.com → http://localhost:8080, ssh.example.com → ssh://localhost:22, then the http_status:404 catch-all. In the dashboard path you do the same thing by adding multiple routes to the same tunnel instead of editing YAML.

The DNS side is worth understanding once. Routes created in the dashboard automatically get a proxied CNAME pointing at <your-tunnel-UUID>.cfargotunnel.com; on the CLI you create the same record with cloudflared tunnel route dns <UUID or NAME> www.example.com. The record is independent of the tunnel — stop cloudflared and the DNS record stays, so visitors see a Cloudflare 1016 error until the connector comes back. That is per Cloudflare's routing docs, and it explains the most common "my tunnel is down but DNS looks fine" confusion.

How Do You Run cloudflared in Docker?

The cloudflared Docker path runs the official cloudflare/cloudflared image with your tunnel token as an environment variable — and that token is a password, so it lives in a .env file, never in a committed compose file and never pasted into a guide. Say the token rule once and keep it: anyone holding your token can attach a connector to your tunnel. The minimal run looks like this:

docker run cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token $TUNNEL_TOKEN

In Compose, put TUNNEL_TOKEN=... in a .env file next to your compose file (gitignore it), and reference the variable in the service definition — this is the pattern sumguy's deployment guide uses. If you have never touched Compose before, our Docker beginner guide walks through the install and the first stack. One more Flavio Copes gotcha: a quick tunnel will refuse to start if a ~/.cloudflared/config.yml already exists, because the leftover config conflicts with the throwaway run — delete or move it first.

How Do You Keep the Tunnel Running After a Reboot?

You install cloudflared as a system service, so the OS restarts it with the machine. Cloudflare's get-started docs give the one-liners: sudo cloudflared service install <TUNNEL_TOKEN> on Linux and macOS, cloudflared.exe service install <TUNNEL_TOKEN> on Windows. After that the connector survives reboots and crashes without you babysitting a terminal window. Remember the ssdnodes note from the ingress section: the service snapshots the config file it finds at install time, so make your config edits in the file the service actually reads (/etc/cloudflared/config.yml on Linux) and restart the service afterward.

How Do You Add SSH Over the Tunnel?

Cloudflare Tunnel SSH starts with a route whose service is ssh://localhost:22, then you teach your local SSH client to dial through cloudflared instead of the open internet. On the server side this is just another route: hostname ssh.example.com, service type SSH, pointing at port 22. On your laptop, install cloudflared and add this to ~/.ssh/config:

Host ssh.example.com
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

Then ssh [email protected] works like normal SSH — except the first connection opens a browser for an identity-provider login instead of trusting whatever key happens to be on disk. That is Cloudflare's documented SSH flow, and their docs recommend stacking a Cloudflare Access application on top of the route, which the next section covers. The practical win: your SSH port is reachable from anywhere you are, and from nowhere else.

How Do You Lock a Route Behind a Login?

You create a Cloudflare Access application in the Zero Trust dashboard — Access → Applications — and attach it to the hostname; the tunnel config file has nothing to do with it. This is the caution the queue item flagged, and it is still true: login policies live in Zero Trust → Access, not in the tunnel's ingress rules. An Access application lets you require, say, a Google or GitHub login (or a one-time PIN) before Cloudflare will proxy a single byte to your origin. Pricing, from Cloudflare's own Access page: free for teams under 50 users, then $7 per user per month billed annually. For a homelab that means the login gate costs nothing.

The beginner arc is therefore: get the route working open first (so you know the tunnel itself is healthy), then add the Access application, then test from a logged-out browser to confirm strangers actually get stopped. Never skip the last step — "it has a login" is a claim you verify, not a feeling.

What Is a Quick Tunnel, and When Should You Use One?

A Cloudflare Tunnel quick tunnel is one command that gives you a temporary public URL with no account and no domain — and it dies the moment you press Ctrl-C, so it is never production. Run cloudflared tunnel --url http://localhost:8080 and you get a trycloudflare.com address for whatever is listening on port 8080. That is the whole product: the fastest possible way to show someone your local work.

Know the verified limits before you lean on it (Cloudflare's TryCloudflare docs): no uptime guarantee, a maximum of 200 in-flight requests with anything beyond that rejected as a 429, no Server-Sent Events, and the hostname changes on every run. The newest docs add that --allowed-mail email-PIN protection requires an interactive browser — non-interactive clients cannot use it. The honest use case, and the one indie guides keep coming back to, is throwaway webhook testing: point a third-party webhook at the temporary URL, watch the traffic, kill the tunnel when you are done. For a stable registered webhook URL you want a named tunnel, because the quick URL will be different next time.

Cloudflare Tunnel vs ngrok: Which Should You Pick?

Both punch through NAT with no open ports; pick Cloudflare Tunnel when you want a stable hostname on your own domain for free, and ngrok when you want the fastest anonymous share with built-in traffic inspection. They are the two names every beginner compares, so here is the honest split on facts I verified this run — Tunnel facts from Cloudflare's docs, ngrok facts from ngrok's own docs and blog (both crawled within the last day):

Cloudflare Tunnelngrok
Account needed for a quick shareNone — a quick tunnel needs no account and no domainRequired — the agent needs your auth token even for a quick share
Your own domain on the free tierYes — any domain on the free Cloudflare planNo — bring-your-own domains need the pay-as-you-go plan; free gets a static ngrok-free.dev dev domain
Does the free URL stay stable?Quick tunnels change every run; named tunnels are stable on your domainYes — every account, free included, gets a permanent dev domain
Free-tier traffic limitsQuick tunnels: 200 in-flight requests max; no published quota on named-tunnel bandwidth found anywhere in the docs20,000 requests/month, 1 GB/month bandwidth, 3 concurrent endpoints
Visitor experience on freeDirect to your domain, no interstitialBrowser warning interstitial on free HTTP/S endpoints that visitors must click through
Multiple servicesOne tunnel, one ingress table, unlimited hostnames3 concurrent endpoints on free, one per tunnel command

The one-line version: ngrok optimizes for developer velocity (one command, instant URL, inspect the traffic in the dashboard); Cloudflare Tunnel optimizes for permanence (your domain, your TLS, stable routing, login gates) at zero marginal cost. If neither fits — because you want to own the tunnel server itself rather than rent Cloudflare's edge — our Pangolin beginner guide covers the self-hosted tunnel lane, where you run the ingress on your own VPS.

Is the Cloudflare Tunnel Free Tier Really Free?

The Cloudflare Tunnel free tier costs nothing: the tunnel is free on every Cloudflare plan, quick tunnels do not even need an account, and the only hard number I could verify is the general proxy upload cap of 100 MB on Free and Pro plans. That upload figure comes from Cloudflare's own Error-413 documentation, and it is a proxy-wide limit, not a tunnel-specific one. What I could not find, after checking the docs this run: any published limit on concurrent named tunnels or total tunnel bandwidth. The docs simply do not state one, and indie write-ups say the same. So when a forum post quotes a confident number for either, treat it as invented — the verified answer is "unstated".

The genuinely free stack for a homelab is therefore: free Cloudflare account, free DNS on your domain, free tunnel, and free Access login for up to 50 users. The bill is zero until your usage outgrows the free plan's general limits.

What Are the 7 Mistakes Beginners Make with Cloudflare Tunnel?

Every one of these comes from a real gotcha in the docs or the indie field notes above — avoid all seven and your first tunnel will behave.

MistakeWhat actually happensDo this instead
Committing the tunnel token to gitAnyone with the token can attach a connector to your tunnel.env file, gitignored, never pasted in guides
Using a quick tunnel for anything realIt dies on Ctrl-C and the URL rotates every runQuick tunnels for throwaway tests only; named tunnels for anything stable
Forgetting the catch-all ingress ruleThe config is invalid without a final no-hostname ruleAlways end ingress with - service: http_status:404
Stopping cloudflared but leaving the DNS recordThe CNAME persists independently; visitors get a 1016 errorDelete or disable the route/DNS record when you retire a tunnel
Blocking outbound 7844 on a strict firewallConnectors cannot reach Cloudflare; tunnel never goes HealthyAllow 7844 UDP+TCP outbound (inbound stays closed)
Looking for Access settings in the tunnel configThey are not there — login policies live in Zero Trust → AccessConfigure Access applications in the Zero Trust dashboard
Installing an old cloudflared and forgetting itYou miss security advisories like the October 2026 certificate oneCheck the downloads page for the current release; update on a schedule

Sources

  1. Cloudflare One docs — "Cloudflare Tunnel" overview (developers.cloudflare.com/cloudflare-one/connections/connect-networks/, doc updated 2026-08-04) — definition, outbound-only model, UUID tunnels, multi-connector design.
  2. Cloudflare docs — TryCloudflare / quick tunnels (updated 2026-09-30) — quick-tunnel command, 200 in-flight request cap, 429 behavior, no SSE, no uptime guarantee, --allowed-mail interactive-browser requirement.
  3. Cloudflare docs — "Create a remotely-managed tunnel" (updated 2026-06-23) — dashboard path: Networks → Tunnels → Healthy → Routes → Published application.
  4. Cloudflare docs — "Locally managed tunnels: configuration file" — ingress YAML shape, top-to-bottom matching, mandatory catch-all.
  5. Cloudflare docs — "Get started with cloudflared" — service install one-liners, Docker run command, token-as-password rule.
  6. Cloudflare docs — Tunnel routing / DNS — auto-created CNAME to <UUID>.cfargotunnel.com, route dns CLI, 1016 when the connector is down.
  7. Cloudflare docs — "SSH with cloudflared access" (updated 2026-04-17) — SSH route, ~/.ssh/config ProxyCommand, browser login, Access-on-top recommendation.
  8. Cloudflare — Access product pricing page — free for teams under 50 users; $7/user/month billed annually above that.
  9. Cloudflare docs — Error 413 troubleshooting (updated 2026-10-29) — 100 MB max upload on Free and Pro plans.
  10. Flavio Copes — "The complete guide to Cloudflare Tunnel" (flaviocopes.com/cloudflare-tunnel/, updated Oct 7, 2026) — full beginner arc, port 7844 outbound requirement (self-tested 2026-09-22, cloudflared 2026.9.1), token-is-password gotcha, config-conflict quick-tunnel gotcha.
  11. devstories.blog — Cloudflare tunnels explainer — the 4-piece model (tunnel UUID → connector → route → config), quick-tunnel-first framing.
  12. sumguy.com — "How to securely deploy Cloudflare Tunnels" — Docker Compose with TUNNEL_TOKEN in .env, never committed.
  13. ssdnodes.com — Cloudflare Tunnel no-open-ports guide — service-install config path (/etc/cloudflared/config.yml), ingress validate debugging.
  14. dev.to/libme — webhook testing guide — quick tunnel for throwaway webhook tests vs named tunnel for stable registered URLs.
  15. ngrok docs — Domains (ngrok.com/docs/gateway/domains, crawled 2026-11-03) — free static dev domains, BYO domains on pay-as-you-go, free-plan domain rules.
  16. ngrok blog — "Static dev domains for all ngrok users" — free limits (20k requests/month, 1 GB/month, 3 concurrent endpoints), free-plan browser interstitial.
  17. xcloud.host — October 20, 2026 cloudflared upgrade advisory (indie report) — 2026.10.2+ requested after compromised certificates; verify on the downloads page.

Frequently Asked Questions

Do I need my own domain to use Cloudflare Tunnel?

For a named tunnel, yes: the tunnel publishes hostnames on your domain, and that domain's DNS must be on Cloudflare (the free plan covers it). For a quick tunnel, no — cloudflared tunnel --url hands you a trycloudflare.com address with no account and no domain at all. If you are domain-shopping, get DNS onto Cloudflare first; everything else in this guide follows from that.

Is Cloudflare Tunnel really free forever?

The tunnel is free on every Cloudflare plan, quick tunnels need no account, and I found no published limit on concurrent named tunnels or tunnel bandwidth in Cloudflare's docs — that absence is verified, not a guess. The hard numbers that do exist: quick tunnels cap at 200 in-flight requests, uploads through the proxy cap at 100 MB on Free/Pro, and the Access login gate is free under 50 users. "Free" here means the tunnel; your domain registration and your server are still your own bills.

Is a quick tunnel safe for anything real?

No. A quick tunnel dies on Ctrl-C, its hostname changes on every run, it carries no uptime guarantee, and it tops out at 200 in-flight requests. It is perfect for showing a colleague your local build or catching a throwaway webhook, and wrong for anything a user, a cron job, or a third-party integration depends on. Anything stable gets a named tunnel.

How is this different from a VPN like Tailscale?

A Cloudflare Tunnel publishes public HTTPS hostnames through Cloudflare's edge with no client installed on any device — strangers can visit your site. Tailscale is a mesh VPN: every device installs a client and joins one private network, and nothing is public unless you deliberately share it. Use a tunnel for public services, a mesh VPN for private access to your own machines; many homelabs run both.

What happens if I stop cloudflared?

The tunnel's DNS records stay exactly where they were, because DNS and the tunnel are independent — dashboard routes create a CNAME to <UUID>.cfargotunnel.com that does not self-delete. Visitors will hit a Cloudflare 1016 error until a connector comes back online. So when you retire a tunnel for good, delete its routes and DNS records too, instead of leaving a dead hostname that errors.

Featured on Twelve Tools Hunt for Tools Featured on LaunchBuff Launch Llama Tools Launch your MCP