Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 12.09.2026 · 17 min Lesezeit

Pocket ID mit Docker Compose installieren: Passkey-SSO ohne Keycloak-Ballast

Pocket ID ist ein quelloffener OIDC-Provider, bei dem sich Nutzer ausschließlich per Passkey anmelden. Diese Anleitung zeigt Schritt für Schritt die Installation per Docker Compose, erklärt alle wichtigen Umgebungsvariablen, die zwingende HTTPS-Bereitstellung wegen WebAuthn, Reverse-Proxy-Beispiele für Caddy und NGINX sowie Backup, Updates und typische Fehler.

Grafik zeigt ein Pocket-ID-Dashboard mit Passkey-Anmeldung und angebundenen Anwendungen KI-generiert

Pocket ID ist ein schlanker, quelloffener OIDC-Provider, bei dem sich Nutzer ausschließlich per Passkey anmelden. Wer Single Sign-on für die eigenen Dienste braucht, dem Keycloak oder Authentik aber zu schwergewichtig sind, bekommt hier einen Dienst, der sich in wenigen Minuten per Docker Compose starten lässt. Diese Anleitung zeigt Installation, Konfiguration, Absicherung per Reverse Proxy, Backup, Updates und Fehlerdiagnose.

Der praktische Teil dieser Anleitung wurde am 12. September 2026 auf einem Ubuntu-Testsystem mit Docker 29.1.3 und Docker Compose 2.40.3 ausgeführt. Welche Schritte tatsächlich selbst geprüft wurden und welche nur aus der offiziellen Dokumentation stammen, steht weiter unten ausdrücklich im Abschnitt zur Prüfung.

Was Pocket ID leistet und wo die Grenzen liegen

Pocket ID ist ein OpenID-Connect-Provider. Es übernimmt die Anmeldung für angeschlossene Anwendungen, die OIDC sprechen, und gibt diesen nach erfolgreicher Authentifizierung ein Token mit Identitätsdaten zurück. Der entscheidende Unterschied zu den großen Lösungen ist die Reduktion: Es gibt genau einen Anmeldeweg, nämlich den Passkey nach dem WebAuthn-Standard. Keine Passwörter, keine E-Mail-Magic-Links als Hauptweg, keine Kerberos-Integration.

Das ist bewusst als Feature gedacht und zugleich die größte Einschränkung. Wer Passkeys im Unternehmen bereits etabliert hat, bekommt einen sehr geradlinigen Dienst. Wer noch Geräte im Einsatz hat, die WebAuthn nicht sauber unterstützen, oder wer Nutzer ohne eigenes Smartphone beziehungsweise ohne modernen Browser betreut, stößt schnell an Grenzen.

  • Pocket ID ist kein LDAP-Ersatz. Es ersetzt keinen Verzeichnisdienst und keine zentrale Benutzerverwaltung für Dateifreigaben oder Domaenenanmeldungen.
  • Pocket ID ist kein vollständiger Identity-Provider mit SAML, Benutzer-Self-Service-Portal, komplexen Authentifizierungsflüssen und Policy-Engine. Genau das leisten Keycloak und Authentik, und genau dafür brauchen sie deutlich mehr Ressourcen und Einarbeitung.
  • Pocket ID ist gut geeignet als zentrale Anmeldung für eine überschaubare Zahl selbst gehosteter Dienste, etwa Dashboards, Monitoring-Oberflächen, interne Werkzeuge oder Anwendungen hinter einem Reverse Proxy mit OIDC-Unterstützung.
  • Pocket ID ist ungeeignet, wenn zwingend ein zweiter Anmeldeweg ohne Passkey vorhanden sein muss, etwa für Notfallzugriffe von fremden Geräten ohne Sicherheitsschlüssel.
  • Pocket ID läuft standardmäßig auf SQLite. Das reicht für kleine bis mittlere Installationen, ist aber kein Cluster-Setup mit mehreren aktiven Instanzen.

Pocket ID im Vergleich zu Keycloak und Authentik

Die folgende Gegenüberstellung ordnet die drei Projekte für die Auswahl ein. Sie bewertet den typischen Einsatz in kleinen Umgebungen, nicht den maximalen Funktionsumfang im Konzernbetrieb.

KriteriumPocket IDKeycloakAuthentik
Anmeldeverfahrenausschließlich Passkey nach WebAuthnPasswort, OTP, WebAuthn, Kerberos, externe ProviderPasswort, OTP, WebAuthn, konfigurierbare Flows
ProtokolleOIDCOIDC, OAuth 2.0, SAMLOIDC, OAuth 2.0, SAML, LDAP-Ausgabe, Proxy-Auth
Standard-DatenbankSQLite im Datenverzeichnisexterne Datenbank empfohlenPostgreSQL plus Redis
Container im Minimalbetriebein Containerein Container plus Datenbankmehrere Container
Einarbeitungsaufwandgeringhochmittel bis hoch
Typischer EinsatzSelfhosting, kleine TeamsUnternehmen mit vielen AnwendungenSelfhosting bis Unternehmen mit Proxy-Auth-Bedarf
Verzeichnisdienst-Anbindungnicht vorgesehenLDAP und Active DirectoryLDAP und Active Directory

Zur Verbreitung: Das Repository weist am 12. September 2026 laut GitHub 9.162 Sterne aus. Der letzte Push in das Repository stammt vom 11. September 2026, das Projekt wird also aktiv gepflegt und ist nicht archiviert. Quelle ist das GitHub-Repository selbst, Abrufdatum 12. September 2026.

Voraussetzungen und Ressourcenbedarf

Für den Betrieb per Docker Compose braucht es wenig. Entscheidend ist nicht die Rechenleistung, sondern die korrekte Netzwerk- und TLS-Umgebung.

  • Ein Linux-Host mit installierter Docker Engine und dem Compose-Plugin. Getestet wurde mit Docker 29.1.3 und Docker Compose 2.40.3.
  • Ein Benutzerkonto mit Rechten für Docker-Befehle, entweder über die Gruppe docker oder über sudo.
  • Ein freier TCP-Port auf dem Host. Standard ist 1411.
  • Ein Verzeichnis für persistente Daten, im Beispiel ./data neben der Compose-Datei.
  • Eine Domain mit gültigem TLS-Zertifikat für den Produktivbetrieb, bereitgestellt über einen Reverse Proxy oder einen vorgelagerten Dienst.
  • Ein Endgerät mit Passkey-Unterstützung für die Erstanmeldung, also ein aktueller Browser plus Plattform-Authenticator oder ein Hardware-Sicherheitsschlüssel.
  • Der Dienst kommt mit sehr wenig Arbeitsspeicher aus, ein Container ohne separate Datenbank genügt für den Start.

HTTPS-Pflicht wegen WebAuthn

Das ist der Punkt, an dem die meisten Erstinstallationen scheitern. Pocket ID nutzt die WebAuthn-API des Browsers. Diese Schnittstelle steht nur in einem sogenannten sicheren Kontext zur Verfügung. Praktisch heißt das: Die Anwendung muss über HTTPS ausgeliefert werden. Ohne HTTPS bietet der Browser die Passkey-Registrierung gar nicht erst an oder bricht sie ab.

Die offizielle Dokumentation nennt dafür zwei Wege: einen Reverse Proxy wie Caddy oder NGINX, der das Zertifikat terminiert, oder einen vorgelagerten Dienst wie Cloudflare, der HTTPS für die Domain bereitstellt. Beides ist gleichwertig, solange der Browser am Ende eine gültige HTTPS-Verbindung sieht.

Es gibt genau eine Ausnahme: localhost gilt im Browser als sicherer Kontext. Ein reiner Funktionstest auf dem lokalen Rechner unter http://localhost:1411 funktioniert deshalb auch ohne TLS. Für den Produktivbetrieb reicht das nicht, denn sobald der Dienst über eine IP-Adresse oder einen Hostnamen im Netz erreichbar sein soll, greift die Regel wieder.

Plattformen, Architekturen und geprüfter Versionsstand

Pocket ID wird als Container-Image und zusätzlich als eigenständiges Binary veröffentlicht.

  • Container-Image bei GitHub Container Registry: ghcr.io/pocket-id/pocket-id:v2
  • Alternatives Image bei Docker Hub: pocketid/pocket-id:v2
  • Standalone-Binary von der Releases-Seite nach dem Namensschema pocket-id-<betriebssystem>-<architektur>, zum Beispiel pocket-id-linux-amd64
  • Zusätzlich existiert eine nicht offiziell unterstützte Community-Variante mit Podman und Quadlet. Diese Anleitung behandelt sie nicht weiter, Schwerpunkt bleibt Docker Compose.

Das aktuelle Release laut GitHub ist v2.14.0, veröffentlicht am 18. August 2026. Das in den Beispielen verwendete Tag v2 ist ein gleitendes Major-Tag: Es zieht neue Versionen innerhalb der Hauptversion 2 automatisch nach, sobald das Image neu geladen wird. Wer das nicht will, setzt stattdessen ein festes Tag mit vollständiger Versionsnummer.

Lizenziert ist das Projekt unter BSD-2-Clause.

Installation Schritt für Schritt

Die offizielle Installation besteht aus drei Schritten: Vorlagen herunterladen, .env ausfüllen, Stack starten. Zuerst ein eigenes Verzeichnis anlegen und hineinwechseln.

# Arbeitsverzeichnis anlegen und hineinwechseln
mkdir -p /opt/pocket-id
cd /opt/pocket-id

Danach die beiden Vorlagen aus dem Repository laden. Die erste Datei ist die Compose-Definition, die zweite die Beispielkonfiguration, die anschließend als .env dient.

# offizielle Compose-Datei herunterladen
curl -o docker-compose.yml https://raw.githubusercontent.com/pocket-id/pocket-id/main/docker-compose.yml

# Beispielkonfiguration als .env herunterladen
curl -o .env https://raw.githubusercontent.com/pocket-id/pocket-id/main/.env.example

Jetzt den Verschluesselungsschluessel erzeugen. Er wird gleich in die .env eingetragen.

# Verschlüsselungsschlüssel erzeugen und anzeigen
openssl rand -base64 32

Außerdem die eigene Benutzer- und Gruppenkennung ermitteln, damit die Dateien im Datenverzeichnis später dem richtigen Konto gehören.

# eigene UID und GID ermitteln
id -u
id -g

Erst wenn .env vollständig ausgefüllt ist, wird der Stack gestartet. Die nächsten beiden Abschnitte zeigen beide Dateien vollständig.

Die vollständige docker-compose.yml

Das ist die offizielle Compose-Datei des Projekts. Sie definiert genau einen Dienst, bindet die .env ein, veröffentlicht Port 1411 und mountet das Datenverzeichnis.

services:
  pocket-id:
    image: pocketid/pocket-id:v2
    restart: unless-stopped
    env_file: .env
    ports:
      - 1411:1411
    volumes:
      - "./data:/app/data"
    healthcheck:
      test: ["CMD", "/app/pocket-id", "healthcheck"]
      interval: 1m30s
      timeout: 5s
      retries: 2
      start_period: 10s

Wer statt Docker Hub die GitHub Container Registry nutzen will, ersetzt lediglich die Image-Zeile. Beide Images sind gleichwertig.

    image: ghcr.io/pocket-id/pocket-id:v2

Erläuterung der wichtigsten Einträge:

  • restart: unless-stopped startet den Container nach einem Neustart des Hosts automatisch wieder, solange er nicht ausdrücklich gestoppt wurde.
  • env_file: .env lädt alle Umgebungsvariablen aus der Datei .env im selben Verzeichnis. Die Datei ist damit die einzige Stelle, an der konfiguriert wird.
  • ports: - 1411:1411 veröffentlicht den Dienst auf allen Adressen des Hosts. Wie man das einschränkt, steht im Abschnitt zur Netzwerkfreigabe.
  • volumes: - "./data:/app/data" bindet das lokale Verzeichnis data in den Container ein. Dort liegen Datenbank und Uploads. Ohne dieses Mount wären alle Daten nach dem Entfernen des Containers verloren.
  • Der healthcheck ruft das mitgelieferte Kommando /app/pocket-id healthcheck auf. Docker markiert den Container erst dann als healthy, wenn dieser Aufruf erfolgreich ist.

Die .env-Datei und ihre Variablen

Die offizielle Beispieldatei enthält die folgenden Einträge. Der Schlüssel im Beispiel ist ein offensichtlicher Platzhalter und muss durch die Ausgabe von openssl rand -base64 32 ersetzt werden.

# Öffentlich erreichbare Adresse der Anwendung
APP_URL=https://your-pocket-id-domain.com

# Schlüssel zum Verschlüsseln gespeicherter Daten
# erzeugen mit: openssl rand -base64 32
ENCRYPTION_KEY=BITTE-HIER-EIGENEN-SCHLUESSEL-EINTRAGEN

# Vertrauenswürdige Reverse-Proxy-Adressen
TRUST_PROXY=false

# Optionaler MaxMind-Lizenzschlüssel für die Standortanzeige im Audit-Log
MAXMIND_LICENSE_KEY=

# Benutzer- und Gruppenkennung im Container
PUID=1000
PGID=1000

Alternativ zu ENCRYPTION_KEY kann ENCRYPTION_KEY_FILE gesetzt werden. Die Variable zeigt dann auf eine Datei, die den Schlüssel enthält. Das funktioniert auch mit Docker Secrets und ist laut Dokumentation die empfohlene Methode, weil der Schlüssel dann nicht im Klartext in der Umgebungskonfiguration steht.

# Variante mit separater Schlüsseldatei statt Klartext in der .env
# Schlüssel einmalig erzeugen und in eine Datei schreiben
openssl rand -base64 32 > /opt/pocket-id/secrets/encryption.key

# Datei nur für den eigenen Benutzer lesbar machen
chmod 600 /opt/pocket-id/secrets/encryption.key

Die folgende Tabelle fasst die für Administratoren wichtigsten dokumentierten Variablen zusammen.

VariableStandardBedeutung
APP_URLhttp://localhost:1411Öffentlich erreichbare Adresse der Anwendung. Muss exakt der Adresse entsprechen, unter der Nutzer die Oberfläche aufrufen.
ENCRYPTION_KEYleerSchlüssel zum Verschlüsseln gespeicherter Daten einschließlich der privaten Schlüssel. Zu erzeugen mit openssl rand -base64 32.
ENCRYPTION_KEY_FILEleerPfad zu einer Datei mit dem Schlüssel. Auch mit Docker Secrets nutzbar und laut Dokumentation die empfohlene Methode.
TRUST_PROXYfalseVertrauenswürdige Reverse-Proxy-Adressen oder CIDR-Bereiche. Die Werte true und false sind ebenfalls möglich.
PROXY_PROTOCOLleerAdressen, die PROXY-Protokoll-Header senden dürfen.
TRUSTED_PLATFORMleerHeader, über den die echte Client-IP ermittelt wird.
ALLOW_INSECURE_CALLBACK_URLStrueSollte aus Sicherheitsgründen auf false gesetzt werden, sofern kein Client eine HTTP-Callback-URL braucht. Callbacks auf Loopback-Adressen wie localhost bleiben ohnehin erlaubt.
MAXMIND_LICENSE_KEYleerLizenzschlüssel für die GeoLite2-Datenbank zur Standortanzeige im Audit-Log. Ohne Key werden IP-Standorte als unbekannt markiert, ein kostenloser Key ist erhältlich.
PUID1000Benutzerkennung im Container. Bestimmt zusammen mit PGID die Eigentümerschaft der gemounteten Dateien, ermittelbar mit dem Befehl id.
PGID1000Gruppenkennung im Container.
DB_CONNECTION_STRINGdata/pocket-id.dbVerbindung zur Datenbank. Standard ist SQLite im Datenverzeichnis.
FILE_BACKENDfilesystemAblageort für Dateien. Möglich sind filesystem, s3 und database.
UPLOAD_PATHdata/uploadsVerzeichnis für hochgeladene Dateien. Nur wirksam bei filesystem oder s3.
S3_BUCKET, S3_REGION, S3_ENDPOINT, S3_ACCESS_KEY_IDleerNur nötig, wenn FILE_BACKEND auf s3 steht.
VERSION_CHECK_DISABLEDfalseAuf true setzen für Betrieb ohne Internetzugang.
ANALYTICS_DISABLEDfalseAuf true setzen, wenn kein täglicher Heartbeat an den Analytics-Server gesendet werden soll.

Start und Erstkonfiguration über /setup

Ist die .env ausgefüllt, wird der Stack gestartet. Der erste Start lädt das Image und legt die Datenbank an.

# Stack im Hintergrund starten
docker compose up -d

# Status prüfen
docker compose ps

# Startprotokoll ansehen
docker compose logs -f pocket-id

Danach wird die Einrichtungsseite im Browser geöffnet. Der Pfad ist /setup unterhalb der Adresse, die in APP_URL steht. Dort wird das erste Administratorkonto angelegt und mit einem Passkey verknüpft.

# Adresse der Einrichtungsseite
# https://<deine-app-url>/setup
  • Der Aufruf von /setup ist nur so lange sinnvoll, wie noch kein Administratorkonto existiert. Die Seite ist der einzige Weg, das erste Konto anzulegen.
  • Für die Registrierung muss der Browser eine gültige HTTPS-Verbindung sehen, sonst bietet er die Passkey-Erstellung nicht an.
  • Der Passkey wird an das Gerät oder den Sicherheitsschlüssel gebunden. Ein zweiter Passkey auf einem anderen Gerät ist dringend zu empfehlen, damit der Zugang bei Geräteverlust nicht verloren geht.
  • Erst danach werden im Administrationsbereich die OIDC-Clients angelegt, also die Anwendungen, die Pocket ID zur Anmeldung nutzen sollen.

Funktions- und Healthcheck im Praxistest

Die folgenden Prüfungen wurden am 12. September 2026 auf dem beschriebenen Ubuntu-Testsystem tatsächlich ausgeführt. Gestartet wurde ein Stack nach der offiziellen Compose-Vorlage mit dem Image ghcr.io/pocket-id/pocket-id:v2, mit APP_URL=http://localhost:1411, einem per openssl rand -base64 32 erzeugten ENCRYPTION_KEY sowie ANALYTICS_DISABLED=true und VERSION_CHECK_DISABLED=true.

  • Der Container erreichte den Status Up (healthy). Der in der Compose-Datei definierte Healthcheck hat also gegriffen.
  • Das Port-Mapping 0.0.0.0:1411->1411/tcp war aktiv.
  • Der Healthcheck-Befehl wurde zusätzlich manuell im Container ausgeführt und endete mit Rückgabewert 0.
  • Der Pfad /healthz antwortete mit Status 204, die Startseite / mit Status 200 und die Einrichtungsseite /setup mit Status 200.

Die dafür verwendeten Befehle lassen sich eins zu eins nachvollziehen.

# Containerstatus und Port-Mapping anzeigen
docker compose ps

# Healthcheck-Kommando manuell im Container ausführen
docker compose exec -T pocket-id /app/pocket-id healthcheck

# Rückgabewert des letzten Befehls prüfen, 0 bedeutet erfolgreich
echo $?

# HTTP-Status der wichtigsten Pfade prüfen
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:1411/healthz
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:1411/
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:1411/setup

Nicht selbst geprüft wurden das Anlegen des Administratorkontos über /setup mit einem echten Passkey, die Registrierung eines OIDC-Clients, die Anmeldung an einem angebundenen Dienst, der Betrieb hinter einem Reverse Proxy mit echtem TLS-Zertifikat, die S3-Dateiablage, die MaxMind-Anbindung, die Wiederherstellung aus einem Backup sowie ein Update von einer älteren Version. Diese Schritte stammen ausschließlich aus der offiziellen Dokumentation.

Persistente Daten und Dateirechte

Im gemounteten Datenverzeichnis ./data entstanden nach dem Start die SQLite-Datenbank pocket-id.db samt den Begleitdateien pocket-id.db-shm und pocket-id.db-wal sowie ein Unterverzeichnis uploads. Das wurde im Test so beobachtet und bestätigt, dass SQLite im WAL-Modus läuft.

# Inhalt des Datenverzeichnisses anzeigen
ls -la ./data

# Eigentümer und Gruppe der Dateien prüfen
stat -c "%U %G %n" ./data/*

Die Variablen PUID und PGID bestimmen, unter welcher Kennung der Prozess im Container läuft und wem die erzeugten Dateien gehören. Stimmen die Werte nicht mit dem Konto auf dem Host überein, gehört das Datenverzeichnis anschließend einer fremden Kennung. Backups und manuelle Eingriffe scheitern dann an fehlenden Rechten.

# Eigentümer des Datenverzeichnisses auf das eigene Konto setzen
# UID und GID vorher mit id -u und id -g ermitteln
sudo chown -R 1000:1000 ./data

Sichere Netzwerkfreigabe und Reverse Proxy mit TLS

Die Vorlage veröffentlicht Port 1411 auf allen Adressen des Hosts. Sobald ein Reverse Proxy auf derselben Maschine läuft, sollte die Veröffentlichung auf die Loopback-Adresse begrenzt werden. Der Dienst ist dann nur noch über den Proxy erreichbar.

    ports:
      - "127.0.0.1:1411:1411"

Wichtig ist in beiden Proxy-Varianten: APP_URL muss auf die öffentliche HTTPS-Adresse gesetzt werden, nicht auf localhost. Und TRUST_PROXY muss so gesetzt sein, dass Pocket ID dem vorgelagerten Proxy vertraut, sonst wird im Audit-Log die Adresse des Proxys statt der echten Client-IP protokolliert.

# Anpassungen in der .env für den Betrieb hinter einem Reverse Proxy
APP_URL=https://id.example.com

# Adresse oder CIDR-Bereich des Reverse Proxy eintragen
TRUST_PROXY=127.0.0.1

Caddy holt und erneuert das Zertifikat selbstständig. Die Konfiguration bleibt entsprechend kurz.

# /etc/caddy/Caddyfile
id.example.com {
    reverse_proxy 127.0.0.1:1411
}

Bei NGINX wird das Zertifikat separat verwaltet, etwa per Certbot. Die Weiterleitung der Original-Header ist hier Pflicht, damit Pocket ID Protokoll, Hostnamen und Client-Adresse korrekt erkennt.

# /etc/nginx/sites-available/pocket-id.conf
server {
    listen 443 ssl;
    http2 on;
    server_name id.example.com;

    ssl_certificate     /etc/letsencrypt/live/id.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/id.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:1411;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name id.example.com;
    return 301 https://$host$request_uri;
}

Der Betrieb hinter einem Reverse Proxy mit echtem TLS-Zertifikat wurde im Rahmen dieser Anleitung nicht selbst getestet. Die Konfigurationsbeispiele folgen der offiziellen Empfehlung, HTTPS über einen Proxy bereitzustellen.

Backup und Wiederherstellung

Das Backup besteht aus drei Bestandteilen. Fehlt einer davon, ist die Sicherung im Ernstfall wertlos.

  • Die SQLite-Datenbank im Datenverzeichnis. Weil sie im WAL-Modus läuft, gehören pocket-id.db, pocket-id.db-shm und pocket-id.db-wal zusammen. Wer nur die Hauptdatei kopiert, riskiert einen inkonsistenten Stand.
  • Das Unterverzeichnis uploads mit den abgelegten Dateien.
  • Der ENCRYPTION_KEY beziehungsweise die Datei hinter ENCRYPTION_KEY_FILE. Ohne diesen Schlüssel lässt sich der verschlüsselte Inhalt der Datenbank nicht mehr nutzen. Der Schlüssel gehört deshalb getrennt vom Datenbackup an einen sicheren Ort, etwa in einen Passwortmanager oder ein Tresorsystem.

Der sauberste Weg ist, den Container vor dem Kopieren zu stoppen. Dann sind Datenbank und WAL-Datei garantiert konsistent.

# Dienst stoppen, damit die Datenbank konsistent ist
docker compose stop pocket-id

# gesamtes Datenverzeichnis sichern
tar czf pocket-id-backup-$(date +%F).tar.gz ./data

# Dienst wieder starten
docker compose start pocket-id

Für die Wiederherstellung wird der Dienst gestoppt, das Datenverzeichnis ersetzt und die .env mit dem passenden Schlüssel wiederhergestellt. Erst danach darf der Container wieder starten.

# Dienst stoppen
docker compose down

# altes Datenverzeichnis beiseite legen statt löschen
mv ./data ./data.alt

# Sicherung zurückspielen
tar xzf pocket-id-backup-2026-09-12.tar.gz

# Eigentümer wieder korrekt setzen
sudo chown -R 1000:1000 ./data

# Dienst starten und Status prüfen
docker compose up -d
docker compose ps

Die Wiederherstellung aus einem Backup wurde nicht selbst getestet. Der Ablauf folgt dem üblichen Vorgehen für containerisierte Dienste mit SQLite-Datenbank und dem im Test beobachteten Dateibestand.

Updates und die Grenzen eines Rollbacks

Das Image-Tag v2 zieht Minor-Updates innerhalb der Hauptversion 2 automatisch nach, sobald das Image neu geladen wird. Ein Update besteht deshalb aus zwei Befehlen.

# neues Image laden
docker compose pull

# Container mit dem neuen Image neu erstellen
docker compose up -d

# Status und Protokoll prüfen
docker compose ps
docker compose logs --tail 50 pocket-id
  • Vor jedem Update ein Backup nach dem vorherigen Abschnitt anlegen. Das ist keine Formalie: Datenbank-Migrationen sind in der Regel nicht rueckwaertskompatibel.
  • Ein Rollback auf ein älteres Image funktioniert deshalb nur zuverlässig zusammen mit dem zugehörigen Datenbankstand aus dem Backup. Nur das Image zurückzusetzen genügt nicht, sobald eine Migration gelaufen ist.
  • Wer Updates kontrolliert einspielen will, setzt statt v2 ein festes Versions-Tag in der Compose-Datei und hebt es bewusst an.
  • Alte Images lassen sich später mit docker image prune aufräumen. Vor einem geplanten Rollback sollte das Vorgängerimage aber noch vorhanden sein.
  • Ein Update von einer älteren Version wurde im Rahmen dieser Anleitung nicht selbst getestet.

Typische Fehler, Diagnose und Lösung

Die folgenden Fehlerbilder treten in der Praxis am häufigsten auf.

  • Die Passkey-Registrierung wird gar nicht angeboten oder bricht ab. Ursache ist fast immer ein fehlender sicherer Kontext. Der Dienst wird über HTTP oder über eine reine IP-Adresse aufgerufen. Lösung: HTTPS über einen Reverse Proxy oder einen vorgelagerten Dienst bereitstellen. Zum reinen Funktionstest ist nur http://localhost:1411 zulässig, weil localhost als sicherer Kontext gilt.
  • Anmeldung schlägt fehl oder die Weiterleitung landet auf der falschen Adresse. Ursache ist meist eine APP_URL, die nicht exakt der tatsächlich aufgerufenen Adresse entspricht. Schon ein abweichendes Protokoll oder ein zusätzlicher Port reicht. Lösung: APP_URL in der .env korrigieren und den Container neu starten.
  • Der Container startet nicht und meldet Schreibfehler im Datenverzeichnis. Ursache sind falsche Rechte, weil PUID und PGID nicht zum Eigentümer von ./data passen. Lösung: Kennungen mit id -u und id -g ermitteln, in der .env setzen und den Eigentümer des Verzeichnisses per chown angleichen.
  • Im Audit-Log steht überall dieselbe IP-Adresse. Das ist die Adresse des Reverse Proxy. Ursache ist ein nicht gesetztes TRUST_PROXY. Lösung: Adresse oder CIDR-Bereich des Proxy eintragen und sicherstellen, dass der Proxy die Header X-Real-IP und X-Forwarded-For weiterreicht.
  • Der Dienst startet, aber gespeicherte Daten sind nach einem Umzug unbrauchbar. Ursache ist ein fehlender oder geänderter ENCRYPTION_KEY. Der Schlüssel gehört zwingend zum Datenbestand. Lösung: den ursprünglichen Schlüssel wiederherstellen. Ein neuer Schlüssel stellt die alten Daten nicht wieder her.
  • Der Versuch, die Version über das Binary abzufragen, schlägt fehl. Im Test endete der Aufruf mit der Meldung unknown flag: --version. Das Binary kennt keinen solchen Schalter. Die Versionsprüfung läuft deshalb über das Image-Tag beziehungsweise über die Weboberfläche, nicht über ein CLI-Argument.

Für die Diagnose sind vor allem Protokoll und Healthcheck hilfreich.

# vollständiges Protokoll des Dienstes ansehen
docker compose logs pocket-id

# nur die letzten Zeilen, fortlaufend
docker compose logs --tail 100 -f pocket-id

# geladene Umgebungsvariablen im Container prüfen
docker compose exec -T pocket-id env

# verwendetes Image-Tag anzeigen
docker compose images

Saubere Deinstallation

Beim Entfernen ist Vorsicht geboten, weil zwei der üblichen Befehle Daten unwiderruflich löschen.

# Container stoppen und entfernen, Daten im Verzeichnis ./data bleiben erhalten
docker compose down

Wer zusätzlich Volumes entfernt, verliert alle darin gespeicherten Daten. Dasselbe gilt für das Löschen des Datenverzeichnisses. Beide Schritte sind nicht rückgängig zu machen, wenn kein Backup vorliegt.

# ACHTUNG: Dieser Befehl entfernt zusätzlich alle Volumes des Stacks.
# Alle darin gespeicherten Daten sind danach verloren.
docker compose down -v

# ACHTUNG: Dieser Befehl löscht Datenbank und Uploads unwiderruflich.
# Vorher ein Backup anlegen, falls die Daten noch gebraucht werden.
rm -rf ./data

# Image entfernen, falls es nicht mehr gebraucht wird
docker image rm ghcr.io/pocket-id/pocket-id:v2
  • Vor jedem Löschvorgang prüfen, ob ein aktuelles Backup samt ENCRYPTION_KEY vorliegt.
  • Angebundene Anwendungen vorher auf einen anderen Anmeldeweg umstellen, sonst sperrt man sich aus den Diensten aus, die Pocket ID als einzigen Identity-Provider nutzen.
  • Den Eintrag im Reverse Proxy entfernen und das zugehörige Zertifikat aufräumen.

Einordnung für Selfhoster und kleine Unternehmen

Pocket ID löst eine klar umrissene Aufgabe: zentrale Anmeldung per Passkey für eine Handvoll eigener Dienste, mit minimalem Betriebsaufwand. Der Start per Docker Compose dauert wenige Minuten, der laufende Betrieb beschränkt sich auf Image-Updates und Backups.

Die Entscheidung gegen Pocket ID fällt in der Regel aus einem von zwei Gründen: Entweder werden Protokolle oder Anmeldewege gebraucht, die das Projekt bewusst nicht anbietet, oder die Passkey-Pflicht passt nicht zur Gerätesituation im Betrieb. In beiden Fällen sind Keycloak oder Authentik die richtige Wahl, mit entsprechend höherem Aufwand. Wer dagegen ohnehin auf Passkeys umstellt, bekommt mit Pocket ID einen sehr aufgeräumten Einstieg in Single Sign-on.

Passende Anleitungen auf S-EDV

Quellen

Pocket IDDocker ComposePasskeyOIDCSingle Sign-onWebAuthnSelfhosting