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)
šŸ’” The domain does not need to have been purchased from Cloudflare. You can move nameservers from an existing registrar (Namecheap, GoDaddy, etc.) to Cloudflare for free and keep your registration where it is.

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
āš ļø Never commit the .env file to git. Add it to .gitignore immediately.

Step 3 – Add a public hostname

Back in the Cloudflare dashboard under Public Hostnames, add:

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

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.

Sources