Expose a Pi Service with Cloudflare Tunnel
Cloudflare Tunnel (formerly Argo Tunnel) lets you publish a service running on your Pi to a public hostname without opening ports on your router, getting a static IP, or running dynamic DNS. The Pi makes an outbound connection to Cloudflare; clients hit Cloudflare; Cloudflare proxies through the tunnel.
You'll need
- A Raspberry Pi running something you want to expose (e.g. a small web server on port 8080)
- A free Cloudflare account
- A domain on Cloudflare (transferring DNS to Cloudflare is free)
1. Install cloudflared on the Pi
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
Use cloudflared-linux-armhf.deb instead if you're on a 32-bit OS (older Pi Zero W, Pi 1/2).
2. Log in
cloudflared tunnel login
This prints a URL. Open it on any device, sign in to Cloudflare, and authorize the domain you want to use. A cert file lands in ~/.cloudflared/.
3. Create a tunnel
cloudflared tunnel create pi-home
It returns a tunnel UUID and writes credentials to ~/.cloudflared/<uuid>.json. Note both — you'll need them.
4. Configure routing
Create ~/.cloudflared/config.yml:
tunnel: <uuid-from-step-3>
credentials-file: /home/pi/.cloudflared/<uuid>.json
ingress:
- hostname: home.example.com
service: http://localhost:8080
- service: http_status:404
The final catch-all rule is required — without it, cloudflared refuses to start.
5. Bind the hostname
cloudflared tunnel route dns pi-home home.example.com
This creates a CNAME in your Cloudflare DNS pointing the hostname at the tunnel.
6. Run it as a service
sudo cloudflared service install
sudo systemctl enable --now cloudflared
Now it starts on boot. Visit https://home.example.com — you should hit your local service through Cloudflare.
Troubleshooting
- Tunnel running but 502 errors? The service on
localhost:8080isn't responding. Test withcurl localhost:8080from the Pi itself. - DNS not resolving? Check Cloudflare dashboard → DNS — confirm the CNAME exists and is proxied (orange cloud).
- Find your existing tunnels:
cloudflared tunnel listshows everything tied to your account. - Logs:
journalctl -u cloudflared -f