Whether a new home lab enthusiast or an experienced homelabber, Cloudflare is often their first choice for building their infrastructure. Not because Cloudflare is free, but because it solves real problems without any unnecessary hassle. A few days ago, I wrote about how Cloudflare had quietly become a load-bearing infrastructure in my setup and mentioned I was experimenting with Pangolin to replace Cloudflare Tunnel.
Trying Pangolin didn’t mean Cloudflare suddenly became evil in my setup, but I was trying to reduce dependency on one company for my home lab. I took a real daily-used service, my self-hosted Vaultwarden, and routed it to Pangolin. Getting there took longer than I expected, for reasons that were entirely my fault.
How are Cloudflare tunnels different from a VPN?
Both let you access your services remotely but they do it in very different ways.
Pangolin is the self-hosted answer to Cloudflare Tunnel
Same no-open-ports model, different ownership
I had already decided to go ahead with Pangolin, but before actually moving forward with it, I wanted to know what I was getting into. And at first glance, I was surprised to see familiar concepts under different names. Pangolin creates a similar outbound-only tunnel like Cloudflare from my home server but via a VPS in the middle. No port forwarding. No exposing my home IP. No opening inbound firewall rules.
There were four major layers in this setup: the Pangolin handled the control plane dashboard, Gerbil handled the WireGuard server, Traefik handled the reverse proxy, and Newt ran as the tunnel client. So, it was the same architecture as Cloudflare Tunnel, but all self-hosted on my own servers. Requests arrived at the VPS and were forwarded through a secure tunnel to services running at my home. The major difference between Cloudflare and Pangolin was that the public entry point was the VPS I controlled and not the edge network, which I had no control over.
With Cloudflare, traffic arrived at their edge, they terminated the TLS, and then handled routing, whereas with Pangolin, the same things happened but inside the VPS I controlled. It was ownership that mattered here, not the speed, features, or performance. There were many factors that Cloudflare Tunnel depended on, but the case was different with Pangolin. Cloudflare routing issue? Pangolin didn't care. Cloudflare changes Tunnel pricing? Pangolin didn't care. Want to know exactly where requests go? I could trace every hop.
I wasn't switching because Cloudflare Tunnel failed me. I was switching because my priorities had changed. Cloudflare Tunnel was genuinely a better default for anyone not already running a VPS. That was all theory until now. Standing it up on my actual stack is where it got interesting.
Setting up Pangolin and pointing it at my Vaultwarden
A weekend project, with two screw-ups worth mentioning
Why would I want to replace a free working solution with a paid one? No, I didn’t want that, but I already had a VPS with me, paying for a different reason, and I could borrow a space there to self-host the Pangolin setup. Then why not? I already rent a Hetzner VPS (CPX32 — 4x Core, 4GB RAM, and 160GB SSD) to host a few of my own web apps, tools, and open-source projects. Adding Pangolin to it cost me nothing extra.
My DNS was still hosted on Cloudflare, but I set the Pangolin subdomain to DNS-only, as the orange cloud would have put Cloudflare back into the traffic path; that was the one thing I didn’t want. The initial installation was smoother than expected. Two commands, and after two minutes of interactive prompts to choose between the editions, base domain, Let's Encrypt email, Gerbil, and SMTP choices, it was up and running. Honestly, this was one of the smoothest installers I’ve used for a self-hosted reverse proxy. Less intimidating than traditional reverse-proxy setups and closer to a guided installer than a DIY networking project.
curl -fsSL https://static.pangolin.net/get-installer.sh | bash
./installer
Once that was done, I opened the Pangolin dashboard via the initial setup domain and created a “site” that was representing my home Debian server. To connect Pangolin to my home server, I deployed the Newt tunnel client as a Portainer stack, a tiny compose file with three environment variables. The site in the dashboard flipped to Online in a couple of seconds. I didn’t open any ports on my home network (though it would have been tough because of my CGNAT issue), and the whole thing felt like setting up Tailscale: easy and straightforward.
Now, I just had to add Vaultwarden as a new resource on the site, targeting the home server local IP with Vaultwarden’s port, with Pangolin handling HTTPS externally, and I was good to test it out. This was the real step in replacing Cloudflare Tunnel; until now, it was setting up the one-time prerequisite. Within a few seconds, the new Vaultwarden domain was live and resolving.
As soon as I hit the new Vaultwarden domain, I was redirected to a Pangolin authentication page, which was set by default when I added a new resource. I didn’t want that. So, I went back to the dashboard to turn it off. I toggled the auth off and changed a few TLS settings. And when I revisited the domain, I got a 404 because the changes left Traefik's config out of sync. I re-enabled everything, but it didn’t help. Then I deleted and recreated the resource with zero post-create toggles, and it worked.
But now the domain was getting a delayed 502 Bad Gateway error, likely due to upstream connection failure caused by the incorrect port. I had no idea what the issue was. I tried restarting Traefik, I checked Newt’s network access multiple times, and I tried verbose curl from the VPS; nothing helped. Finally, when I was going through the resource configuration, I noticed that I had put the wrong Vaultwarden port. Once that was corrected, everything was smooth.
The new Vaultwarden loaded instantly with a valid Let’s Encrypt certificate. No Cloudflare Tunnel and no exposed home ports. The bigger realization came after everything was working. I could trace every hop between the internet and my password manager.
Every hop between visitors and my password manager is now mine
That's the whole point, and it's worth the tradeoffs
So what changed after all this work? I now finally owned the path. Today the path is Visitor -> Hetzner VPS -> Pangolin / Traefik -> WireGuard tunnel -> Newt -> Vaultwarden. And the good thing about this path is that everything is mine, either rented or owned, with no third-party company in between. Every configuration belongs to me, and every routing decision happens on the infrastructure I control.
As soon as Cloudflare resolves (non-proxied state) the DNS to my rented server IP, TLS terminates there, meaning the requests stop at the infrastructure I rented. No third party sees them in plaintext. Pangolin is free, which means no platform risk — Hetzner is a vendor; I can change it whenever I want, whereas Cloudflare’s free tier is a business strategy with no guarantee.
As I mentioned many times in my previous articles, self-hosting comes with independence and ownership, but the trade-offs are also complementary. One of the major trade-offs was Cloudflare’s edge network performance. My Hetzner VPS is one server hosted in Germany, whereas Cloudflare is hundreds of POPs. Though Hetzner has basic DDoS protection and WAF, it is no match to Cloudflare. Crowdsec does exist in Pangolin’s ecosystem, but I haven't implemented it yet; it is on my list for a follow-up. And finally, more infrastructure to maintain. I was already maintaining my home Debian server, and Pangolin itself became another service to monitor and maintain on top of everything else.
Pangolin is free, but it is not free to run. It requires a server with a public IP, whereas Cloudflare has a generous free tier and is usually more than sufficient for most home labbers. If you don’t already run a VPS, paying a minimum of €5/mo to escape Cloudflare’s tier doesn't make sense. For me, Pangolin didn’t eliminate Cloudflare from my life. I still use Cloudflare for DNS, domains, workers, and everything else, but it no longer sits in front of this particular service.
The goal was never to leave Cloudflare entirely; it was to reduce one dependency.
5 networking tools I use weekly that don't cost anything
No subscriptions, just five free networking essentials.
Cloudflare is still here, just not in the way
In my previous article, I argued that Cloudflare has become more than just a DNS provider in my setup. I said I’d try Pangolin as a Cloudflare Tunnel alternative, and I tried it. Now that I’ve deployed it, the experiment worked. It worked not because Pangolin is better than Cloudflare Tunnel, but because it solved a different problem. For me, Cloudflare removed the complexity when I needed it the most, whereas Pangolin removed the dependency. I still use Cloudflare for everything else in my setup, but this one service now runs on my infrastructure. Honestly, this setup only makes sense if you already run a VPS and don’t want all your eggs in one basket. For most people, Cloudflare Tunnel is still the right choice.
