Skip to main content

Pocket ID

A simple OIDC provider that authenticates users via passkeys.

Pocket ID is a lightweight, self-hosted OIDC identity provider that uses passkeys (WebAuthn) as the sole authentication method — no passwords. It provides OIDC/OAuth2 endpoints for applications to integrate SSO. Self-hosting means full control over your identity provider without paying for Auth0, Okta, or similar cloud services.

Alternatives considered

Cloud Hosted

ToolOpen SourceFree TierMonthly Cost
Auth0NoLimitedFrom $35/mo

Self Hosted

ToolOpen SourceFull FeaturesNotes
KeycloakYesYesFull IAM suite; much heavier
AuthentikYesYesModern IdP with more auth methods

Installation

Architecture

  • Deployment: Single pocketid deployment in the pocketid namespace
  • Image: ghcr.io/pocket-id/pocket-id:v2.5.0 (digest-pinned)
  • Database: CNPG PostgreSQL cluster with Longhorn-encrypted PVCs
  • Storage: Longhorn PVC (pocketid-data) for app files
  • Networking: ClusterIP service on port 80, HTTPRoute via public gateway

Security

  • Runs as runAsUser: 0, runAsNonRoot: false
  • Longhorn PVC and CNPG PVCs encrypted at rest via SOPS-managed keys

Updates

Managed by Renovate. Image is digest-pinned.

Data Management

  • Database: CNPG PostgreSQL cluster (Longhorn-encrypted PVCs)
  • PVC: pocketid-data (Longhorn-encrypted) for passkey registrations and app files
  • Backups: k8up Schedule backs up CNPG Longhorn PVCs to Hetzner S3. CNPG annotated with k8up.io/backupcommand: pg_dump.

User Management

Pocket ID is the OIDC provider for this cluster — it does not consume OIDC itself. Clients registered include DefectDojo, Gatus, RomM, and others. Users register passkeys via the web UI.

Configuration Management

  • SMTP credentials for email notifications from SOPS-encrypted secret (allinkl-smtp-credentials)
  • Database connection string injected from CNPG-generated secret
  • ANALYTICS_DISABLED and other app settings from env vars

Administration

Usage

Register passkeys via the web UI for passwordless authentication. Add OIDC clients for applications that need SSO. Users authenticate by scanning a QR code or using a device passkey. Email notifications for account events are sent via the configured SMTP server.

Cluster-specific deviations from the above live in the per-cluster README — see k8s/apps/talos/pocketid/README.md.

Cluster Deployment

Pocket ID — Talos cluster

Cluster-specific notes only. General product info, "why we use it", and alternatives live in docusaurus/docs/apps/pocketid.mdx.

Deviations from defaults

Defaults live in docusaurus/docs/apps/pocketid.mdx — document anything this cluster does differently here, with a one-line reason.

Kubernetes Metadata
  • Image: ghcr.io/pocket-id/pocket-id:v2.8.0@sha256:a073640418b2cfc8587c488a7270580b3ab95cae2c543f5d64bbbe1fd7ccbae8
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app: pocketid
name: pocketid
namespace: pocketid
spec:
replicas: 1
selector:
matchLabels:
app: pocketid
ingress: public
strategy:
rollingUpdate: null
type: Recreate
template:
metadata:
labels:
app: pocketid
ingress: public
spec:
containers:
- env:
- name: ANALYTICS_DISABLED
value: 'true'
- name: SMTP_TLS
value: starttls
- name: SMTP_HOST
valueFrom:
secretKeyRef:
key: host
name: allinkl-smtp-credentials
- name: SMTP_FROM
valueFrom:
secretKeyRef:
key: from
name: allinkl-smtp-credentials
- name: SMTP_PORT
valueFrom:
secretKeyRef:
key: port
name: allinkl-smtp-credentials
- name: SMTP_USER
valueFrom:
secretKeyRef:
key: username
name: allinkl-smtp-credentials
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: allinkl-smtp-credentials
- name: DB_CONNECTION_STRING
valueFrom:
secretKeyRef:
key: uri
name: cnpg-app
envFrom:
- secretRef:
name: pocketid
image: ghcr.io/pocket-id/pocket-id:v2.8.0@sha256:a073640418b2cfc8587c488a7270580b3ab95cae2c543f5d64bbbe1fd7ccbae8
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 1411
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 2
name: pocketid
ports:
- containerPort: 1411
readinessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 1411
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 2
volumeMounts:
- mountPath: /app/data
name: pocketid-data
securityContext:
seccompProfile:
type: RuntimeDefault
volumes:
- name: pocketid-data
persistentVolumeClaim:
claimName: pocketid-data