Commit Graph

7 Commits

Author SHA1 Message Date
3f95a7adf3 TP16.3 §6 Abbau durch, TP GESCHLOSSEN (User zog §6 vor)
Die 7-Tage-Frist wurde auf User-Entscheid aufgehoben ("es wird nichts mehr
sein"). Reihenfolge Container -> Tunnel eingehalten (umgekehrt gaebe es 530er).

Vorbedingung geprueft: alle vier Namen auf bf-public, kein Name mehr an den
Alttunneln -> Abbau gefahrlos.

7 Container entfernt, per exakter Namensliste (nicht per Filter):
  LXC 400 (pve): cloudflared-bfmm, cloudflared-bfnas
  macmini:       cloudflared-bfpve, cloudflared-bfnas
  NAS ep14:      cloudflared-bfpve, cloudflared-bfmm
  plus terpene-cloudflared -- auf zusaetzlichen User-Entscheid, weil
  420.teilzeitladen.xyz jetzt ueber Caddy/CF laeuft. Kein Stack dahinter, also
  kein Wiederauferstehen.

Beweis VOR der Tunnel-Loeschung: 420.teilzeitladen.xyz lieferte mit bereits
entferntem terpene-cloudflared echten Origin-Inhalt (assetlinks-JSON, 200) --
der Dienst haengt also nicht mehr am Tunnel.

4 Tunnel geloescht: bf-mm, bf-nas, bf-pve, terpene-db -- jede ID gegen die
Behalten-Liste (bf-public, fm) geprueft.

Schlusskontrolle: nur noch bf-public (12) + fm (4) healthy; alle vier BF-Namen
und 420 weiterhin 200.

Der terpene-db-Tunnel-Token stand kurz im docker-inspect-Output; mit der
Tunnel-Loeschung ungueltig, kein Rotationsbedarf.

TP16.3 damit vollstaendig abgeschlossen (Status ✅ 2026-09-01). Quick-Index,
Abschnittsheader, §6-Record, Ist-Stand, Runbook §6 und Handoff nachgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 01:08:34 +02:00
73fec72abe 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>
2026-09-01 00:25:39 +02:00
f6283fd813 TP16.3 §5: die sechs AP-Drifts ins Soll, 28. Regel interface-veth
veth / ip address / ip firewall nat der drei cloudflared-Connectoren standen seit
der Vor-Ort-Session per Direkt-Write am Geraet (Runbook §3.4), waehrend /ip address
und /ip firewall unter GC-Drift-Kontrolle stehen: sechs extra-Drifts, Compliance
128/135. Sie sind inhaltlich richtig und sollen DAUERHAFT gelten -- deshalb ins
Template und nicht in eine gc-transaktion (die ist fuer befristete Versuche).
Kein Re-Baseline, kein Rueckbau, keine Zeile aufs Geraet: nur die SoT nachgezogen.

Neu ist die 28. ComplianceRule interface-veth. Vorher gab es fuer /interface veth
keine Regel -- das tragende Stueck des ganzen Aufbaus haette geloescht werden
koennen, ohne dass irgendetwas meldet.

Zwei Funde:

(a) Der veth-Export traegt zwei geraetevergebene MACs (mac-address,
    container-mac-address), auf jedem AP anders. Eine nackte Regel haette damit
    Dauer-Drift auf allen drei APs erzeugt, also genau die immer-rote Zahl, die
    niemand mehr liest. Zwei eng auf die veth-Zeile verankerte ConfigReplace-Regeln
    normalisieren sie im Backup (Lookbehind haelt container-mac-address heraus,
    [^\n]*? haelt die Regel in der Zeile; Selbsttest mit Negativfaellen im Skript).
    Bewusst mit der vorhandenen Maske <<REDACTED>> statt einer eigenen: sie ist im
    Repo zugleich die Push-Sperre (gc-configplan.py verweigert config_set damit) --
    eine Zeile mac-address=<<...>> darf nie aufs Geraet.
    Kostet Backup-Treue: die veth-MACs stehen in bf-golden-config nicht mehr im
    Klartext. Vertretbar, RouterOS vergibt sie beim Neuanlegen ohnehin neu.
    Verworfene Alternative: MACs je Geraet modellieren -- widerspricht der
    Begruendung, die fuer die VAP-MACs schon im ConfigContext-Skript steht.

(b) Der erste Compliance-Lauf meldete SUCCESS und war trotzdem unvollstaendig:
    139 statt 140 Eintraege, crs326-core/interface-veth fehlte, im Job-Log
    "RENDER COMPLIANCE TASK GROUP failed: Broken pipe". Zweiter Lauf sauber.
    Merkregel im Runbook (Falle 16): Abnahme ist die ANZAHL der Eintraege
    (Regeln x Geraete), nicht die Konformitaetsquote.

Stand danach: 139/140. Uebrig bleibt genau crs326-core/wifi-security -- die offene
Transaktion TP25-fund-e-ft-over-ds einer laufenden Messung, die bleiben muss.

Ausserdem: frischer Ingress-Snapshot von bf-public vor §5 und das geschaerfte
§5.1-Erfolgskriterium (200 mit leerem Body + server: Caddy = Strecke bewiesen,
404 = Ingress-Regel fehlt) -- am Live-System gemessen, nicht angenommen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 20:13:47 +02:00
60360fc3cc TP16.3 §2/§3 durch: cloudflared auf ap1/ap2/ap3, bf-public healthy mit 12 Connectoren
Merge von claude/nervous-williams-acf000 (d5b3ce3) plus Ergebnis der
Vor-Ort-Session vom 2026-08-31.

Ergebnis
- je ein cloudflared 2026.6.1 auf ap1/ap2/ap3, bf-public healthy/12
  (vorher 0 Connectoren), Flash je AP 54-55 MiB frei, WLAN zurueck.

Drei Runbook-Fehler aufgedeckt und korrigiert (§2.2, §3.3, §3.5, §8)
- Flash-Budget war Faktor 2,5 zu optimistisch: cloudflared entpackt
  69,5 MiB (gemessen mit docker export), nicht 28 MB -- das offizielle
  Image passt auf keinen der drei APs. Ersatz: eigenes FROM-scratch-Image
  mit 35,3 MiB aus dem statisch gelinkten Binary, Binary-SHA e93824f6
  gepinnt, Neubau byte-identisch. tools/build-cfd-image.py.
- docker save schreibt seit Docker 25 OCI statt docker-v1 -> RouterOS
  meldet "no config found in manifest". tools/oci2docker.py als Konverter.
- /container/envs nimmt list=, nicht name= (auch MikroMCPs
  manage_container_env ist dadurch fuer dieses Feld unbrauchbar).

Weitere Funde
- Der device-mode-Bestaetigungs-Boot installiert keine Pakete; erst
  Paket-Reboot, dann device-mode.
- "A - AVAILABLE" in /system package print ist ein Download-Katalog,
  kein Paket auf dem Geraet (Gegenprobe am Core: 2,9 MB frei, listet
  10,1 MB wifi-qcom als verfuegbar).
- MikroMCPs export_config exportiert unvollstaendig (301 B statt 6,2 KiB).

Offen und entscheidungsbeduerftig
- Compliance 128/135: §3.4 verlangt Direkt-Writes fuer ip address/nat,
  die unter GC-Kontrolle stehen -> sechs neue extra-Drifts, zwei je AP.
  Inhaltlich richtig, gehoeren ins Soll -- kein Re-Baseline, kein Rueckbau.
- Zwei Nautobot-Tokens sind in dieser Session ins Transkript geraten
  (unzureichende sed-Maskierung) -> Rotation noetig, TP30. Merkregel in
  CLAUDE.md ergaenzt.

Merge-Konflikte aufgeloest
- Nummernkonflikt: beide Branches hatten ein TP37. main behaelt TP37
  (Nautobot als Netzwerkdoku, User-Okay 08-30), OOB-Mgmt wird TP38.
  Braucht noch Christophs Okay.
- Drei CF-Rollback-Snapshots hatten gleichen Namen bei verschiedenem
  Inhalt -> aelterer Stand als *-vor-hostname-schnitt.json erhalten,
  keiner verworfen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 16:15:13 +02:00
452ea53576 ROS 7.24.1 auf allen fuenf nachgezogen + Handover fuer TP16.3 §2/§3
Nautobot: ap1 stand als einziges Geraet noch auf SoftwareVersion 7.24 (ap2,
ap3, core, branch waren bereits richtig) -> auf 7.24.1 gesetzt. Danach
Backup/Intended/Compliance.

Folge fuers Runbook: aus zwei container.npk wird EINE. Die Zwei-Dateien-Regel
vom 08-30 war rein versionsbedingt, nicht modellbedingt - cAP ax und hAP ax^2
teilen sich die arm64-Pakete. §0, §2.1, §3.1 und Falle 1 umgeschrieben.
Die Regel dahinter bleibt: npk muss exakt zur ROS-Version passen, sonst ist
das Paket nach dem Reboot inaktiv - ohne Fehlermeldung.

Neue Compliance-Drift, NICHT von dieser Session und bewusst offen gelassen:
crs326-core / wifi-security - sec-main hat am Geraet ft-over-ds=no, Soll ist
yes (ft=yes ist korrekt). Kam mit dem Upgrade. 134/135 compliant. Braucht eine
Entscheidung (Geraet korrigieren oder neuen Wert zum Soll erklaeren) plus
Re-Provisionierung der CAPs; ein Re-Baseline ohne Entscheid wuerde die
Drift-Erkennung wertlos machen.

Handover docs/handoff-20260831-tp16.3-vorort-session.md fuer die Folgesession
(§2/§3: npk, device-mode, Container). Enthaelt u.a. den Hinweis, dass ein
fehlschlagendes /tool fetch vom AP auf Caddy KEIN Fehler ist, sondern die
SNI-Abweisung - und dass der TLS-Alert sogar beweist, dass die Freigabe traegt.

Offen notiert, nicht angelegt: TP-Vorschlag "dedizierter untagged-VLAN99-Port
je Switch" (Out-of-Band-Mgmt) - Auslöser war, dass crs326-branch beim
Core-Neustart nicht erreichbar war. Wartet auf Christophs Okay.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 14:57:35 +02:00
badf715f5a TP16.3 §1: die drei Blocker remote behoben (Ingress, Firewall via GC, ap3-Cred)
A) bf-public-Ingress von http://10.40.20.40:80 auf https://10.40.20.40:443
   umgestellt, originServerName je Regel. Die :80-Variante haette ueber
   Cloudflare eine Redirect-Schleife gebaut (Caddy antwortet dort 308 auf
   https, das Ziel laeuft zurueck in denselben Tunnel).

B) Freigabe vlan99 -> vlan20:443 auf crs326-core angelegt - ueber Nautobot
   Golden Config, NICHT per Direkt-Write: ip-firewall-filter steht seit TP26
   unter Drift-Kontrolle, und die zwei genehmigten Ausnahmen (#2 Bring-up,
   #4 WireGuard-Keys) decken diesen Fall nicht.
   - Backup vorher: core-pre-tp16.3-blockerB-20260831.backup (TP22-Regel 3)
   - gc-manual-plan.py, Change-ID TP16.3-BlockerB, Plan Completed
   - Position verifiziert: direkt vor TP5: log-only / TP5: deny-by-default
   - Re-Baseline ingest-core-firewall.py --apply, dann --refresh-compliance
     => 135/135 compliant, 0 Drifts
   - funktional: /tool fetch von ap3 erreicht Caddy und bekommt einen
     TLS-Alert VON Caddy - ein Alert kann nur vom Server kommen, das Paket
     ist also da. Der Alert ist die SNI-Abweisung (ohne SNI 000, mit
     korrektem SNI 200) und damit genau der Grund fuer originServerName.

C) ROUTER_AP3_USER/_PASS in ~/.secrets/credentials.env nachgetragen (war nur
   in ~/.claude.json), chmod 600, Sicherung .bak-20260831. REST-Auth gegen
   ap3 = HTTP 200.

Vor Ort startet die Arbeit damit bei §2/§3 (container.npk, device-mode,
Container). Quick-Index, TP16.3-Abschnitt und Ist-Stand mitgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 08:06:38 +02:00
b697ffc6fa TP16.3/TP31 Schritt 5: Vor-Ort-Runbook fuer bf-public-Connector (ap1/ap2/ap3)
Runbook docs/tp16.3-bf-public-ap-connector-runbook.md fuer die Vor-Ort-Session
geschrieben; docs/tp31-schritt5-runbook.md abgeloest (read-only-Header).

Live-Befunde 2026-08-30, die den Plan aendern:

- ap3 ist neu und NICHT baugleich: cAP ax (cAPGi-5HaxD2HaxD, 10.40.99.13),
  arm64/96 MB frei, aber ROS 7.24.1 gegen 7.24 auf ap1/ap2 => zwei
  verschiedene container.npk. device-mode=basic statt home (fetch bereits an).
- Blocker A: bf-public-Ingress zeigt auf :80, Caddy antwortet dort mit 308 auf
  https => Redirect-Schleife ueber CF fuer alle vier Namen. Faellt heute nicht
  auf, weil die Alttunnel an Caddy vorbei direkt aufs Backend gehen.
  Fix: https://10.40.20.40:443 + originServerName je Regel (ueber 443 4x 200).
- Blocker B: es gibt KEINE Freigabe vlan99 -> vlan20:443. Die forward-Kette
  wurde vollstaendig gelesen (36 Regeln); die einzige MGMT->INFRA-Regel ist ein
  src-port=8728-Rueckweg. Der Vorgaenger-Runbook behauptet das Gegenteil
  ("Regel 27 deckt vlan99->vlan20:80 ab") - Regel 27 ist IOT->INFRA.
- Blocker C: ROUTER_AP3_PASS fehlt in ~/.secrets/credentials.env (nur in
  ~/.claude.json). Nebenbefund: credentials.env laesst sich in zsh nicht
  sourcen (rohe WireGuard-Zeilen ab ~Z.69) - Variablen bleiben still leer.
- Kein PoE an beiden CRS326 => kein Remote-Power-Cycle, Bestaetigung physisch.
- Die sechs abzubauenden Container auf allen drei Hosts verifiziert;
  terpene-cloudflared und fm.emsenhuber.net bleiben.

CF-Rollback-Snapshots unter docs/cf-backup/*-20260830-vor-tp16.3-schnitt.json
neu angelegt (vier Ingress-Configs + CNAMEs inkl. Record-IDs) - es gab sie
vorher nicht.

Quick-Index, TP16.3-Abschnitt und Ist-Stand-Block mitgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 21:07:17 +02:00