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:
friessn
2026-07-13 06:31:36 +00:00
parent 58983e6855
commit 6c9cd67a08
36 changed files with 579 additions and 245 deletions
@@ -0,0 +1,18 @@
---
- name: Reload gitea user systemd
become_user: "{{ deploy_user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ deploy_uid }}"
systemd:
daemon_reload: true
scope: user
- name: Restart gitea
become_user: "{{ deploy_user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ deploy_uid }}"
systemd:
name: gitea
state: restarted
enabled: true
scope: user
+13 -15
View File
@@ -1,26 +1,24 @@
---
- name: Create Gitea quadlet directory
# Gitea runs rootless as {{ deploy_user }} — see group_vars/all.yml.
- name: Enable linger for {{ deploy_user }} (user services survive logout/reboot)
command: "loginctl enable-linger {{ deploy_user }}"
changed_when: false
- name: Create user Quadlet directory
file:
path: /etc/containers/systemd
path: "/home/{{ deploy_user }}/.config/containers/systemd"
state: directory
mode: "0755"
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
- name: Deploy Gitea container quadlet
template:
src: gitea.container.j2
dest: /etc/containers/systemd/gitea.container
dest: "/home/{{ deploy_user }}/.config/containers/systemd/gitea.container"
owner: "{{ deploy_user }}"
group: "{{ deploy_user }}"
mode: "0644"
notify:
- Reload systemd
- Reload gitea user systemd
- Restart gitea
handlers:
- name: Reload systemd
systemd:
daemon_reload: true
- name: Restart gitea
systemd:
name: gitea
state: restarted
enabled: true
@@ -6,11 +6,13 @@ After=network-online.target
Image=docker.io/gitea/gitea:latest
ContainerName=gitea
PublishPort=127.0.0.1:{{ gitea_http_port }}:3000
Volume={{ gitea_data_dir }}:/data:Z
Environment=USER_UID=1000
Environment=USER_GID=1000
PublishPort={{ gitea_ssh_port }}:22
Volume={{ gitea_data_volume }}:/data
Environment=USER_UID={{ deploy_uid }}
Environment=USER_GID={{ deploy_uid }}
Environment=GITEA__server__DOMAIN={{ gitea_domain }}
Environment=GITEA__server__ROOT_URL=https://{{ gitea_domain }}/
Environment=GITEA__server__SSH_DOMAIN={{ gitea_domain }}
Environment=GITEA__server__HTTP_PORT=3000
Environment=GITEA__packages__ENABLED=true
Environment=GITEA__packages__CHUNKED_UPLOAD_PATH=/data/tmp/package-upload
@@ -20,4 +22,4 @@ Restart=always
TimeoutStartSec=120
[Install]
WantedBy=multi-user.target default.target
WantedBy=default.target