Guía de despliegue

ZITADEL en VPS: IAM de código abierto para desarrolladores

Desplegar en un VPS Cloud →

Tutorial

ZITADEL en VPS: IAM de código abierto para desarrolladores

Autoalojamiento11 min de lectura8 pasos

ZITADEL es una plataforma IAM de código abierto escrita en Go: SSO OIDC/OAuth 2.0, passkeys y multi-tenancy nativo, en self-hosted. Esta guía la despliega en un VPS de ServOrbit con Docker Compose, corrige cifras que la versión anterior repetía sin fuente y documenta lo que aún no funciona: el descubrimiento de dominio, un bug abierto en la v4 desde septiembre de 2025. Guía proporcionada, sin soporte incluido.

Contenido· ¿Por qué elegir ZITADEL frente a Authentik o Keycloak?1/18
  1. 01¿Por qué elegir ZITADEL frente a Authentik o Keycloak?
  2. 02Requisitos previos cuantificados
  3. 03Instalar ZITADEL desde el Marketplace
  4. 04Instalación en 3 pasos
  5. 05Qué despliega la plantilla
  6. 06Dominio externo, TLS y reverse proxy
  7. 07Crear su primera aplicación OIDC
  8. 08Integrar ZITADEL con sus aplicaciones self-hosted
  9. 09Gestión multi-tenant: organizaciones y proyectos
  10. 10Consejo: activar passkeys desde el principio
  11. 11Descubrimiento de dominio: lo que debería funcionar
  12. 12Límites conocidos: la incidencia n.º 10662 de zitadel/zitadel
  13. 13Incidencia n.º 10662: confirmado y reportado
  14. 14Solución de problemas del inicio de sesión SSO y del dominio verificado
  15. 15Diagnóstico en 5 pasos
  16. 16Actualizaciones y seguridad
  17. 17Antes de actualizar
  18. 18Instalar ZITADEL desde el Marketplace de ServOrbit

¿Por qué elegir ZITADEL frente a Authentik o Keycloak?

ZITADEL ocupa un nicho preciso entre las plataformas de autenticación de código abierto. A diferencia de Authelia (proxy de autenticación sin gestión de usuarios propia) o Authentik (IdP full-stack rico en funcionalidades), se dirige a equipos de desarrollo que quieren un IAM de nivel empresarial desde el principio: multi-tenancy nativo, APIs gRPC + REST completas y un proveedor Terraform oficial (zitadel/zitadel en el registro de Terraform).

Con la memoria, conviene ser prudente. La documentación de operación indica que el propio ZITADEL necesita unos 512 MB de RAM y menos de un núcleo de CPU, sin contar la base de datos, con picos de CPU al calcular el hash de las contraseñas. La versión anterior de este artículo anunciaba «menos de 100 MB»: esa cifra no figura en la documentación, no dimensione su VPS con ella. La comparación de recursos con Keycloak no se cuantifica aquí por falta de una medición con fuente.

Requisitos previos cuantificados

  • VPS: 2 vCPU y 2 GB de RAM (la guía de Docker Compose del proyecto pide al menos 2 GB), Ubuntu 24.04. Prevea más cuando la base crezca: el proyecto cuenta unos 4 GB de RAM por núcleo de base de datos.
  • Docker: Docker Engine 24 o superior con Compose v2; el antiguo binario docker-compose (v1) no es compatible.
  • PostgreSQL: se admiten las versiones 14 a 18. La plantilla de ServOrbit despliega PostgreSQL 16.
  • Puertos: ZITADEL escucha internamente en 8080. Solo 443 debe ser público (más 80 si deja que Let's Encrypt emita el certificado). La plantilla enlaza 8080 a 127.0.0.1 y deja que nginx sirva el exterior.
  • Dominio: un nombre o subdominio que apunte a la IP del VPS, por ejemplo auth.your-domain.com, en HTTPS.
  • Masterkey: ZITADEL_MASTERKEY debe tener exactamente 32 caracteres y no puede cambiar tras la inicialización sin perder el acceso a los datos cifrados. La plantilla la genera; guárdela fuera del VPS.

Instalar ZITADEL desde el Marketplace

Instalación en 3 pasos

  1. Crear el VPS

    Desde su área de cliente de ServOrbit, elija la gama VPS y haga clic en Configurar. En el campo Aplicación, seleccione ZITADEL. Introduzca su dominio (p. ej. auth.your-domain.com).

    Si no tiene dominio, el subdominio gratuito de ServOrbit está disponible inmediatamente, HTTPS incluido.

  2. Inicio automático

    El script de instalación genera el MASTERKEY, la contraseña de PostgreSQL y la contraseña de administrador, luego lanza PostgreSQL 16 y ZITADEL mediante Docker Compose. Duración habitual: 2 a 4 minutos.

  3. Acceder a la consola

    Una vez completada la instalación, sus credenciales se muestran en el área de cliente.
    - URL: https://<su-dominio>/ui/console
    - Usuario: admin. Si la página lo rechaza, pruebe admin@zitadel.<su-dominio>: ZITADEL compone los nombres de inicio de sesión como usuario@organización.dominio, como en el ejemplo [email protected] del proyecto.
    - Contraseña: la generada

    Inicie sesión y cámbiela de inmediato.

Qué despliega la plantilla

La plantilla es un archivo Docker Compose de dos servicios: db (PostgreSQL 16) y zitadel, lanzado con start-from-init --tlsMode disabled --masterkeyFromEnv. El TLS lo termina, por tanto, nginx y no ZITADEL. La imagen seguida es la etiqueta stable de ghcr.io/zitadel/zitadel, lo que significa que la versión realmente en marcha depende del día en que se descargó la imagen: compruébela con docker compose images (véase la sección sobre actualizaciones).

El dominio se pasa a ZITADEL_EXTERNALDOMAIN, con ZITADEL_EXTERNALPORT=443 y ZITADEL_EXTERNALSECURE=true. La plantilla considera el dominio fijo desde el primer arranque: elija el correcto desde el principio.

Dominio externo, TLS y reverse proxy

  • Tres valores que alinear — ZITADEL_EXTERNALDOMAIN, ZITADEL_EXTERNALPORT y ZITADEL_EXTERNALSECURE deben describir la URL pública real. ZITADEL solo atiende las peticiones enviadas al protocolo, host y puerto esperados; si no, obtiene «Instance not found».
  • Cambiar de dominio — el proyecto documenta que estas opciones pueden modificarse en cualquier momento, siempre que se repita la fase de setup. No es imposible, como afirmaba la versión anterior, pero tampoco es un gesto trivial: toda aplicación cliente referencia la URL antigua.
  • Host conservado — el reverse proxy debe transmitir la cabecera Host original y X-Forwarded-Proto: https. El ejemplo de nginx del proyecto termina el TLS y habla con ZITADEL en HTTP/2 sin cifrar (h2c) con grpc_pass.
  • HTTP/2 de extremo a extremo — la consola exige HTTP/2 hasta ZITADEL. Los proxys probados por el proyecto son Traefik v3, NGINX 1.x estable, Caddy v2 y Apache httpd 2.4.
  • CDN o WAF por delante — la documentación precisa que un proxy, WAF o CDN situado delante de ZITADEL también debe admitir HTTP/2. Pruebe la consola tras cualquier cambio de DNS a un modo con proxy.

Crear su primera aplicación OIDC

Una vez conectado a la consola de ZITADEL:

1. Vaya a Projects y luego Create
2. Asigne un nombre a su proyecto (p. ej. My App)
3. Haga clic en Add Application
4. Elija el tipo: Web (aplicaciones servidor), Native (móvil/escritorio) o API (machine-to-machine)
5. Para una app Web, seleccione PKCE (recomendado) e introduzca sus Redirect URIs

ZITADEL genera el Client ID. Anote el discovery endpoint OIDC: https://<su-dominio>/.well-known/openid-configuration.

Integrar ZITADEL con sus aplicaciones self-hosted

Cualquier aplicación que hable OIDC puede apoyarse en ZITADEL: basta con el Client ID, el secreto si lo hay y el discovery endpoint. Ejemplos comunes:

  • Gitea: Administración del sitio, Autenticación, añadir una fuente OAuth2 de tipo OpenID Connect e introducir Client ID, secreto y discovery endpoint
  • Grafana: sección [auth.generic_oauth] de grafana.ini con las URL de autorización, token e información de usuario de ZITADEL
  • Nextcloud: aplicación Social Login u OpenID Connect user backend
  • Cualquier otra aplicación OIDC: indique el discovery endpoint, el Client ID y las Redirect URIs declaradas en el proyecto; consulte la documentación de la aplicación para los ajustes exactos

Gestión multi-tenant: organizaciones y proyectos

ZITADEL se basa en un modelo multi-tenant nativo: puede crear varias Organizaciones (por ejemplo una por cliente de su SaaS), cada una con sus usuarios y sus políticas de inicio de sesión. Cada organización puede tener sus Proyectos y Roles.

Atención: los roles no se incluyen automáticamente en los tokens, al contrario de lo que afirmaba la versión anterior. Hay que marcar Assert Roles on Authentication en el proyecto para obtenerlos mediante userinfo, o User Roles Inside ID Token en la aplicación, y solicitar el scope de roles urn:zitadel:iam:org:project:{projectId}:roles. Añada también urn:zitadel:iam:org:project:id:{projectId}:aud si obtiene «Invalid audience».

Consejo: activar passkeys desde el principio

En la configuración de la instancia, active la autenticación Passkey/WebAuthn. Sus usuarios se autentican sin contraseña desde su navegador.

Descubrimiento de dominio: lo que debería funcionar

El descubrimiento de dominio (Domain Discovery) dirige al usuario a la organización correcta según el dominio de su dirección de correo. En el escenario que describe el proyecto, un usuario de [email protected] es redirigido al proveedor de identidad de su empresa, un usuario de [email protected] ve una página de inicio de sesión con contraseña y MFA, y un dominio desconocido cae en la organización por defecto.

Las condiciones descritas en la guía del proyecto son:

  • Instancia — en Login Behavior and Security, la opción «Domain discovery allowed» está activada
  • Organización por defecto — recibe a todos los usuarios sin coincidencia
  • Dominio verificado — cada dominio se verifica en las Organization Domains de la organización, mediante registro DNS TXT o desafío HTTP; conserve el registro DNS, porque ZITADEL revalida periódicamente
  • Política de inicio de sesión de la organización — «External IDP allowed» activado y, para una organización puramente federada, «Username Password allowed» desactivado
  • Proveedor de identidad — configurado y asociado a esa organización; con un solo proveedor la redirección es automática, con varios el usuario elige
  • Inicio de sesión por correo — el nombre de inicio de sesión introducido debe poder ser una dirección de correo cuyo dominio coincida

Límites conocidos: la incidencia n.º 10662 de zitadel/zitadel

En ZITADEL v4.1.2 autoalojado, el descubrimiento de dominio no funciona en algunos despliegues pese a tener organizaciones con dominio verificado y un proveedor de identidad configurado. La incidencia n.º 10662 («Domain Discovery doesn't work») se abrió en septiembre de 2025 y sigue abierta al redactar este artículo. La tabla separa lo que el equipo o la documentación establecen de lo que los usuarios reportan.

Incidencia n.º 10662: confirmado y reportado

Desplace la tabla

PuntoConfirmado (equipo o documentación)Reportado por usuarios, sin confirmar
SíntomaLa incidencia está abierta, con prioridad media en octubre de 2026 y las etiquetas area/console, area/loginV1 y ng-v4-legacyMensaje «User not found in the system» para una dirección del dominio verificado, en v4.1.2, idéntico en OKD y en Docker
Corrección anunciadaUn mantenedor indicó en octubre de 2025 que la PR n.º 10729 la corregía y después la incidencia se reabrióEl fallo persiste en v4.3.1 y después, en Login V1, en v4.5.0, v4.6.3, v4.7.0 y v4.11.0
CausaNo hay ninguna causa establecida públicamenteNinguna hipótesis verificada
AlcanceExisten subincidencias (estado a 16 de julio de 2026: una terminada, dos en curso, una sin empezar), vinculadas al trabajo padre n.º 12337Reproducido en Login V2 (informe inicial) y luego en Login V1; el caso de varios dominios en una misma organización sigue sin respuesta
ConsolaEl 27 de julio de 2026 una colaboradora indica que la Consola se deprecará en 12 meses y que no se prioriza ninguna corrección hasta entonces; la incidencia se mantiene abiertaNada que señalar
Solución provisionalEl hilo no documenta ninguna solución provisionalNingún participante ha probado ninguna

En la práctica: no construya una arquitectura SSO empresarial únicamente sobre el descubrimiento de dominio mientras esta incidencia siga abierta. Prevea una segunda vía (un enlace de inicio de sesión por proveedor, véase más abajo) y pruebe el enrutamiento con un usuario real antes de producción. El 27 de octubre de 2026 un miembro del equipo pidió verificar el estado de la incidencia: siga la incidencia, y no este artículo, para saber cómo termina.

Solución de problemas del inicio de sesión SSO y del dominio verificado

Diagnóstico en 5 pasos

  1. Comprobar la instancia

    En la configuración de la instancia, sección Login Behavior and Security, compruebe que «Domain discovery allowed» está activado. Sin él no se consulta ninguna regla de organización.

  2. Comprobar el dominio

    En la organización afectada, abra Organization Domains: el dominio debe figurar como verificado. Si la verificación falla, restablezca el registro TXT o el desafío HTTP solicitado y no elimine nunca el registro después.

  3. Comprobar la política de inicio de sesión

    En la misma organización, «External IDP allowed» debe estar activado y el proveedor de identidad activo. Si «Username Password allowed» sigue activado, el usuario puede acabar en la solicitud de contraseña en lugar de ser redirigido, síntoma descrito en la incidencia.

  4. Probar el nombre de inicio de sesión

    En una ventana privada, introduzca una dirección completa cuyo dominio sea exactamente el verificado. Un error en el dominio, un subdominio o un usuario ya existente en otra organización cambian el resultado.

  5. Eludir el descubrimiento

    Si todo es conforme y «User not found in the system» persiste, probablemente está en el caso de la incidencia n.º 10662. El scope urn:zitadel:iam:org:idp:id:<idp_id> redirige directamente al usuario al proveedor de identidad elegido: la documentación lo describe, pero no se ha probado con este fallo.

  • «User not found in the system»: aplique los cinco pasos anteriores; si son conformes, es el fallo de la incidencia
  • «Instance not found» (404): el host, puerto y protocolo recibidos no coinciden con ZITADEL_EXTERNALDOMAIN, ZITADEL_EXTERNALPORT y ZITADEL_EXTERNALSECURE; compruebe que nginx conserva la cabecera Host
  • Consola en blanco o llamadas a la API que fallan tras un proxy o CDN: compruebe HTTP/2 de extremo a extremo
  • Usuario admin rechazado: pruebe la forma admin@zitadel.<su-dominio> indicada más arriba
  • Verificación de dominio que falla: la guía del proyecto señala que el desafío ACME de verificación puede desactivarse en los ajustes por defecto, pero hágalo solo con conocimiento de causa

Actualizaciones y seguridad

  • Versión actual — al redactar, la última versión estable publicada es la v4.20.0, aparecida en octubre de 2026; lea las notas de versión antes de cada actualización
  • Aviso GHSA-jh92-5mrj-p2w2 — toma de control de cuenta por identificadores de sesión predecibles en Login V2 (gravedad alta, sin identificador CVE indicado). Afecta a las versiones 4.0.0 a 4.19.1 y se corrige en la 4.19.2; un despliegue que solo usa Login V1 no está afectado
  • Secreto de la cookie de sesión — la corrección pide ZITADEL_SESSION_COOKIE_SECRET (al menos 32 caracteres, idéntico en todas las réplicas); los usuarios deben volver a iniciar sesión tras la actualización
  • Rama 3.x — llegó al final de su vida el 31 de agosto de 2026 y no recibirá corrección: migre a una 4.x reciente

Antes de actualizar

Haga una copia de la base con pg_dump y de la masterkey, y después ejecute docker compose pull seguido de docker compose up -d desde la carpeta del Compose. Como la plantilla sigue la etiqueta stable, compruebe después la versión en marcha con docker compose images.

Instalar ZITADEL desde el Marketplace de ServOrbit

Puede instalar ZITADEL directamente desde el [Marketplace de ServOrbit](/marketplace/security/zitadel): VPS preconfigurado con Docker Compose, nginx, HTTPS y secretos generados automáticamente. La plantilla se ofrece como punto de partida, sin soporte para su configuración de identidad.

Desplegar ZITADEL en su VPS

IAM de código abierto, OIDC/OAuth 2.0, passkeys y multi-tenancy nativo — preconfigurado con Docker Compose y HTTPS incluido.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva