# Zitadel Bootstrap ## 1. Terraform — Vault KV + database engine ```bash vault kv put secret/cloudflare/api-token api-token="" vault kv put secret/postgres/admin username="********" password="" ``` ```bash cd terraform/internal/vault ../../scripts/tofu-versitygw-state apply \ -var="internal_domain=quorate.internal" \ -var='users=[""]' \ -var="admin_user=" ``` ## 2. PostgreSQL — roles and database ```bash cd terraform/internal/postgres ../../scripts/tofu-versitygw-state apply ``` ## 3. Network policies ```bash kubectl --context default apply -f vendor/platform/postgres/network-policies.yaml kubectl --context default apply -f vendor/platform/vault/network-policies.yaml ``` ```bash vault read database/config/postgres ``` ## 4. cert-manager — Cloudflare token + Let's Encrypt issuer ```bash kubectl --context default apply -f vendor/platform/cert-manager/config/vso.yaml kubectl --context default apply -f vendor/platform/cert-manager/config/issuers.yaml ``` ```bash kubectl --context default get secret cloudflare-api-token -n cert-manager ``` ## 5. Gateway R ```bash flux reconcile kustomization platform-cilium-config --context default -n flux-system --with-source ``` The `gateway-relay-tls` Certificate triggers a DNS-01 ACME challenge. Monitor: ```bash kubectl --context default describe certificate gateway-relay-tls -n kube-system ``` Cloudflare declares `auth.quorate.dev` from the OCI relay state in `terraform/external/cloudflare`. ## 6. Zitadel namespace + network policies + VSO ```bash kubectl --context default create namespace zitadel # Pre-create the service account so VSO can authenticate before Helm runs kubectl --context default create serviceaccount zitadel -n zitadel kubectl --context default apply -f vendor/platform/zitadel/network-policies.yaml kubectl --context default apply -f vendor/platform/zitadel/vso.yaml ``` Wait for both secrets: ```bash kubectl --context default get secret zitadel-masterkey -n zitadel kubectl --context default get secret zitadel-db -n zitadel ``` ## 7. Helm install ```bash helm repo add zitadel https://charts.zitadel.com helm upgrade --install zitadel zitadel/zitadel \ --namespace zitadel \ -f vendor/platform/zitadel/values.yaml ``` ## 8. HTTPRoute ```bash kubectl --context default apply -f vendor/platform/zitadel/route.yaml ``` ## 9. Post-deploy — organization and OIDC clients Once Zitadel is up and the IAM admin machine key secret exists, mirror it to Vault for Terraform: ```bash kubectl --context default get secret iam-admin -n zitadel -o jsonpath='{.data.iam-admin\.json}' | base64 -d > iam-admin.json vault kv put secret/zitadel/iam-admin iam-admin.json=@iam-admin.json ``` ```bash cd terraform/internal/zitadel ../../scripts/tofu-versitygw-state apply -var="zitadel_domain=auth.quorate.dev" ``` This creates the primary service organization, the shared service project, and the Forgejo OIDC application. The Forgejo OIDC client material is mirrored into Vault for later VSO sync. Use the non-secret outputs when configuring or verifying Forgejo's OAuth2 authentication source: ```bash tofu output forgejo_oidc_authentication_name tofu output forgejo_oidc_discovery_url tofu output forgejo_oidc_redirect_uri tofu output forgejo_oidc_vault_secret_path ``` The Forgejo authentication source name must stay aligned with the redirect URI: `https://forge.quorate.internal/user/oauth2/Zitadel/callback`.