TP16.3 §5 durch: vier Namen auf bf-public + 10-Sekunden-DNS-Fund behoben

FLIP (User-Freigabe, vorgezogen)
n8n / gitea / hass / vw laufen jetzt ueber bf-public, der oeffentliche Verkehr
geht damit erstmals ueber Caddy statt an ihm vorbei. Je Name einzeln geflippt und
dazwischen gemessen; Antwortzeiten vorher/nachher unveraendert. Nachweise:
gitea echte Gitea-Antwort, hass WebSocket 101 Switching Protocols (der
Companion-App-Pfad, den das Runbook als "nur vom User pruefbar" fuehrte),
vw /alive + /api/config 200 und WS-Hub 401 von Vaultwarden selbst, n8n vom User
im Browser bestaetigt (von aussen nicht bis zum Origin pruefbar, s. TP14.4).
Die drei Alttunnel bleiben als Rueckfallebene stehen -- §6 ist NICHT Teil davon.

10-SEKUNDEN-ZOLL AUF gitea/vw/hass -- Ursache gefunden und behoben
gitea hing bei ~10% der Anfragen exakt 10,1 s, quer ueber Web-UI, /api/healthz
und den Git-Pfad. MariaDB (LXC 302) hatte skip-name-resolve auskommentiert und
machte bei JEDER NEUEN Verbindung einen Reverse-Lookup, waehrend ihr resolv.conf
auf den toten 10.40.41.254 zeigte: 10.010 ms je Lookup, Pool-Verbindungen
schnell -- daher wirkte es sporadisch. An derselben DB haengen Vaultwarden, Home
Assistant und gitea (per Verbindungstabelle belegt, nicht vermutet; die erste
Annahme "vaultwarden nutzt SQLite" war falsch und wurde vom User korrigiert).
Fix: nameserver 10.40.20.1 + Reboot fuer fuenf LXCs (302, 102, 106, 107, 150).
Nachher 21-24 ms und 0 von 25 Proben langsam.
Offen: skip-name-resolve selbst -- bricht Hostname-basierte Grants, vorher
mysql.user lesen (DB-Zugang fehlt).

LATENT, NICHT VON DIESER SESSION VERURSACHT
networking.service + ifupdown-wait-online.service sind in 101/102/106/107
failed; influxdb2 kam nach dem Reboot nicht hoch (Unit enabled, kein
Startversuch im Journal). 101 wurde nie angefasst und zeigt dasselbe -- die
Container liefen nur 13+ Tage ohne Neustart.

RUNBOOK-KORREKTUREN
§5.3 "Caddy sieht den Request" konnte nie funktionieren: im Caddyfile steht keine
log-Direktive, ein erfolgreicher Request hinterlaesst nichts. Ersetzt durch die
Werkzeuge, die tatsaechlich etwas beweisen -- erzwungener oeffentlicher Weg per
curl --resolve (Pflicht wegen Split-Horizon), Verbindungstabelle am Core statt
Firewall-Zaehler (cloudflared haelt die Origin-Verbindung offen, der Zaehler
steht still obwohl alles laeuft), Antwort-Fingerabdruck, WebSocket mit --http1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 00:25:39 +02:00
parent f6283fd813
commit 73fec72abe
4 changed files with 202 additions and 4 deletions

View File

@@ -0,0 +1,95 @@
# Handoff — TP16.3 §5 durch: alle vier Namen auf `bf-public`, plus ein 10-Sekunden-Fund
> **2026-08-31/09-01.** Nachfolger von
> [`handoff-20260831-tp16.3-paragraph2-3-durch.md`](handoff-20260831-tp16.3-paragraph2-3-durch.md).
> **Nicht** Teil dieser Session: §6 (Abbau).
---
## 1. Was jetzt steht
**Alle vier öffentlichen Namen laufen über `bf-public`** — der öffentliche Verkehr geht damit
erstmals über **Caddy** statt an ihm vorbei.
| Name | Nachweis von außen | Origin bewiesen? |
|---|---|---|
| `gitea` | 200, `i_like_gitea`-Cookie = echte Gitea-Antwort | ✅ |
| `hass` | 200 + `manifest.json` 200 + **WebSocket `101 Switching Protocols`** | ✅ inkl. Companion-App-Pfad |
| `vw` | `/`, `/alive`, `/api/config` je 200; WS-Hub `401` **von Vaultwarden** | ✅ |
| `n8n` | 302 zum Access-Login (vor *und* nach dem Flip) | ❌ — vom User im Browser bestätigt |
Antwortzeiten vorher/nachher unverändert ⇒ **Caddy im Pfad kostet nichts Messbares.**
🚫 **Die drei Alttunnel stehen bewusst weiter** (`bf-mm`/`bf-nas`/`bf-pve`, je healthy/8) — sie sind
die Rückfallebene. Rückweg je Name = ein `PATCH` auf die alte Tunnel-ID.
**Schicht davor, ebenfalls durch:** die sechs AP-Drifts sind ins Soll gehoben, **Compliance 139/140**
(28 Regeln × 5 Geräte). Übrig bleibt genau `crs326-core`/`wifi-security` = offene Transaktion
`TP25-fund-e-ft-over-ds`. Neu: ComplianceRule **`interface-veth`** + zwei `ConfigReplace`-Regeln, die
die gerätevergebenen veth-MACs normalisieren (`nautobot/ingest-veth-rule.py`).
---
## 2. 🔴 Der eigentliche Fund der Nacht: ein 10-Sekunden-Zoll auf drei Diensten
`gitea` hing bei ~10 % der Anfragen **exakt 10,1 s** — quer über Web-UI, `/api/healthz` **und** den
Git-Pfad. **Ursache:** MariaDB (LXC **302**) hatte `skip-name-resolve` auskommentiert und machte bei
**jeder neuen Verbindung** einen Reverse-Lookup, während ihr `/etc/resolv.conf` auf den **toten**
`10.40.41.254` zeigte. Gemessen: **10.010 ms je Lookup**.
**An derselben DB hängen `Vaultwarden` (.127), `Home Assistant` (.105) und `gitea` (.157)** —
über die Verbindungstabelle belegt.
**Fix (User-Freigabe, Wartungsfenster):** `pct set <id> --nameserver 10.40.20.1` + Reboot für
`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.
---
## 3. 🔴 Latenter Fund: vier Container überleben keinen Reboot sauber
`networking.service` und `ifupdown-wait-online.service` sind in **`101`, `102`, `106`, `107`**
fehlgeschlagen. Folge: alles mit `After=network-online.target` startet nach einem Reboot **nicht** —
**influxdb2 kam nicht hoch**, Unit `enabled`, **kein Startversuch im Journal**. Von Hand sofort ok.
🔑 **Nicht von dieser Session verursacht:** `101` wurde nie angefasst und zeigt dieselben Units.
Die Container liefen nur 13+ Tage ohne Neustart. **Diese vier sind einen Reboot davon entfernt,
still einen Dienst zu verlieren.**
---
## 4. Drei Messfallen, die diese Session Zeit gekostet haben
1. **Split-Horizon:** der Haus-Resolver liefert für alle vier Namen direkt `10.40.20.40` — ein Test
von zuhause sieht Cloudflare **nie**. Prüfen nur mit `curl --resolve <name>:443:188.114.96.10`
oder von außerhalb. *(Guter Nebeneffekt: ein misslungener Flip bricht intern nichts.)*
2. **Access antwortet je nach Standort verschieden:** `n8n` aus dem Haus 200 (`bf4`-Policy),
von außen 302. `hass`/`vw`/`gitea` stehen auf **`bypass`** — dort **nie** ein Login.
⚠️ Die App `hass, vw, gitea` heisst **zu Recht** so: sie führt alle drei in `self_hosted_domains`,
das Feld `domain` zeigt nur den ersten. Ein Rename wäre eine Verschlechterung gewesen.
3. 🔴 **„Der Host ist ausgefallen" war der eigene Standortwechsel.** Ping/SSH/Caddy waren tot, weil
die Session-Maschine auf einen **Hotspot** gewandert war (`route -n get default` = `172.20.10.1`).
Daraufhin wurde ein **bereits erfolgreicher `n8n`-Flip grundlos zurückgerollt**.
**Merkregel: vor jeder Ausfallmeldung die eigene Default-Route lesen.**
Dazu zwei Werkzeug-Befunde: **der Zähler der Blocker-B-Firewallregel taugt nicht als Wegbeweis**
(cloudflared hält die Origin-Verbindung offen ⇒ kaum neue Verbindungen ⇒ Zähler steht still, obwohl
alles läuft; richtig ist die **Verbindungstabelle**), und **Caddy führt gar kein Access-Log** ⇒ der
alte §5.3-Punkt „Caddy sieht den Request" konnte nie funktionieren.
---
## 5. Nächste Schritte
1. **§6 Abbau** — sechs Container + drei Alttunnel. Frühestens nach störungsfreiem Betrieb;
Christoph hat den **Flip** vorgezogen freigegeben, **nicht** den Abbau.
🚫 `terpene-cloudflared` (LXC 400) und `fm.emsenhuber.net` bleiben. **Namen lesen, nicht Zeilen zählen.**
2. **`skip-name-resolve`** auf der MariaDB — vorher `mysql.user` gegen Hostname-Grants prüfen.
3. **`networking.service`** in `101`/`102`/`106`/`107` reparieren (Punkt 3).
4. **TP30:** die zwei Nautobot-Tokens rotieren (vom User vertagt, weiterhin offen).
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`.