Pangolin: Self-Hosted Tunnels Without Cloudflare
A VPS, a WireGuard tunnel and a reverse proxy, wrapped into something you can hand to a friend

Contents
The problem is old and the shape of it never changes. You have services running at home. You want to reach them from outside, and possibly let other people reach them. Your connection has no usable inbound path, or you have a sensible objection to punching holes in your own firewall, or both.
Cloudflare Tunnel solves this beautifully and I have written about the cost. The daemon at home dials out, Cloudflare’s edge accepts the world’s requests, and traffic flows without a single open port. The price is that Cloudflare terminates your TLS. Every request to every service you host is decrypted on their infrastructure, and you take that on trust, along with a terms of service that has opinions about video streaming and an account that can be suspended by a process you cannot appeal to a human.
Pangolin is the attempt to have the first part without the second. It is a young project — the codebase appeared in 2024 and it has been moving fast ever since — and the idea is straightforward enough that the interesting question is whether the execution holds up.
What it actually is
Strip away the branding and Pangolin is three known-good components wired together with a management layer:
- A VPS you rent, running the Pangolin server with a public address.
- Newt, a lightweight client on your home network that dials out to the VPS over WireGuard and holds the tunnel open.
- Traefik on the VPS, terminating TLS with Let’s Encrypt certificates and reverse-proxying requests down the tunnel to your services.
- An identity layer on top, providing users, roles, per-resource access rules, and an authentication gate in front of anything you choose.
The traffic path: a request hits your VPS, Traefik terminates TLS, matches the hostname to a configured resource, and forwards the plaintext HTTP down the WireGuard tunnel to Newt, which delivers it to the service on your LAN.
Note where the TLS terminates. It terminates on a VPS you rent and control, then rides an encrypted WireGuard tunnel to your house. Cloudflare’s model terminates it on hardware belonging to a company with 20% of the web’s traffic. Both models decrypt your traffic somewhere outside your home; the difference is who holds the root on the box where it happens. If that distinction matters to you, it matters a lot; if it does not, Cloudflare is free and better-engineered and you should use it.
The other genuine differentiator is that Pangolin does TCP and UDP, so it is not limited to HTTP the way the free Cloudflare Tunnel tier effectively is. A game server on UDP goes through it. That is a real capability gap it closes.
You could build all of this yourself in an afternoon. A VPS, a WireGuard link, a reverse proxy, some auth. People have been doing exactly that for years and I have done it twice. What Pangolin sells is the assembly and, more importantly, the management interface — a place where adding a service is a form rather than three config edits and a reload.
Standing it up
Everything runs in Docker Compose on the VPS. The smallest tier at any provider is enough; this is a proxy and it does no work of consequence.
| |
gerbil is the WireGuard interface manager on the server side, and Traefik sharing its network namespace is what lets Traefik route into the tunnel. That is a slightly unusual arrangement and it is the bit that makes the compose file look stranger than it is.
DNS needs a wildcard pointed at the VPS, which is how new services appear without touching DNS again:
| |
Then Newt at home, which needs no ports and no forwarding:
| |
From there, adding a service is: create a resource in the UI, give it a subdomain, point it at an internal address and port, choose whether it sits behind authentication. TLS is issued automatically. The whole loop takes about forty seconds, and that loop is honestly the product.
The access control layer
This is where Pangolin does something the DIY version does not, and it is the reason I kept it running past the evaluation.
Resources can be public, or gated behind Pangolin’s own auth, and the gate is a real one — a login page in front of the service, evaluated at the proxy, before the request ever reaches your LAN. You get users, roles, per-resource permissions, one-time email codes and shared links with expiry.
The practical value shows up with other people. Giving a relative access to a self-hosted photo library has historically meant either exposing the service publicly and trusting its own login, or teaching them to use a VPN client. Both are bad: the first puts an application’s auth code on the internet as your only defence, and the second means a phone call every time their phone updates. A shared link with an expiry date, gated at the proxy, is the first answer to this I have been able to hand to someone non-technical without a tutorial.
Worth being precise about what the gate does. Traffic reaches your VPS regardless — the box is public and it is exposed to the internet, so it needs the same hardening any public box needs. The gate means unauthenticated requests are refused at the VPS, so nothing unauthorised traverses the tunnel to your home network. That is a meaningful boundary and it is the correct place to put one.
The comparison that actually decides it
Three ways to publish a home service to the internet, and the choice comes down to which box holds your plaintext.
| Cloudflare Tunnel | Pangolin | Hand-rolled VPS + proxy | |
|---|---|---|---|
| Open inbound ports at home | none | none | none |
| TLS terminates on | Cloudflare’s edge | your VPS | your VPS |
| Monthly cost | £0 | VPS rental | VPS rental |
| Non-HTTP protocols | restricted | TCP and UDP | anything |
| Auth in front of a service | Access, free tier limited | built in | you build it |
| Bandwidth ceiling | effectively none | your VPS allowance | your VPS allowance |
| Latency | their global edge | one VPS, one region | one VPS, one region |
| Who patches the public box | Cloudflare | you | you |
| Time to add a service | a minute | forty seconds | a config edit and a reload |
| Project maturity | a large company | months old | as old as your notes |
Cloudflare wins every row about engineering and operations, which should tell you something. It loses exactly one row, and for some people that row outweighs the rest. That is the whole decision, and dressing it up as anything more sophisticated does a disservice to whichever choice you make.
The row I would draw attention to is bandwidth. A VPS with a 2 TB monthly allowance sounds enormous until a photo library syncs or somebody streams a film, and the overage billing on some providers is genuinely alarming. Check that number before you point anything media-shaped at a tunnel you rent by the gigabyte.
Where the young edges show
Being fair about a project a few months old requires saying the awkward parts out loud.
The documentation assumes the happy path. Anything off the standard install — an existing Traefik on the VPS, a non-Docker deployment, a custom certificate — means reading the source or the Discord. The Discord is active and the maintainers are responsive, and that is a dependency on people’s goodwill rather than on documentation.
It moves fast and breaks things. Minor releases have changed config formats. latest is a bad tag here; pin a version and read the release notes before you move. I got bitten by exactly this and it was my own fault for running latest on something this young.
The bus factor is small. This is a young open-source project with a handful of core contributors. It may be thriving in three years or it may be an archived repo. The mitigation is that the components underneath — WireGuard, Traefik, Let’s Encrypt — are all boring and permanent, so a Pangolin that dies leaves you with a stack you can rebuild by hand, holding the same knowledge. That is a much better failure mode than a proprietary service disappearing.
The VPS is a new thing to run. It is a public box on the internet with your traffic in it. It needs patching, hardening, monitoring and a plan for when it is compromised. Cloudflare’s version of this box is somebody else’s problem and they are much better at it than you are. Be honest that “self-hosted” here means “I moved the responsibility to myself”, and that responsibility has an ongoing cost measured in your evenings.
Troubleshooting
“Newt connects and nothing proxies.” Check the resource’s internal target. Newt resolves it from your home network, so localhost:8096 means localhost from Newt’s perspective — inside its own container. Use the LAN address of the service, or put Newt on the same Docker network as the target and use the container name.
“Certificates fail to issue.” Traefik needs port 80 reachable for the HTTP-01 challenge, and the wildcard record needs to exist and resolve. dig +short test.example.com from anywhere in the world should return the VPS address. Hitting Let’s Encrypt’s rate limits during a fiddly first setup is easy; the staging endpoint exists precisely for this and you should use it while experimenting.
“WebSockets drop.” Anything real-time behind the proxy needs the connection upgrade to survive both hops. If a service works for page loads and its live-update features die, this is why. Check the resource’s proxy settings before blaming the application.
“It works and it is slow.” All your traffic crosses the VPS, so its location and bandwidth allowance are now your ceiling. A VPS in another continent adds that round trip to every request. Pick a region near you, and check the provider’s bandwidth cap before you point a media library at it — video will find that limit fast.
“The tunnel dies overnight and returns in the morning.” Newt’s WireGuard link needs its NAT mapping held open, and a household router with an aggressive UDP timeout will drop it during idle hours. The keepalive is managed for you, so if this happens, look at the router: some ISP-supplied units are notoriously eager to reap UDP state.
Is it worth it?
Pangolin is worth running if you have a specific objection to Cloudflare terminating your TLS, and you want the convenience anyway. That is a narrower audience than the project’s enthusiasm suggests, and it is a real one — I am in it. The VPS costs a few pounds a month and the setup is an afternoon.
It is also worth it if you need to expose non-HTTP services, or if you want to give other people access to things without teaching them a VPN. That second use case is the one that surprised me. Solving the CGNAT problem generically, for TCP and UDP, with an auth gate in front and a UI a friend can be pointed at, is a genuinely useful combination.
Skip it if Cloudflare Tunnel already works for you and the trust question does not keep you up. Their edge is faster than your VPS will ever be, it is free, and it is operated by people whose entire job is operating it. There is no shame in that trade and most people should take it.
Skip it too if your requirement is really just your own devices reaching your own services. A mesh overlay is simpler, faster and has no public box in the path at all — running your own control plane covers that ground with less exposed surface. Pangolin’s whole reason to exist is publishing services to people who will never install anything. If nobody like that exists in your life, you are paying for a capability you will not use.
I run it. I pin the version, I patch the VPS, and I keep a written note of how to rebuild the stack by hand if the project goes quiet. That last item is the price of running something this young, and I think it is a fair one.




