Runbook: añadir PocketID OIDC a un servicio nuevo¶
Estado al 2026-04-29: Vaultwarden, Karakeep, Paperless, Audiobookshelf, Immich, integrados con PocketID (nota: Jellyseerr va por CF Access edge, no OIDC nativo). Patrón verificado, gotchas conocidas documentadas abajo.
Cuándo usar OIDC nativo vs CF Access¶
| Servicio tiene OIDC nativo | Mobile/desktop apps lo consumen | → |
|---|---|---|
| Sí (audiobookshelf, immich, paperless, etc.) | Sí | OIDC nativo (no CF Access — rompería las apps) |
| No | Sólo web admin (dockge, dozzle, etc.) | CF Access + PocketID (ver ../security/cloudflare-access-pocketid.md) |
| Sí | Sólo web | Tu elección — OIDC nativo es mejor (1 menos punto de fallo) |
Patrón general¶
- Crear OIDC client en PocketID (vía UI o DB script)
- Configurar la app (env vars o admin UI)
- Verificar email_verified=1 del user (auto-trigger lo hace)
- Probar login
1. Crear OIDC client¶
Vía UI (1 servicio)¶
https://pocketid.monxas.casa/settings/admin/oidc-clients → New:
- Name: <service>
- Callback URLs: depende del servicio (ver tabla abajo)
- Public: OFF
- PKCE: ON
- Require re-auth: OFF
Tras crear, copia Client ID + Client Secret.
Vía script (en batch)¶
~/stacks/scripts/create-pocketid-clients.py (en VM 208) — define clients en lista,
genera bcrypt secrets, INSERT directo. Output con plaintext para copiar
a .env de cada app.
2. Callback URLs por servicio (verificadas)¶
| Servicio | Callback URL | Mobile callback (si aplica) |
|---|---|---|
| Vaultwarden | https://<host>/identity/connect/oidc-signin |
— |
| Karakeep | https://<host>/api/auth/callback/custom |
— |
| Audiobookshelf | https://<host>/auth/openid/callback |
audiobookshelf://oauth |
| Immich | https://<host>/auth/login |
app.immich:///oauth-callback |
| Paperless-ngx | https://<host>/accounts/oidc/<provider_id>/login/callback/ |
— |
| Jellyseerr | https://<host>/api/v1/auth/oidc-callback |
— |
| Grafana | https://<host>/login/generic_oauth |
— |
| Stirling-PDF | https://<host>/login/oauth2/code/<provider> |
— |
3. Config por tipo de app¶
Tipo A — env vars en compose¶
Vaultwarden (ojo: requiere fork timshel/oidcwarden)¶
image: timshel/oidcwarden:latest # mainline NO incluye SSO
environment:
- SSO_ENABLED=true
- SSO_ONLY=false
- SSO_AUTHORITY=https://pocketid.monxas.casa
- SSO_CLIENT_ID=${VW_OIDC_ID}
- SSO_CLIENT_SECRET=${VW_OIDC_SECRET}
- SSO_PKCE=true
- SSO_SCOPES=openid profile email
- SSO_FRONTEND=override # importante para que el botón aparezca
- SSO_CALLBACK_PATH=/identity/connect/oidc-signin
Karakeep¶
environment:
- NEXTAUTH_URL=https://<host> # debe ser el público, NO LAN
- OAUTH_WELLKNOWN_URL=https://pocketid.monxas.casa/.well-known/openid-configuration
- OAUTH_CLIENT_ID=${KK_OIDC_ID}
- OAUTH_CLIENT_SECRET=${KK_OIDC_SECRET}
- OAUTH_PROVIDER_NAME=PocketID
- OAUTH_SCOPE=openid profile email
- OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING=true
Paperless-ngx (ojo: requiere PAPERLESS_APPS extra)¶
environment:
- PAPERLESS_URL=https://<host>
- PAPERLESS_APPS=allauth.socialaccount.providers.openid_connect # CRÍTICO
- PAPERLESS_SOCIALACCOUNT_PROVIDERS={"openid_connect":{"APPS":[{"provider_id":"pocketid","name":"PocketID","client_id":"${PAP_OIDC_ID}","secret":"${PAP_OIDC_SECRET}","settings":{"server_url":"https://pocketid.monxas.casa/.well-known/openid-configuration"}}],"OAUTH_PKCE_ENABLED":true}}
- PAPERLESS_SOCIAL_AUTO_SIGNUP=True
- PAPERLESS_ACCOUNT_DEFAULT_HTTP_PROTOCOL=https
Tipo B — admin UI¶
Audiobookshelf (Settings → Auth → OpenID Connect)¶
- Issuer URL:
https://pocketid.monxas.casa - Authorization URL:
https://pocketid.monxas.casa/authorize - Token URL:
https://pocketid.monxas.casa/api/oidc/token - Userinfo URL:
https://pocketid.monxas.casa/api/oidc/userinfo - JWKS URL:
https://pocketid.monxas.casa/.well-known/jwks.json - Logout URL:
https://pocketid.monxas.casa/api/oidc/end-session - Match by:
email - Auto-register: ✅
- Subfolder for Redirect URLs: VACIO (si no, mete
/audiobookshelfen la callback)
Immich (Administration → Authentication → OAuth)¶
- Issuer URL:
https://pocketid.monxas.casa/.well-known/openid-configuration - Scope:
openid email profile - Signing alg:
RS256 - Storage label claim:
preferred_username - Auto register: ✅
Jellyseerr (Settings → Users → OIDC Login)¶
- OIDC Domain:
pocketid.monxas.casa(sin https) - Allow new users: ✅
- Email match required: ✅
4. PocketID gotchas (todas con triggers automáticos)¶
is_group_restricted=1 por defecto¶
Cualquier client recién creado vía UI sale restricted y bloquea a todos
con "You're not allowed to access this service". Triggers activo:
CREATE TRIGGER auto_unrestrict_clients AFTER INSERT ON oidc_clients
BEGIN UPDATE oidc_clients SET is_group_restricted=0 WHERE id=NEW.id; END;
email_verified=0 por defecto¶
Sin verify, apps que requieren email verificado (ABS, Paperless, Immich)
fallan con "User not found and email is not verified" o similar.
Trigger activo:
CREATE TRIGGER auto_verify_email AFTER INSERT ON users
BEGIN UPDATE users SET email_verified=1 WHERE id=NEW.id; END;
Sólo bcrypt para crear clients vía DB¶
Si insertas un client a mano, el secret debe ir hasheado con bcrypt cost
10. Script ~/stacks/scripts/create-pocketid-clients.py (en media-208) lo hace.
5. Smoke test post-config¶
# Para cada hostname con OIDC:
curl -sk https://<host>/<oidc-login-url> -L -o /dev/null -w "%{http_code} -> %{url_effective}\n"
# Debe redirigir a https://pocketid.monxas.casa/authorize?client_id=...
O directamente: ir a la app en navegador, ver botón "Login with PocketID", click → debe redirigir a PocketID, hacer passkey, volver autenticado.
6. Limpieza¶
Si necesitas borrar un OIDC client:
ssh media-208 'sqlite3 /home/monxas/stacks/pocket-id/data/pocket-id.db "DELETE FROM oidc_clients WHERE name=\"<name>\""'
Si una app deja de necesitar OIDC: quitar env vars (Tipo A) o desactivar en la UI de admin (Tipo B), recrear container.
7. Reference¶
- Doc OIDC + CF Access:
../security/cloudflare-access-pocketid.md - Endpoints PocketID:
https://pocketid.monxas.casa/.well-known/openid-configuration - PocketID admin DB:
/home/monxas/stacks/pocket-id/data/pocket-id.db