diff --git a/docs/handoff-20260901-tp16.3-paragraph5-flip-durch.md b/docs/handoff-20260901-tp16.3-paragraph5-flip-durch.md index 834db83..afc0bb9 100644 --- a/docs/handoff-20260901-tp16.3-paragraph5-flip-durch.md +++ b/docs/handoff-20260901-tp16.3-paragraph5-flip-durch.md @@ -43,9 +43,14 @@ Git-Pfad. **Ursache:** MariaDB (LXC **302**) hatte `skip-name-resolve` auskommen `302 mariadb`, `102 mqtt5`, `106 influxdb2`, `107 redis`, `150 iob-exposed`. **Nachher: Lookup 21–24 ms; gitea 0 von 25 Proben langsam**, langsamste 75 ms. -⚠️ **Strukturell offen:** `skip-name-resolve` ist weiter **aus**. Setzen bricht alle Grants, die auf -**Hostnamen** statt IPs lauten ⇒ vorher `mysql.user` lesen. **DB-Zugang fehlt** (`root@localhost` -ohne Passwort verweigert) — das ist der nächste konkrete Schritt. +✅ **Beseitigt 2026-09-01:** `skip-name-resolve` aktiviert (Drop-in +`/etc/mysql/mariadb.conf.d/90-skip-name-resolve.cnf`, `@@skip_name_resolve=1`). `mysql.user` vorher +geprüft — **kein Hostname-Grant**, alle `%`/IP/`localhost`, also gefahrlos. Wirkung: gitea/vw/hass +je 0 von 12 frischen Anfragen langsam, max 0,25 s. Der Reverse-Lookup ist damit nicht mehr schnell, +sondern **abgeschafft**. +🔴 **Dabei ist das root-DB-Passwort ins Transkript geraten** (`.my.cnf` mit `password ` ohne `=`, +Maskierung ankerte auf `=`) — **TP30 Posten #6**, zu rotieren. Ausserdem: **LXC 302 war 100 % voll**, +`+30G` online ⇒ 95 GB / 69 %; die Ursache (HA-Recorder, 41 GB `states`) ist **TP40**. --- @@ -101,7 +106,8 @@ alte §5.3-Punkt „Caddy sieht den Request" konnte nie funktionieren. fehlt). **Punkt 2 (`networking.service`) ist am 2026-09-01 bereits erledigt** — offen bleiben `skip-name-resolve` und der Resolver-Sweep als **wiederkehrende** Kontrolle, auch über die NAS-Container. -3. **TP30:** die zwei Nautobot-Tokens rotieren (vom User vertagt, weiterhin offen). -4. **TP14.4:** ohne Service-Token für die Wildcard-App ist `n8n` von außen nicht bis zum Origin prüfbar. -5. **Caddy-Access-Log** (TP31/TP34): der öffentliche Reverse Proxy protokolliert keine Requests. -6. `mcp/mikromcp/config/routers.yaml` meldet weiter `rosVersion: "7.24"`, live ist `7.24.1`. +3. **TP30:** Nautobot-Tokens (#5) + **MariaDB-root-Passwort (#6, neu 09-01)** rotieren. +4. **TP40:** HA-Recorder-Retention — die 41-GB-`states`-Tabelle beschneiden (angelegt 09-01). +5. **TP14.4:** ohne Service-Token für die Wildcard-App ist `n8n` von außen nicht bis zum Origin prüfbar. +6. **Caddy-Access-Log** (TP31/TP34): der öffentliche Reverse Proxy protokolliert keine Requests. +7. `mcp/mikromcp/config/routers.yaml` meldet weiter `rosVersion: "7.24"`, live ist `7.24.1`. diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 61810dd..31a157b 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -41,6 +41,14 @@ liest, liest ihn als Erstes: er wird bei jeder Änderung mitgezogen, nicht nur d 🚫 **§6 (Abbau) bewusst NICHT** — die drei Alttunnel bleiben als Rückfallebene (healthy/8). 🔴 **Christoph hat den Flip ausdrücklich vorgezogen freigegeben** („aus Gründen"); die 7-Tage-Regel betrifft ohnehin §6, nicht den Flip. +- 🆕 **TP39 fast durch (2026-09-01):** `skip-name-resolve` auf der MariaDB **aktiviert** (mysql.user + vorher geprüft — kein Hostname-Grant, gefahrlos; Wirkung: gitea/vw/hass 0 von 36 frischen Anfragen + langsam). LXC 302 war **100 % voll** → `+30G` online (95 GB/69 %). 🔴 **root-DB-Passwort dabei ins + Transkript geraten** (`.my.cnf` ohne `=`), zu rotieren (→ TP30). Offen in TP39: nur noch der Sweep. +- 🆕 **TP40 angelegt (2026-09-01, User-Okay):** HA-Recorder-Retention — die `homeassistant`-DB frisst + 59 GB (`states.ibd` **41 GB**), unbegrenzt gewachsen. Das `+30G` aus TP39 ist ein Puffer; die + dauerhafte Lösung (`purge_keep_days`, `exclude`, `purge repack`) ist HA-seitig und **Christophs + Policy-Entscheidung** — kein eigenmächtiges Löschen. - 🆕 **TP39: `networking.service` in vier Containern repariert (2026-09-01).** Ursache war dieselbe Altlast wie beim Resolver: tote `auto`-Stanzas in `/etc/network/interfaces` aus dem VLAN1-Schema (`eth0` → `10.40.41.x`) und alten Versuchen — `ifup -a` scheiterte an Interfaces, die es nicht gibt, @@ -425,7 +433,8 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na > | TP36 | 🔜 | SSoT via Nautobot für teilprojekte.md-Live-Daten + Datei-Aufteilung | — | > | TP37 | 🔜 | Nautobot als Netzwerkdoku: Hosts/Container/Dienste + CF-Connectoren (Okay 08-30) | — | > | TP38 | 🔜 | OOB-Mgmt: untagged-VLAN99-Port je Switch | — | -> | TP39 | ⏳ | LXC-Hygiene pve (Resolver ✅ + `networking.service` ✅ 09-01 — offen: `skip-name-resolve`, Sweep) | — | +> | TP39 | ⏳ | LXC-Hygiene pve (Resolver ✅, `networking.service` ✅, `skip-name-resolve` ✅, Resize ✅ 09-01 — offen: nur Sweep) | — | +> | TP40 | 🔜 | HA-Recorder-Retention: 41 GB `states` beschneiden (Okay 09-01) | — | > | — | — | **34 archivierte TPs** in `teilprojekte-archiv.md` | — | ### TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt @@ -2035,6 +2044,8 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört | 2 | **IoT-WLAN-PSK** (`sec-iot`) | `dirtyvader-iot`, 26 Clients | steht **im Klartext** im TP17-Text ⇒ auch in der **Git-Historie**; Redigieren holt ihn dort nicht raus | Hebel `multi-passphrase` am Core verifiziert vorhanden, Tabelle leer | 23 Shellys per Skript + **3 von Hand** (`.249` NSPanel Pro, `.244` Nuki Bridge, `.227` SwitchBot) | | 3 | **Shelly-Gerätepasswort** *(vormals TP17.2)* | 23 Shellys | Härtung (bisher **keine** Auth auf den Geräten) | ✅ Werkzeug fertig (`migrate.py cmd_auth` + Digest-Fallback) | **je Gerät ein HA-Re-Auth-Flow** — das ist der Aufwand, nicht `SetAuth` | | 4 | **CF-Access-Service-Token** (`CF_API_TOKEN`) | Cloudflare-Zugang, s. TP14.4 | ⏳ **läuft am 2027-01-09 ohnehin ab** — harter Termin, unabhängig vom Projektende | Runbook liegt (`tp14.4-cf-access-token-runbook.md`) | Token neu ausstellen + `~/.secrets` nachziehen; **account-owned**, anderer verify-Endpoint | +| 5 | **Nautobot-Tokens** (`NAUTOBOT_SUPERUSER_API_TOKEN`, `NAUTOBOT_GITEA_TOKEN`) | Nautobot-Superuser + Gitea-Anbindung | 🔴 in der TP16.3-§2/§3-Session (2026-08-31) durch schwache `sed`-Maskierung **ins Transkript** geraten | Werte in `docs/nas-vlan20/stacks/210-nautobot.yml` (gitignored) | neu ausstellen + Stack-YML nachziehen; Superuser-Token wird von den `gc-*`-Skripten gelesen | +| 6 | **MariaDB `root`** (LXC 302, `10.40.20.23`) | root-DB-Login | 🔴 am 2026-09-01 (TP39) ins Transkript geraten — die `/root/.my.cnf` trug `password ` **ohne `=`**, die Feld-Maskierung ankerte auf `=` und griff nicht | Wert in `/root/.my.cnf` (chmod 600) | `SET PASSWORD` + `.my.cnf` nachziehen; **kein** externer Konsument (Dienste nutzen eigene DB-User) ⇒ billigste Rotation der Liste | > ✅ **Der Leak-MECHANISMUS hinter #1 ist seit 2026-08-31 zu — der Wert bleibt trotzdem verbrannt.** > Alle sechs Skripte im Repo, die `sshpass -p ` benutzten (`nautobot/gc-transaktion.py` und @@ -2046,6 +2057,14 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört > also nicht blind. 🔴 **Das ändert an #1 nichts:** ein Wert, der einmal in einem Transkript stand, > wird nicht dadurch sauber, dass der Weg dorthin geschlossen ist. Rotation bleibt fällig. > +> 🔴 **Posten #6 ist die dritte Maskierungs-Panne derselben Klasse** (nach `SHELLY_DEVICE_PW` 08-28 +> und den Nautobot-Tokens 08-31): das Muster ankerte auf ein **Trennzeichen** (`=`), das im +> konkreten File gar nicht stand (`password ` mit Leerzeichen). **Merkregel, jetzt zum dritten +> Mal:** vor jedem Ausgeben einer Secret-Datei den **Schlüsselnamen** ankern und das ganze Feld +> ersetzen, nie auf ein Trennzeichen vertrauen, das evtl. fehlt — und Werte gar nicht erst suchen, +> um sie zu sehen. #6 ist zugleich der **billigste** Posten (kein externer Konsument), aber die +> Panne dahinter ist der teure Teil. +> > ℹ️ **#3 war bis 2026-08-24 TP17.2** und ist jetzt vollständig hier (s. Detailabschnitt unten) — > es benutzt denselben Geräte-Durchgang wie #2, **ein Reboot statt zwei**. #4 gehört sachlich zu > **TP14.4**, das als TP bestehen bleibt (dort steckt das CF-Access-Profil, nicht nur der Token). @@ -2708,11 +2727,16 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein. #### Scope (was dieses TP noch zu tun hat) -1. 🔴 **`skip-name-resolve` in der MariaDB aktivieren.** Der Lookup ist heute nur *schnell*, nicht - *abgeschafft* — die Ursache ist entschärft, nicht beseitigt. ⚠️ **Vorher `mysql.user` lesen:** - Grants, die auf **Hostnamen** statt IPs lauten, brechen damit sofort und sperren im schlimmsten - Fall alle drei Dienste aus. **Blocker: DB-Zugang** — `root@localhost` ohne Passwort wird - verweigert, die Credentials sind noch nicht lokalisiert. +1. ✅ **ERLEDIGT 2026-09-01: `skip-name-resolve` aktiviert.** Vorher `mysql.user` gelesen (User gab + den DB-Zugang per `/root/.my.cnf`) — **kein einziger Grant lautet auf einen DNS-Hostnamen**, alle + sind `%` / IP-Literal / `localhost`. Damit kann `skip-name-resolve` niemanden aussperren; der + Reverse-Lookup war reiner Ballast. Gesetzt als eigenes Drop-in + `/etc/mysql/mariadb.conf.d/90-skip-name-resolve.cnf` (nicht die `#`-Zeile in `50-server.cnf` + editiert — Paket-Update-stabil), `@@skip_name_resolve=1` nach Neustart verifiziert. + **Wirkung: gitea/vw/hass je 0 von 12 frischen Anfragen langsam, max 0,25 s.** Alle drei Clients + danach wieder verbunden. Die Ursache ist damit **beseitigt**, nicht nur entschärft. + 🔴 **Sicherheitsvorfall dabei:** die `.my.cnf` trug `password ` **ohne `=`**, die Maskierung + griff nicht ⇒ das **root-DB-Passwort ist ins Transkript geraten** und gehört rotiert (→ TP30). 2. ✅ **ERLEDIGT 2026-09-01: `networking.service` + `ifupdown-wait-online.service` in `101`, `102`, `106`, `107` repariert.** **Ursache — dieselbe Altlast wie beim Resolver:** in `/etc/network/interfaces` standen noch `auto`-Stanzas aus dem **alten VLAN1-Schema** @@ -2728,11 +2752,15 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein. Bild — die Container liefen nur 13+ Tage ohne Neustart, deshalb war es unsichtbar. 🟡 **Rest, bewusst liegen gelassen:** `run-rpc_pipefs.mount` (101, 150) und `proxmox-regenerate-snakeoil.service` (108) — vorbestehend, ohne Bezug zu Netz oder DNS. -3. 🟡 **Resolver-Sweep als wiederkehrende Kontrolle**, nicht als Einmalaktion — und über pve hinaus: +3. ✅ **ERLEDIGT 2026-09-01 (im selben Fenster aufgetaucht): LXC 302 war zu 100 % voll** (62/65 GB), + Rootfs `+30G` online gewachsen ⇒ 95 GB / 69 %, MariaDB lief durch. 🔴 **Das ist ein Puffer, kein + Fix:** 59 GB davon sind die `homeassistant`-DB (`states.ibd` allein **41 GB**), die unbegrenzt + wächst (~1 GB/Tag) — die dauerhafte Lösung ist HA-seitig und liegt in **TP40**. +4. 🟡 **Resolver-Sweep als wiederkehrende Kontrolle**, nicht als Einmalaktion — und über pve hinaus: die **NAS-Container** sind nach derselben Logik zu prüfen (der DSM-Fallstrick von 2026-07-10: „Allgemein"-DNS ≠ was `dockerd` liest, laufende Container frieren den Upstream beim Erstellen ein). Sweep über pve: `for c in $(pct list|awk 'NR>1{print $1}'); do pct exec $c -- grep ^nameserver /etc/resolv.conf; done` -4. 🟡 **Abnahme-Regel festschreiben:** vor jedem geplanten LXC-Neustart `systemctl --failed` lesen +5. 🟡 **Abnahme-Regel festschreiben:** vor jedem geplanten LXC-Neustart `systemctl --failed` lesen und danach die **Ports gegen vorher** vergleichen — sonst verliert man still einen Dienst (genau so wäre `influxdb2` durchgerutscht). @@ -2750,6 +2778,48 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein. - **Nicht** TP31/TP34 (Caddy) und nicht TP11 (Monitoring) — obwohl gilt: ein Monitoring, das DB-Verbindungszeiten kennt, hätte diesen Fall Monate früher gezeigt. +### TP40 — Home-Assistant-Recorder-Retention: die 41-GB-`states`-Tabelle beschneiden ▸ 🔜 **ANGELEGT 2026-09-01 (User-Okay erteilt)** + +**Auslöser:** LXC 302 (MariaDB) lief am 2026-09-01 auf **100 %** voll. Sofortmassnahme war `+30G` +(TP39 Punkt 3), aber 59 der 65 GB sind die **`homeassistant`-Datenbank**, und die wächst weiter — +`+30G` verschiebt das Problem um ~4 Wochen, es löst es nicht. + +#### Befund (live gemessen) + +| Tabelle | Größe | +|---|---| +| `homeassistant.states` | **41 GB** | +| `homeassistant.state_attributes` | 8,6 GB | +| `homeassistant.statistics_short_term` | 8,1 GB | +| `homeassistant.statistics` / `events` | je ~0,7 GB | + +Der HA-Recorder schreibt **unbegrenzt** — es ist keine `purge_keep_days`-Grenze wirksam, sonst wäre +`states` nicht auf 41 GB gewachsen. Das ist ein Konfigurations-, kein Plattenproblem. + +#### Scope + +1. **HA-`recorder`-Retention setzen** (`configuration.yaml` bzw. `.storage`): `purge_keep_days` + auf einen bewussten Wert (Vorschlag 30) — **Christoph entscheidet die Zahl**, das ist eine + Aufbewahrungs-Policy, keine rein technische Größe. +2. **Rauschende Entities ausschließen** (`recorder: exclude`) — die üblichen Verdächtigen sind + hochfrequente Sensoren (Leistung, Netz-Durchsatz, `sensor.time`/`date`). Vorher per + `SELECT COUNT(*) … GROUP BY entity_id` die Top-Schreiber ermitteln, nicht raten. +3. **`recorder.purge` mit `repack: true`** — erst nach 1+2, sonst wächst es sofort nach. `repack` + gibt den Plattenplatz auf InnoDB-Ebene **real** frei (ohne repack bleibt die `.ibd`-Datei gross). + 🔴 **`states` hängt per FK an `state_attributes` und `events`** — purge räumt beide mit; die + Reihenfolge macht HA selbst, **nicht** von Hand einzelne Tabellen truncaten. +4. **Danach die TP39-Vergrösserung bewerten:** schrumpft `states` deutlich, waren die `+30G` + Vorhalt und keine Dauerlösung — die Platte lässt sich zwar nicht online verkleinern, aber der + Druck ist weg. + +#### Abgrenzung + +- **Nicht** TP39: das ist LXC-/DB-Hygiene (Resolver, `networking`, `skip-name-resolve`). Der + Resize tauchte dort nur auf; die **Ursache** (HA-Retention) ist HA-seitig und darum ein eigenes TP. +- 🔴 **Kein eigenmächtiger Datenlöschvorgang** — `purge` wirft echte Historie weg; die + Aufbewahrungsdauer ist eine Nutzerentscheidung. Diese Session hat **nur** vergrössert und gemessen. +- Bezug **TP11** (Monitoring): eine Plattenfüllstand-Warnung hätte das Wochen früher gezeigt. + ### TP37 — Nautobot als durchgehende Netzwerkdoku: Hosts/Container/Dienste, erster Anwendungsfall CF-Connectoren ▸ 🔜 ANGELEGT 2026-08-30 (User-Okay erteilt) > **Christophs Formulierung (2026-08-30):** *„können wir das setup mit den cf-connectoren dann auch in > nautobot abbilden. quasi eine durchgehende netzwerkdoku stück für stück. muss eh fast sein, da du auf