All articles

Cloudflare Tunnel: the modern way to expose your home server

CGNAT, dynamic IPs, and port-forwarding hassles all evaporate with Cloudflare Tunnel — a free reverse-tunnel service that exposes anything you run at home through a stable public hostname. Here's how to set one up in 15 minutes.

May 6, 20266 min read

If you've tried to host something at home — a Plex server, a Home Assistant dashboard, a personal site — you've run into one of three walls:

  • Your IP changes (dynamic DHCP from your ISP).
  • You're behind CGNAT and port forwarding silently fails.
  • You don't want to expose your home IP to the open internet.

Cloudflare Tunnel solves all three for free. You install a small client at home, connect a domain through Cloudflare, and any service you choose is reachable from anywhere — over HTTPS, behind Cloudflare's DDoS protection, with no inbound port open on your router.

This guide walks through setting one up in about 15 minutes.

How it works

Normal "host at home" setups rely on inbound connections — your router accepts traffic from the internet and forwards it to your server. Cloudflare Tunnel inverts that: your home server makes an outbound connection to Cloudflare, and that tunnel becomes the path inbound traffic takes.

[Visitor] → [Cloudflare edge] ⇄ [Your home — outbound HTTPS] → [Local service]

Visitors hit a Cloudflare hostname (myhome.example.com). Cloudflare routes the request down the tunnel to your home machine, which forwards it to the local service. Replies flow back through the same tunnel.

The home machine never accepts an inbound connection. CGNAT, dynamic IPs, port forwarding — none of them matter.

What you need

  • A domain on Cloudflare (free plan is fine; you can transfer a domain in or buy one through Cloudflare Registrar).
  • A computer at home that can run the cloudflared daemon (Linux, macOS, Windows, FreeBSD, Docker, Raspberry Pi).
  • A local service to expose — anything HTTP/HTTPS or TCP/SSH.

That's it. No public IP. No port forwarding. No static IP. No paid plan.

Step 1 — Add your domain to Cloudflare

If your domain is already on Cloudflare, skip this.

  1. Sign up at cloudflare.com (free).
  2. Click "Add a site," enter your domain, choose Free plan.
  3. Cloudflare scans your existing DNS records. Confirm them.
  4. Update your domain's nameservers at your registrar to the ones Cloudflare gives you.
  5. Wait for activation (usually under 24 hours; often within minutes).

Once your domain shows "Active" in Cloudflare's dashboard, continue.

Step 2 — Create a tunnel

In the Cloudflare dashboard, navigate to Zero TrustNetworksTunnels, then click Create a tunnel.

  1. Choose Cloudflared as the connector type.
  2. Name your tunnel (e.g., home-server).
  3. Cloudflare shows you a one-line install command for your OS — copy it.

The command looks something like this on Linux:

sudo cloudflared service install eyJh...long-token...gIn0=

Run that on your home server. The cloudflared daemon installs, starts, and immediately registers itself with Cloudflare using the token. Within seconds, the dashboard should show your connector as "Healthy."

For Docker, the command is docker run cloudflare/cloudflared:latest tunnel run --token eyJh.... For Windows/macOS, there's an installer.

Step 3 — Route traffic to your local service

In the dashboard's tunnel configuration, click Public HostnameAdd a public hostname.

Fill in:

  • Subdomain: e.g., home (or whatever you want)
  • Domain: select your Cloudflare-managed domain
  • Path: leave blank (or specify if you want to route only certain paths)
  • Service type: HTTP, HTTPS, SSH, RDP, or TCP
  • URL: where the service runs locally — e.g., http://localhost:8080

Save. Within seconds, https://home.yourdomain.com is live, serving whatever you exposed at http://localhost:8080.

You can add multiple public hostnames per tunnel — each pointing to a different local service.

Step 4 — Verify

From any device, visit https://home.yourdomain.com. You should see your local service.

Things to notice:

  • It's on HTTPS automatically. Cloudflare provides the cert and terminates TLS at their edge.
  • The page loads via Cloudflare's network — your home IP is never exposed to the visitor.
  • Even if your home IP changes, the tunnel stays up. Even if you're behind CGNAT, no problem.

Optional: lock it down

By default, your service is exposed to anyone who knows the hostname. For private services (Home Assistant, internal dashboards), add authentication.

In Cloudflare dashboard: Zero TrustAccessApplicationsAdd applicationSelf-hosted.

  • Set the application URL to your tunnel hostname.
  • Add an Access policy. Common ones:
    • Email allowlist — only specific email addresses can sign in.
    • OTP via email — Cloudflare sends a one-time code to a verified email.
    • Google / GitHub / Microsoft SSO — for shared work setups.

After saving, anyone hitting the hostname must authenticate first. Cloudflare handles the auth UI; your local service never sees unauthenticated requests.

This turns Cloudflare Tunnel from "expose a service publicly" into "expose a service to a specific group of people."

Common use cases

  • Home Assistant — access your smart home dashboard from anywhere without exposing port 8123.
  • Plex / Jellyfin — stream from home without router port-forwarding (note: Plex's official docs prefer their own relay; use Tunnel if you've outgrown it).
  • Personal git — Gitea or Forgejo hosted at home, available everywhere.
  • Internal tools — devboards, monitoring, anything you'd rather not expose to the open internet.
  • SSH to your home machine — the SSH service type lets you SSH in via Cloudflare without exposing port 22.

What it doesn't do

  • Bandwidth-heavy hosting at scale. Cloudflare's free plan has fair-use limits. If you're streaming 4K video to many viewers from your home, you'll hit them eventually. For typical personal use, you won't notice.
  • Real-time gaming and voice. TCP-only routing adds latency that gaming hates. Use a different solution for game servers.
  • Truly anonymous hosting. Cloudflare is in the middle of the request — they have logs of which IPs hit your service. Tunnel hides your home IP from visitors but not from Cloudflare.

For 95% of home-hosting use cases, none of those matter.

Alternatives

If Cloudflare Tunnel doesn't fit, similar tools:

  • Tailscale Funnel — same idea, different vendor; integrates with Tailscale's mesh.
  • ngrok — older, established, free tier limited; great for development.
  • localtunnel / serveo — lightweight, sometimes flaky.
  • FRP (Fast Reverse Proxy) — open source; you self-host the public side on a cheap VPS.

Cloudflare's tunnel is the easiest one I've found that's also free, with a serious global anycast network behind it.

Quick FAQ

Is it really free? Yes — for personal use, including the domain (if you transfer to Cloudflare Registrar at cost) and DDoS protection. Paid Zero Trust plans add advanced auth options for organizations.

Does it require a Cloudflare account for visitors? No. Visitors just hit the hostname. Auth (if you set it up) is enforced by Cloudflare Access, which can be email OTP or any OAuth provider.

Can I tunnel non-HTTP services? Yes — TCP, SSH, RDP, Unix socket. You configure the local service URL to be e.g., tcp://localhost:5432 for Postgres.

What happens if Cloudflare goes down? Your service is unreachable until they recover. This is a real (if rare) availability tradeoff for the convenience.

Is this a VPN? Sort of, but reversed. Instead of your traffic going out through a remote server, remote traffic comes in through your local server. Different use case, similar idea.

TL;DR

  • Sign up for Cloudflare, add your domain, install cloudflared at home with the token they give you.
  • Add a public hostname pointing at your local service.
  • Done — your home service is reachable globally over HTTPS, no port forwarding, no static IP, no exposed home IP.

In 2026 this is the modern default for "host something at home and reach it from anywhere." Skip port forwarding, skip dynamic DNS — go straight to Tunnel.