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:

ComponentRole
PangolinControl plane. Dashboard, user management, access policies, resource configuration.
GerbilWireGuard tunnel manager. Creates and maintains encrypted tunnels between the VPS and remote sites.
NewtUser-space WireGuard client. Runs on your private network. No root required, no kernel modules, no firewall changes.
TraefikReverse 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.

  1. A browser sends an HTTPS request to app.yourdomain.com.
  2. DNS resolves to your VPS IP. Traefik on the VPS terminates TLS.
  3. Pangolin checks whether the visitor has a valid session for that resource.
  4. If the resource lives on a remote site, Traefik forwards the request through the WireGuard tunnel managed by Gerbil.
  5. 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)

ToolWhat it doesCan Pangolin replace it?
Cloudflare TunnelTunneled reverse proxyYes. Same function, self-hosted.
Cloudflare AccessIdentity-aware access controlYes. Built into Pangolin with local users, TOTP, and OIDC.
TailscaleMesh VPN with ACLsPartially. Pangolin handles remote access to services, not full mesh networking between devices.
Tailscale FunnelExpose services publicly via TailscaleYes. Same use case, no Tailscale account required.
frp / ratholeRaw tunnel, no auth layerYes, plus identity-aware access that frp lacks.
Authelia / AuthentikSSO / identity providerPartially. 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:

PortProtocolPurpose
80TCPHTTP and Let's Encrypt certificate validation
443TCPHTTPS traffic (dashboard and all proxied services)
51820UDPWireGuard tunnel (Gerbil to Newt)
21820UDPClient 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.com pointing to your VPS IP. This is the dashboard URL.
  • Create a wildcard A record for *.yourdomain.com pointing 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:

  1. Edition: Community Edition (free, open source).
  2. Base domain: Your root domain, for example yourdomain.com.
  3. Dashboard domain: The subdomain for the admin UI, for example pangolin.yourdomain.com.
  4. Let's Encrypt email: A real email address for certificate expiry notices.
  5. Admin email: The login email for your first Pangolin admin account.
  6. Admin password: Choose a strong password. You can enable 2FA later.
  7. Enable Gerbil tunneling: Yes. Without Gerbil, Pangolin functions only as a plain reverse proxy with no tunnel support.
  8. CrowdSec: Optional intrusion detection. You can skip this and add it later.
  9. SMTP settings: Optional. Needed for email-based one-time codes and magic links. You can configure this later.
  10. Install Docker: Yes, if Docker is not already on the system.
  11. 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.com from another machine).
  • Check container status with sudo docker compose ps in 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.