You Don’t Have to Trust Cloudflare
Cloudflare Tunnels are genuinely great. You install cloudflared on your home server, point it at your service, and your domain starts resolving from CF’s edge — no port forwarding, no exposed public IP, no drama. We’ve covered how to deploy them securely and the edge security model in earlier posts.
But here’s the thing: every byte of your traffic flows through Cloudflare’s infrastructure. They can read it. They can terminate TLS. Their ToS can change. And if you’re running something sensitive — a private dashboard, internal tools, anything your threat model says “no third parties” — you’re stuck trusting a corporation you don’t control.
Pangolin is what happens when you decide you’re done with that.
It’s a self-hosted tunnel platform: a VPS acts as your ingress, WireGuard meshes back to your home server, and a built-in reverse proxy routes traffic to your services. You own every hop. No Cloudflare, no Tailscale, no accounts, no pricing tiers.
The Architecture in Plain English
Pangolin has three moving parts:
Pangolin server — runs on your VPS (the $5/month kind). It handles the WireGuard server, the routing table, the identity/auth layer, and the admin dashboard. Think of it as the brain that lives on a public IP.
Newt — the agent that runs on your home server (or wherever your actual services live). It dials out to Pangolin over WireGuard, registers your exposed services, and forwards traffic back. No inbound firewall rules needed. Your home router never opens a port.
Traefik-style routing — Pangolin includes a reverse proxy layer that routes by hostname. You define a resource (e.g. homeassistant.yourdomain.com) and bind it to a target behind Newt. HTTP, HTTPS, or raw TCP. That last one matters — Cloudflare Tunnels only do HTTP/S. Pangolin does TCP, which means you can expose SSH, databases, game servers, whatever.
The traffic flow looks like this:
Browser → VPS:443 → Pangolin → WireGuard tunnel → Newt → Home ServiceYour home server never touches the public internet directly. The VPS is the only exposed machine, and it’s only doing routing — no state, no data.
What You Need
- A VPS with a public IP. Hetzner CAX11, DigitalOcean Droplet, whatever’s cheap. 1 vCPU and 512 MB RAM is enough for personal use.
- A domain you control. You’ll be creating wildcard DNS.
- Docker and Docker Compose on the VPS.
- Docker on your home server (or bare-metal if you prefer Newt as a binary).
Deploying Pangolin on Your VPS
Create a directory and drop in a docker-compose.yml:
services: pangolin: image: fosrl/pangolin:latest container_name: pangolin restart: unless-stopped ports: - "443:443" - "80:80" - "51820:51820/udp" # WireGuard volumes: - ./config:/app/config - ./data:/app/data environment: - PANGOLIN_BASE_DOMAIN=tunnel.yourdomain.com - PANGOLIN_ADMIN_PASSWORD=changeme-seriously healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/health"] interval: 30s timeout: 10s retries: 3
gerbil: image: fosrl/gerbil:latest container_name: gerbil restart: unless-stopped network_mode: host cap_add: - NET_ADMIN - SYS_MODULE volumes: - /lib/modules:/lib/modules:ro depends_on: - pangolin environment: - PANGOLIN_ENDPOINT=http://pangolin:3001Two containers: pangolin is the control plane and reverse proxy; gerbil is the WireGuard daemon (needs NET_ADMIN to manage kernel interfaces — that’s normal, not scary).
docker compose up -ddocker compose logs -f pangolinOn first boot, Pangolin generates WireGuard keys, sets up the admin account, and starts listening. Hit https://tunnel.yourdomain.com — you’ll land on the dashboard.
DNS Setup
Point your base domain at the VPS IP, then add a wildcard:
tunnel.yourdomain.com A <vps-ip>*.tunnel.yourdomain.com A <vps-ip>The wildcard is how Pangolin routes per-service subdomains without you manually creating DNS records for every service. Define homeassistant.tunnel.yourdomain.com in the dashboard, and it just works.
Connecting Your Home Server with Newt
On your home server — the one running the actual services — you need Newt. You can run it as a container or a binary. Container is easier:
services: newt: image: fosrl/newt:latest container_name: newt restart: unless-stopped network_mode: host cap_add: - NET_ADMIN environment: - PANGOLIN_ENDPOINT=https://tunnel.yourdomain.com - NEWT_ID=your-newt-id # from Pangolin dashboard - NEWT_SECRET=your-newt-secret # from Pangolin dashboardThe NEWT_ID and NEWT_SECRET come from the Pangolin dashboard when you create a new “site.” Think of a site as a named tunnel endpoint — one Newt per physical location or network segment.
network_mode: host lets Newt reach your local services directly. It dials out to Pangolin, establishes the WireGuard peer, and registers. You’ll see it appear in the dashboard within seconds.
Exposing Your First Service
Once Newt is connected, add a resource in the Pangolin dashboard:
- New Resource → give it a subdomain (
homeassistant) - Target →
http://192.168.1.100:8123(your local HA IP) - Site → select the Newt you just registered
- Save
That’s it. https://homeassistant.tunnel.yourdomain.com now routes through your VPS, down the WireGuard tunnel, and hits Home Assistant on your LAN. TLS is handled by Pangolin (Let’s Encrypt via ACME). Your home server doesn’t need a cert.
For TCP resources — say you want to forward SSH:
- New Resource → type: TCP
- Port →
2222(the VPS-side port that gets opened) - Target →
192.168.1.10:22 - Site → your Newt
Now ssh -p 2222 [email protected] lands on your home server’s SSH daemon. Try doing that with Cloudflare Tunnels without paying for their enterprise tier.
Auth Layer
This is where Pangolin earns its keep beyond “just another WireGuard helper.” Every resource can sit behind Pangolin’s identity layer:
- No auth — public resource, anyone can hit it
- PIN/password — simple shared secret, good for family dashboards
- SSO / OIDC — hook it to Authentik, Authelia, Keycloak, or any OIDC provider
The OIDC integration means you can gate every service behind your existing SSO stack. Hit paperless.tunnel.yourdomain.com, get redirected to Authentik, log in once, and you’re good for all resources. No per-service auth configuration in Traefik, no middleware chains, no forwarded auth headers to debug at 2 AM.
Crowdsec Integration
Pangolin has native Crowdsec support. Drop your Crowdsec bouncer key in the config and Pangolin will query the Crowdsec LAPI before forwarding requests. Malicious IPs get blocked at the VPS before they even touch your WireGuard tunnel.
In config/pangolin.yml:
crowdsec: enabled: true lapi_url: http://crowdsec:8080 lapi_key: your-bouncer-keyRun Crowdsec as a sidecar on the VPS alongside Pangolin. Combine with the community blocklists and you’ve got a reasonably aggressive WAF-lite for free. Not Cloudflare’s billion-IP reputation database, but better than nothing — and you control what gets blocked.
Exit Node ACLs
One thing Pangolin does that Cloudflare Tunnels don’t: you can configure ACLs on which Newt (exit node) a resource routes through. If you have multiple sites — home lab, office, friend’s server — you can create resources that only use specific exit nodes.
This matters for:
- Geo-restriction workarounds — route a streaming service through a specific location
- Network segmentation — IoT resources only exit through the IoT-network Newt
- Access control — dev resources only reachable via the dev site’s Newt
It’s not a full zero-trust network access platform, but for a homelab context it’s surprisingly capable.
Pangolin vs. Cloudflare Tunnels: When to Pick Which
Choose Pangolin when:
- You don’t want your traffic touching third-party infrastructure (legal, privacy, paranoia — all valid)
- You need to expose TCP services, not just HTTP/S
- You want self-hosted SSO and auth without bolting on separate tools
- You’re running multiple sites and want centralized routing under your control
- You want Crowdsec or custom WAF rules without paying for enterprise features
Stick with Cloudflare Tunnels when:
- You want anycast DDoS mitigation without managing it yourself
- You need zero-cost and zero-maintenance for simple HTTP services
- Your threat model doesn’t include Cloudflare as an adversary
- You don’t have (or don’t want) a VPS to maintain
Honestly, these aren’t mutually exclusive. You could run Pangolin for sensitive internal tools and keep Cloudflare Tunnels for the public-facing stuff that benefits from CF’s edge network. Belt and suspenders.
Resource Usage
On a Hetzner CAX11 (Ampere ARM, 2 vCPU, 4 GB RAM, $4.15/month), Pangolin + Gerbil idles at around 80 MB RAM and barely touches the CPU between requests. Under moderate load (a handful of active browser sessions), it stays well under 200 MB. You could probably run it on 512 MB if you had to.
The WireGuard overhead is negligible — it’s in-kernel on Linux, same as Tailscale’s approach. Latency is just your VPS-to-home round trip, which for a geographically close VPS is typically 10-30ms.
What Pangolin Doesn’t Do (Yet)
Be honest about the gaps:
- No built-in DDoS protection — your VPS IP is public, and if someone finds it, you’re absorbing the traffic. Put it behind Cloudflare’s proxy (orange cloud, not tunnels) if you’re worried.
- No global edge network — one VPS means one failure point and one geographic location. Fine for homelab, not fine for production SLAs.
- Dashboard auth is basic — the admin panel doesn’t have 2FA out of the box. Use a strong password and consider putting it behind your own OIDC.
- Relatively new project — Pangolin is actively developed but not battle-hardened at scale. Check the GitHub issues before trusting it for anything critical.
The Bottom Line
If you’ve been running Cloudflare Tunnels because it was the easiest path to exposing home services — and you’re not thrilled about the vendor dependency — Pangolin is the cleanest self-hosted alternative I’ve seen. The architecture is sound: WireGuard handles the mesh, Newt keeps your home network firewalled, and the routing layer is mature enough to handle real workloads.
The $5 VPS cost is the only overhead. You trade Cloudflare’s edge network for full control of your traffic, TCP support, and an auth layer that doesn’t phone home.
Your 2 AM self will still be debugging WireGuard peer states instead of CF tunnel connector logs. Different problems, same hour. At least they’re your problems.
Deploy it, break it, fix it. That’s the homelab way.