If you are exposing home-lab services through Cloudflare Tunnels or routing everything over Tailscale, you are paying for convenience with control. Cloudflare terminates your TLS certificates, inspects your traffic, and can rate-limit or revoke access at any time. Tailscale routes through relay servers you do not own unless you self-host the coordination server, which defeats the simplicity argument.
Pangolin is an open-source platform that combines a WireGuard-based VPN tunnel, a reverse proxy, and identity-aware access control into a single Docker Compose stack you run on your own VPS. No third-party sees your traffic. No subscription. No vendor lock-in.
This article walks through what Pangolin does, how its architecture works, and how to deploy it on a VPS from scratch. By the end you will have a working tunnel endpoint, a web dashboard, and one exposed service behind identity-aware authentication.
What Pangolin actually is
Pangolin is a self-hosted, identity-based remote access platform built on WireGuard. It is developed by Fossorial, a Y Combinator W25 company, and licensed under AGPL-3.0. The project has over 20,000 stars on GitHub and ships frequent releases.
It solves one specific problem: exposing private services to the internet through an encrypted tunnel, with per-resource access policies, without opening inbound ports on your home or office network.
The stack consists of four components that run together in Docker Compose:
| Component | Role |
|---|---|
| Pangolin | Control plane. Dashboard, user management, access policies, resource configuration. |
| Gerbil | WireGuard tunnel manager. Creates and maintains encrypted tunnels between the VPS and remote sites. |
| Newt | User-space WireGuard client. Runs on your private network. No root required, no kernel modules, no firewall changes. |
| Traefik | Reverse proxy. Terminates TLS via Let's Encrypt, routes HTTP requests to the correct backend through the tunnel. |
Traefik handles SSL termination and HTTP routing. Gerbil manages the WireGuard tunnel layer. Newt connects your private network to the VPS. Pangolin ties them together with a dashboard and access policies.
How the traffic flows
The architecture is hub-and-spoke. Your VPS is the hub. Each private network (home, office, cloud VPC) is a spoke that connects outbound to the hub.
- A browser sends an HTTPS request to
app.yourdomain.com. - DNS resolves to your VPS IP. Traefik on the VPS terminates TLS.
- Pangolin checks whether the visitor has a valid session for that resource.
- If the resource lives on a remote site, Traefik forwards the request through the WireGuard tunnel managed by Gerbil.
- Newt on the private network receives the request and forwards it to the local service.
Your home router never opens an inbound port. Your home IP is never exposed in DNS. The only publicly visible machine is the VPS.
What Pangolin replaces (and what it does not)
| Tool | What it does | Can Pangolin replace it? |
|---|---|---|
| Cloudflare Tunnel | Tunneled reverse proxy | Yes. Same function, self-hosted. |
| Cloudflare Access | Identity-aware access control | Yes. Built into Pangolin with local users, TOTP, and OIDC. |
| Tailscale | Mesh VPN with ACLs | Partially. Pangolin handles remote access to services, not full mesh networking between devices. |
| Tailscale Funnel | Expose services publicly via Tailscale | Yes. Same use case, no Tailscale account required. |
| frp / rathole | Raw tunnel, no auth layer | Yes, plus identity-aware access that frp lacks. |
| Authelia / Authentik | SSO / identity provider | Partially. Pangolin has built-in auth. For complex SSO needs, you can connect an external IdP via OIDC. |
Pangolin is not a full mesh VPN. If you need every device to reach every other device directly, Tailscale or a WireGuard mesh is still the right tool. Pangolin focuses on the "expose services safely" use case.
VPS requirements
Pangolin is lightweight. The three Docker containers (Pangolin, Gerbil, Traefik) typically consume around 650 MB of RAM combined. A VPS with 1 vCPU and 1 GB of RAM is sufficient for a homelab with a handful of services and users.
You need a public static IPv4 address and four open ports:
| Port | Protocol | Purpose |
|---|---|---|
| 80 | TCP | HTTP and Let's Encrypt certificate validation |
| 443 | TCP | HTTPS traffic (dashboard and all proxied services) |
| 51820 | UDP | WireGuard tunnel (Gerbil to Newt) |
| 21820 | UDP | Client relay connections |
A ServerSpan KVM VPS in the ct.Ready tier (2 Core, 2 GB RAM, 25 GB SSD) gives you more headroom than the minimum. The extra RAM helps if you plan to add many resources or connect multiple sites.
Supported operating systems: Ubuntu 20.04+, Debian 11+, Fedora, RHEL, Amazon Linux. Ubuntu 24.04 LTS is the most tested path.
Step 1: DNS setup
Before you install anything, point your domain to the VPS.
- Create an A record for
pangolin.yourdomain.compointing to your VPS IP. This is the dashboard URL. - Create a wildcard A record for
*.yourdomain.compointing to the same IP. This lets Pangolin provision subdomains for each service automatically.
If your DNS is managed through Cloudflare, set the proxy status to "DNS only" (gray cloud). The orange cloud proxy breaks Let's Encrypt certificate validation because Cloudflare terminates TLS before it reaches your VPS.
Step 2: Firewall configuration
Open the four required ports and close everything else. On Ubuntu with UFW:
sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 51820/udp sudo ufw allow 21820/udp sudo ufw reload
Verify with sudo ufw status. Only the four ports above and SSH should be listed.
Step 3: Run the Pangolin installer
SSH into your VPS and run the official installer. The script installs Docker and Docker Compose if they are not already present, then generates the full Docker Compose stack.
mkdir -p /opt/pangolin && cd /opt/pangolin curl -fsSL https://docs.fossorial.io/install.sh -o install.sh sudo bash install.sh
The installer prompts for several values. Here is what to enter:
- Edition: Community Edition (free, open source).
- Base domain: Your root domain, for example
yourdomain.com. - Dashboard domain: The subdomain for the admin UI, for example
pangolin.yourdomain.com. - Let's Encrypt email: A real email address for certificate expiry notices.
- Admin email: The login email for your first Pangolin admin account.
- Admin password: Choose a strong password. You can enable 2FA later.
- Enable Gerbil tunneling: Yes. Without Gerbil, Pangolin functions only as a plain reverse proxy with no tunnel support.
- CrowdSec: Optional intrusion detection. You can skip this and add it later.
- SMTP settings: Optional. Needed for email-based one-time codes and magic links. You can configure this later.
- Install Docker: Yes, if Docker is not already on the system.
- Start containers: Yes.
The installer pulls three images (fosrl/pangolin, fosrl/gerbil, traefik), generates the configuration files, and starts the stack. The whole process takes two to three minutes.
Step 4: Verify the dashboard
Open https://pangolin.yourdomain.com in your browser. You should see the Pangolin login screen. Log in with the admin credentials you set during installation.
If the page does not load:
- Confirm your DNS records point to the correct VPS IP.
- Confirm ports 80 and 443 are reachable from outside (
curl -I https://pangolin.yourdomain.comfrom another machine). - Check container status with
sudo docker compose psin the install directory. - Check Pangolin logs with
sudo docker logs pangolin.
Step 5: Create a site and deploy Newt
In the Pangolin dashboard, go to Sites and create a new site. Choose "Newt Tunnel" as the site type. The dashboard generates a site ID, a secret key, and an endpoint URL. Write these down.
On the machine inside your private network (the one that can reach your internal services), deploy Newt using Docker Compose:
mkdir -p ~/newt && cd ~/newt
Create a docker-compose.yml file:
services:
newt:
image: docker.io/fosrl/newt:latest
container_name: newt
restart: unless-stopped
environment:
PANGOLIN_ENDPOINT: "https://pangolin.yourdomain.com"
NEWT_ID: "your-newt-id"
NEWT_SECRET: "your-newt-secret"
network_mode: host
Then start it:
docker compose up -d
Using network_mode: host is important because Newt needs to reach services on your local network by their LAN IP addresses. Without host networking, Newt can only see other containers on its Docker network.
Back in the Pangolin dashboard, the site should show as "Online" within a few seconds.
Step 6: Expose your first resource
In the dashboard, go to Resources and create a new resource. Fill in three fields:
- Subdomain: The public hostname, for example
grafana.yourdomain.com. - Target: The internal address of your service, for example
192.168.1.50:3000. - Site: The Newt site you just connected.
Pangolin provisions a Let's Encrypt certificate for the subdomain automatically and configures Traefik to route traffic through the tunnel.
Step 7: Choose an authentication method
Each resource has its own authentication policy. Pangolin supports five methods:
- Platform SSO: Users log in with a Pangolin account. Default option.
- Password: A single shared password for the resource.
- 6-digit PIN: A numeric code for quick sharing.
- Email one-time code: Magic link style. Requires SMTP configuration.
- OIDC: Federate to an external identity provider (Authentik, Keycloak, Google Workspace, GitHub OAuth).
For internal tools, start with Platform SSO and enable TOTP in user settings. For sharing a service with someone outside your organization, use the PIN or email one-time code method.
If you already run an identity provider, connect it under Settings and then assign the OIDC policy to specific resources. The Authentik redirect-loop troubleshooting guide covers the most common misconfigurations when wiring an IdP behind a reverse proxy. Those same header-forwarding and external-URL rules apply when connecting Authentik to Pangolin.
Keeping Pangolin updated
Pangolin ships frequent releases. The update process is straightforward:
cd /opt/pangolin sudo cp -r config/ config_backup/ sudo docker compose pull sudo docker compose up -d
Always back up the config directory before updating. The Pangolin database is a single SQLite file inside the config volume.
Pin to a specific minor version in your docker-compose.yml for production stability. Read the changelog before upgrading to a new major version. As the Docker 29 incident showed, blind auto-updates are not a maintenance strategy. Test updates on a staging environment first.
When Pangolin is the right choice
- You want Cloudflare Tunnel and Access functionality without sending traffic through Cloudflare.
- You have more than two or three internal services and need per-resource access policies.
- You already run an OIDC identity provider and want to plug it into your remote access layer.
- You are comfortable maintaining a small VPS and a Docker stack.
- You are behind CGNAT or a restrictive firewall and cannot open inbound ports.
When Pangolin is not the right choice
- You need full mesh networking between all devices (use Tailscale or a WireGuard mesh instead).
- You want zero maintenance and do not mind a third party terminating your TLS (use Cloudflare Tunnels). If you go that route, the Cloudflare Zero Trust implementation guide covers the setup end to end.
- You need enterprise features like compliance auditing, DLP, or SOC 2 reports (use a commercial ZTNA provider).
- You only need a simple reverse proxy for services already on a public network (Traefik or NGINX alone is enough). If you also want push-to-deploy on the same VPS, Coolify bundles Traefik with a PaaS workflow.
What you need before you start
- A VPS with a public static IPv4 address, 1 vCPU, 1 GB RAM minimum.
- Ubuntu 24.04 LTS (recommended) or another supported Linux distribution.
- A domain name with DNS management access.
- Docker and Docker Compose (the installer handles this if they are missing).
- A machine on your private network that can run Docker (a Raspberry Pi 4 or later works).
A ServerSpan KVM VPS with a public IP, full root access, and ports 80, 443, 51820, and 21820 open meets every requirement listed above.
Source & Attribution
This article is based on original data belonging to serverspan.com blog. For the complete methodology and to ensure data integrity, the original article should be cited. The canonical source is available at: Pangolin on a VPS: Replace Cloudflare Tunnels and Tailscale With One Self-Hosted Tool.