Skip to content

Phase 1: stand up shared Zitadel + OpenFGA at auth.* / authz.*, wire LiturgicalCalendarAPI as first consumer #1

@JohnRDOrazio

Description

@JohnRDOrazio

Tracks the Phase 1 rollout of the umbrella auth stack scaffolded in 6b3acd4.

Architecture and decisions: see the open-question discussion at CatholicOS/cdcf-website#98. Working assumptions are pinned in auth/README.md; will be revised if the Discussion thread shifts them.

Track 1 — Stand up the shared stack on the VPS

  • DNS: add A/AAAA records for auth.catholicdigitalcommons.org and authz.catholicdigitalcommons.org pointing at the existing VPS public IP.
  • Plesk subdomains: create both subdomains, enable Let's Encrypt, configure nginx reverse-proxy directives per auth/README.md (proxy to 127.0.0.1:8080 and 127.0.0.1:8081 respectively; pass X-Forwarded-Proto: https). (In practice routed via Plesk Docker Proxy Rules to the named containers — see docs/SYSADMIN.md §4.6. Equivalent outcome.)
  • VPS prep: create /var/lib/cdcf-auth/{zitadel-pgdata,zitadel-data,openfga-pgdata} bind-mount targets (zitadel-data must be world-writable per scratch-image PAT constraint). (Switched to host Postgres in PR refactor(auth): use host Postgres + make /opt/cdcf-auth/ paths explicit #2 — only /opt/cdcf-auth/runtime/zitadel-data/ is needed now; the *-pgdata dirs are no longer applicable.)
  • Secrets: copy auth/.env.production.example to .env.production on the VPS; generate ZITADEL_MASTERKEY (32 chars, NEVER rotated) and OPENFGA_PRESHARED_KEY; fill remaining DB passwords + admin credentials.
  • Bring-up: docker compose --env-file .env.production -f docker-compose.prod.yml up -d. Wait for healthchecks.
  • Smoke: curl http://127.0.0.1:8080/debug/ready and curl http://127.0.0.1:8081/healthz return 200. Public URLs serve the Zitadel console (/ui/console/) and OpenFGA health.
  • Backup wiring: install auth/backup/pg-dump.sh at /opt/cdcf-auth/backup/; add cron entry; copy first dump off-server within 24h. Confirm the masterkey is backed up separately, out-of-band. (Script tested manually 2026-05-16; cron not yet wired, no off-server copy yet. See docs/SYSADMIN.md §7.1 for procedure.)

Track 2 — Bootstrap provisioning scripts (currently SKELETON)

The two setup-*.sh scripts are skeletons honouring the --target {local,production} convention from cdcf-website. They document the canonical operations and have the curl-based API helper plumbed, but the per-action calls are marked TODO. To complete:

Track 3 — Hand off LiturgicalCalendarAPI

  • Run the completed provisioning scripts on the VPS.
  • Write auth/handoffs/liturgicalcalendar.md per the template in auth/handoffs/README.md — issuer URL, Org name, Project ID, Client ID, OpenFGA store ID + model ID (all non-secret). Client secret + preshared key delivered out-of-band.
  • Open a follow-up issue on the LiturgicalCalendarAPI repo with the handoff embedded, asking the LitCal maintainer to point its prod env at the shared infra. (Liturgical-Calendar/LiturgicalCalendarAPI#597)

Track 4 — Pre-provision stubs for the other three properties

In the same --create-orgs run, the script also creates:

  • CDCF Org (no Project yet; cdcf-website wiring is deferred — prototype on feature/zitadel-integration needs rework to drop the v2 login UI before it can be merged against the shared infra).
  • BibleGet Org (no Project; BibleGet API at ~/development/BibleGet-I-O/endpoint currently has zero auth wiring — needs OIDC client work in its own repo before it can be wired).
  • OntoKit Org (no Project; OntoKit API has Zitadel client wiring in dev but no prod domain yet — defer until callbacks are stable).

Out of scope for this issue

  • Wiring cdcf-website / BibleGet / OntoKit (each in their own repo, separate phases).
  • E2E browser tests for the login flows (separate concern; LitCal validates JWTs server-side).
  • OpenFGA gRPC port exposure (HTTP-only at authz.*:443 for Phase 1; flip on if a consumer needs it).

Verification

Per auth/README.md:

  1. https://auth.catholicdigitalcommons.org/debug/ready returns 200 from the public internet. ✅
  2. https://auth.catholicdigitalcommons.org/ui/console/ loads; IAM-OWNER credentials log in (forced password change works). ✅
  3. https://authz.catholicdigitalcommons.org/healthz returns 200. ✅
  4. pg_dump cron has produced ≥1 off-server backup of both DBs within 24h. ⏳ (script works manually; cron + off-server not yet wired — see remaining Track 1 checkbox)
  5. Four Orgs visible in the Zitadel console: CDCF, LiturgicalCalendar, BibleGet, OntoKit. ✅
  6. LiturgicalCalendar Org has the LiturgicalCalendarAPI Project + OIDC API app + roles. ✅ (plus the Frontend Web/PKCE app via PR feat(setup-zitadel): --provision-litcal-frontend (Web/PKCE app) + handoff update #6)
  7. OpenFGA liturgical_calendar store exists with the lifted model applied. ✅ (store named LiturgicalCalendar)
  8. Handoff doc exists; follow-up issue opened on the LitCal repo. ✅
  9. Existing https://catholicdigitalcommons.org and https://cms.catholicdigitalcommons.org continue to serve normally (no regression). ✅

Status as of 2026-05-18: only remaining Phase 1 work is wiring the backup cron + off-server copy (Track 1 last checkbox + verification #4). Everything else complete.

Metadata

Metadata

Assignees

No one assigned

    Labels

    authZitadel-related (identity)authzOpenFGA-related (relationship authorization)infraDocker compose, VPS setup, networking, certsphase-1Phase 1 of the rollout (infra + LitCal wiring)trackingUmbrella tracking issue (don't close — gates subtasks)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions