ZITADEL
Run your own identity API, login UI and private PostgreSQL database.
Choose your deployment and the way you want to use Selfhost. The instructions below follow that choice.
Set up ZITADEL
Run your own identity API, login UI and private PostgreSQL database.
Customize deployment inputs (3)
- Public identity hostname
domain - hostnameDefault:
"identity.example.com" - Local HTTP port behind your TLS proxy
port - portDefault:
18081 - Administrator email
admin-email - emailDefault:
"admin@example.com"
Save this as inputs.json and adjust the values before initialization.
{
"domain": "identity.example.com",
"port": 18081,
"admin-email": "admin@example.com"
}selfhost app --directory ./zitadel init zitadel --stack --inputs inputs.json Initialization writes portable files and does not start the app. Review compose.yaml, the private .env and any files in files/, then start it:
selfhost app --directory ./zitadel startNo Selfhost dashboard or background service is needed. You can also start these files directly:
cd zitadel
docker compose -f compose.yaml up -d- Review the generated Compose and environment, then start the project.
- Connect the loopback HTTP port to a local TLS proxy or restricted SSH tunnel. Use verified HTTPS for cross-server hops.
- Sign in using the administrator email and ADMIN_PASSWORD from the project environment, then change the bootstrap password.
- Create an OIDC Web application with Authorization Code and PKCE and Selfhost's HTTPS /auth/callback URL. Add its issuer, client and your exact subject ID in Selfhost login settings.
- Back up ZITADEL_MASTERKEY with the database. Changing or losing it prevents decryption of stored data.
- Rotate the login-client personal access token before LOGIN_TOKEN_EXPIRES. Its lifetime is one year from creation.
Connect an existing installation
Use Existing apps → Link an app in the dashboard, or the CLI’s existing-app commands. Choose ZITADEL, its URL and, optionally, its exact Docker container on a connected server.
Save existing.json with your app URL. Add server_id and container for container inspection and actions.
{
"profile": "zitadel",
"name": "ZITADEL",
"url": "https://app.example.com"
}selfhost existing link --file existing.json
selfhost existing list
selfhost existing inspect EXISTING_IDLinking enables the existing-app profile’s supported inspection and actions. It does not import Compose or attach the new-deployment settings and onboarding profiles described below.
Existing app commands, permissions and unlinkingIntegrations for this deployment
This deployment has no attached native settings or onboarding profile. Follow its setup instructions above and use the app’s own administration interface. Choosing another deployment can expose different Selfhost integrations.
Versions and updates
This deployment uses the following images. Existing projects retain their saved recipe and images. A new catalogue version does not silently update them.
- database:
postgres:17-alpine - api:
ghcr.io/zitadel/zitadel:v4.19.1 - login:
ghcr.io/zitadel/zitadel-login:v4.19.1 - identity:
caddy:2.11.2-alpine
Review compatibility and back up app data before an update. Choose an image version and review the change.
Keep control of your setup
Selfhost remains optional. Your app runs using ordinary Compose files, its own settings and persistent data. Keep the Compose project name and volumes to preserve storage. Configuration exports and setting backups do not include application data.