What you need
PREREQUISITES
- Raspberry Pi (any model) running Raspberry Pi OS Bookworm (64-bit recommended for Pi 4/5)
- A Cloudflare account (free) with a domain pointed at Cloudflare's nameservers
- SSH access to your Pi
- Docker + Docker Compose (optional, but recommended if you already use it)
Step 1 ā Create the tunnel in Cloudflare Zero Trust
Go to dash.cloudflare.com ā Zero Trust ā Networks ā Tunnels and click
Create a tunnel. Choose Cloudflared as the connector type and give
the tunnel a name. home-pi works fine.
Cloudflare generates a unique token for your tunnel. You will use it in the next step. Keep the browser tab open.
Step 2 ā Install cloudflared on the Pi
Cloudflare shows an installation command directly in the dashboard. It looks roughly like this:
Method A: Debian package (recommended for Pi 4/5)
# Download the ARM64 package
curl -L -o cloudflared.deb \
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
sudo dpkg -i cloudflared.deb
# Register and start as a systemd service
sudo cloudflared service install YOUR_TOKEN_HERE
Use cloudflared-linux-arm.deb (ARMv7) instead if you are running a Pi 3 or older
with a 32-bit OS.
Method B: Docker Compose
Add this to your docker-compose.yml:
cloudflared:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
Store the token in a .env file in the same directory:
CLOUDFLARE_TUNNEL_TOKEN=paste_your_token_here
.env file to git. Add it to .gitignore immediately.
Step 3 ā Add a public hostname
Back in the Cloudflare dashboard under Public Hostnames, add:
- Subdomain: e.g.
home - Domain: your domain, e.g.
example.com - Service:
http://localhost:8080(or whatever port your service is on)
Cloudflare creates a DNS record automatically. Your service is now reachable at
home.example.com over HTTPS. Cloudflare handles the certificate.
Step 4 ā Cloudflare Access (optional but worth it)
Without Access, your service is public. To require a login, go to Zero Trust ā Access ā Applications ā Add an application.
Select Self-hosted, enter your URL, and pick an identity provider: Google, GitHub, or just a "One-time PIN" sent to e-mail. It costs nothing and gives you a login gate without writing a single line of code.
Check status
# Systemd installation:
sudo systemctl status cloudflared
# Docker:
docker compose logs cloudflared
You should see Connection registered in the logs and tunnel status as Healthy in the dashboard.
Troubleshooting
- Tunnel not showing as Healthy: Check that the token is correct and that the Pi has internet access.
- 502 Bad Gateway: Check that the service URL in the hostname config points to the right port and protocol (
httpvs.https). - TLS error in browser: The Cloudflare certificate is self-signed against the origin. Set the SSL/TLS mode to Flexible in the Cloudflare dashboard, or install an origin certificate.
Frequently asked questions
Do I need to open ports in my router with Cloudflare Tunnel?
No. That is the entire point. Your Pi makes an outbound connection to Cloudflare's edge network, so no inbound port forwarding is needed. This also means Cloudflare Tunnel works even if you are behind CG-NAT ā a situation where port forwarding is impossible because you do not have a dedicated public IP.
Is Cloudflare Tunnel free?
Yes. Cloudflare Tunnel is included in the free tier of Cloudflare Zero Trust. You only need a Cloudflare account and a domain pointed at Cloudflare's nameservers. The domain itself does not need to be purchased from Cloudflare ā you can move nameservers from any registrar for free. Cloudflare Access (the login gate in front of your services) is also free for up to 50 users.
What can I expose with a Cloudflare Tunnel?
Any HTTP or HTTPS service running on your Pi: Nextcloud, Home Assistant, Grafana, a Raspberry Pi web interface, a self-hosted Bitwarden instance ā anything with a local port. You can add multiple public hostnames in a single tunnel, each pointing to a different service and port. TCP and UDP services are also supported but require the WARP client on the other end, which is a more advanced setup.