diff --git a/homeassistant/INTERNET_ZUGRIFF_EINRICHTEN.md b/homeassistant/INTERNET_ZUGRIFF_EINRICHTEN.md index 552990d..c8d0694 100644 --- a/homeassistant/INTERNET_ZUGRIFF_EINRICHTEN.md +++ b/homeassistant/INTERNET_ZUGRIFF_EINRICHTEN.md @@ -133,13 +133,23 @@ zusätzliche Härtung, kein Ersatz dafür. Durchprobieren, ersetzt aber nicht den Token. **Nginx Proxy Manager, Proxy Host:** -- **"Force SSL"** und **"Block Common Exploits"** aktivieren. -- Nach dem Einfügen des Codeblocks aus `REVERSE_PROXY.md` in *Advanced*: prüfen, ob NPM die - Konfiguration ohne Fehler übernimmt. NPM erzeugt aus dem *Details*-Tab selbst schon einen - `location /`-Block - der kann sich mit dem abschließenden `location / { return 404; }` aus der - eingefügten Freigabeliste überschneiden. Meldet NPM beim Speichern einen Konfigurationsfehler, diesen - letzten Block aus dem eingefügten Code weglassen (NPMs eigener Standard-Block fängt dann alles - Nicht-Gematchte ab, sofern die vorderen `location`-Blöcke wie vorgesehen zuerst greifen). +- **"Block Common Exploits"** und **"Websockets Support"** aktivieren. **"Force SSL"** braucht ihr nur, + wenn ihr dem Host ein eigenes Zertifikat gebt - bei "HTTP Only" (siehe SSL-Abschnitt oben, kein + eigenes Zertifikat nötig, da Cloudflare die Verschlüsselung nach außen übernimmt) ist die Option + ohnehin ausgegraut. +- ⚠️ **Echter, live gefundener Fehler (2026-08-28) - `include conf.d/include/proxy.conf;` NICHT + verwenden.** Der Codeblock in `REVERSE_PROXY.md` enthielt ursprünglich diese Zeile in jedem + `location`-Block (Standard-Praxis bei der vanilla jc21-nginx-proxy-manager-Doku). Beim + `homeassistant-apps/app-cloudflared`-Gegenstück - genauer: bei diesem NPM-Add-on + (`homeassistant-apps`, Frenck) - enthält diese geteilte Datei selbst bereits ein `proxy_pass`, + zusammen mit dem eigenen `proxy_pass` im Block ergibt das `nginx: [emerg] "proxy_pass" directive is + duplicate` - die Konfiguration lädt dann gar nicht mehr (nginx startet nicht, das Add-on + crash-loopt). Symptom, falls das passiert: **alle** Pfade liefern "Not Found", auch die, die + eigentlich erlaubt sein sollten, und das Protokoll zeigt diese `[emerg]`-Zeile beim Start. Ein + einfacher Neustart des Add-ons behebt das NICHT (die Datei bleibt kaputt) - nötig war eine komplette + Deinstallation + Neuinstallation des Add-ons. Der aktuelle, korrigierte Codeblock in + `REVERSE_PROXY.md` verzichtet deshalb auf die `include`-Zeile und schreibt die nötigen + `proxy_set_header`-Zeilen direkt in jeden Block. **Zugriffstoken:** - **Pro Gerät ein eigener Token**, nicht denselben auf mehreren Handys - dann lässt sich ein verlorenes diff --git a/homeassistant/REVERSE_PROXY.md b/homeassistant/REVERSE_PROXY.md index e81500b..cde9c2a 100644 --- a/homeassistant/REVERSE_PROXY.md +++ b/homeassistant/REVERSE_PROXY.md @@ -74,27 +74,46 @@ handeln (kein Absturz, siehe `AGENTS.md` Abschnitt L). ## Nginx Proxy Manager -Im Add-on unter *Hosts → Proxy Hosts → Edit → Advanced* eintragen. Ziel ist der interne Name der -Home-Assistant-Instanz (im Supervisor-Netz `homeassistant:8123`). +Im Add-on unter *Hosts → Proxy Hosts → Edit → (Zahnrad-Tab) "Custom Nginx Configuration"* eintragen. +Ziel ist der interne Name der Home-Assistant-Instanz (im Supervisor-Netz `homeassistant:8123`). + +> **Live gefundener Fehler (2026-08-28), deshalb ohne `include conf.d/include/proxy.conf;`:** die +> ursprüngliche Fassung dieses Blocks nutzte diese Zeile pro Block (Standard-Praxis der vanilla +> jc21-nginx-proxy-manager-Doku, um die üblichen `X-Forwarded-*`-Header zu setzen). Beim hier +> verwendeten NPM-Add-on (`homeassistant-apps/addon-nginx-proxy-manager`, Frenck) enthält diese +> geteilte Datei selbst bereits ein `proxy_pass` - zusammen mit dem eigenen `proxy_pass` im Block +> ergibt das `nginx: [emerg] "proxy_pass" directive is duplicate in +> /etc/nginx/conf.d/include/proxy.conf:7`, nginx startet dann gar nicht mehr (dauerhaft, ein bloßer +> Neustart des Add-ons behebt es nicht - nötig war eine komplette Deinstallation + Neuinstallation). +> Die Header stehen deshalb unten direkt ausgeschrieben statt über das `include`. ```nginx # Reihenfolge zählt: die erlaubenden Blöcke stehen vor dem pauschalen Verbot. location = /api/ { proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } location ~ ^/api/states/sensor\.audi_dashboard_[a-z0-9_]+$ { limit_except GET { deny all; } proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } location ~ ^/api/services/audi_dashboard/[a-z_]+$ { limit_except POST { deny all; } proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } # Genau ein Dienst außerhalb der eigenen Domain - siehe "Ehrliche @@ -103,7 +122,10 @@ location ~ ^/api/services/audi_dashboard/[a-z_]+$ { location = /api/services/homeassistant/restart { limit_except POST { deny all; } proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } location = /api/websocket { @@ -112,7 +134,10 @@ location = /api/websocket { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } # Das OTA-Oberflächen-Bündel für die native App (siehe Hinweis oben - das ist @@ -120,14 +145,20 @@ location = /api/websocket { location ^~ /audi_dashboard_static/app/ { limit_except GET { deny all; } proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } # Die Fotos der Fahrzeuge, die die App anzeigt. Nur Lesen, nur Bilder. location ~ ^/local/bilder/[a-z0-9_-]+\.(webp|png|jpg|svg)$ { limit_except GET { deny all; } proxy_pass http://homeassistant:8123; - include conf.d/include/proxy.conf; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } # Alles Übrige: nicht durchlassen. @@ -136,6 +167,41 @@ location / { } ``` +> **Wichtig, live erlebt (2026-08-28):** Wird dieser letzte Block beim Testen/Debuggen mal entfernt +> (z. B. um eine andere Theorie zu prüfen), unbedingt danach wieder einfügen und speichern - ohne ihn +> landet jede nicht explizit erlaubte Anfrage (auch die reine Root-Adresse `/`) direkt bei Home +> Assistant und zeigt dessen echte Anmeldemaske, was genau die Einschränkung aufhebt, die dieser +> ganze Aufbau eigentlich herstellen soll. Test: `https:///` (ohne Pfad) muss `404` liefern, +> niemals die HA-Anmeldemaske. + +## Home Assistant muss dem Proxy vertrauen (nötig, nicht optional) + +**Bestätigt korrekt, Stand 2026-08-28.** Beim ersten Live-Test kamen alle Anfragen (egal ob `/api/`, +`/lovelace`, oder sogar zufällige Bot-Scan-Pfade wie `/.env`) mit exakt derselben, byte-identischen +Fehlerantwort zurück (NPMs eigene generische Fehlerseite, nicht Home Assistants). Das lag daran, dass +Home Assistant die Anfragen grundsätzlich ablehnte, weil der Proxy nicht als vertrauenswürdig +eingetragen war - NPM fing Home Assistants Fehlerantwort dabei ab und zeigte seine eigene Seite, was +die eigentliche Ursache verdeckte. + +Wichtig: seit einer HA-Version wird die `http:`-Konfiguration aus `configuration.yaml` **automatisch +in einen UI-verwalteten Config-Entry migriert und danach ignoriert** (Reparatur-Hinweis "HTTP-YAML- +Konfiguration wird nach Migration ignoriert"). Der YAML-Block unten dient nur noch der +Dokumentation/als Referenz - tatsächlich gesetzt wird es unter **Einstellungen → System → Netzwerk → +Reverse-Proxy**: "X-Forwarded-For vertrauen" aktivieren, `172.30.33.0/24` unter "Vertrauenswürdige +Proxys" eintragen, speichern (löst automatisch einen HA-Neustart aus, mit Bestätigungs-Dialog). + +```yaml +# Nur noch als Referenz - wird bei aktueller HA-Version über die UI gesetzt, siehe oben. +http: + use_x_forwarded_for: true + trusted_proxies: + - 172.30.33.0/24 +``` +(`172.30.33.0/24` ist das Supervisor-interne Docker-Netz, in dem auch Nginx Proxy Manager läuft.) + +**Live verifiziert:** `https://datametric360.de/api/` liefert jetzt `401 Unauthorized` (korrekt, ohne +Token) statt der generischen NPM-Fehlerseite - die Anfrage kommt vollständig bis Home Assistant durch. + **Ein einziger Hostname genügt.** Die frühere Überlegung, App und Schnittstelle auf zwei getrennte Hostnamen zu legen (`datametric360.de` für die App, `api.datametric360.de` für die Schnittstelle), stammte aus der Annahme, die App würde selbst als Web-Build unter einer eigenen Adresse ausgeliefert