Hosten Sie Ihren eigenen KI-Agenten mit OpenClaw - kostenlose 1-Klick-Installation!

Pangolin auf einem VPS selbst hosten (Cloudflare Tunnels ersetzen)

Pangolin auf einem VPS selbst hosten (Cloudflare Tunnels ersetzen)

Kurz gesagt. Pangolin ist eine mögliche Alternative zu Cloudflare Tunnels oder Tailscale. Du betreibst den Pangolin-Server auf einem VPS mit öffentlicher IP, installierst den Newt-Client in deinem privaten Netz und leitest Traffic sicher über WireGuard-Tunnel. Am heimischen Router musst du keine Ports öffnen. Die Einrichtung dauert mit Docker Compose unter 30 Minuten. Pangolin verwaltet SSL-Zertifikate, Reverse Proxying und identitätsbewusste Zugriffskontrolle über ein einziges Dashboard.

Voraussetzungen

Bevor du mit der Pangolin-Installation startest, stelle sicher, dass folgendes bereitsteht:

  • Ein VPS mit öffentlicher IP. Ein Contabo VPS der Einstiegsklasse bewältigt den gesamten Stack ohne Probleme und hat noch Kapazität für weitere Dienste daneben.
  • Ubuntu 22.04, 24.04 oder 26.04 (Neuinstallation empfohlen).
  • Docker und das Docker-Compose-Plugin installiert.
  • Eine Domain oder Subdomain mit einem A-Record, der auf die VPS-IP zeigt. Du benötigst Zugriff auf die DNS-Zonenverwaltung deiner Domain.
  • Die Ports 22/TCP, 80/TCP, 443/TCP, 51820/UDP und 21820/UDP in deiner Firewall geöffnet. Das lässt sich einfach über die Contabo Firewall einrichten.

Auf der Seite deines privaten Netzes – also dein Heimserver, Bürorechner oder ein sonstiges Remote-Gerät – brauchst du Docker oder die Newt-Binärdatei. Keine offenen Ports, keine Port-Weiterleitung, keine öffentliche IP auf dieser Maschine erforderlich.

Schritt 1: Den VPS vorbereiten

Melde dich per SSH als root an und aktualisiere das System, bevor du weitermachst.

  • Verbinden: ssh root@<deine-vps-ip>
  • Aktualisieren: apt update &amp;& apt upgrade -y
  • Docker und das Compose-Plugin aus dem offiziellen Docker-apt-Repository installieren:
apt install -y ca-certificates curl gnupg

install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc

chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update

apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

Prüfe die Installation mit docker compose version. Du solltest eine 2.x-Versionsangabe sehen.

Öffne als Nächstes die Ports, die Pangolin benötigt. Jeder Contabo VPS und VDS kommt mit einer kostenlosen integrierten Firewall, die du direkt aus dem Customer Control Panel verwaltest – ohne zusätzliche Software zu installieren. Öffne die Contabo-Firewall-Anleitung und lege eingehende Erlaubnisregeln für folgende Ports an: 22/TCP, 80/TCP, 443/TCP, 51820/UDP und 21820/UDP.

Schritt 2: Pangolin mit Docker Compose installieren

Der Pangolin-Server-Stack läuft als drei Container. Pangolin übernimmt Dashboard, API und Zugriffskontrolle. Gerbil verwaltet das WireGuard-Interface auf der VPS-Seite und belegt die exponierten Ports. Traefik läuft im Netzwerk-Namespace von Gerbil, nicht direkt auf dem Host. Traefik terminiert TLS, stellt Let’s-Encrypt-Zertifikate automatisch bereit und leitet HTTP-Traffic an das richtige Ziel weiter. CrowdSec lässt sich später als optionales Traefik-Plugin für reputationsbasiertes Blocking hinzufügen.

Lege das Projektverzeichnis und die erforderlichen Unterverzeichnisse an:

mkdir -p /opt/pangolin/config/db \
         /opt/pangolin/config/letsencrypt \
         /opt/pangolin/config/traefik/logs

cd /opt/pangolin

Generiere ein Secret für die Session-Signierung von Pangolin. Du brauchst die Ausgabe in config.yml:

openssl rand -hex 32

Erstelle jetzt die vier Konfigurationsdateien. Schreibe jede in den angegebenen Pfad, bevor du mit der nächsten weitermachst.

docker-compose.yml

name: pangolin

services:

  pangolin:
    image: docker.io/fosrl/pangolin:latest
    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
      - 22:22

  traefik:
    image: docker.io/traefik:v3.6
    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

config/traefik/traefik_config.yml – ersetze [email protected] durch deine echte E-Mail-Adresse:

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.4.0"

log:
  level: "INFO"
  format: "common"
  maxSize: 100
  maxBackups: 3
  maxAge: 3
  compress: true

certificatesResolvers:
  letsencrypt:
    acme:
      httpChallenge:
        entryPoint: web
      email: "[email protected]"
      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"

config/traefik/dynamic_config.yml – ersetze jeden Eintrag pangolin.example.com durch deinen Dashboard-Hostnamen:

http:
  middlewares:
    badger:
      plugin:
        badger:
          disableForwardAuth: true
    redirect-to-https:
      redirectScheme:
        scheme: https

  routers:
    main-app-router-redirect:
      rule: "Host(`pangolin.example.com`)"
      service: next-service
      entryPoints:
        - web
      middlewares:
        - redirect-to-https
        - badger

    next-router:
      rule: "Host(`pangolin.example.com`) && !PathPrefix(`/api/v1`)"
      service: next-service
      entryPoints:
        - websecure
      middlewares:
        - badger
      tls:
        certResolver: letsencrypt

    api-router:
      rule: "Host(`pangolin.example.com`) && PathPrefix(`/api/v1`)"
      service: api-service
      entryPoints:
        - websecure
      middlewares:
        - badger
      tls:
        certResolver: letsencrypt

    ws-router:
      rule: "Host(`pangolin.example.com`)"
      service: api-service
      entryPoints:
        - websecure
      middlewares:
        - badger
      tls:
        certResolver: letsencrypt

  services:
    next-service:
      loadBalancer:
        servers:
          - url: "http://pangolin:3002"
    api-service:
      loadBalancer:
        servers:
          - url: "http://pangolin:3000"

tcp:
  serversTransports:
    pp-transport-v1:
      proxyProtocol:
        version: 1
    pp-transport-v2:
      proxyProtocol:
        version: 2

config/config.yml – ersetze alle drei Platzhalter-Domains und füge das mit openssl generierte Secret ein:

gerbil:
    start_port: 51820
    base_endpoint: "pangolin.example.com"

app:
    dashboard_url: "https://pangolin.example.com"
    log_level: "info"
    telemetry:
        anonymous_usage: true

domains:
    domain1:
        base_domain: "example.com"

server:
    secret: "paste-your-openssl-output-here"
    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: false
    disable_user_create_org: false
    allow_raw_resources: true

Schritt 3: Pangolin starten und aufs Dashboard zugreifen

  • Stack starten: docker compose up -d
  • Prüfen, ob alle drei Container laufen: docker compose ps. Gerbil und Traefik warten darauf, dass der Healthcheck von Pangolin erfolgreich durchläuft, bevor sie starten – gib dem Ganzen etwa 30 Sekunden.
  • Das Einmal-Setup-Token aus den Pangolin-Logs abrufen:
docker compose logs pangolin

Suche nach dem Block === SETUP TOKEN GENERATED === und kopiere das Token.

  1. Öffne https://pangolin.example.com/auth/initial-setup im Browser. Die erste Let’s-Encrypt-Zertifikatsanfrage kann bis zu 60 Sekunden dauern. Falls beim ersten Aufruf eine Zertifikatswarnung erscheint, warte eine Minute und lade die Seite neu.
  2. Füge das Setup-Token ein, lege deine Admin-E-Mail-Adresse und dein Passwort fest und erstelle dann deine erste Organisation.

Kann Traefik kein Zertifikat beziehen, prüfe, ob dein DNS-A-Record propagiert ist und ob nichts anderes die Ports 80 oder 443 auf dem Host belegt.

Schritt 4: Eine private Site per Newt über WireGuard verbinden

Newt ist der Site-Connector-Agent von Pangolin. Er läuft in deinem privaten Netz, baut eine ausgehende WireGuard-Verbindung zum Pangolin-Hub auf und leitet Traffic an deine lokalen Dienste weiter. Da Newt die Verbindung ausgehend initiiert, muss dein Heimrouter keine Ports öffnen, keine Port-Weiterleitung einrichten und keine öffentliche IP haben.

Im Pangolin-Dashboard gehst du zu Sites, klickst auf Add Site, wählst Newt Tunnel und gibst der Site einen Namen. Pangolin zeigt dir drei Zugangsdaten: die Endpoint-URL, die Newt-ID und das Newt-Secret. Kopiere alle drei. Sie werden nur einmal angezeigt.

Auf deinem Heimserver deployst du Newt per Docker Compose:

services:
  newt:
    image: fosrl/newt
    container_name: newt
    restart: unless-stopped
    environment:
      - PANGOLIN_ENDPOINT=https://pangolin.example.com
      - NEWT_ID=<deine-newt-id>
      - NEWT_SECRET=<dein-newt-secret>

Starte ihn mit docker compose up -d. Innerhalb weniger Sekunden wechselt der Site-Indikator im Dashboard deiner Pangolin-Instanz auf grün und zeigt Online.

Schritt 5: Deinen ersten Dienst per Reverse Proxy freigeben

Sobald der Newt-Tunnel aktiv ist, braucht es keine Konfigurationsdatei-Änderungen, um einen Dienst freizugeben. Alles läuft über das Pangolin-Dashboard:

  • Öffne deine Site und klicke auf Add Resource.
  • Vergib einen Namen für die Ressource und wähle eine Subdomain.
  • Gib unter Target Configuration die interne Adresse des Dienstes so ein, wie Newt ihn sieht. Für einen Dienst unter 192.168.1.10:3000 in deinem Heimnetz trägst du http://192.168.1.10:3000 ein. Für einen Dienst im selben Docker-Netzwerk wie Newt verwendest du Containername und Port.
  • Aktiviere HTTPS. Traefik stellt das Zertifikat automatisch bereit.
  • Lege eine Zugriffsrichtlinie fest: öffentlich, passwortgeschützt oder auf bestimmte Nutzer oder E-Mail-Domains beschränkt.

Die Ressource ist innerhalb von Sekunden unter ihrer Subdomain erreichbar. Wenn du einen Wildcard-A-Record hinzufügst (*.pangolin.example.com, der auf die VPS-IP zeigt), ist jede neue Ressource sofort erreichbar – ohne einen separaten DNS-Eintrag pro Dienst.

Schritt 6: Browser-basierten SSH-/RDP-Zugriff einrichten (ab v1.19)

Ab Pangolin 1.19 sind SSH, RDP und VNC als vollwertige öffentliche Ressourcentypen neben HTTP verfügbar. Ein Nutzer öffnet die Ressource-URL, authentifiziert sich über Pangolin und erhält eine vollständige interaktive Session im Browser. Ein separater SSH-Client, eine Remote-Desktop-App oder ein VNC-Viewer ist nicht erforderlich.

Um Browser-SSH für einen VPS zu aktivieren, klickst du auf Add Resource, wählst SSH als Protokoll und den Modus Pangolin SSH. Dieser Modus setzt lediglich voraus, dass Newt als root auf dem Zielrechner läuft. Änderungen an sshd_config oder PAM-Konfiguration sind nicht nötig. Vergib eine Subdomain und eine Zugriffsrichtlinie – das Terminal ist dann live im Browser.

Für RDP wählst du RDP als Protokoll, trägst die IP des Windows-Hosts und Port 3389 als Ziel ein und vergibst eine Domain. Die Session wird im Browser gerendert, mit vollständiger Zwischenablage und Dateitransfer-Unterstützung.

Browser-basiertes SSH, RDP und VNC erfordern Newt 1.13.0 oder neuer. Führe docker compose pull &&amp; docker compose up -d auf deinem Heimserver aus, bevor du diese Ressourcentypen aktivierst.

Sicherheits-Checkliste

Bevor du etwas Sensibles freigibst, arbeite diese Liste durch:

  • Setze ein starkes Admin-Passwort und ändere es sofort, falls du bei der Ersteinrichtung ein schwaches verwendet hast.
  • Beschränke den Dashboard-Zugriff auf bekannte IP-Adressen über eine Pangolin-Zugriffsrichtlinie.
  • Halte die Pangolin-, Gerbil- und Traefik-Images aktuell. Führe docker compose pull && docker compose up -d aus /opt/pangolin regelmäßig aus. Ab Pangolin 1.19 gibt es optionale automatische Newt-Updates, die du im Dashboard pro Site aktivieren kannst.
  • Prüfe, ob deine Contabo-Firewall-Regeln nur die Ports freigeben, die du wirklich brauchst.
  • Aktiviere CrowdSec als optionales Traefik-Plugin, wenn deine Ressourcen öffentlichem Traffic ausgesetzt sind. Es blockiert bekannte schädliche IPs am Eingang, bevor Anfragen deine Dienste erreichen.
  • Sichere das config/-Verzeichnis auf dem VPS regelmäßig. Es enthält die SQLite-Datenbank, TLS-Zertifikate und die gesamte Ressourcenkonfiguration.

FAQ: Pangolin selbst hosten

Wie viel RAM braucht Pangolin auf einem VPS?

Die Container Pangolin, Gerbil und Traefik verbrauchen im Leerlauf zusammen nur wenige Hundert MB RAM. Ein VPS mit 4 GB RAM deckt den Stack komfortabel ab und hat noch Puffer für mehrere aktive Tunnel. Planst du, weitere Dienste auf demselben VPS zu betreiben – einen Monitoring-Stack, ein Wiki oder eine Datenbank – steig auf 8 GB oder mehr auf, damit sich die Dienste unter Last nicht gegenseitig behindern.

Kann ich Pangolin ohne eigene Domain selbst hosten?

Mit dem Standard-Setup nicht. Traefik verwendet den Let’s-Encrypt-HTTP-01-Challenge, um Zertifikate auszustellen. Das erfordert eine Domain mit einem gültigen A-Record, der auf den VPS zeigt. Eine Domain kostet nur wenige Euro im Jahr und lohnt sich für jedes dauerhafte Remote-Access-Setup. Pangolin Cloud ist eine Alternative, wenn du die Steuerungsebene ohne eigenen VPS verwaltet haben möchtest.

Was ist der Newt-Client in Pangolin?

Newt ist der Site-Connector von Pangolin: ein WireGuard-Tunnel-Client im Userspace, der in deinem privaten Netz läuft und eine verschlüsselte ausgehende Verbindung zum Pangolin-Server aufbaut. Da Newt die Verbindung ausgehend initiiert, muss dein Heimrouter keine Ports öffnen – nicht einmal WireGuards Standard-UDP-Port 51820. Newt fungiert außerdem als TCP/UDP-Proxy und leitet Traffic vom Pangolin-Reverse-Proxy an Dienste in deinem lokalen Netz weiter.

Wie aktualisiere ich Pangolin?

Wechsle in das Verzeichnis /opt/pangolin und führe docker compose pull && docker compose up -d aus. Sichere vorher immer das config/-Verzeichnis. Es enthält die SQLite-Datenbank und TLS-Zertifikate – einen einfachen Downgrade-Pfad gibt es nicht, sobald Migrationen gelaufen sind. Für Newt auf deinem Heimserver gilt dasselbe Vorgehen. Ab Pangolin 1.19 gibt es optionale automatische Newt-Updates: Aktiviere sie im Dashboard auf Organisations- oder Site-Ebene, um Edge-Geräte ohne manuellen Eingriff aktuell zu halten.

Nach oben scrollen