Rebuild auth on Keycloak OIDC, fix rootless Ansible deploy
Replaces the single shared HTTP Basic service-account credential (which caused a production outage from a username mismatch) with per-user login: Keycloak (already running on this VM for gcnm, now also fronted on auth.friessn.de with its own "homekeeper" realm) authenticates the user once via the landing page, FastAPI verifies the OIDC id_token and mints its own signed session JWT as a cookie, and both Shiny apps forward that per-session token as a Bearer credential instead of a static shared one. Authorization is a simple ALLOWED_USERS allowlist; the old auth.users table and bcrypt seeding are gone entirely. Also carries forward the in-progress rootless Podman/Quadlet migration (gitea, homekeeper, podman roles) and fixes a pre-existing bug where each role's handlers were malformed inside tasks/main.yml instead of their own handlers/main.yml, which broke ansible-playbook entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FbiCdckkTX2HyAkyi1R39d
This commit is contained in:
@@ -2,28 +2,71 @@
|
||||
# Main domain (apps + landing page)
|
||||
domain: home.friessn.de
|
||||
|
||||
# Everything runs rootless — one Linux user owns all Podman Quadlets
|
||||
# (systemd --user units under ~/.config/containers/systemd), started via
|
||||
# `loginctl enable-linger` so they survive logout/reboot without root.
|
||||
deploy_user: nico
|
||||
deploy_uid: 1000
|
||||
|
||||
# Gitea on a subdomain — cleaner than a subpath, required for container registry
|
||||
gitea_domain: git.friessn.de
|
||||
gitea_data_dir: /opt/gitea
|
||||
gitea_data_volume: gitea-data # named Podman volume, not a bind mount (avoids rootless UID mapping issues)
|
||||
gitea_http_port: 3000 # internal port, nginx proxies HTTPS → here
|
||||
gitea_admin_user: nico
|
||||
gitea_ssh_port: 2222 # published directly (nginx can't proxy SSH)
|
||||
gitea_admin_user: friessn # actual Gitea account created during the install wizard
|
||||
gitea_admin_password: CHANGE_ME # replace — set via ansible-vault in production
|
||||
gitea_admin_email: nico.friess@googlemail.com
|
||||
|
||||
# Container registry — Gitea's built-in OCI registry, same host as Gitea
|
||||
# Images: git.friessn.de/nico/homekeeper-api:latest
|
||||
# Container registry — Gitea's built-in OCI registry, same host as Gitea, over HTTPS (443)
|
||||
# Images: git.friessn.de/friessn/homekeeper-api:latest
|
||||
registry_host: "{{ gitea_domain }}"
|
||||
registry_user: "{{ gitea_admin_user }}"
|
||||
registry_token: CHANGE_ME # Gitea API token with package:write — set after first Gitea start
|
||||
registry_token: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
33626439663535643963613436373132336333633839613965396539653834313831383039323961
|
||||
3339613430323237636532663665313331303735623137660a613032306362343435633034383965
|
||||
61383131393939393561366335376339343432636431663033363036346337633865363561303238
|
||||
3339313363656137380a663264346666346166663362656638343838643333626438646162643835
|
||||
39656564316130383766656364303035343061653164356664643433336531363334396530376432
|
||||
3162326539326134323639363661363165323632383932623434
|
||||
|
||||
# Homekeeper app
|
||||
homekeeper_data_dir: /opt/homekeeper
|
||||
homekeeper_db_volume: homekeeper-db-data # named Podman volume
|
||||
db_name: homestead
|
||||
db_user: homestead
|
||||
db_password: CHANGE_ME # replace — set via ansible-vault in production
|
||||
api_user: homestead
|
||||
api_pass: CHANGE_ME # replace
|
||||
initial_users: "nico:CHANGE_ME" # user:password pairs for API auth
|
||||
|
||||
# Auto-update timer interval (OnCalendar syntax)
|
||||
# Auth — Keycloak (already running on this VM for the unrelated gcnm app,
|
||||
# published on 127.0.0.1:8080) acts as OIDC identity provider, exposed here
|
||||
# on its own subdomain with its own realm so it's cleanly separated from
|
||||
# gcnm's realm. FastAPI verifies the Keycloak login once via the "homekeeper"
|
||||
# realm, then mints its own session JWT — see api/app/auth.py.
|
||||
# NOTE: the Keycloak container itself is not managed by this repo/role — only
|
||||
# the nginx site + the "homekeeper" realm/client (created manually in the
|
||||
# Keycloak admin console) belong to this setup.
|
||||
keycloak_domain: auth.friessn.de
|
||||
keycloak_realm: homekeeper
|
||||
# This Keycloak instance serves under a /auth path prefix (KC_HTTP_RELATIVE_PATH=/auth
|
||||
# in gcnm's docker-compose setup) — not at root.
|
||||
oidc_issuer_url: "https://{{ keycloak_domain }}/auth/realms/{{ keycloak_realm }}"
|
||||
oidc_client_id: homekeeper
|
||||
oidc_client_secret: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
66323965333830653838356233623461323835303663353530396166653330303130616231323262
|
||||
3233626366633532643434326338313835646533343934640a333037646138393531613730616633
|
||||
64653330623639376164353033663061636436323465646662333934306337353765343739313561
|
||||
3631333636643965370a663464333430306539396164363466633636643466383461636463626631
|
||||
30343732363664356165363565393565346439646235313637346164376265326635613132663132
|
||||
6232663636656233653466393338333532383764616633653234
|
||||
session_jwt_secret: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
64613365363266313061396438313965646462313630636631353236353032383532376631303138
|
||||
6663626664346538363464386333383136306165343163320a653763633839353637613136333464
|
||||
62373231363664633935373632346161613865623930613436306661323439656462323538623864
|
||||
6136343462376436320a666463346530653062323431626135666665373135393262633766353264
|
||||
65303164373366393635653964316664633031313536383965353330343936623532
|
||||
allowed_users: "nico" # comma-separated Keycloak usernames allowed to log in
|
||||
|
||||
# Auto-update timer interval (OnCalendar syntax) — rootless uses podman-auto-update.timer
|
||||
# in the user systemd instance, same schedule override mechanism as the system one.
|
||||
autoupdate_schedule: "*:*:0/10" # every 10 seconds
|
||||
|
||||
Reference in New Issue
Block a user