feat(2-Schritt3): nginx-Cutover — App per Token-Link, Admin hinter Authelia

Sicherheits-Architektur umgestellt (live verifiziert):
- App-Routen (/, /ws/) ohne Authelia -> Auth via Capability-Token-Cookie
  (Senioren: Ein-Klick-Link, kein 2FA). Remote-User wird in nginx HART
  geleert (Anti-Spoofing: App vertraut Remote-User von der Proxy-IP).
- /api/admin/* (und /api/admin/log) zusätzlich hinter Authelia (Doppelschutz).
- gate_web_ui: statt SSO-Redirect (würde nach Cutover schleifen) eine
  freundliche "Persönlicher Zugang nötig"-Hinweisseite (401).

Endabnahme durch nginx: Link->303+Cookie, /api/me->200 (kein 2FA),
Admin->302 Authelia, Header-Spoofing->401. DEPLOYMENT.md 2.8 aktualisiert.
Test auf neue Hinweisseite angepasst. 219 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 04:45:11 +02:00
commit 6e824d8f9b
3 changed files with 43 additions and 22 deletions

View file

@ -1019,25 +1019,7 @@ server {
}
# WebSocket-Routen /ws/chat und /ws/voice
location /ws/ {
auth_request /authelia-check;
auth_request_set $user $upstream_http_remote_user;
error_page 401 =302 https://auth.jamulix.de/?rd=$scheme://$http_host$request_uri;
proxy_pass http://127.0.0.1:8003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For "";
proxy_set_header Remote-User $user;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# Admin-Live-Log (WebSocket) — Auth wie unten, aber mit WS-Upgrade wie /ws/.
# OHNE diesen Block bleibt der Log-Tab im Admin-Panel leer ("Verbindungsfehler"),
# weil /api/admin/log sonst in location / ohne Upgrade-Header landet.
# Admin-Live-Log (WebSocket) — hinter Authelia, mit WS-Upgrade.
location = /api/admin/log {
auth_request /authelia-check;
auth_request_set $user $upstream_http_remote_user;
@ -1054,11 +1036,11 @@ server {
proxy_send_timeout 300s;
}
# Alle anderen Routen — Authelia 2FA-Schutz
location / {
# Admin-API — ZUSÄTZLICH hinter Authelia (Doppelschutz). Identität via Remote-User.
location /api/admin/ {
auth_request /authelia-check;
auth_request_set $user $upstream_http_remote_user;
error_page 401 =302 https://auth.jamulix.de/?rd=$scheme://$host$request_uri;
error_page 401 =302 https://auth.jamulix.de/?rd=$scheme://$http_host$request_uri;
proxy_pass http://127.0.0.1:8003;
proxy_http_version 1.1;
@ -1068,6 +1050,33 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Remote-User $user;
}
# Sprach-/Chat-WebSockets — KEIN Authelia. Auth via Token-Cookie (Senioren-Link).
# Remote-User HART LEEREN: sonst könnte ein Client per Header eine Identität
# vortäuschen (die App vertraut Remote-User von der Proxy-IP 127.0.0.1).
location /ws/ {
proxy_pass http://127.0.0.1:8003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For "";
proxy_set_header Remote-User "";
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# App (Senioren) — KEIN Authelia. Auth via Token-Cookie / Ein-Klick-Link
# (https://voice.jamulix.de/?k=<token>). Remote-User HART LEEREN (Anti-Spoofing).
location / {
proxy_pass http://127.0.0.1:8003;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For "";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Remote-User "";
}
}
```