Post-Tyranny-Tech-Infrastru.../PROJECT_REFERENCE.md
Pieter 48ef4da920 Fix Zitadel deployment by removing FirstInstance variables
- Remove all ZITADEL_FIRSTINSTANCE_* environment variables
- Fixes migration error: duplicate key constraint violation
- Root cause: Bug in Zitadel v2.63.7 FirstInstance migration
- Workaround: Complete initial setup via web UI
- Upstream issue: https://github.com/zitadel/zitadel/issues/8791

Changes:
- Clean up obsolete documentation (OIDC_AUTOMATION.md, SETUP_GUIDE.md, COLLABORA_SETUP.md)
- Add PROJECT_REFERENCE.md for essential configuration info
- Add force recreate functionality with clean database volumes
- Update bootstrap instructions for web UI setup
- Document one-time manual setup requirement for OIDC automation

Zitadel now deploys successfully and is accessible at:
https://zitadel.test.vrije.cloud

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-06 16:43:57 +01:00

4.5 KiB

Project Reference

Quick reference for essential project information and common operations.

Project Structure

infrastructure/
├── ansible/              # Ansible playbooks and roles
│   ├── hcloud.yml       # Dynamic inventory (Hetzner Cloud)
│   ├── playbooks/       # Main playbooks
│   │   ├── deploy.yml   # Deploy applications to clients
│   │   └── setup.yml    # Setup base server infrastructure
│   └── roles/           # Ansible roles (traefik, zitadel, nextcloud, etc.)
├── keys/
│   └── age-key.txt      # SOPS encryption key (gitignored)
├── secrets/
│   ├── clients/         # Per-client encrypted secrets
│   │   └── test.sops.yaml
│   └── shared.sops.yaml # Shared secrets
└── terraform/           # Infrastructure as Code (Hetzner)

Essential Configuration

SOPS Age Key

Location: infrastructure/keys/age-key.txt Usage: Always set before running Ansible:

export SOPS_AGE_KEY_FILE="../keys/age-key.txt"

Hetzner Cloud Token

Usage: Required for dynamic inventory:

export HCLOUD_TOKEN="MlURmliUzLcGyzCWXWWsZt3DeWxKcQH9ZMGiaaNrFM3VcgnASlEWKhhxLHdWAl0J"

Ansible Paths

Working Directory: infrastructure/ansible/ Inventory: hcloud.yml (dynamic, pulls from Hetzner Cloud API) Python: ~/.local/bin/ansible-playbook (user-local installation)

Current Deployment

Client: test

Common Operations

Deploy Applications

cd infrastructure/ansible
export HCLOUD_TOKEN="MlURmliUzLcGyzCWXWWsZt3DeWxKcQH9ZMGiaaNrFM3VcgnASlEWKhhxLHdWAl0J"
export SOPS_AGE_KEY_FILE="../keys/age-key.txt"

# Deploy everything to test client
~/.local/bin/ansible-playbook -i hcloud.yml playbooks/deploy.yml --limit test

# Force recreate Zitadel (clean database)
~/.local/bin/ansible-playbook -i hcloud.yml playbooks/deploy.yml --limit test \
  --extra-vars "zitadel_force_recreate=true"

Check Service Status

# List inventory hosts
export HCLOUD_TOKEN="..."
~/.local/bin/ansible-inventory -i hcloud.yml --list

# Run ad-hoc commands
~/.local/bin/ansible test -i hcloud.yml -m shell -a "docker ps"
~/.local/bin/ansible test -i hcloud.yml -m shell -a "docker logs zitadel 2>&1 | tail -50"

Edit Secrets

cd infrastructure
export SOPS_AGE_KEY_FILE="keys/age-key.txt"

# Edit client secrets
sops secrets/clients/test.sops.yaml

# View decrypted secrets
sops --decrypt secrets/clients/test.sops.yaml

Architecture Notes

Service Stack

  • Traefik: Reverse proxy with automatic Let's Encrypt certificates
  • Zitadel v2.63.7: Identity provider (OIDC/OAuth2)
  • PostgreSQL 16: Database for Zitadel
  • Nextcloud 30.0.17: File sync and collaboration
  • Redis: Caching for Nextcloud

Docker Networks

  • traefik: External network for all web-accessible services
  • zitadel-internal: Internal network for Zitadel ↔ PostgreSQL
  • nextcloud-internal: Internal network for Nextcloud ↔ Redis

Volumes

  • zitadel_zitadel-db-data: PostgreSQL data
  • zitadel_zitadel-machinekey: JWT keys for service accounts
  • nextcloud_nextcloud-data: Nextcloud files and database

Known Issues

Zitadel FirstInstance Configuration Bug

Issue: ALL ZITADEL_FIRSTINSTANCE_* environment variables cause migration errors in v2.63.7:

ERROR: duplicate key value violates unique constraint "unique_constraints_pkey"
Errors.Instance.Domain.AlreadyExists

Root Cause: Bug in Zitadel v2.63.7 FirstInstance migration logic Workaround: Remove all FirstInstance variables; complete initial setup via web UI Upstream Issue: https://github.com/zitadel/zitadel/issues/8791 Status: Waiting for upstream fix

OIDC Automation

Issue: Automatic OIDC app provisioning requires manual one-time setup Workaround:

  1. Complete Zitadel web UI setup wizard (first access)
  2. Create service user with JWT key via web UI
  3. Store JWT key in secrets for automated provisioning

Status: Manual one-time setup required per Zitadel instance

Service Credentials

Zitadel Admin

Nextcloud Admin