· 7 min de lectura

SSO Self-Hosted con PocketID: Autenticación OIDC para tu Homelab

Cómo implementar Single Sign-On en un homelab usando PocketID como proveedor OIDC, Caddy con caddy-security como reverse proxy, y passkeys como método de autenticación. Sin contraseñas, sin dependencias cloud.

Imagen de SSO Self-Hosted con PocketID: Autenticación OIDC para tu Homelab

Cada servicio self-hosted tiene su propio login. Si gestionas más de cinco servicios, la fatiga de contraseñas es real. La solución empresarial es un Identity Provider con SSO. La solución homelab era Authelia o Authentik — hasta que apareció PocketID.

PocketID es un proveedor OpenID Connect minimalista que usa passkeys como método principal de autenticación. Sin contraseñas que gestionar, sin tokens TOTP, sin dependencias externas. En este artículo explico cómo desplegarlo y cómo proteger servicios que no tienen autenticación propia usando Caddy + caddy-security.

El Problema

Un homelab típico acumula servicios con el tiempo: Jellyfin, Grafana, Mealie, dashboards varios… Algunos tienen auth propia, pero muchos no. La opción clásica era basic auth en el reverse proxy, pero gestionar usuarios y contraseñas por servicio es tedioso y poco seguro.

Lo que necesitamos es un Identity Provider ligero que:

  1. No requiera infraestructura compleja (ni LDAP, ni bases de datos adicionales)
  2. Soporte OIDC estándar para integrar con cualquier servicio
  3. Sea fácil de mantener — esto es un homelab, no un datacenter

PocketID: OIDC Minimalista con Passkeys

PocketID es un proveedor OIDC escrito en Go + SvelteKit que almacena todo en SQLite. No necesita PostgreSQL, Redis, ni ninguna dependencia externa. Su diferenciador principal: la autenticación es vía passkeys (WebAuthn/FIDO2) o códigos de un solo uso por email.

Por Qué PocketID y No Authelia/Authentik

PocketIDAutheliaAuthentik
AlmacenamientoSQLitePostgreSQL/MySQL + RedisPostgreSQL + Redis
Recursos~30MB RAM~100MB RAM~500MB+ RAM
Auth principalPasskeysContraseña + TOTPContraseña + TOTP/WebAuthn
Complejidad configMínima (.env)Media (YAML)Alta (UI + flows)
OIDCNativoAdd-onNativo

Para un homelab personal con 1-3 usuarios, PocketID es la opción más sensata. Authentik es potente pero excesivo; Authelia es un buen punto medio pero requiere más infraestructura.

Despliegue

PocketID se puede desplegar en cualquier host con Docker:

# docker-compose.yml
services:
  pocketid:
    image: ghcr.io/pocket-id/pocket-id:latest
    ports:
      - "1411:80"
    environment:
      - TRUST_PROXY=true
      - SMTP_HOST=smtp.example.com
      - SMTP_PORT=587
      - [email protected]
      - [email protected]
      - SMTP_PASSWORD=secret
    volumes:
      - ./data:/app/backend/data

El setup inicial se hace desde el navegador. PocketID crea el primer usuario admin y te pide registrar un passkey inmediatamente. A partir de ahí, todo el login es biométrico: huella, Face ID, Windows Hello o llave de seguridad física.

Registrar un Cliente OIDC

Para cada servicio que quieras proteger:

  1. Accede al panel admin de PocketID
  2. Crea un nuevo cliente OIDC con nombre descriptivo
  3. Configura el callback URL del servicio
  4. Copia el client_id y client_secret

PocketID mantiene un catálogo con guías de integración para más de 90 servicios — desde Grafana y Proxmox hasta Jellyfin, Immich o Portainer. Cada guía incluye las variables exactas, scopes y callback URLs que necesitas. Es probablemente la mejor referencia para integrar OIDC en servicios self-hosted, independientemente del proveedor que uses.

Proteger Servicios Sin Auth: Caddy + caddy-security

Los servicios con soporte OIDC nativo se integran directamente con PocketID. Pero los que no tienen autenticación propia necesitan un reverse proxy que la gestione por ellos.

Para esto usamos Caddy con el plugin caddy-security, que actúa como middleware OIDC delante de cualquier servicio.

Imagen Docker Personalizada

Caddy no incluye caddy-security por defecto. Hay que construir una imagen custom:

FROM caddy:builder AS builder
RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/greenpau/caddy-security

FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

El plugin caddy-dns/cloudflare es opcional — útil si necesitas certificados vía DNS challenge para servicios internos no expuestos a internet.

Configuración del Caddyfile

La configuración tiene tres bloques: el provider OIDC, el portal de login, y las policies de autorización.

{
  order authenticate before respond
  order authorize before basicauth

  security {
    oauth identity provider generic {
      realm generic
      driver generic
      client_id {$OIDC_CLIENT_ID}
      client_secret {$OIDC_CLIENT_SECRET}
      scopes openid email profile
      metadata_url https://auth.example.com/.well-known/openid-configuration
    }

    authentication portal myportal {
      crypto default token lifetime 86400
      enable identity provider generic
      transform user {
        match email {$ADMIN_EMAIL}
        action add role authp/admin authp/user
      }
    }

    authorization policy mypolicy {
      set auth url https://portal.example.com/oauth2/generic
      allow roles authp/admin authp/user
    }
  }
}

# Portal de login
portal.example.com {
  authenticate with myportal
}

# Servicio protegido
metube.example.com {
  authorize with mypolicy
  reverse_proxy metube:8081
}

# Otro servicio protegido
browser.example.com {
  authorize with mypolicy
  reverse_proxy chromium:3000
}

Cada servicio nuevo solo necesita dos líneas: authorize with mypolicy y reverse_proxy. El flujo completo:

  1. Usuario accede a metube.example.com
  2. Caddy detecta que no hay sesión → redirige al portal
  3. El portal redirige a PocketID para login con passkey
  4. PocketID valida → devuelve token OIDC al portal
  5. Caddy establece sesión → redirige al servicio original

Gotchas Importantes

El realm DEBE llamarse “generic”. Si usas un nombre custom, caddy-security no encuentra el provider. Esto no está documentado y cuesta horas de debug.

No uses cookie domain compartido con múltiples subdominios. Si configuras un cookie domain como .example.com, la sesión se comparte entre subdominios y el redirect URL del primer login se aplica a todos, creando un bucle infinito. Sin cookie domain, cada subdominio mantiene su propia sesión.

Usa metadata_url siempre. PocketID expone /.well-known/openid-configuration con todos los endpoints (authorization, token, userinfo, JWKS). Caddy-security los descubre automáticamente. Configurar endpoints a mano es innecesario y propenso a errores.

Servicios con OIDC Nativo

Los servicios que soportan OIDC directamente no necesitan caddy-security. Se configuran apuntando a PocketID. Dos ejemplos comunes:

Grafana

[auth.generic_oauth]
enabled = true
name = PocketID
client_id = tu-client-id
client_secret = tu-client-secret
auth_url = https://auth.example.com/authorize
token_url = https://auth.example.com/api/oidc/token
api_url = https://auth.example.com/api/oidc/userinfo
scopes = openid email profile

GitLab

gitlab_rails['omniauth_providers'] = [
  {
    name: "openid_connect",
    label: "PocketID",
    args: {
      name: "openid_connect",
      scope: ["openid", "profile", "email"],
      client_auth_method: "basic",
      discovery: true,
      issuer: "https://auth.example.com",
      client_options: {
        identifier: "tu-client-id",
        secret: "tu-client-secret",
        redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
      }
    }
  }
]

Resultado

Una vez configurado el flujo completo:

  • Login sin contraseñas: Touch ID, huella, Windows Hello. Tarda 2 segundos.
  • Un solo punto de gestión: dar de alta o baja un usuario es una operación, no quince.
  • Phishing-resistant: las passkeys están vinculadas al dominio. No hay password que robar ni token TOTP que interceptar.
  • Mínimo mantenimiento: SQLite no necesita backups complejos. Actualizar es un docker pull y recrear el contenedor.

Limitaciones

  • PocketID es relativamente joven — menos battle-tested que Authentik o Keycloak. Para producción empresarial, miraría alternativas más maduras.
  • Passkeys requieren dispositivos compatibles — cualquier navegador y SO de los últimos 3 años los soporta, pero dispositivos antiguos pueden ser un problema.
  • caddy-security tiene poca documentación — la configuración tiene trampas no documentadas. Una vez funcionando es sólido, pero el setup inicial requiere paciencia.
  • No sustituye a un IdP completo — si necesitas LDAP, grupos granulares, flujos de aprobación o federación con otros IdPs, necesitas Authentik o Keycloak.

Conclusión

PocketID llena un hueco real en el ecosistema self-hosted: un proveedor OIDC que se despliega en 5 minutos, sin infraestructura adicional, con passkeys como método principal. Combinado con Caddy + caddy-security, puedes proteger cualquier servicio web con SSO sin tocar su código.

Si tu homelab tiene más de un puñado de servicios y estás gestionando contraseñas por separado, merece la pena invertir una tarde en configurar SSO. Tu yo futuro te lo agradecerá cada vez que haga login con la huella en vez de buscar una contraseña.

¿Usas otro proveedor OIDC en tu homelab? Me interesa saber qué soluciones habéis encontrado para la autenticación centralizada en entornos self-hosted. Únete al grupo de Telegram para comentar.