ZITADEL Docs
Deploy & OperateSelf-HostedManageConfiguration

Connect your Self-Hosted Login UI to Zitadel

To enable your self-hosted Login UI to connect to the Zitadel API, it needs a token for a user with the IAM_LOGIN_CLIENT role. Place that service account in a dedicated organization for instance administrators and follow Hardening instance administrators for least-privilege and login settings alignment.

On new installations, the Zitadel setup job can be configured to automatically write a Personal Access Token (PAT) for the login client. Check out one of the deployment examples to learn how to do this.

However, if you want to replace the v1 login of an existing installation by a self-hosted v2 login, the setup job won't execute these steps. In that case, you can create a new PAT for the login client manually.

For the full cutover on an existing v4 installation (routing, auth options, gradual vs instance-wide enablement), see Adopt Login V2 on an existing installation.

Create a Login Client User

In the following URLs, replace the base URL and the user ID according to your environment.

  1. Create a new service account, for example at http://localhost:8080/ui/console/users/create-machine
  2. Create a PAT, for example at http://localhost:8080/ui/console/users/332169800719532035?new=true&id=pat
  3. Save the PAT to a file, for example /path/on/your/host/login-client.pat
  4. Make sure the user has the Instance Login Client role (internally called IAM_LOGIN_CLIENT), for example at http://localhost:8080/ui/console/instance/members

Configure the Login UI

Make sure your Login UI has the environment variable ZITADEL_SERVICE_USER_TOKEN set with your PAT. If you run the Login UI with Docker, you can also mount the file into the container and reference it by passing the environment variable ZITADEL_SERVICE_USER_TOKEN_FILE. For example:

docker run -p 3000:3000 -v /path/on/your/host/login-client.pat:/path/in/container/login-client.pat:ro -e ZITADEL_SERVICE_USER_TOKEN_FILE=/path/in/container/login-client.pat ghcr.io/zitadel/zitadel-login:latest

The Login UI stores the sessions of a browser in an httpOnly cookie and signs every entry, so that a tampered or guessed session ID is ignored. If no dedicated secret is configured, the signing key is derived from the API credential you configured above (ZITADEL_SERVICE_USER_TOKEN, SYSTEM_USER_PRIVATE_KEY, SYSTEM_USER_PRIVATE_KEY_FILE or ZITADEL_LOGINCLIENT_KEYFILE). This fallback is deprecated and will be removed in a future major release; set a dedicated secret as described below. The Login UI logs a warning at startup while it uses this fallback.

The fallback has one consequence to be aware of: rotating the value of that credential (for example creating a new PAT) invalidates all existing session cookies, and users have to sign in to the Login UI again. Their application sessions and tokens are not affected. Switching from one credential type to another (for example from a PAT to a login client key) does not invalidate cookies as long as both credentials are configured during the migration.

Set a dedicated secret with ZITADEL_SESSION_COOKIE_SECRET (at least 32 characters, for example openssl rand -base64 32). This is the recommended configuration and will become required in a future major release: it decouples the cookie lifetime from credential rotation. If a configured value is shorter than 32 characters, the Login UI does not fall back to the API credential: it logs an error and reports not ready on /ready. It accepts a comma-separated list, which allows rotating the secret without signing users out: the first value is used for signing, all values are accepted for verification.

# initial setup
ZITADEL_SESSION_COOKIE_SECRET=$(openssl rand -base64 32)

# rotate: sign with the new secret, still accept cookies signed with the old one
ZITADEL_SESSION_COOKIE_SECRET=<new-secret>,<old-secret>
# after the longest session lifetime has passed, drop the old secret
ZITADEL_SESSION_COOKIE_SECRET=<new-secret>

All replicas of the Login UI must be configured with the same secret (or the same credential), otherwise cookies written by one replica are rejected by the others.

Enable the Login UI for all users

Before doing this, make sure you have a working PAT for an instance Owner user. In case something goes wrong and you lock yourself out from the login screen, you can revert the changes. Create a service account PAT like you created the login client PAT above, but give the user the instance Owner role (internally called IAM_OWNER).

Enable the Login V2 feature flag, for example at the bottom of http://localhost:8080/ui/console/instance?id=features. Enter the base URI of your Login UI, for example http://localhost:3000/ui/v2/login.

Test

That's it! Click your users avatar in the top right corner of the management console and select Log in With Another Account. You should see the new Login UI.

Was this page helpful?

On this page