REVERSE_PROXY.md verwies auf INTERNET_ZUGRIFF_EINRICHTEN.md, das nie geschrieben wurde - jetzt vorhanden (Cloudflare-Konto, Nameserver-Umstellung, Cloudflared/NPM-Add-ons, Pfad-Freigabeliste eintragen, Prüfung). Dabei einen echten Fehler in der Freigabeliste gefunden: sie ging noch von einem companion-app-Web-Build unter /local/dm360/ aus (Planungsstand 2026-08-11) - das wurde nie gebaut, die App ist nativ/sideload-only. Ersetzt durch den tatsächlichen Fernbedarf: das OTA-Bündel unter /audi_dashboard_static/app/* (@capgo/capacitor-updater). Damit genügt auch ein einziger Hostname statt der ursprünglich erwogenen App-/API-Trennung. COMPANION_APP_ARCHITECTURE.md §5 und AGENTS.md entsprechend nachgezogen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9.7 KiB
Reverse-Proxy: Pfad-Freigabeliste für DataMetric360
Vorbereitet, noch nicht in Betrieb. Gehört zu ../COMPANION_APP_ARCHITECTURE.md §4. Reverse Proxy
ist entschieden: Nginx Proxy Manager (Add-on), auf demselben Host wie Home Assistant selbst. Die
konkreten Einrichtungsschritte (Cloudflare-Konto, Nameserver-Umstellung, Add-ons, ...) stehen in
INTERNET_ZUGRIFF_EINRICHTEN.md - dieses Dokument ist nur die
technische Pfad-Freigabeliste selbst, die dort im letzten Schritt eingetragen wird.
Ziel: Die App erreicht Home Assistant von unterwegs, ohne dass Home Assistant selbst im Internet steht. Dazu ein Cloudflare-Tunnel (baut nur nach außen auf, kein Port am Router) auf einen Reverse Proxy, der ausschließlich die unten aufgeführten Pfade durchlässt.
2026-08-28 aktualisiert: die ursprüngliche Fassung dieses Dokuments ging noch von den pyscript-Zeiten aus (
pyscript.audi_dashboard_*,pyscript.reifen_*,/api/services/pyscript/...). Seit der Umstellung auf eine native Integration (2026-08-23, sieheAGENTS.mdAbschnitt H) heißen Entitätensensor.audi_dashboard_*und Diensteaudi_dashboard.<name>- keine doppelten Präfixe mehr. Die Regeln unten sind auf den aktuellen Stand korrigiert und um zwei seither neu hinzugekommene Bedarfe ergänzt (homeassistant.restartfürs Selbst-Update, sowie das OTA-Bündel unter/audi_dashboard_static/app/*- beide fehlten in der alten Fassung ersatzlos, ohne sie hätte weder der Update-Neustart-Knopf noch ein OTA-Update über den Tunnel funktioniert).Zweite Korrektur, selber Tag: die erste Überarbeitung übernahm noch ungeprüft die alte Annahme aus der frühen Planungsphase (2026-08-11), die App würde als eigener Web-Build unter
/config/www/dm360/bzw./local/dm360/ausgeliefert. Das wurde nie gebaut - die Distributionsart ist seit der Architekturentscheidung "sideload only" (sieheCOMPANION_APP_ARCHITECTURE.md§1) eine native Capacitor-App, direkt per Xcode aufs Gerät geladen, nicht über HA im Browser aufgerufen. Ein/local/dm360/*-Pfad existiert auf dieser Instanz nicht und wird nie gebraucht. Was die native App stattdessen tatsächlich extern erreichen muss, ist ihr eigener Oberflächen-Nachlieferweg (OTA,@capgo/capacitor-updater, sieheAGENTS.mdAbschnitt "Deployed-parity"-Unterabschnitt): das Bündel liegt unter/audi_dashboard_static/app/bundle.zip, ausgeliefert von der Integration selbst (custom_components/audi_dashboard/frontend/app/,const.py'sBUENDEL_URL) - dieselbebasisUrl, die die App auch für ihre normalen API-Aufrufe verwendet (ota.ts'sbuendelAnwenden()), also derselbe Tunnel-Hostname, kein zweiter. Die Regel unten ist entsprechend ersetzt, nicht nur umbenannt.
Was die App wirklich braucht
Aus dem tatsächlichen Code der Datenschicht (companion-app/src/api/rest.ts, index.ts) abgeleitet,
nicht geschätzt - dort gibt es genau drei REST-Aufrufmuster plus WebSocket:
| Methode | Pfad | Wofür |
|---|---|---|
GET |
/api/ |
Verbindungsprüfung bei der Ersteinrichtung |
GET |
/api/states/sensor.audi_dashboard_* |
Profil, Fahrten, Tankvorgänge, Status, Batterieverlauf, Belegergebnis, Importstatus, App-Version, Reifen-Kilometerstände |
POST |
/api/services/audi_dashboard/* |
alle schreibenden Vorgänge (Fahrt/Tankvorgang anlegen/ändern, CSV-/Historien-Import, Update prüfen/installieren, ...) |
POST |
/api/services/homeassistant/restart |
genau ein Dienst außerhalb der eigenen Domain - der "Jetzt neu starten"-Knopf nach einem Integrations-Update (siehe AGENTS.md Abschnitt L) |
GET (Upgrade) |
/api/websocket |
Live-Aktualisierung |
GET |
/audi_dashboard_static/app/* |
das OTA-Oberflächen-Bündel (bundle.zip) für die native App - ohne diesen Pfad findet ein Update aus der Ferne nicht statt (die App selbst läuft nativ auf dem Gerät, wird nicht über diesen Pfad "geladen") |
GET |
/local/bilder/*.{webp,png,jpg,svg} |
Fahrzeugfotos, die die App anzeigt |
Alles andere wird geblockt, insbesondere /auth/*, /lovelace*, /config*, /api/config,
/api/history*, /developer-tools* und die Home-Assistant-Oberfläche selbst.
Ehrliche Einschränkung
Der WebSocket lässt sich nicht pfadgenau beschneiden. Nach auth_ok kann über /api/websocket
grundsätzlich jeder Zustand gelesen werden, nicht nur die audi_dashboard-Entitäten. Die Freigabeliste
ist an dieser Stelle also grobkörniger als beim REST-Zugriff.
Was bleibt: Ohne gültigen Token kommt gar keine Verbindung zustande, und ein verlorenes Gerät wird durch Zurückziehen genau seines Tokens ausgesperrt. Das ist die im Architekturdokument bewusst akzeptierte Abwägung - sie sollte nur nicht in Vergessenheit geraten.
Wer sie nicht eingehen will, hat eine Alternative: den WebSocket weglassen und die App auf regelmäßiges Abfragen umstellen. Kostet Akku und Datenvolumen, verkleinert die Angriffsfläche aber auf die exakt aufgeführten REST-Pfade.
homeassistant.restart verdient eine eigene Erwähnung: wer den Token besitzt, kann damit die gesamte
Home-Assistant-Instanz neu starten, nicht nur etwas im Rahmen dieser App. Dasselbe gilt lokal schon
heute (derselbe Token, dieselbe Berechtigung) - der Tunnel ändert am Berechtigungsumfang nichts, nur am
Netzwerkpfad. Wer das nicht mit ausliefern will: den Block für homeassistant/restart unten weglassen -
der Update-Knopf zeigt dann nach einem Update lediglich "bitte manuell neu starten" statt selbst zu
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).
# 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;
}
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;
}
location ~ ^/api/services/audi_dashboard/[a-z_]+$ {
limit_except POST { deny all; }
proxy_pass http://homeassistant:8123;
include conf.d/include/proxy.conf;
}
# Genau ein Dienst außerhalb der eigenen Domain - siehe "Ehrliche
# Einschränkung" oben, wer ihn nicht mit ausliefern will, lässt diesen
# Block weg.
location = /api/services/homeassistant/restart {
limit_except POST { deny all; }
proxy_pass http://homeassistant:8123;
include conf.d/include/proxy.conf;
}
location = /api/websocket {
proxy_pass http://homeassistant:8123;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
include conf.d/include/proxy.conf;
}
# Das OTA-Oberflächen-Bündel für die native App (siehe Hinweis oben - das ist
# NICHT die App selbst, die läuft nativ; nur ihr nachladbares HTML/CSS/JS).
location ^~ /audi_dashboard_static/app/ {
limit_except GET { deny all; }
proxy_pass http://homeassistant:8123;
include conf.d/include/proxy.conf;
}
# 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;
}
# Alles Übrige: nicht durchlassen.
location / {
return 404;
}
Ein einziger Hostname genügt. Die frühere Überlegung, App und Schnittstelle auf zwei getrennte
Hostnamen zu legen (datametric360.app für die App, api.datametric360.app für die Schnittstelle),
stammte aus der Annahme, die App würde selbst als Web-Build unter einer eigenen Adresse ausgeliefert
(siehe Korrektur-Hinweis oben) - das entfällt mit der nativen Distribution ersatzlos. Es gibt nur noch
eine Adresse, die überhaupt gebraucht wird: die, die die App beim Einrichten als "Server-Adresse"
bekommt, und über die sie sowohl die API-Aufrufe als auch das OTA-Bündel erreicht. Ein zweiter Hostname
wäre zusätzlicher Aufwand ohne Gegenwert.
Nach der Einrichtung prüfen
Von einem Netz ohne VPN, etwa über Mobilfunk (Hostnamen unten sind Platzhalter - eintragen, was bei der Einrichtung tatsächlich gewählt wurde):
API=https://datametric360.app
T=<Zugriffstoken>
# muss gehen
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" "$API/api/"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" \
"$API/api/states/sensor.audi_dashboard_profil"
# kein Token nötig - statische Auslieferung, kein API-Aufruf
curl -s -o /dev/null -w '%{http_code}\n' "$API/audi_dashboard_static/app/bundle.zip"
# muss 404 oder 403 liefern
curl -s -o /dev/null -w '%{http_code}\n' "$API/auth/authorize"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" "$API/api/config"
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $T" \
"$API/api/states/sensor.audi_rs_4_avant_mileage"
# ohne Token: 401, nicht 200
curl -s -o /dev/null -w '%{http_code}\n' "$API/api/states/sensor.audi_dashboard_profil"
Zusätzlich: Port 8123 darf von außen gar nicht antworten.
Noch offen
Siehe INTERNET_ZUGRIFF_EINRICHTEN.md für den vollständigen,
geordneten Ablauf - kurz zusammengefasst bleibt vor der ersten echten Nutzung dieser Liste offen:
- Cloudflare-Konto anlegen,
datametric360.app-Zone hinzufügen - Nameserver von
datametric360.appbei all-inkl auf Cloudflare umstellen („Full setup") - Cloudflared- und Nginx-Proxy-Manager-Add-ons installieren, Tunnel + öffentlichen Hostnamen einrichten
https://datametric360.appals Server-Adresse in der App eintragen (jedes Gerät, beim Einrichten)