Skip to content
Go back

Pangolin: Self-Hosted Cloudflare Tunnel Alternative

By SumGuy 9 min read
Pangolin: Self-Hosted Cloudflare Tunnel Alternative

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 Service

Your 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


Deploying Pangolin on Your VPS

Create a directory and drop in a docker-compose.yml:

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:3001

Two 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).

Terminal window
docker compose up -d
docker compose logs -f pangolin

On 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:

docker-compose.yml
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 dashboard

The 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:

  1. New Resource → give it a subdomain (homeassistant)
  2. Targethttp://192.168.1.100:8123 (your local HA IP)
  3. Site → select the Newt you just registered
  4. 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:

  1. New Resource → type: TCP
  2. Port2222 (the VPS-side port that gets opened)
  3. Target192.168.1.10:22
  4. 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:

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:

config/pangolin.yml
crowdsec:
enabled: true
lapi_url: http://crowdsec:8080
lapi_key: your-bouncer-key

Run 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:

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:

Stick with Cloudflare Tunnels when:

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:


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.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
ModSecurity vs Coraza WAF

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts