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

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
| Kriterium | Pocket ID | Keycloak | Authentik |
|---|---|---|---|
| Anmeldeverfahren | ausschließlich Passkey nach WebAuthn | Passwort, OTP, WebAuthn, Kerberos, externe Provider | Passwort, OTP, WebAuthn, konfigurierbare Flows |
| Protokolle | OIDC | OIDC, OAuth 2.0, SAML | OIDC, OAuth 2.0, SAML, LDAP-Ausgabe, Proxy-Auth |
| Standard-Datenbank | SQLite im Datenverzeichnis | externe Datenbank empfohlen | PostgreSQL plus Redis |
| Container im Minimalbetrieb | ein Container | ein Container plus Datenbank | mehrere Container |
| Einarbeitungsaufwand | gering | hoch | mittel bis hoch |
| Typischer Einsatz | Selfhosting, kleine Teams | Unternehmen mit vielen Anwendungen | Selfhosting bis Unternehmen mit Proxy-Auth-Bedarf |
| Verzeichnisdienst-Anbindung | nicht vorgesehen | LDAP und Active Directory | LDAP 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
dockerodersudo). - 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-idLaden Sie die offizielle Beispielkonfiguration als .env:
curl -o .env https://raw.githubusercontent.com/pocket-id/pocket-id/main/.env.example
chmod 600 .envErzeugen Sie den Verschlüsselungsschlüssel für die .env:
openssl rand -base64 32Ermitteln Sie Ihre Benutzer- und Gruppenkennung, damit die Dateien in ./data Ihrem Konto gehören:
id -u
id -gStarten 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: .envlädt alle Variablen aus.env; nur dort wird konfiguriert../data:/app/dataenthält Datenbank und Uploads. Ohne dieses Mount gehen die Daten beim Entfernen des Containers verloren.- Der
healthchecknutzt das mitgelieferte Kommando/app/pocket-id healthcheck; erst danach meldet Docker den Container alshealthy.
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.keyDie wichtigsten dokumentierten Variablen:
| Variable | Standard | Bedeutung |
|---|---|---|
| APP_URL | http://localhost:1411 | Öffentlich erreichbare Adresse der Anwendung. Muss exakt der Adresse entsprechen, unter der Nutzer die Oberfläche aufrufen. |
| ENCRYPTION_KEY | leer | Schlüssel für gespeicherte Daten einschließlich privater Schlüssel. |
| ENCRYPTION_KEY_FILE | leer | Pfad zu einer Datei mit dem Schlüssel. Auch mit Docker Secrets nutzbar; empfohlene Methode. |
| TRUST_PROXY | false | Vertrauenswürdige Proxy-Adressen oder CIDR-Bereiche, alternativ true/false. |
| PROXY_PROTOCOL | leer | Adressen, die PROXY-Protokoll-Header senden dürfen. |
| TRUSTED_PLATFORM | leer | Header, über den die echte Client-IP ermittelt wird. |
| ALLOW_INSECURE_CALLBACK_URLS | true | Auf false setzen, sofern kein Client eine HTTP-Callback-URL braucht. Loopback-Adressen wie localhost bleiben erlaubt. |
| MAXMIND_LICENSE_KEY | leer | GeoLite2-Key für Standorte im Audit-Log. Ohne Key bleiben Standorte unbekannt. |
| PUID | 1000 | Benutzerkennung im Container. Bestimmt mit PGID den Eigentümer der Dateien in ./data. |
| PGID | 1000 | Gruppenkennung im Container. |
| DB_CONNECTION_STRING | data/pocket-id.db | Datenbankverbindung, Standard SQLite. |
| FILE_BACKEND | filesystem | filesystem, s3 oder database. |
| UPLOAD_PATH | data/uploads | Upload-Verzeichnis (filesystem/s3). |
| S3_* | leer | Nur bei FILE_BACKEND=s3. |
| VERSION_CHECK_DISABLED | false | true für Betrieb ohne Internetzugang. |
| ANALYTICS_DISABLED | false | true: 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.
/setupist der einzige Weg zum ersten Konto und nur nutzbar, solange keines existiert.- Der Browser bietet die Passkey-Erstellung nur über HTTPS oder
localhostan. - 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/setupAm 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 ./dataSichere 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-shmundpocket-id.db-walgehören zusammen. Nur die Hauptdatei zu kopieren kann einen inkonsistenten Stand ergeben. - Verzeichnis
uploads. ENCRYPTION_KEYbzw. die Datei hinterENCRYPTION_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-idWiederherstellung (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 psUpdates 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_URLweicht von der aufgerufenen Adresse ab, schon ein anderes Protokoll oder ein zusätzlicher Port genügt.APP_URLkorrigieren, Container neu starten. - HTTP 403
Cross-origin requests are not allowedbeim Speichern: Ab 2.19.0 weist Pocket ID schreibende Anfragen ab, deren Ursprung weder zur aufgerufenen Adresse noch zuAPP_URLpasst, etwa wenn der Proxy den Host-Header umschreibt undAPP_URLeine andere Adresse nennt.APP_URLauf die öffentliche HTTPS-Adresse setzen und den Host-Header im Proxy weitergeben. - Schreibfehler im Datenverzeichnis:
PUID/PGIDpassen nicht zum Eigentümer von./data. Werte mitid -uundid -gsetzen, Eigentümer perchownangleichen. - Audit-Log zeigt überall dieselbe IP: Das ist der Proxy.
TRUST_PROXYsetzen und prüfen, dass der ProxyX-Real-IPundX-Forwarded-Forweitergibt. - Daten nach Umzug unbrauchbar:
ENCRYPTION_KEYfehlt 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 imagesSaubere Deinstallation
Dieser Befehl entfernt nur den Container, ./data bleibt erhalten:
docker compose downDie 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
- Sichere Passwörter und Passkeys im Unternehmen: Grundlagen zu Passkeys, bevor Sie eine Passkey-Pflicht wie bei Pocket ID einführen.
- NGINX als Reverse Proxy mit TLS einrichten: Die HTTPS-Vorschaltung, die Pocket ID für WebAuthn zwingend braucht.
- Single Sign-on mit Authentik, Authelia und Traefik Forward Auth: Der Vergleichsweg, wenn Pocket ID zu wenig Protokolle oder Anmeldewege bietet.
Quellen
- GitHub-Repository pocket-id/pocket-id: Quellcode, Lizenz BSD-2-Clause, Release-Stand, abgerufen am 2. Oktober 2026.
- Pocket ID: Installation: Offizielle Installationsanleitung mit Docker, Standalone-Binary und dem Hinweis auf den sicheren Kontext.
- Pocket ID: Environment Variables: Vollständige Referenz der Umgebungsvariablen und ihrer Standardwerte.


