Zum Hauptinhalt springen

Pingvin und Pocket ID - Share sicher Dateien

·1682 Wörter·8 min· loading · loading · ·
Security Homelab Docker Container
Luca-Leon Hausdörfer
Autor
Luca-Leon Hausdörfer
Hi, ich bin Fachinformatiker für Systemintegration und teile hier Projekte aus meinem Homelab sowie persönliche Einblicke – ehrlich und inspirierend.
Inhaltsverzeichnis

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, vim oder 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
#

Die Installation für Docker und Docker Compose kann abweichen. Siehe hierzu in der Docker Dokumentation nach, wie die Software für dein Betriebssystem installiert wird. Diese Doku hier bezieht sich auf Ubuntu.
  1. 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
  1. 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.

Benutzer bearbeiten und Passkey anlegen
Benutzer bearbeiten und Passkey anlegen

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

Pingvin Startseite
Pingvin Startseite

Klicke nun auf Registrieren um deinen Admin Benutzer anzulegen und klicke anschließend auf Lass uns loslegen.

Administrator Konto anlegen
Administrator Konto anlegen

Hinweis: Du solltest hier unbedingt den gleichen Benutzernamen und E-Mail Adresse wählen, wie du es in Pocket ID schon getan hast, damit die Administrator Berechtigung dann übertragen wird.

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.

Beachte bitte, dass du dich zu diesem Zeitpunkt NICHT mehr abmelden solltest, da du dich sonst nicht mehr anmelden kannst. Nach der Konfiguration von Pocket ID wird die Anmeldung wieder funktionieren.

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.

Anmeldung mit Passwort deaktivieren
Anmeldung mit Passwort deaktivieren

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.

OIDC Discovery URL eingeben
OIDC Discovery URL eingeben

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.

Eintragen der Secrets
Eintragen der Secrets


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.