Pangolin mit Docker installieren: Identity-aware Tunnel-Reverse-Proxy auf WireGuard-Basis
Pangolin ist die selbstgehostete Cloudflare-Tunnel-Alternative mit 21k+ Stars: Identity-aware Reverse Proxy auf WireGuard-Basis, der interne Dienste ohne Portfreigabe sicher nach außen bringt – mit Web-UI, RBAC und automatischem TLS über Traefik.
Geprüft am 22.10.2026 · für Pangolin 1.25.1
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Interne Dienste wie Home Assistant oder Nextcloud sollen ohne Portfreigabe am Router von außen erreichbar sein. Pangolin ist die selbst gehostete Alternative: Der identitätsbasierte Reverse Proxy (Identity-aware Proxy, prüft vor jedem Zugriff den angemeldeten Benutzer) verbindet einen öffentlichen VPS über WireGuard-Tunnel mit internen Servern hinter NAT. Dazu kommen Web-Dashboard, rollenbasierte Zugriffskontrolle (RBAC) und Let's-Encrypt-Zertifikate. Die Anleitung beschreibt die manuelle Installation mit Docker Compose nach der offiziellen Dokumentation (Stand Oktober 2026, Pangolin 1.25.1).
Voraussetzungen
- VPS oder Cloud-Server mit öffentlicher IPv4-Adresse und Linux (Ubuntu 22.04 oder 24.04 empfohlen)
- Docker Engine 24+ und Docker Compose v2, siehe Docker und Docker Compose auf Linux installieren
- Eigene Domain mit Zugriff auf die DNS-Einstellungen (A-Record auf Server-IP gesetzt)
- Ports offen in der VPS-Firewall: 80/tcp, 443/tcp, 51820/udp, 21820/udp
- Mindestens 512 MB RAM (empfohlen: 1 GB+), 1 vCPU, 5 GB freier Speicher, x86_64 oder arm64
- Ports 80 und 443 dürfen auf dem VPS nicht von einem anderen Reverse Proxy belegt sein
- Interner Host für den Newt-Client (Heimserver, NAS, Raspberry Pi o. ä.)
opensslundcurlauf dem VPS verfügbar
Schritt 1: Projektordner und Verzeichnisstruktur anlegen
Pangolin erwartet eine feste Verzeichnisstruktur. Legen Sie die Ordner vorab an:
mkdir -p /opt/pangolin/config/db
mkdir -p /opt/pangolin/config/letsencrypt
mkdir -p /opt/pangolin/config/traefik/logs
cd /opt/pangolinZielstruktur; config/key legt Gerbil beim ersten Start an:
/opt/pangolin/
├── compose.yaml
├── config/
│ ├── config.yml # Pangolin-Hauptkonfiguration (noch anzulegen)
│ ├── db/ # SQLite-Datenbank (automatisch erstellt)
│ ├── letsencrypt/ # ACME-Zertifikate (automatisch befüllt)
│ └── traefik/
│ ├── logs/ # Traefik Access-/Error-Logs
│ ├── traefik_config.yml # Traefik statische Konfiguration
│ └── dynamic_config.yml # Traefik dynamische RoutenVerifizieren: Prüfen Sie die Ordnerstruktur mit find /opt/pangolin -type d. Alle Verzeichnisse aus der obigen Liste müssen vorhanden sein.
Schritt 2: Server-Secret generieren und config.yml anlegen
Die Einstellungen stehen in config/config.yml. Pflichtfeld ist server.secret; Pangolin verschlüsselt damit sensible Daten in der Datenbank. Erzeugen Sie ihn einmalig:
openssl rand -hex 32Tragen Sie die Ausgabe ein und ersetzen Sie pangolin.example.com (Dashboard-Hostname) und example.com (Basisdomain) durch Ihre Werte:
# /opt/pangolin/config/config.yml
gerbil:
start_port: 51820
base_endpoint: "pangolin.example.com"
app:
dashboard_url: "https://pangolin.example.com"
log_level: "info"
domains:
domain1:
base_domain: "example.com"
server:
secret: "HIER-openssl-rand-hex-32-Ausgabe-einfuegen"
cors:
origins: ["https://pangolin.example.com"]
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
flags:
require_email_verification: false
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: trueYAML erlaubt nur Leerzeichen zur Einrückung. Die dashboard_url entspricht exakt dem Hostnamen des Dashboards, ohne abschließenden Schrägstrich. disable_signup_without_invite: true verhindert, dass sich Fremde selbst registrieren.
Verifizieren: Prüfen Sie die YAML-Syntax mit python3 -c "import yaml; yaml.safe_load(open('config/config.yml'))" && echo "YAML OK". Ausgabe muss YAML OK lauten.
Schritt 3: Traefik-Konfiguration anlegen
Traefik braucht eine statische Konfiguration (Entry Points, Let's Encrypt, das Pangolin-Plugin Badger für die Anmeldeprüfung und den HTTP-Provider, über den Pangolin die Routen der Ressourcen liefert) und eine dynamische Konfiguration für das Dashboard. Ersetzen Sie die E-Mail-Adresse:
# /opt/pangolin/config/traefik/traefik_config.yml
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.7.0" # aktuelle Version: github.com/fosrl/badger
log:
level: "INFO"
format: "common"
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "admin@example.com" # ERSETZEN
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"Die dynamische Konfiguration leitet die Weboberfläche an Port 3002 und die API an Port 3000 von Pangolin weiter. Ersetzen Sie den Hostnamen an allen vier Stellen:
# /opt/pangolin/config/traefik/dynamic_config.yml
http:
middlewares:
badger:
plugin:
badger:
disableForwardAuth: true
redirect-to-https:
redirectScheme:
scheme: https
routers:
main-app-router-redirect:
rule: "Host(`pangolin.example.com`)" # ERSETZEN
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
- badger
next-router:
rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)" # ERSETZEN
service: next-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
api-router:
rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)" # ERSETZEN
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
ws-router:
rule: "Host(`pangolin.example.com`)" # ERSETZEN
service: api-service
entryPoints:
- websecure
middlewares:
- badger
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Weboberfläche
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API
tcp:
serversTransports:
pp-transport-v1:
proxyProtocol:
version: 1
pp-transport-v2:
proxyProtocol:
version: 2Verifizieren: ls -la /opt/pangolin/config/traefik/ zeigt traefik_config.yml, dynamic_config.yml und logs/; grep -rn example.com /opt/pangolin/config liefert keine Treffer mehr.
Schritt 4: compose.yaml anlegen
Traefik teilt über network_mode: service:gerbil den Netzwerk-Namespace mit Gerbil, der gesamte externe Verkehr läuft also durch den WireGuard-Container. Gerbil und Traefik starten erst, wenn Pangolin gesund ist. Pangolin ist auf eine Version festgeschrieben, damit Updates bewusst erfolgen.
# /opt/pangolin/compose.yaml
name: pangolin
services:
pangolin:
image: docker.io/fosrl/pangolin:1.25.1
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "10s"
timeout: "10s"
retries: 15
gerbil:
image: docker.io/fosrl/gerbil:latest
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3004
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51820:51820/udp
- 21820:21820/udp
- 443:443
- 80:80
traefik:
image: docker.io/traefik:v3.7
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro
- ./config/letsencrypt:/letsencrypt
- ./config/traefik/logs:/var/log/traefik
networks:
default:
driver: bridge
name: pangolin
# enable_ipv6: true./config/traefik ist schreibgeschützt (:ro) eingebunden, ./config/letsencrypt nicht, denn Traefik schreibt dort die acme.json.
Verifizieren: docker compose config --quiet im Projektordner meldet keinen Fehler.
Schritt 5: Stack starten und Ersteinrichtung abschließen
Starten Sie die Container im Hintergrund:
docker compose up -dGerbil und Traefik warten, bis Pangolin seinen Healthcheck besteht. Den Fortschritt zeigt:
docker compose psErwartete Ausgabe:
NAME IMAGE STATUS
pangolin fosrl/pangolin:1.25.1 Up (healthy)
gerbil fosrl/gerbil:latest Up
traefik traefik:v3.7 UpLesen Sie das einmalige Setup-Token aus dem Pangolin-Log:
docker compose logs pangolin | grep -i tokenTragen Sie es mit den Administrator-Zugangsdaten auf der Einrichtungsseite ein:
https://pangolin.example.com/auth/initial-setupVerifizieren: docker compose ps zeigt alle drei Container mit Up, Pangolin zusätzlich (healthy). config/db/db.sqlite und config/key existieren. https://pangolin.example.com öffnet das Login-Formular mit gültigem Let's-Encrypt-Zertifikat.
Schritt 6: Newt-Client auf dem internen Host deployen
Newt läuft auf dem internen Host (Heimserver, NAS, Raspberry Pi) und baut eine ausgehende WireGuard-Verbindung zum Pangolin-Server auf; am Heimrouter geben Sie keinen Port frei. Für neue Standorte empfiehlt Pangolin inzwischen die Pangolin CLI; Newt wird weiter gepflegt.
Legen Sie im Dashboard unter Sites einen neuen Standort mit Newt an und notieren Sie ID und Secret. Erstellen Sie dann auf dem internen Host eine compose.yaml:
# ~/newt/compose.yaml (auf dem internen Host)
services:
newt:
image: fosrl/newt:latest
container_name: newt
restart: unless-stopped
environment:
- PANGOLIN_ENDPOINT=https://pangolin.example.com
- NEWT_ID=ID-aus-dem-Dashboard
- NEWT_SECRET=Secret-aus-dem-Dashboard
network_mode: hostStarten Sie Newt:
docker compose up -d
docker compose logs -f newtDanach legen Sie im Dashboard Ressourcen an, etwa einen internen Dienst auf Port 8123 (Home Assistant), und weisen sie dem Standort zu.
Verifizieren: Im Dashboard unter Sites zeigt der neue Standort Online. Die Logs des Newt-Containers (docker compose logs newt) enthalten keine Fehlermeldungen wie connection refused oder timeout.
Schritt 7: Updates und Backups
Für ein Update passen Sie den Versions-Tag von Pangolin in der compose.yaml an und lesen vorher die Release Notes. Sichern Sie ./config vor jedem Update, denn die Datenbank wird beim Start migriert und ein Downgrade ist laut Hersteller nicht ohne Weiteres möglich. Alle persistenten Daten liegen in ./config. Ab 1.24 setzen private Exit-Node-Ressourcen auf den Standorten Newt ab Version 1.18.0 voraus; aktualisieren Sie Newt daher vor der Nutzung dieser Funktion.
Version 1.25 bringt Weiterleitungen (Redirects), mTLS als Anmeldemethode für öffentliche Ressourcen, eine wählbare Lastverteilung sowie das Neuerzeugen von Zugangsdaten für Standorte und Clients auch in der Community Edition; 1.25.1 behebt Relay-Probleme aktualisierter Clients. Laut Release Notes funktionieren alle Lastverteilungsoptionen erst ab Traefik 3.6, die Compose-Datei oben nutzt bereits traefik:v3.7. Für dauerhafte Weiterleitungen nennt das Projekt Badger v1.8.0, rät aber ausdrücklich, vorerst bei v1.7.0 zu bleiben, weil v1.8.0 die Integritätsprüfung für Traefik-Plugins nicht besteht und Traefik das Plugin dann abschaltet. Lassen Sie version: "v1.7.0" in der traefik_config.yml deshalb unverändert. Das Update von 1.24.0 auf 1.25.1 lief am 22.10.2026 auf einem Testsystem mit genau diesem Ablauf: Pangolin spielte die Migration 1.25.0 automatisch ein und meldete All migrations completed successfully, der Container war wieder healthy, Traefik lud das Plugin Badger v1.7.0, die Anmeldung des zuvor eingerichteten Administrators funktionierte (HTTP 200), ein falsches Passwort wurde mit 401 abgelehnt. Ohne öffentliche Domain blieb acme.json im Test leer, was Pangolin mit einer Warnung acmeCertSync: could not parse quittiert; mit ausgestelltem Zertifikat entfällt die Meldung.
# Update (im Projektordner /opt/pangolin)
docker compose pull
docker compose up -d
# Logs im Fehlerfall prüfen
docker compose logs -f
# Backup: gesamtes config-Verzeichnis sichern
tar -czf pangolin-backup-$(date +%Y%m%d).tar.gz /opt/pangolin/configÄndern Sie server.secret nicht direkt in der config.yml; verschlüsselte Daten wären sonst unlesbar. Zum Wechsel dient docker exec -it pangolin pangctl rotate-server-secret. Eine Backup-Strategie beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
Verifizieren: Nach docker compose pull && docker compose up -d zeigt docker compose ps alle Container mit aktualisierten Image-IDs und Status Up (healthy) für Pangolin.
Eckdaten auf einen Blick
| Eigenschaft | Wert |
|---|---|
| Image (empfohlen) | fosrl/pangolin:latest (SQLite, Community Edition) |
| Varianten | latest, postgresql-latest, ee-latest, ee-postgresql-latest |
| Aktuelle Version | 1.25.1 (21. Oktober 2026) |
| Lizenz | Community Edition AGPL-3.0; Enterprise Edition kommerziell, kostenlos privat und bis 100.000 USD Jahresumsatz |
| Architektur | amd64, arm64 |
| RAM (min/empfohlen) | 512 MB / 1 GB+ |
| Port | Protokoll | Funktion | Extern? |
|---|---|---|---|
| 80 | tcp | HTTP-Eingang (HTTPS-Redirect) | ja |
| 443 | tcp | HTTPS/TLS (Traefik) | ja |
| 51820 | udp | WireGuard Site-Connector | ja |
| 21820 | udp | Newt-Client Relay/Hole-Punch | ja |
| 3000–3002 | tcp | Pangolin intern: API, interne API, Weboberfläche (nie am Host exponieren) | nein |
| Volume (Host) | Container-Pfad | Inhalt |
|---|---|---|
| ./config | /app/config | SQLite-DB, config.yml, Logs (Pangolin) |
| ./config/ | /var/config | WireGuard-Schlüssel (Gerbil) |
| ./config/traefik | /etc/traefik:ro | Traefik-Konfiguration (read-only) |
| ./config/letsencrypt | /letsencrypt | ACME-Zertifikate (schreibbar!) |
| ./config/traefik/logs | /var/log/traefik | Access- und Error-Logs |
Troubleshooting / Typische Fehler
- „failed to create wireguard interface“: Gerbil fehlen die Linux-Capabilities. Prüfen Sie, ob
cap_add: [NET_ADMIN, SYS_MODULE]in dercompose.yamlvorhanden ist. Auf manchen Cloud-VMs (z. B. OpenVZ-Basis) muss das WireGuard-Kernelmodul zusätzlich auf dem Host geladen sein:modprobe wireguard. - „failed to parse config“ im Pangolin-Log:
config.ymlenthält einen YAML-Fehler, häufig Tabs statt Leerzeichen. Prüfen Sie mitpython3 -c "import yaml; yaml.safe_load(open('config/config.yml'))". - HTTPS scheitert oder kein Zertifikat: Traefik hängt nicht per
network_mode: service:gerbilan Gerbil, lädt ohne--configFileseine Konfiguration nicht, oder Port 80/tcp ist für die HTTP-Challenge gesperrt.docker compose logs traefikzeigt die Ursache. - CORS-Fehler im Browser:
app.dashboard_urloderserver.cors.originsweicht vom aufgerufenen Hostnamen ab. Korrigieren unddocker compose restart pangolinausführen. - Setup-Token nicht mehr im Log: Das Token steht nur im Log des ersten Starts. Starten Sie Pangolin mit
docker compose restart pangolinneu und prüfen Sie sofortdocker compose logs pangolin | grep -i token. - Newt meldet „connection timeout“: Port 51820/udp oder 21820/udp ist in der VPS-Firewall (UFW, Security Group des Anbieters) nicht freigegeben. Prüfen Sie
ufw statusbzw. die Cloud-Konsole. - Traefik kann acme.json nicht schreiben:
./config/letsencryptist mit:roeingebunden. Flag entfernen, Traefik neu starten. - Gerbil meldet „connection refused“: Pangolin war beim Start noch nicht gesund. Prüfen Sie Healthcheck und
depends_on.pangolin.condition: service_healthy.
Häufige Fragen
Brauche ich wirklich eine eigene Domain?
Ja. Cookies, CORS und die Zertifikate setzen einen Hostnamen voraus. Sie brauchen mindestens einen A-Record auf die öffentliche IP des VPS, für Ressourcen zusätzlich deren Subdomains. Starten Sie Pangolin erst, wenn der DNS-Eintrag auflöst.
Funktioniert Pangolin ohne Portweiterleitung am Heimrouter?
Ja, das ist der Hauptanwendungsfall. Newt baut eine ausgehende WireGuard-Verbindung zum Pangolin-Server auf; im internen Netz öffnen Sie keinen Port.
Welche Image-Variante soll ich nehmen?
Die Standardvariante fosrl/pangolin:<version> (SQLite, Community Edition) reicht für die meisten Installationen. Die PostgreSQL-Variante lohnt sich bei vorhandener PostgreSQL-Infrastruktur oder hoher Last. Die Enterprise Edition (ee-*) enthält Zusatzfunktionen unter kommerzieller Lizenz.
Wie verbinde ich einen internen Dienst, z. B. Home Assistant auf Port 8123?
Installieren Sie Newt auf dem internen Host (Schritt 6). Legen Sie dann unter Resources eine Ressource mit Ziel localhost:8123 an und weisen Sie sie dem Standort zu. Pangolin richtet die Subdomain ein und beschafft das Zertifikat.
Kann ich Pangolin neben einer bestehenden Traefik-Instanz betreiben?
Ja, mit Einschränkungen: Pangolin bringt eine eigene Traefik-Instanz mit. Nutzen Sie Pangolin als einzigen Einstiegspunkt, oder legen Sie es auf andere Ports hinter den vorhandenen Proxy. Traefik allgemein erklärt die Anleitung Traefik als Docker-Reverse-Proxy mit automatischem HTTPS.
Ist Pangolin produktionsreif?
Das Projekt wird aktiv entwickelt (Version 1.25.1, Oktober 2026). Die Community Edition steht unter AGPL-3.0 und ist frei nutzbar; die Umsatzgrenze von 100.000 USD betrifft nur die kostenlose Nutzung der Enterprise Edition.
Was passiert, wenn ich server.secret ändere?
Mit dem Secret verschlüsselt Pangolin unter anderem OIDC-Zugangsdaten; eine Änderung nur in der config.yml macht sie unlesbar. Wechseln Sie es deshalb ausschließlich mit docker exec -it pangolin pangctl rotate-server-secret --old-secret "alt" --new-secret "neu".
Fazit
Pangolin bietet externen Zugriff auf interne Dienste ohne Portfreigabe, vergleichbar mit Cloudflare Tunnel, aber vollständig selbst gehostet. Voraussetzung sind ein öffentlicher VPS und eine eigene Domain. Die Grundabsicherung des VPS beschreibt die Anleitung VPS absichern und härten: UFW, SSH-Keys und Fail2Ban.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- VPS absichern und härten: UFW, SSH-Keys und Fail2Ban
- 3-2-1-Backup-Strategie umsetzen
- WireGuard-VPN für Homeoffice und Standortvernetzung einrichten
- Headscale selbst hosten: Tailscale-Mesh-VPN ohne Cloud-Abhängigkeit für KMU
Offizielle Dokumentation und Quellen: Pangolin Docs – Docker Compose Setup · GitHub: fosrl/pangolin · Docker Hub: fosrl/pangolin


