Self-Hosting with Cloudflare Tunnels


I run a handful of services on my home server — Gitea, a media server, some internal tools. For years I used port forwarding with dynamic DNS, which worked but always felt fragile and exposed.

Cloudflare Tunnels changed the game. The idea is simple: instead of opening ports inbound, you run a lightweight daemon (cloudflared) on your server that creates an outbound connection to Cloudflare’s edge. Traffic flows through Cloudflare to your service. Your public IP is never exposed.

Setup

Install cloudflared on the host:

curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb

Authenticate and create a tunnel:

cloudflared tunnel login
cloudflared tunnel create homelab

Configure your routes in ~/.cloudflared/config.yml:

tunnel: your-tunnel-id
credentials-file: /home/user/.cloudflared/your-tunnel-id.json

ingress:
  - hostname: gitea.yourdomain.com
    service: http://localhost:3000
  - hostname: media.yourdomain.com
    service: http://localhost:8096
  - service: http_status:404

Run it as a systemd service and forget about it.

Why This Matters

  • Zero open ports on your router
  • Cloudflare handles SSL termination
  • DDoS protection comes free
  • Access policies can require authentication before traffic even reaches your server

The only downside is you’re trusting Cloudflare as a middleman. For personal services, that tradeoff is easy to accept.