--- # ============================================================================= # GENERATED FILE — DO NOT EDIT BY HAND. # # source: platform/keycloak/keycloak-realm-import.yaml (spec.realm.clients) # regenerate: python3 ci/render-keycloak-client-urls.py --write # gated by: conformance/tests/l0-static/keycloak-client-secret-reconciler # (runs this renderer with --check on every merge) # # WHAT THIS IS: the DESIRED STATE for every environment-derived client URL in the # `homelab` realm — redirectUris, webOrigins, rootUrl, baseUrl, adminUrl. The # client-secret reconciler CronJob mounts it and makes the live realm match it. # # WHY IT IS A SEPARATE OBJECT: the realm import is a ONE-SHOT that never re-runs # once Done=True, so a redirect URI edited in git never reaches the realm. Prod's # stored redirect URIs were measured still pointing at the pre-migration hostname # while git declared the new one, and every OIDC login would have failed with a # redirect_uri mismatch. The reconciler is the level-triggered loop that closes # that; this file is what it reconciles TOWARDS. # # WHY IT IS GENERATED AND NOT AUTHORED: a hand-written copy of every public # hostname would be a second source of truth, free to disagree with the realm # import. It is rendered from the import and the render is gated, so the two # cannot drift. URL strings are copied VERBATIM — if the source uses a # ${BASE_DOMAIN} token it appears here unchanged, and both files are substituted # by the SAME Flux Kustomization (./platform-config), so the domain is decided in # exactly one place. # # A field that is NOT declared on a client in the realm import is simply ABSENT # here, and the reconciler leaves it alone. Absence means UNMANAGED, never # "force to empty". # ============================================================================= apiVersion: v1 kind: ConfigMap metadata: name: keycloak-client-urls namespace: keycloak labels: app.kubernetes.io/name: keycloak-client-urls app.kubernetes.io/part-of: keycloak data: client-urls.json: | { "crafty": { "redirectUris": [ "https://crafty.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://crafty.${BASE_DOMAIN}" ] }, "gitea": { "redirectUris": [ "https://gitea.${BASE_DOMAIN}/user/oauth2/keycloak/callback" ], "webOrigins": [ "https://gitea.${BASE_DOMAIN}" ] }, "grafana": { "redirectUris": [ "https://grafana.${BASE_DOMAIN}/login/generic_oauth" ], "webOrigins": [ "https://grafana.${BASE_DOMAIN}" ] }, "headlamp": { "redirectUris": [ "https://headlamp.${BASE_DOMAIN}/oidc-callback" ], "webOrigins": [ "https://headlamp.${BASE_DOMAIN}" ] }, "jackett": { "redirectUris": [ "https://jackett.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://jackett.${BASE_DOMAIN}" ] }, "kubernetes": { "redirectUris": [ "http://localhost:8000", "http://localhost:8000/", "http://localhost:18000", "http://localhost:18000/", "http://127.0.0.1:8000", "http://127.0.0.1:8000/", "http://127.0.0.1:18000", "http://127.0.0.1:18000/" ], "webOrigins": [ "http://localhost", "http://127.0.0.1" ] }, "nextcloud": { "redirectUris": [ "https://nextcloud.${BASE_DOMAIN}/apps/user_oidc/code" ], "webOrigins": [ "https://nextcloud.${BASE_DOMAIN}" ] }, "oauth2-proxy": { "redirectUris": [ "https://*.${BASE_DOMAIN}/oauth2/callback", "https://auth.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://*.${BASE_DOMAIN}" ] }, "pihole": { "redirectUris": [ "https://pihole.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://pihole.${BASE_DOMAIN}" ] }, "qbittorrent": { "redirectUris": [ "https://qbittorrent.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://qbittorrent.${BASE_DOMAIN}" ] }, "radarr": { "redirectUris": [ "https://radarr.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://radarr.${BASE_DOMAIN}" ] }, "semaphore": { "redirectUris": [ "https://semaphore.${BASE_DOMAIN}/api/auth/oidc/keycloak/redirect" ], "webOrigins": [ "https://semaphore.${BASE_DOMAIN}" ] }, "sonarr": { "redirectUris": [ "https://sonarr.${BASE_DOMAIN}/oauth2/callback" ], "webOrigins": [ "https://sonarr.${BASE_DOMAIN}" ] } }