Pingvin Stack mit Pocket-ID und Traefik einrichten #
Einleitung #
In dieser Anleitung wird Schritt für Schritt erklärt, wie man einen Pingvin Stack mit Pocket-ID und Traefik aufsetzt. Ziel ist es, eine sichere und einfach zu wartende Umgebung zum Teilen von Dateien bereitzustellen, die durch einen Identity-Provider (IdP) abgesichert ist und durch Traefik als Reverse-Proxy verwaltet wird.
Diese Dokumentation richtet sich sowohl an Einsteiger als auch an erfahrene Nutzer, die detaillierte Anleitungen und Codebeispiele bevorzugen. Alle Konfigurationsdateien werden hier bereitgestellt.
Voraussetzungen #
Bevor du startest, stelle sicher, dass die folgenden Voraussetzungen erfüllt sind:
- Betriebssystem: Linux (z. B. Ubuntu 20.04 oder neuer) oder ein anderes kompatibles System.
- Benutzerrechte: Zugriff auf eine Shell mit Root-Rechten oder sudo-Berechtigungen.
- Installierte Tools:
- Docker (mindestens Version 20.10)
- Docker Compose (mindestens Version 2.0)
- Ein Texteditor (z. B.
nano,vimoder ein beliebiger Editor Ihrer Wahl).
- Domain: Eine registrierte Domain, die für Traefik genutzt wird (z. B.
example.com). - TLS-Zertifikate: Automatisiert über Let’s Encrypt oder manuell bereitgestellt.
Schritt 1: Vorbereitungen #
1.1 Aktualisierung des Systems #
Führe zunächst eine Systemaktualisierung durch, um sicherzustellen, dass alle Pakete auf dem neuesten Stand sind:
sudo apt update && sudo apt upgrade -y
1.2 Docker und Docker Compose installieren #
- Führe den folgenden Befehl aus, um Docker zu installieren:
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
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" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- Verifizieren der Installation:
docker --version
1.3 Netzwerk konfigurieren #
Erstelle ein dediziertes Netzwerk für Docker, falls noch keines existiert:
docker network create webproxy
Damit wird ein eigenes Netzwerk erstellt, das von Traefik und den Containern gemeinsam genutzt werden kann.
1.4 Ordnerstruktur vorbereiten #
Für das Deployment brauchst du eine gewisse Ordnerstruktur. Du kannst diese aus dem folgenden Beispiel übernehmen. Erstelle die Ordner und Dateien. Wir befüllen diese in den nächsten Schritten
├── traefik
│ ├── data
│ │ ├── dynamic
│ │ │ └── middlewares.yml
│ │ ├── acme.json
│ │ └── traefik.yml
│ ├── error-pages
│ │ └── app-down.html
│ └── docker-compose.yml
├── pingvin-stack
│ ├── .env
│ └── docker-compose.yml
├── portainer
│ └── docker-compose.yml
Schritt 2: Traefik einrichten #
2.1 Erstellung der Traefik-Konfigurationsdatei #
Erstelle eine neue Datei namens traefik.yml im Arbeitsverzeichnis:
# /root/traefik/data/traefik.yml
api:
dashboard: true # Aktiviert das Dashboard
debug: true
entryPoints:
http:
address: ":80" # Port 80 für HTTP Traffic
https:
address: ":443" # Port 443 für HTTPS Traffic
serversTransport:
insecureSkipVerify: true # Selfsigned Zertifikate von Containern werden ignoriert
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false # Automatisches Exposen von Containern disablen
file:
directory: /dynamic # Discovery von manuellen Routen im Dynamic Ordner
watch: true # Files werden automatisch beobachtet und aktualisiert
certificatesResolvers: # Let's Encrypt Zertifikate über Cloudflare
cloudflare:
acme:
email: [email protected]
storage: acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
2.2 Erstellung der Docker-Compose-Konfiguration #
Erstelle eine docker-compose.yml für Traefik:
# /root/traefik/docker-compose.yml
services:
traefik:
image: "traefik:v3.2"
container_name: traefik
command:
# Enable Hub communication (open the port 9900 and 9901 by default)
- --experimental.hub=true
- --hub.tls.insecure=true
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- webproxy
ports:
- 80:80
- 443:443
depends_on:
- error-pages
environment:
- [email protected]
- CF_DNS_API_TOKEN=xyzxyzxyzxyzxyzxyzxyzxyzxyzxyz
- TZ=Europe/Berlin
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /root/traefik/data/traefik.yml:/traefik.yml:ro
- /root/traefik/data/acme.json:/acme.json
- /root/traefik/data/dynamic:/dynamic:ro
labels:
# Enabeling Traefik
- "traefik.enable=true"
# Traefik Default HTTP Endpoint with HTTPS Redirection
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)" # Hier Domain einsetzen
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
# Traefik Error Pages
- "traefik.http.routers.traefik.middlewares=error-pages-middleware"
# Traefik HTTPS Endpoint with Wildcard Cert, issued from Cloudflare
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.com`)" # Hier Domain einsetzen
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=example.com" # Hier Domain einsetzen
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.example.com" # Hier Domain einsetzen
# Exposure of the API interface
- "traefik.http.routers.traefik-secure.service=api@internal"
# Catchall HTTP and redirect to HTTPS
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:[a-z-.]+}`)"
- "traefik.http.routers.http-catchall.entrypoints=http"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
error-pages:
image: tarampampam/error-pages:3.2.0
restart: unless-stopped
command: serve --add-template /opt/app-down.html
# environment:
# - TEMPLATE_NAME=app-down #connection #app-down # set the error pages template
volumes:
- /root/traefik/error-pages/app-down.html:/opt/app-down.html:ro
networks:
- webproxy
labels:
traefik.enable: true
# use as "fallback" for any NON-registered services (with priority below normal)
traefik.http.routers.error-pages-router.rule: HostRegexp(`{host:.+}`)
traefik.http.routers.error-pages-router.priority: 1
# should say that all of your services work on https
traefik.http.routers.error-pages-router.tls: 'true'
traefik.http.routers.error-pages-router.entrypoints: https
traefik.http.routers.error-pages-router.middlewares: error-pages-middleware
traefik.http.services.error-pages-service.loadbalancer.server.port: 8080
# "errors" middleware settings
traefik.http.middlewares.error-pages-middleware.errors.status: 400-599
traefik.http.middlewares.error-pages-middleware.errors.service: error-pages-service
traefik.http.middlewares.error-pages-middleware.errors.query: /{status}.html
networks:
webproxy:
external: true
In dem obenstehenden File wird neben Traefik auch noch ein weiterer Container namens error-pages aufgesetzt. Diese stellt Fehlerseiten passend zum HTTP Code zur Verfügung, sollte eine Seite nicht erreichbar sein.
2.4 Traefik starten #
Starte den Traefik-Container:
docker compose up -d
Überprüfe, ob Traefik läuft und erreichbar ist, indem du die Domain aufrufst oder die Logs prüfst:
docker logs traefik
Schritt 3: Pingvin Pocket-ID einrichten #
3.1 Erstellung der Pocket-ID-Umgebungsvariablen #
Erstelle eine Datei namens .env und füge die folgenden Inhalte hinzu:
# /root/pingvin-stack/.env
# See the README for more information: https://github.com/stonith404/pocket-id?tab=readme-ov-file#environment-variables
PUBLIC_APP_URL=https://login.example.com
TRUST_PROXY=true
# MAXMIND_LICENSE_KEY: hier bitte die Dokumentation lesen.
# Dieser Key wird für die Standortauflösung im Audit Log später verwendet.
MAXMIND_LICENSE_KEY=xyzxyzxyzxyzxyzxyzxyz
# Für die UserID muss der entsprechende User mit der ID verwendet werden, dies sollte nicht root sein.
PUID=1000
PGID=1000
3.2 Erstellung der Docker-Compose-Konfiguration für den Pingvin Stack #
Erstelle eine Datei docker-compose.yml mit folgendem Inhalt:
# /root/pingvin-stack/docker-compose.yml
services:
pingvin-share:
container_name: pingvin-app
image: stonith404/pingvin-share
restart: unless-stopped
ports:
- 3000:3000
environment:
- TRUST_PROXY=false # Set to true if a reverse proxy is in front of the container
volumes:
- "./pingvin/data:/opt/app/backend/data"
- "./pingvin/data/images:/opt/app/frontend/public/img"
networks:
- webproxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.share.rule=Host(`share.example.com`)" # Hier Domain einsetzen
- "traefik.http.routers.share.entrypoints=http"
- "traefik.http.routers.share-secure.rule=Host(`share.example.com`)" # Hier Domain einsetzen
- "traefik.http.routers.share-secure.entrypoints=https"
- "traefik.http.routers.share-secure.tls=true"
- "traefik.http.routers.share.middlewares=default-headers@file,error-pages-middleware"
- "traefik.http.services.share.loadbalancer.server.port=3000"
pocket-id:
container_name: pocket-id-app
image: stonith404/pocket-id # or ghcr.io/stonith404/pocket-id
restart: unless-stopped
env_file: .env
ports:
- 3001:80
volumes:
- "./pocket-id/data:/app/backend/data"
networks:
- webproxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.login.rule=Host(`login.example.com`)" # Hier Domain einsetzen
- "traefik.http.routers.login.entrypoints=http"
- "traefik.http.routers.login-secure.rule=Host(`login.example.com`)" # Hier Domain einsetzen
- "traefik.http.routers.login-secure.entrypoints=https"
- "traefik.http.routers.login-secure.tls=true"
- "traefik.http.routers.login.middlewares=default-headers@file,error-pages-middleware"
- "traefik.http.services.login.loadbalancer.server.port=80"
healthcheck:
test: "curl -f http://localhost/health"
interval: 1m30s
timeout: 5s
retries: 2
start_period: 10s
networks:
webproxy:
external: true
3.3 Pingvin Stack mit Pocket ID starten #
Starten der Container mit folgendem Befehl:
docker compose up -d
Schritt 4: Einrichten der beiden neuen Dienste #
4.1 Konfiguration von Pocket ID #
Rufe zunächst die URL https://login.example.com/login/setup auf, um auch hier deinen Administrator User anzulegen.
Anschließend kannst du deinen Namen und Benutzernamen festlegen. Wichtig ist hier, dass du unbedingt einen Passkey hinterlegen musst, da du dich mit diesem dann authentifizierst.
Du kannst unter Application Configuration Anpassungen deiner Pocket ID App vornehmen, ein Logo hochladen und einen Hintergrund festlegen. Anschließend konfigurierst du einen OIDC Client.
Dieser wird benötigt, um dich später am Pingvin anzumelden. Füge Name und Callback URL hinzu und klicke auf Save.
Du erhältst anschließend verschiedene Daten, welche du benötigst um OIDC in Pingvin einzurichten. Lasse diese Seite also geöffnet. Wir brauchen die Daten anschließend.
4.2 Konfiguration von Pingvin #
Hierzu rufst du zunächst die URL von Pingvin auf. Diese sollte etwa so lauten: https://share.examle.com
Klicke nun auf Registrieren um deinen Admin Benutzer anzulegen und klicke anschließend auf Lass uns loslegen.
Du kannst anschließend die Konfiguration durchführen. Klicke hierzu auf Customize Configuration.
Benenne deine App und füge deine URL hinzu. Außerdem empfehle ich Sichere Cookies zu aktivieren. Du kannst auch dein eigenes Logo hochladen.
Unter dem Punkt Freigabe solltest du jetzt die Registrierung abschalten, weil wir das anschließend über OIDC - also Pocket ID realisieren werden. Unter dem Punkt Anmeldung über soziale Netzwerke kannst du das Anmelden mit einem Passwort auch deaktivieren.
Um OIDC nun einzurichten, öffne Anmeldung über soziale Netzwerke.
Deaktiviere jetzt zunächst die Anmeldung per Passwort, um nur noch mit Pocket ID eine Anmeldung zu ermöglichen.
Anschließend scrollst du weiter nach unten um dann OIDC zu konfigurieren. Aktiviere OpenID Connect und füge die Discovery URL ein. Diese findest du im vorhergehenden Tab zu Pocket ID, in dem du den OIDC Client angelegt hast.
Ganz am Ende der Seite muss nun noch die Client ID und das Client Secret hinterlegt werden. Anschließend speicherst du die Konfiguration ab und damit ist OIDC für Pingvin konfiguriert.
Schritt 5: Anmelden per OIDC #
Du kannst Pocket ID nun als OIDC Provider verwenden und dich damit anmelden. Dazu kannst du ein neues Browserfenster öffnen und https://share.example.com öffnen. Du solltest nun automatisch weitergeleitet werden und die Möglichkeit haben, dich mit deinem Passkey anzumelden.
Bonus: Portainer Deployment und OIDC Anbindung #
6.1 Erstellung der Docker-Compose-Konfiguration #
Erstelle eine docker-compose.yml für Traefik:
# /root/portainer/docker-compose.yml
services:
portainer:
container_name: portainer
image: portainer/portainer-ce:latest
command: -H unix:///var/run/docker.sock
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
networks:
- webproxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
- "traefik.http.routers.portainer.entrypoints=https"
- "traefik.http.routers.portainer.tls=true"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
- "traefik.http.routers.portainer.middlewares=default-headers@file,error-pages-middleware"
volumes:
portainer_data:
networks:
webproxy:
external: true
6.2 Anbindung von Portainer an OIDC #
Erstelle zunächst wieder eine OIDC Konfiguration in Pocket ID. Wechsle anschließend zu deiner Portainer Instanz und wähle unter Settings → Authentication die Methode OAuth aus.
Anschließend musst du hier auch entsprechend die Konfigurationen machen, die du in Pocket ID nach der Erstellung des OIDC Client erhältst.
Die Konfiguration sieht ungefähr so aus:
Damit du dich später per OIDC anmelden kannst, musst du deinen User noch anlegen. Hierzu klickst du auf User-related → User und fügst deinen User mit der E-Mail Adresse hinzu, machst ihn zum Administrator und klickst anschließend auf + Create user. Das wars. Jetzt kannst du dich auch hier mit deinem Pocket ID Account anmelden.