Skip to content

Zitadel Infrastructure Setup

John R. D'Orazio edited this page Apr 2, 2026 · 5 revisions

Zitadel Infrastructure Setup

This page covers how to set up the Zitadel infrastructure for local development.

Prerequisites

  • Docker and Docker Compose
  • The monorepo workspace cloned at the root level (the docker-compose.yml lives in the workspace root, not inside LiturgicalCalendarAPI)

Quick Start

From the workspace root:

docker compose up -d

This starts four services:

Service URL Purpose
Zitadel http://localhost:8080/ui/console Admin console
Login V2 http://localhost:8081/ui/v2/login Authentication UI
PostgreSQL localhost:5432 Database
Adminer http://localhost:8088 Database management UI

Initial Zitadel Configuration

After the services are running, configure the Zitadel project:

1. Log in to the Console

Open http://localhost:8080/ui/console and log in with the default admin credentials:

  • Username: root@LiturgicalCalendar.localhost
  • Password: RootPassword1!

2. Create the Project

Create a project named "LiturgicalCalendar".

3. Create Roles

In the project, create these roles:

Role Description
admin System administrator
developer API consumer (register apps, API keys)
calendar_editor Calendar data contributor
test_editor Test definition author

4. Create Applications

API Application (Machine-to-Machine):

  • Name: "LiturgicalCalendar API"
  • Type: API
  • Auth Method: Private Key JWT or Client Credentials
  • Generate a Personal Access Token (PAT) for ZITADEL_MACHINE_TOKEN

Frontend Application (Web with PKCE):

  • Name: "LiturgicalCalendar Frontend"
  • Type: Web
  • Auth Method: PKCE
  • Redirect URIs:
    • http://localhost:3000/auth/callback (development)
    • https://your-production-domain.com/auth/callback (production)
  • Post Logout URIs:
    • http://localhost:3000 (development)
    • https://your-production-domain.com (production)

5. Enable User Self-Registration

In Organization Settings > Login Behavior:

  • Enable self-registration
  • Configure email verification

6. Configure Environment Variables

Copy the client IDs from the applications you created and update your API .env.local:

ZITADEL_ISSUER=http://localhost:8080
ZITADEL_CLIENT_ID=<frontend-client-id>
ZITADEL_PROJECT_ID=<project-id>
ZITADEL_MACHINE_TOKEN=<machine-user-pat>

DB_HOST=localhost
DB_PORT=5432
DB_NAME=litcal
DB_USER=litcal
DB_PASSWORD=litcal_secure_password

Database Initialization

The infrastructure/init-db.sql script runs automatically on first PostgreSQL startup and creates:

  • zitadel database - Managed entirely by Zitadel (users, orgs, projects, roles)
  • litcal database - Application-specific RBAC tables (role requests, permissions, applications, API keys, audit log)

The pgcrypto extension is enabled for UUID generation.

Running Migrations

After the initial setup, apply the incremental migrations to the litcal database:

# Connect to the litcal database
docker compose exec db psql -U litcal -d litcal

# Or apply migration files directly
docker compose exec db psql -U litcal -d litcal -f /path/to/migration.sql

Migration files are in LiturgicalCalendarAPI/migrations/:

Migration Purpose
001_create_rbac_tables.sql Base RBAC schema (may overlap with init-db.sql)
002_add_application_approval_status.sql Application approval workflow columns
003_add_role_request_revoked_status.sql Role revocation status support
004_add_zitadel_sync_status.sql Sync tracking between app DB and Zitadel
005_add_application_requested_scope.sql Read/write scope for applications

Useful Commands

# Start services
docker compose up -d

# Stop services
docker compose down

# View logs
docker compose logs -f zitadel
docker compose logs -f login
docker compose logs -f db

# Reset everything (WARNING: destroys all data)
docker compose down -v
docker compose up -d

# Connect to PostgreSQL as superuser
docker compose exec db psql -U postgres

# Connect to application database
docker compose exec db psql -U litcal -d litcal

# Check login names if you can't log in
docker compose exec db psql -U postgres -d zitadel -c "select * from projections.login_names3;"

Troubleshooting

Zitadel won't start

Check if PostgreSQL is healthy:

docker compose ps
docker compose logs db

Login V2 not working

Check if Zitadel is healthy and the PAT was generated:

docker compose logs login

The Login V2 service uses network_mode: service:zitadel to share Zitadel's network, so it can reach Zitadel at localhost:8080 internally.

Cannot connect to Zitadel Console

Ensure port 8080 is not in use by another service:

lsof -i :8080

Database connection issues

Verify both databases were created:

docker compose exec db psql -U postgres -c '\l'

You should see both zitadel and litcal databases listed.

Clone this wiki locally