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

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

Pocket ID ist ein quelloffener OIDC-Provider mit Anmeldung ausschließlich per Passkey. Die Anleitung zeigt Installation per Docker Compose, wichtige Umgebungsvariablen, die HTTPS-Pflicht wegen WebAuthn, Reverse Proxy mit Caddy oder NGINX sowie Backup und Updates.

Geprüft am 22.10.2026 · für Pocket ID 2.19.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

Smartphone auf heller Steinplatte mit leuchtendem Fingerabdrucksymbol, daneben ein zugeklappter Laptop und Pflanzen

Pocket ID ist ein schlanker, quelloffener OIDC-Provider (OpenID Connect), bei dem sich Benutzer ausschließlich per Passkey anmelden. Er eignet sich für Single Sign-on über eigene Dienste, wenn Keycloak oder Authentik zu aufwendig sind. Diese Anleitung zeigt Installation von Pocket ID 2.19 per Docker Compose, HTTPS über einen Reverse Proxy, Backup und Updates.

Was Pocket ID leistet und wo die Grenzen liegen

Pocket ID übernimmt die Anmeldung für Anwendungen, die OIDC unterstützen, und gibt ihnen nach erfolgreicher Authentifizierung ein Token mit Identitätsdaten zurück. Es gibt genau einen Anmeldeweg: den Passkey nach dem WebAuthn-Standard, ohne Passwörter und ohne Magic Links als Hauptweg.

  • Kein LDAP-Ersatz: Pocket ID ersetzt keinen Verzeichnisdienst für Dateifreigaben oder Domänenanmeldungen.
  • Kein vollständiger Identity-Provider: SAML, Self-Service-Portal, komplexe Authentifizierungsflüsse und Policy-Engine bieten Keycloak und Authentik.
  • Ungeeignet, wenn ein zweiter Anmeldeweg ohne Passkey Pflicht ist, etwa für Notfallzugriffe von fremden Geräten.
  • Standarddatenbank ist SQLite: ausreichend für kleine bis mittlere Installationen, kein Cluster mit mehreren aktiven Instanzen.

Pocket ID im Vergleich zu Keycloak und Authentik

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

Voraussetzungen und Ressourcenbedarf

  • Linux-Host (x86_64 oder ARM64) mit Docker Engine und Compose-Plugin; 1 CPU-Kern, 512 MB freier RAM und 1 GB Speicher genügen.
  • Benutzerkonto mit Docker-Rechten (Gruppe docker oder sudo).
  • Freier TCP-Port 1411 auf 127.0.0.1.
  • Domain mit gültigem TLS-Zertifikat über einen Reverse Proxy oder vorgelagerten Dienst.
  • Endgerät mit Passkey-Unterstützung: aktueller Browser mit Plattform-Authenticator oder Hardware-Sicherheitsschlüssel.

HTTPS-Pflicht wegen WebAuthn

Die WebAuthn-API des Browsers steht nur in einem sicheren Kontext zur Verfügung, also über HTTPS. Ohne HTTPS bietet der Browser die Passkey-Registrierung nicht an oder bricht sie ab. Die offizielle Dokumentation nennt zwei Wege: einen Reverse Proxy wie Caddy oder NGINX, der das Zertifikat terminiert, oder einen vorgelagerten Dienst wie Cloudflare.

Einzige Ausnahme ist localhost: Ein Funktionstest direkt auf dem Server unter http://localhost:1411 funktioniert ohne TLS. Über IP-Adresse oder Hostnamen im Netz gilt die HTTPS-Pflicht.

Plattformen, Architekturen und geprüfter Versionsstand

  • Container-Image bei Docker Hub: pocketid/pocket-id, gleichwertig bei GitHub Container Registry: ghcr.io/pocket-id/pocket-id, jeweils für amd64 und arm64.
  • Standalone-Binary von der Releases-Seite, zum Beispiel pocket-id-linux-amd64.

Aktuelles Release ist v2.19.1 vom 22. Oktober 2026 (Lizenz BSD-2-Clause). Die offizielle Vorlage nutzt das gleitende Tag v2, das bei jedem docker compose pull neue Versionen der Hauptversion 2 nachzieht. Diese Anleitung legt die Version mit v2.19.1 fest, damit Updates kontrolliert erfolgen.

Installation Schritt für Schritt

Legen Sie ein Arbeitsverzeichnis an:

mkdir -p /opt/pocket-id
cd /opt/pocket-id

Laden Sie die offizielle Beispielkonfiguration als .env:

curl -o .env https://raw.githubusercontent.com/pocket-id/pocket-id/main/.env.example
chmod 600 .env

Erzeugen Sie den Verschlüsselungsschlüssel für die .env:

openssl rand -base64 32

Ermitteln Sie Ihre Benutzer- und Gruppenkennung, damit die Dateien in ./data Ihrem Konto gehören:

id -u
id -g

Starten Sie den Container erst, wenn .env vollständig ausgefüllt ist.

Die vollständige docker-compose.yml

Legen Sie docker-compose.yml mit folgendem Inhalt an. Sie entspricht der offiziellen Vorlage, mit festem Image-Tag und Port-Bindung an 127.0.0.1: Der Dienst ist dann nur über den Reverse Proxy erreichbar, und niemand im Netz kann vor Ihnen /setup aufrufen.

services:
  pocket-id:
    image: pocketid/pocket-id:v2.19.1   # alternativ ghcr.io/pocket-id/pocket-id:v2.19.1
    restart: unless-stopped
    env_file: .env
    ports:
      - "127.0.0.1:1411:1411"
    volumes:
      - "./data:/app/data"
    healthcheck:
      test: ["CMD", "/app/pocket-id", "healthcheck"]
      interval: 1m30s
      timeout: 5s
      retries: 2
      start_period: 10s
  • env_file: .env lädt alle Variablen aus .env; nur dort wird konfiguriert.
  • ./data:/app/data enthält Datenbank und Uploads. Ohne dieses Mount gehen die Daten beim Entfernen des Containers verloren.
  • Der healthcheck nutzt das mitgelieferte Kommando /app/pocket-id healthcheck; erst danach meldet Docker den Container als healthy.

Die .env-Datei und ihre Variablen

Die Vorlage enthält diese Einträge. Ersetzen Sie IHR_SCHLUESSEL durch die Ausgabe von openssl rand -base64 32 und APP_URL durch Ihre HTTPS-Adresse:

APP_URL=https://your-pocket-id-domain.com

# erzeugen mit: openssl rand -base64 32
ENCRYPTION_KEY=IHR_SCHLUESSEL
TRUST_PROXY=false
MAXMIND_LICENSE_KEY=
PUID=1000
PGID=1000

Statt ENCRYPTION_KEY können Sie ENCRYPTION_KEY_FILE setzen. Die Variable zeigt auf eine Datei mit dem Schlüssel. Die Dokumentation empfiehlt diesen Weg. Die Datei muss im Container erreichbar sein, zum Beispiel über ein zusätzliches Volume.

mkdir -p /opt/pocket-id/secrets
openssl rand -base64 32 > /opt/pocket-id/secrets/encryption.key
chmod 600 /opt/pocket-id/secrets/encryption.key

Die wichtigsten dokumentierten Variablen:

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 für gespeicherte Daten einschließlich privater Schlüssel.
ENCRYPTION_KEY_FILEleerPfad zu einer Datei mit dem Schlüssel. Auch mit Docker Secrets nutzbar; empfohlene Methode.
TRUST_PROXYfalseVertrauenswürdige Proxy-Adressen oder CIDR-Bereiche, alternativ true/false.
PROXY_PROTOCOLleerAdressen, die PROXY-Protokoll-Header senden dürfen.
TRUSTED_PLATFORMleerHeader, über den die echte Client-IP ermittelt wird.
ALLOW_INSECURE_CALLBACK_URLStrueAuf false setzen, sofern kein Client eine HTTP-Callback-URL braucht. Loopback-Adressen wie localhost bleiben erlaubt.
MAXMIND_LICENSE_KEYleerGeoLite2-Key für Standorte im Audit-Log. Ohne Key bleiben Standorte unbekannt.
PUID1000Benutzerkennung im Container. Bestimmt mit PGID den Eigentümer der Dateien in ./data.
PGID1000Gruppenkennung im Container.
DB_CONNECTION_STRINGdata/pocket-id.dbDatenbankverbindung, Standard SQLite.
FILE_BACKENDfilesystemfilesystem, s3 oder database.
UPLOAD_PATHdata/uploadsUpload-Verzeichnis (filesystem/s3).
S3_*leerNur bei FILE_BACKEND=s3.
VERSION_CHECK_DISABLEDfalsetrue für Betrieb ohne Internetzugang.
ANALYTICS_DISABLEDfalsetrue: kein täglicher Heartbeat an den Analytics-Server.

Start und Erstkonfiguration über /setup

Starten Sie den Container. Der erste Start lädt das Image und legt die Datenbank an:

docker compose up -d
docker compose ps
docker compose logs -f pocket-id

Öffnen Sie danach https://id.example.com/setup (Ihre APP_URL plus /setup). Dort legen Sie das erste Administratorkonto an und verknüpfen es mit einem Passkey.

  • /setup ist der einzige Weg zum ersten Konto und nur nutzbar, solange keines existiert.
  • Der Browser bietet die Passkey-Erstellung nur über HTTPS oder localhost an.
  • Registrieren Sie einen zweiten Passkey auf einem anderen Gerät, damit der Zugang bei Geräteverlust erhalten bleibt.
  • Erst danach legen Sie im Administrationsbereich die OIDC-Clients für Ihre Anwendungen an.

Funktions- und Healthcheck im Praxistest

Im Test am 12. September 2026 (Ubuntu, Docker 29.1.3, Compose 2.40.3) lief ein Container nach der offiziellen Vorlage mit APP_URL=http://localhost:1411, per openssl erzeugtem Schlüssel sowie ANALYTICS_DISABLED=true und VERSION_CHECK_DISABLED=true. Ergebnis: Status Up (healthy), Healthcheck-Kommando mit Rückgabewert 0, /healthz mit HTTP 204, / und /setup mit HTTP 200. Mit diesen Befehlen prüfen Sie Ihre Installation:

docker compose ps
docker compose exec -T pocket-id /app/pocket-id healthcheck
echo $?
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

Am 10. Oktober 2026 lief ein Update einer v2.17.0-Instanz mit angelegtem Administratorkonto auf v2.18.0 per docker compose pull und docker compose up -d. Pocket ID spielte die SQLite-Migrationen beim Start automatisch ein, der Container war danach wieder Up (healthy), /healthz antwortete mit HTTP 204, /login mit HTTP 200, und das Log meldete version=2.18.0. Neu in 2.18 sind eine Seite zur Passkey-Einrichtung für Benutzer, die über die Anmeldeseite kommen, und die Suche nach Icons aus der selfh.st-Sammlung für OIDC-Clients.

Am 22. Oktober 2026 lief das Update einer v2.18.0-Instanz mit Administratorkonto und einem weiteren Benutzer auf v2.19.1 ebenso durch: Container Up (healthy), Log mit version=2.19.1, /healthz mit HTTP 204, /login mit HTTP 200, beide Benutzer und die bestehende Sitzung blieben erhalten, /api/signup/setup antwortete nach abgeschlossener Ersteinrichtung mit 404. Version 2.19.0 lehnt schreibende Browser-Anfragen von fremden Ursprüngen ab: Im Test ergab ein POST mit fremdem Origin-Header HTTP 403 mit Cross-origin requests are not allowed, mit passendem Origin oder ohne Origin-Header (etwa per curl) HTTP 201. APP_URL gilt dabei als vertrauenswürdiger Ursprung, deshalb muss sie exakt der Adresse im Browser entsprechen. Neu sind außerdem Benachrichtigungsmodi für Anmeldungen, eine erzwingbare E-Mail-Bestätigung und Variablen OUTBOUND_ALLOWED_HOSTS_*, mit denen Sie den SSRF-Schutz für bestimmte Ziele lockern. 2.19.1 aktualisiert nur Go, Alpine und das Distroless-Basisimage auf Debian 13.

Persistente Daten und Dateirechte

In ./data liegen nach dem Start die SQLite-Datenbank pocket-id.db mit pocket-id.db-shm und pocket-id.db-wal (WAL-Modus) sowie das Verzeichnis uploads.

ls -la ./data
stat -c "%U %G %n" ./data/*

PUID und PGID bestimmen, unter welcher Kennung der Prozess läuft und wem die Dateien gehören. Passen sie nicht zu Ihrem Konto, scheitern Backups und manuelle Eingriffe an fehlenden Rechten. Korrigieren Sie den Eigentümer dann so:

sudo chown -R 1000:1000 ./data

Sichere Netzwerkfreigabe und Reverse Proxy mit TLS

Der Port ist in docker-compose.yml bereits an 127.0.0.1 gebunden. Setzen Sie für den Betrieb hinter dem Proxy APP_URL auf die öffentliche HTTPS-Adresse und TRUST_PROXY auf die Adresse des Proxys; sonst protokolliert das Audit-Log die Adresse des Proxys statt der Client-IP. Starten Sie danach mit docker compose up -d neu.

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

TRUST_PROXY=127.0.0.1

Caddy holt und erneuert das Zertifikat selbst:

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

Bei NGINX verwalten Sie das Zertifikat separat, etwa per Certbot. Die Weitergabe der Original-Header ist Pflicht, damit Pocket ID Protokoll, Hostnamen und Client-Adresse 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;
}

Backup und Wiederherstellung

Eine vollständige Sicherung besteht aus drei Teilen:

  • SQLite-Datenbank: pocket-id.db, pocket-id.db-shm und pocket-id.db-wal gehören zusammen. Nur die Hauptdatei zu kopieren kann einen inkonsistenten Stand ergeben.
  • Verzeichnis uploads.
  • ENCRYPTION_KEY bzw. die Datei hinter ENCRYPTION_KEY_FILE. Ohne ihn ist der verschlüsselte Datenbankinhalt unbrauchbar. Bewahren Sie ihn getrennt vom Datenbackup auf, etwa in einem Passwortmanager.

Stoppen Sie den Container vor dem Kopieren, dann sind Datenbank und WAL-Datei konsistent:

docker compose stop pocket-id
tar czf pocket-id-backup-$(date +%F).tar.gz ./data
docker compose start pocket-id

Wiederherstellung (die .env mit passendem Schlüssel muss vorhanden sein):

docker compose down
mv ./data ./data.alt
tar xzf pocket-id-backup-2026-09-12.tar.gz
sudo chown -R 1000:1000 ./data
docker compose up -d
docker compose ps

Updates und die Grenzen eines Rollbacks

Tragen Sie für ein Update die neue Version im Image-Tag ein (Releases auf GitHub) und erstellen Sie den Container neu:

docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail 50 pocket-id
  • Legen Sie vorher ein Backup an: Datenbankmigrationen sind in der Regel nicht rückwärtskompatibel.
  • Ein Rollback funktioniert deshalb nur zusammen mit dem Datenbankstand aus dem Backup; das Image allein zurückzusetzen genügt nach einer Migration nicht.
  • Entfernen Sie das Vorgängerimage erst, wenn die neue Version sicher läuft.

Typische Fehler, Diagnose und Lösung

  • Passkey-Registrierung fehlt oder bricht ab: Kein sicherer Kontext, Aufruf über HTTP oder IP-Adresse. HTTPS über Reverse Proxy bereitstellen; ohne TLS funktioniert nur http://localhost:1411.
  • Anmeldung scheitert oder Weiterleitung auf falsche Adresse: APP_URL weicht von der aufgerufenen Adresse ab, schon ein anderes Protokoll oder ein zusätzlicher Port genügt. APP_URL korrigieren, Container neu starten.
  • HTTP 403 Cross-origin requests are not allowed beim Speichern: Ab 2.19.0 weist Pocket ID schreibende Anfragen ab, deren Ursprung weder zur aufgerufenen Adresse noch zu APP_URL passt, etwa wenn der Proxy den Host-Header umschreibt und APP_URL eine andere Adresse nennt. APP_URL auf die öffentliche HTTPS-Adresse setzen und den Host-Header im Proxy weitergeben.
  • Schreibfehler im Datenverzeichnis: PUID/PGID passen nicht zum Eigentümer von ./data. Werte mit id -u und id -g setzen, Eigentümer per chown angleichen.
  • Audit-Log zeigt überall dieselbe IP: Das ist der Proxy. TRUST_PROXY setzen und prüfen, dass der Proxy X-Real-IP und X-Forwarded-For weitergibt.
  • Daten nach Umzug unbrauchbar: ENCRYPTION_KEY fehlt oder wurde geändert. Den ursprünglichen Schlüssel wiederherstellen; ein neuer stellt die Daten nicht wieder her.
  • unknown flag: --version: Die Version zeigen Image-Tag und Weboberfläche.

Für die Diagnose:

docker compose logs pocket-id
docker compose logs --tail 100 -f pocket-id
docker compose images

Saubere Deinstallation

Dieser Befehl entfernt nur den Container, ./data bleibt erhalten:

docker compose down

Die folgenden Befehle entfernen Volumes bzw. das Datenverzeichnis endgültig. Führen Sie sie nur mit aktuellem Backup samt Schlüssel aus:

# ACHTUNG: Dieser Befehl entfernt zusätzlich alle Volumes des Stacks.
docker compose down -v
# ACHTUNG: Dieser Befehl löscht Datenbank und Uploads unwiderruflich.
rm -rf ./data
docker image rm pocketid/pocket-id:v2.19.1
  • Stellen Sie angebundene Anwendungen vorher auf einen anderen Anmeldeweg um, sonst sperren Sie sich aus.

Einordnung für Selfhoster und kleine Unternehmen

Pocket ID bietet zentrale Anmeldung per Passkey für eine Handvoll eigener Dienste bei geringem Betriebsaufwand. Werden Protokolle wie SAML oder Anmeldewege ohne Passkey gebraucht, oder passt die Passkey-Pflicht nicht zu den Geräten im Betrieb, sind Keycloak oder Authentik die bessere Wahl, mit höherem Aufwand.

Passende Anleitungen auf S-EDV

Quellen

Pocket IDDocker ComposePasskeyOIDCSingle Sign-onWebAuthnSelfhosting