Cloudflare Tunnel lets you securely expose services running on your private network to the internet without opening firewall ports.

Here’s a quick look at it in action. Imagine you have a local web server running on localhost:8080 that you want to make accessible via a public my-app.example.com subdomain.

First, you’ll need to install cloudflared, the agent that creates the tunnel. On Linux, this is often as simple as:

sudo apt update && sudo apt install cloudflared

Then, authenticate cloudflared with your Cloudflare account:

cloudflared login

This will open a browser window asking you to authorize cloudflared with your domain.

Next, create a configuration file, typically at /etc/cloudflared/config.yml. This file tells cloudflared what local services to expose and how to route them.

tunnel: <YOUR_TUNNEL_ID>
credentials-file: /etc/cloudflared/<YOUR_TUNNEL_ID>.json
ingress:
  - hostname: my-app.example.com
    service: http://localhost:8080
  - service: http_status:404

The tunnel and credentials-file fields are generated when you create a new tunnel. You create a tunnel with:

cloudflared tunnel create my-tunnel-name

This command will output a tunnel ID and create a .json file containing your tunnel’s credentials. Make sure to update your config.yml with these values. The ingress section defines the routing rules. Here, my-app.example.com is mapped to your local http://localhost:8080 service. The final service: http_status:404 is a catch-all that returns a 404 for any requests not matching the preceding rules.

Now, you need to create a DNS record in your Cloudflare dashboard for my-app.example.com that points to your tunnel. This is a CNAME record pointing to <YOUR_TUNNEL_ID>.cfargotunnel.com.

Finally, run cloudflared as a service:

sudo systemctl start cloudflared
sudo systemctl enable cloudflared

And that’s it. Requests to my-app.example.com will now be routed through Cloudflare’s edge, securely reaching your localhost:8080 service without any open inbound firewall ports on your server.

The true power of Cloudflare Tunnel lies in its ability to act as a reverse proxy before traffic even hits your origin server. Cloudflare’s edge network terminates TLS, inspects traffic for threats, and applies WAF rules before forwarding the request through your persistent outbound tunnel to your local cloudflared agent. This means your private services benefit from Cloudflare’s global infrastructure and security features without exposing your internal network.

The cloudflared agent establishes a long-lived, outbound-only connection to Cloudflare’s nearest data center. When a request arrives at Cloudflare for your my-app.example.com domain, Cloudflare routes it through this established tunnel to your cloudflared agent, which then forwards it to http://localhost:8080. This outbound-only connection model is key to its security; no inbound ports need to be opened on your firewall.

You can also configure more advanced routing. For instance, to expose a WebSocket service on localhost:3000 under ws.example.com, you’d add to your config.yml:

  - hostname: ws.example.com
    service: ws://localhost:3000

And to handle different protocols, like SSH, you can map a subdomain to a specific port on your local machine:

  - hostname: ssh.example.com
    service: ssh://localhost:22

This would require an additional DNS entry for ssh.example.com pointing to the tunnel, and cloudflared would manage the protocol translation.

A common point of confusion is how cloudflared handles health checks and retries. If your local service (http://localhost:8080) becomes unavailable, cloudflared will automatically stop sending traffic to it and will retry establishing a connection periodically. Cloudflare’s edge will then show a 5xx error to the end-user until the tunnel is re-established and the service responds successfully.

Most people don’t realize that cloudflared can also be configured to run as a systemd service directly, simplifying management and ensuring it restarts automatically on boot. The cloudflared service install command automates this setup, creating the necessary service files and enabling them.

The next logical step is to explore how to integrate Cloudflare Access with your tunnels to provide robust authentication and authorization for your exposed services.

Want structured learning?

Take the full Cloudflare course →