From d0d68e792e506792ad96ec51d5299b7cf89baf64 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sun, 5 Apr 2026 11:04:33 -0300 Subject: [PATCH] Update AGENTS.md: Zitadel setup with container networking --- AGENTS.md | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index c2d3d8d..f5c0393 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -318,3 +318,141 @@ sudo incus snapshot create pre-change-$(date +%Y%m%d%H%M%S) - **DELETE DEAD CODE** — never keep unused code - **GIT WORKFLOW** — always push to ALL repositories - **0 warnings, 0 errors** — loop until clean + +--- + +## 🔐 Zitadel Setup (Directory Service) + +### Container Architecture +- **directory container**: Zitadel running on port **8080** internally +- **tables container**: PostgreSQL database on port 5432 +- Use database **PROD-DIRECTORY** for Zitadel data + +### Network Access (Container Mode) +- **Internal API**: `http://:8080` +- **External port 9000** redirected via iptables NAT to directory:8080 +- **Health check**: `curl -sf http://localhost:8080/debug/healthz` + +### Zitadel Installation Steps + +1. **Reset database** (on tables container): +```bash +psql -h localhost -U postgres -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'PROD-DIRECTORY' AND pid <> pg_backend_pid();" +psql -h localhost -U postgres -d postgres -c "DROP DATABASE IF EXISTS \"PROD-DIRECTORY\";" +psql -h localhost -U postgres -d postgres -c "CREATE DATABASE \"PROD-DIRECTORY\";" +``` + +2. **Create init config** (on directory container): +```bash +cat > /opt/gbo/conf/directory/zitadel-init-steps.yaml << "EOF" +FirstInstance: + InstanceName: "BotServer" + DefaultLanguage: "en" + PatPath: "/opt/gbo/conf/directory/admin-pat.txt" + Org: + Name: "BotServer" + Machine: + Machine: + Username: "admin-sa" + Name: "Admin Service Account" + Pat: + ExpirationDate: "2099-01-01T00:00:00Z" + Human: + UserName: "admin" + FirstName: "Admin" + LastName: "User" + Email: + Address: "admin@localhost" + Verified: true + Password: "Admin123!" + PasswordChangeRequired: false +EOF +``` + +3. **Start Zitadel** (on directory container): +```bash +pkill -9 zitadel || true +nohup env \ + ZITADEL_DATABASE_POSTGRES_HOST= \ + ZITADEL_DATABASE_POSTGRES_PORT=5432 \ + ZITADEL_DATABASE_POSTGRES_DATABASE=PROD-DIRECTORY \ + ZITADEL_DATABASE_POSTGRES_USER_USERNAME=postgres \ + ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=postgres \ + ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable \ + ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=postgres \ + ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=postgres \ + ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable \ + ZITADEL_EXTERNALSECURE=false \ + ZITADEL_EXTERNALDOMAIN= \ + ZITADEL_EXTERNALPORT=9000 \ + ZITADEL_TLS_ENABLED=false \ + /opt/gbo/bin/zitadel start-from-init \ + --masterkey MasterkeyNeedsToHave32Characters \ + --tlsMode disabled \ + --externalDomain \ + --externalPort 9000 \ + --steps /opt/gbo/conf/directory/zitadel-init-steps.yaml \ + > /opt/gbo/logs/zitadel.log 2>&1 & +``` + +4. **Wait for bootstrap** (~90 seconds), then verify: +```bash +curl -sf http://localhost:8080/debug/healthz +cat /opt/gbo/conf/directory/admin-pat.txt +``` + +5. **Configure iptables** (on system container): +```bash +iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination :8080 +iptables -t nat -A OUTPUT -p tcp -d --dport 9000 -j DNAT --to-destination :8080 +``` + +### Zitadel API Usage + +**PAT file location**: `/opt/gbo/conf/directory/admin-pat.txt` (on directory container) + +#### Get IAM Info (internal) +```bash +curl -s -H "Authorization: Bearer $PAT" http://:8080/management/v1/iam +``` + +#### Get IAM Info (external via port 9000) +```bash +curl -s -H "Authorization: Bearer $PAT" -H "Host: " http://:9000/management/v1/iam +``` + +#### Create Human User +```bash +curl -s -X POST \ + -H "Authorization: Bearer $PAT" \ + -H "Host: " \ + -H "Content-Type: application/json" \ + http://:9000/management/v1/users/human \ + -d '{ + "userName": "janedoe", + "name": "Jane Doe", + "profile": {"firstName": "Jane", "lastName": "Doe"}, + "email": {"email": "jane@example.com"} + }' +``` + +### Zitadel API Endpoints Reference + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/management/v1/iam` | GET | Get IAM info | +| `/management/v1/orgs/me` | GET | Get current org | +| `/management/v1/users/human` | POST | Create human user | +| `/management/v1/users/machine` | POST | Create machine user | +| `/oauth/v2/token` | POST | Get access token | +| `/debug/healthz` | GET | Health check | + +### Important Notes + +- **Zitadel listens on port 8080 internally** +- **External port 9000** is forwarded via iptables NAT +- **Use Host header** with directory IP for external API calls +- **PAT file**: `/opt/gbo/conf/directory/admin-pat.txt` +- **Admin credentials**: `admin` / `Admin123!` (human user) +- **Database**: `PROD-DIRECTORY` on tables container +- **Zitadel v4.13.1** is the current version