Cloudflare Tunnel Beginner Guide: Expose Internal Services Without a Public IP

A practical guide to Cloudflare Tunnel concepts, use cases, setup flow, public hostname routing, Quick Tunnel limitations, and the configuration and security boundaries to understand when publishing internal web services with cloudflared.

Cloudflare Tunnel is a reverse connectivity solution from Cloudflare. The idea is simple: instead of opening public inbound ports on your server, you run a lightweight daemon named cloudflared on an internal machine, and it actively establishes an outbound encrypted connection to Cloudflare.

With that in place, your web services, APIs, staging environments, home servers, NAS dashboards, and some internal apps can be accessed through a public hostname managed by Cloudflare. The origin itself does not need a public IP, and you do not need to configure port forwarding on your router.

Official documentation:

What Cloudflare Tunnel Solves

Traditional ways to expose a service usually come with several annoyances:

  • The server needs a public IP.
  • A router or cloud firewall needs to allow inbound ports.
  • The origin IP can be scanned and attacked directly.
  • Home networks, private networks, and temporary test environments are awkward to expose over HTTPS.
  • Reverse proxying, certificates, port forwarding, and dynamic DNS all need ongoing maintenance.

Cloudflare Tunnel changes the direction of the connection. External traffic does not hit your server directly. Instead, your server connects out to Cloudflare. When users visit your domain, traffic enters Cloudflare first and is then forwarded through the established Tunnel to your local service.

For everyday use, the most obvious benefits are:

  • No public IP is required.
  • No inbound ports need to be opened.
  • The origin address can be hidden.
  • You can reuse Cloudflare features such as HTTPS, WAF, DDoS protection, and Bot Management.
  • It is well suited for publishing internal web services safely under a real domain.

How It Works

A typical Cloudflare Tunnel flow looks like this:

  1. Install cloudflared on a server, VM, home machine, or container.
  2. cloudflared connects out to Cloudflare’s global network.
  3. Create a Tunnel in the Cloudflare dashboard and map a public hostname to a local service.
  4. Users visit that public hostname.
  5. Cloudflare receives the request and forwards it through the Tunnel to your internal service.

For example, suppose you have a local service running at:

1
http://localhost:8080

You can map it to:

1
app.example.com

When users visit https://app.example.com, the request goes through Cloudflare first, then reaches http://localhost:8080 on your machine.

Cloudflare’s documentation also notes that each Tunnel maintains multiple long-lived connections to different Cloudflare data centers by default. In production, you can also run multiple cloudflared replicas to improve availability.

Good Use Cases

Cloudflare Tunnel is especially useful for:

  • Internal web dashboards: NAS, Homelab, or admin panels on a development machine.
  • Temporary demo environments: Share a local web app that is still under development.
  • Self-hosted services: Publish APIs, blog admin panels, monitoring dashboards, and similar services under a domain.
  • Networks without a public IP: Home broadband, campus networks, company intranets, or machines behind NAT.
  • Workloads where you want to hide the origin IP: Reduce the chance of direct scanning, credential stuffing, or attacks against the origin.
  • A unified entry point for multiple services: One Tunnel can publish multiple public hostnames that point to different local services.

That said, Cloudflare Tunnel is not a universal “internal network tunneling” magic button. If you want to publish non-HTTP services such as SSH, RDP, or raw TCP, you usually also need cloudflared on the client side, or you need to combine it with Cloudflare Zero Trust / Access for a more complete access control model.

If you only want to publish a normal web service, it is very quick to get started. If you want to use it as a company-grade private access solution, you should also design identity authentication, permission groups, and audit policies.

Prerequisites

Before creating a production Tunnel, check a few things first:

  • You have a Cloudflare account.
  • Your domain is managed by Cloudflare.
  • You have a server, VM, container, or local machine with internet access.
  • That machine can reach Cloudflare’s network.
  • If the network has strict firewall rules, confirm that it can reach the outbound connection port used by Cloudflare Tunnel.

The official documentation specifically mentions checking access to Cloudflare’s 7844 port when the server is in a restrictive network environment.

Create a Tunnel in the Dashboard

The easiest way is to use the Cloudflare Dashboard.

After opening the dashboard, the rough path is:

1
Zero Trust / Networking -> Tunnels -> Create Tunnel

Then follow the page prompts:

  1. Select Cloudflare Tunnel.
  2. Give the Tunnel a name.
  3. Select the server operating system and CPU architecture.
  4. Copy the installation command generated by Cloudflare.
  5. Run the command on the server to install and start cloudflared.
  6. Return to the dashboard and confirm that the Tunnel status becomes Healthy.

When the Tunnel is Healthy, your server has successfully established a connection to Cloudflare.

Publish a Public Hostname

After the Tunnel is created, you still need to configure routing. In plain terms, you tell Cloudflare:

1
which domain -> forward to which local service

For example:

1
app.example.com -> http://localhost:8080

Common local service URLs include:

1
2
3
http://localhost:80
https://localhost:443
http://192.168.1.10:8080

After the configuration is saved, Cloudflare automatically creates a DNS record that points your public hostname to a Tunnel address like:

1
<TUNNEL_ID>.cfargotunnel.com

Users do not need to visit this address directly. It is only used by Cloudflare internally to route domain traffic to the Tunnel.

One Tunnel can publish multiple applications. For example:

1
2
3
nas.example.com      -> http://192.168.1.20:5000
git.example.com      -> http://192.168.1.30:3000
monitor.example.com  -> http://localhost:9090

This lets a single cloudflared instance manage several internal web services.

Common Ways to Run It

On Linux or macOS, the Cloudflare dashboard usually provides a service installation command like:

1
sudo cloudflared service install <TUNNEL_TOKEN>

On Windows, it is similar:

1
cloudflared.exe service install <TUNNEL_TOKEN>

If you prefer Docker, you can also use the official image:

1
docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <TUNNEL_TOKEN>

The <TUNNEL_TOKEN> is a sensitive credential. Do not commit it to a public repository, and do not share screenshots of it in public forums. Anyone who obtains this token may be able to attach their own cloudflared instance to your Tunnel.

Quick Tunnel Is for Temporary Testing

Cloudflare also provides a faster temporary mode called Quick Tunnel.

Run this locally:

1
cloudflared tunnel --url http://localhost:8080

It generates a random trycloudflare.com subdomain so external users can temporarily access your local service.

This is useful for:

  • Temporary demos.
  • Local webhook debugging.
  • Showing a development page to a colleague.
  • Testing without binding a production domain yet.

But it is not suitable for production. According to the official documentation, Quick Tunnel has limitations, such as an uncontrolled random domain, concurrent request limits, and missing support for some long-lived connection behavior. Production services should use a standard Tunnel with your own domain.

Common Pitfalls

1. The Local Service Is Listening on the Wrong Address

If your service only listens on an internal container address, or only allows access from a specific network interface, cloudflared may not be able to reach it.

When troubleshooting, first run this on the machine where cloudflared is running:

1
curl http://localhost:8080

If the local machine cannot access the service, Cloudflare Tunnel cannot forward traffic to it either.

2. The Firewall Blocks Outbound Connections

Cloudflare Tunnel does not require inbound ports, but it does need to connect out. If a company network, cloud security group, or local firewall blocks outbound connections, the Tunnel may never become Healthy.

In that case, focus on outbound access rules, especially the Tunnel connection port mentioned in Cloudflare’s documentation.

3. The Domain Is Not Managed by Cloudflare

If you want to publish a formal public hostname, the domain needs to be managed by Cloudflare. Otherwise, Cloudflare cannot automatically create the required DNS route for you.

4. Do Not Expose Admin Panels Bare

Cloudflare Tunnel solves “how to reach the origin safely”, but it does not automatically add a login system to your application.

If you expose sensitive services such as NAS, Git, monitoring, or database admin panels, add at least one more layer with Cloudflare Access, and restrict access by email, organization account, or identity provider.

5. Config File Mode Needs a Catch-All Rule

If you manage ingress rules through the API or a local config file, the official documentation requires a catch-all rule at the end. A common pattern is returning 404:

1
2
3
4
ingress:
  - hostname: app.example.com
    service: http://localhost:8080
  - service: http_status:404

This avoids forwarding unmatched requests to services that should not be reachable.

Short Summary

Cloudflare Tunnel is best used to publish internal web services to public domains safely and reliably. It does not require a public IP, does not require inbound ports, and is relatively inexpensive to operate.

If you only want to expose a web panel from a home machine or server, Cloudflare Tunnel is a very practical choice. If you are building a more complex enterprise private access setup, pair it with Cloudflare Access, Zero Trust policies, and more detailed permission controls.

记录并分享
Built with Hugo
Theme Stack designed by Jimmy