Skip to main content

Zitadel — Zitadel is the identity provider (users, roles, authentication). ⬆ índice

Zitadel Guide

Zitadel is the identity provider (users, roles, authentication).

Quick start (local)

./infra up security/zitadel      # start
./infra logs security/zitadel # follow logs
./infra status security/zitadel # compose ps

From the service directory (alternative):

cd security/zitadel
./run.sh up
./run.sh logs

Access (local)

  • Main service: http://localhost:${ZITADEL_PORT:-8084}
  • Login UI: http://localhost:${LOGIN_UI_PORT:-8085}

Access (remote)

When deployed with the default Traefik endpoint registry (deployment/remote.env), Zitadel uses:

  • Main service: https://iam.<base-domain>
  • Login UI: https://iam.<base-domain>/ui/v2/login
  • Login alias: https://iam.<base-domain>/login

If you changed the default domains or paths, update deployment/remote.env and redeploy core so Traefik regenerates routes/certs.

Access (local VM / Vagrant targets)

When you deploy to a server marked as local (core2_is_local=true in Ansible inventory), endpoints use short test hostnames over HTTP:

  • Add hostnames on your laptop (example):
    • sudo sh -c 'printf "%s\n" "192.168.56.10 iam portal things" >> /etc/hosts'
  • Access example:
    • http://iam

Prerequisites

  • Centralized DB layer must be running (PostgreSQL + Redis).
    • Quick check: ./infra db status
  • Env must exist and be valid:
    • ./infra env generate
    • ./infra env check

Default bootstrap login

  • User: zitadel-admin@[FIRSTINSTANCE_ORG_NAME].[ZITADEL_EXTERNALDOMAIN]
  • Password: Password1!

Notes:

  • These defaults come from the repo’s first-instance configuration in security/zitadel/.env.
  • The login identifier uses the organization name prefix from FIRSTINSTANCE_ORG_NAME before the external domain.
  • If you changed first-instance variables (or already bootstrapped before), the credentials may differ.

Automated bootstrap

Fresh installs now bootstrap automatically:

  1. Zitadel writes the first-instance management PAT to:
    • security/zitadel/.runtime/management.pat
  2. Bootstrap reconciliation uses that PAT to:
    • create/reconcile the automation machine user
    • generate/reconcile the durable management client secret
    • create/reconcile the Aitha project
    • create/reconcile project roles and apps/clients
    • write resulting GLOBAL_ZITADEL_* values back into .env.secrets

Manual recovery is still possible:

./infra zitadel pat set '<PAT>'
python3 deployment/scripts/python/zitadel_bootstrap.py \
--base-url http://127.0.0.1:${ZITADEL_PORT:-8084} \
--pat-file security/zitadel/.runtime/management.pat \
--env-file .env.secrets \
--url-mode localhost

Import / export helpers

./infra zitadel export [project_name_or_id] [output_file]
./infra zitadel import <json_file> [new_project_name] [--pat <token>] [--org-id <org_id>]

Org ID (--org-id)

  • If your PAT is scoped in a specific org, import may need --org-id.
  • You can usually find the org id in the console (org settings/details), or in console URLs after selecting an org.

PAT resolution order for import:

  1. --pat <token>
  2. ZITADEL_MANAGEMENT_PAT env var
  3. security/zitadel/.runtime/management.pat
  4. interactive prompt (TTY)

About login-client.pat

  • The bootstrap process can also generate a security/zitadel/.runtime/login-client.pat token for login/bootstrap flows.
  • Do not use login-client.pat for project import/export automation (it is typically missing permissions for AddProject operations).

zitadel guide

./infra zitadel guide prints this document (used by local + remote init flows).

Notes

  • If you change Zitadel first-instance/domain/redirect values, update security/zitadel/.env and rerun ./infra up security/zitadel.
  • Keep the security/zitadel phase correct before generating the full application envs.
  • The canonical bootstrap spec now lives in security/zitadel/bootstrap.json.
  • Technology overview: docs/internal/technologies/zitadel.md
  • Roles model: docs/internal/architecture/roles-and-permissions.md