diff --git a/CLAUDE.md b/CLAUDE.md index 2ce79f7..6a2e6cd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -131,7 +131,11 @@ App muss sie **in-place** überschreiben (`open` im Modus `r+`, `flock`, `truncate` — siehe `services/admin.py::_rewrite_env_file`), niemals über Temp-Datei+`rename` (neuer Inode, vom laufenden Mount nicht mehr gesehen). Host-seitige `sed`-Edits in `create_pod_finance.sh` selbst sind unkritisch, -weil das Skript die Container ohnehin bei jedem Lauf neu erstellt. +weil das Skript die Container ohnehin bei jedem Lauf neu erstellt. Für den +Betrieb hinter einem Reverse-Proxy (eine Subdomain, Grafana als +`/grafana/`-Unterpfad) genügen zwei optionale `.env`-Variablen +(`FB_GRAFANA_PUBLIC_URL`, `FB_SESSION_COOKIE_SECURE`) — siehe +`docs/reverse-proxy.md`. **Disaster Recovery = `BIND_DIR`-Backup + Repo + Skript.** Für vollständige Wiederherstellung werden **beide** gebraucht: ein Backup von diff --git a/docs/ARCHITEKTUR.md b/docs/ARCHITEKTUR.md index 584b5ad..fdc0ff4 100644 --- a/docs/ARCHITEKTUR.md +++ b/docs/ARCHITEKTUR.md @@ -196,6 +196,11 @@ sequenceDiagram ## 3. Deployment-Diagramm +> Reverse-Proxy-Betrieb (eine Subdomain, Grafana als `/grafana/`-Unterpfad): +> siehe **`docs/reverse-proxy.md`** (Ausbaustufe 10). Aktivierung rein über +> `.env` (`FB_GRAFANA_PUBLIC_URL`, `FB_SESSION_COOKIE_SECURE`); leer = lokaler +> Direktbetrieb unverändert. + ```mermaid flowchart TB subgraph HOST["Host wlfb (rootless Podman)"] diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md new file mode 100644 index 0000000..37961bc --- /dev/null +++ b/docs/reverse-proxy.md @@ -0,0 +1,91 @@ +# Reverse-Proxy-Betrieb (Ausbaustufe 10) + +Ziel: Erreichbarkeit über **eine** Subdomain +`https://fb.wolfundlaemmlein.de/`, Grafana als Unterpfad `/grafana/`. + +Kette: Internet → **sv003** (Apache, TLS-Terminierung) → WireGuard-VPN → +**sv006** (Traefik, ohne TLS, `10.8.0.6:8080`) → finance_pod +(`127.0.0.1:8096` GUI/API, `127.0.0.1:8097` Grafana). + +Die Proxy-Konfiguration selbst (Traefik, Apache) liegt **außerhalb** dieses +Repos — die folgenden Snippets sind Vorlagen. Tool-seitig genügt es, in der +`.env` unter `~/.local/share/finance_pod/.env` zwei Variablen zu setzen und +`./create_pod_finance.sh` erneut auszuführen. + +## `.env`-Schalter (single-quoted!) + +```sh +FB_GRAFANA_PUBLIC_URL='https://fb.wolfundlaemmlein.de/grafana/' +FB_SESSION_COOKIE_SECURE='true' +``` + +- `FB_GRAFANA_PUBLIC_URL` — öffentliche Grafana-Basis-URL (mit `/grafana/`, + abschließender Slash empfohlen). Bewirkt: + - `create_pod_finance.sh` startet Grafana mit `GF_SERVER_ROOT_URL` + + `GF_SERVER_SERVE_FROM_SUB_PATH=true`; + - interner Health-Check und interne Grafana-API-URL (`FB_GRAFANA_URL`, für + die GUI-Passwortänderung) erhalten automatisch den `/grafana`-Präfix; + - alle GUI-Links/iframes zeigen auf die öffentliche URL statt `:8097`. + - **Leer lassen** = unveränderter Direktbetrieb auf `127.0.0.1`. +- `FB_SESSION_COOKIE_SECURE='true'` — Session-Cookie nur über HTTPS. Vor der + Internet-Freigabe setzen. Default (leer/`false`) für lokalen HTTP-Zugriff. + +Nach dem Editieren: `./create_pod_finance.sh` (übernimmt die `.env` +unverändert, baut Pod/Container neu). HTTPS/HSTS und Login-Rate-Limiting sind +Proxy-Sache (Apache auf sv003 bzw. fail2ban) — außerhalb dieses Repos. + +## Traefik (sv006) — Datei-Provider, Beispiel + +Kein Prefix-Stripping für `/grafana` (Grafana serviert dank +`serve_from_sub_path` selbst unter dem Sub-Pfad): + +```yaml +# /etc/traefik/dynamic/finance.yml +http: + routers: + finance-grafana: + rule: "Host(`fb.wolfundlaemmlein.de`) && PathPrefix(`/grafana`)" + priority: 20 + service: finance-grafana + entryPoints: [web] + finance-app: + rule: "Host(`fb.wolfundlaemmlein.de`)" + priority: 10 + service: finance-app + entryPoints: [web] + services: + finance-grafana: + loadBalancer: + servers: + - url: "http://127.0.0.1:8097" + finance-app: + loadBalancer: + servers: + - url: "http://127.0.0.1:8096" +``` + +## Apache (sv003) — VHost, Beispiel + +TLS terminiert hier; Weiterleitung an Traefik über die WireGuard-IP. `X- +Forwarded-Proto https` ist wichtig, damit uvicorn (mit `--proxy-headers`) das +öffentliche Schema erkennt: + +```apache + + ServerName fb.wolfundlaemmlein.de + + SSLEngine on + SSLCertificateFile /etc/letsencrypt/live/fb.wolfundlaemmlein.de/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/fb.wolfundlaemmlein.de/privkey.pem + + ProxyPreserveHost On + RequestHeader set X-Forwarded-Proto "https" + ProxyPass / http://10.8.0.6:8080/ + ProxyPassReverse / http://10.8.0.6:8080/ + +``` + +## Zurück in den Lokalbetrieb + +`FB_GRAFANA_PUBLIC_URL` und `FB_SESSION_COOKIE_SECURE` aus der `.env` +entfernen (oder leeren) und `./create_pod_finance.sh` erneut ausführen.