CASDOVAL. Back to library
04HOMELAB7 min read

Put your Raspberry Pi online in two minutes with Cloudflare Tunnel

A Raspberry Pi, an old PC, or an unused laptop can be a server. Cloudflare Tunnel makes it reachable from the internet while keeping your router closed and your origin IP private.

Why Tunnel works

Instead of accepting inbound connections, cloudflared opens an outbound connection to Cloudflare. When someone visits your domain, Cloudflare forwards the request through that already-open tunnel to localhost. No port forwarding or static IP is required, and HTTPS is handled at Cloudflare's edge.

With Tunnel, the connection starts from your machine and your router can stay closed.

Requirements

You need a Linux machine with an app running locally, a free Cloudflare account, and a domain managed by Cloudflare for a permanent tunnel. To test without an account or domain, run:

cloudflared tunnel --url http://localhost:3000

Cloudflare will give you a temporary https://...trycloudflare.com URL. It disappears when the process stops.

Quick tunnel
cloudflared tunnel --url http://localhost:3000

Install and authenticate

On a 64-bit Raspberry Pi, install the ARM package:

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
cloudflared --version

For an x86 Debian or Ubuntu machine, replace arm64 with amd64. Then authenticate:

cloudflared tunnel login

Create the permanent tunnel

Create the tunnel and route a hostname to it:

cloudflared tunnel create myapp
cloudflared tunnel route dns myapp app.yourdomain.com

Then create ~/.cloudflared/config.yml:

tunnel: myapp
credentials-file: /home/pi/.cloudflared/<ID>.json
ingress:
  - hostname: app.yourdomain.com
    service: http://localhost:3000
  - service: http_status:404

Replace <ID> with the generated tunnel ID and use an absolute credentials path. The final 404 rule is required as the default catch-all.

Cloudflare forwards the request through the active tunnel to your local service.

Run it as a service

Start the tunnel with:

cloudflared tunnel run myapp

When it works, install it as a systemd service so it starts after a reboot:

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared

Inspect the status and logs with sudo systemctl status cloudflared and sudo journalctl -u cloudflared -f.

Serve multiple apps

One tunnel can route multiple hostnames. Add more ingress entries for localhost:3001, localhost:8080, or any other local service, then create a DNS route for each hostname. Keep the http_status:404 rule last because ingress rules are evaluated in order.

Ingress rules let one tunnel serve several local apps while keeping the catch-all rule last.

Security note

Tunnel hides your IP and puts Cloudflare in front of your app, but it does not authenticate users. If the app is not public by design, protect it with Cloudflare Access and require login before traffic reaches the tunnel. Also check the origin locally when you see Unable to reach the origin service, verify the tunnel name for error 1033, and use absolute paths for credentials-file.

The short version

  • Install cloudflared and run cloudflared tunnel login.
  • Create a tunnel, route your hostname, and point ingress to localhost.
  • Run it as a systemd service and add Cloudflare Access for private apps.