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>
7.5 KiB
Handoff — TP16.3 §2/§3 durch: drei Connectoren live, eine Entscheidung offen
2026-08-31, Vor-Ort-Session. Nachfolger von
handoff-20260831-tp16.3-vorort-session.md. Nicht Teil dieser Session: §5 (CNAME-Flip) und §6 (Abbau).
1. Was jetzt steht
bf-public ist healthy mit 12 Connectoren (3 APs × 4 CF-Edges) — der Tunnel hatte vorher
null. Je ein cloudflared 2026.6.1 läuft auf ap1, ap2 und ap3.
| ap1 | ap2 | ap3 | |
|---|---|---|---|
container-Paket |
7.24.1 ✅ | 7.24.1 ✅ | 7.24.1 ✅ |
device-mode container |
yes ✅ |
yes ✅ |
yes ✅ |
| Container | R running |
R running |
R running |
.tar gelöscht |
✅ | ✅ | ✅ |
| Flash frei | 54,0 MiB | 54,6 MiB | 55,0 MiB |
WLAN auf allen drei zurück, CAPs state=Ok am Manager. Backups je AP liegen auf dem Gerät
(vor-tp16.3-apN.backup) und lokal unter ~/tp16.3/backups/ — inklusive vollständigem
/export (nicht der MCP-Export, s. Punkt 4).
2. 🔴 Die eine offene Entscheidung: Compliance steht auf 128/135
Nach vollem Refresh (Backup → Intended → Compliance, nicht die stale Zahl von vorher):
| Gerät | Regel | Inhalt |
|---|---|---|
| ap1 / ap2 / ap3 | ip-address |
/ip address add address=172.17.0.1/24 interface=veth-cf |
| ap1 / ap2 / ap3 | ip-firewall-nat |
masquerade, Kommentar TP31: cloudflared egress |
| crs326-core | wifi-security |
ft-over-ds — die bekannte, unverändert |
Ursache ist ein Widerspruch zwischen zwei Dokumenten, kein Ausrutscher: Runbook §3.4 schreibt
Direkt-Writes für veth/ip address/nat vor, die Governance stellt /ip address und
/ip firewall unter GC-Pflicht. Ich bin dem Runbook gefolgt.
Die sechs Drifts sind inhaltlich richtig — die Config soll dort stehen, ohne sie läuft kein
Container. Der saubere Weg ist, sie ins Soll zu heben (AP-Template bzw. ConfigContext
ap-common), damit die Compliance sie als konform sieht.
🔴 Kein Re-Baseline (macht die Drift-Erkennung wertlos) und kein Rückbau (killt die Tunnel).
⚠️ /interface veth erzeugt keine Drift — dafür existiert keine ComplianceRule. Wenn das Soll
angepasst wird, gehört die Frage dazu, ob veth überhaupt erfasst sein soll.
3. 🔴 Drei Runbook-Fehler, die diese Session aufgedeckt hat
(a) Die Flash-Rechnung war um Faktor 2,5 zu optimistisch. §3.5 rechnete mit „28 MB .tar
- ~28 MB entpackt ≈ 39 MB Rest". Die 28 MB sind die komprimierte Archivgrösse; entpackt misst
cloudflare/cloudflared:2026.6.172.926.208 B = 69,5 MiB. Der Import braucht Tar und entpacktes Abbild gleichzeitig ⇒ 95,7 MiB gegen ~90 MiB frei. Das offizielle Image passt auf keinen der drei APs. ⚠️docker image inspect .Sizeführt in die Irre (meldete 27.463.950). Für Flash-Budgetsdocker export | wc -cmessen.
Lösung, ausgerollt: eigenes FROM scratch-Image aus dem — nachweislich statisch gelinkten —
Binary (36,8 MB) plus CA-Bundle: 35,3 MiB, Spitzenbedarf 70,6 MiB. Build-Skript liegt jetzt im
Repo (tools/build-cfd-image.py), ein Neubau ist byte-identisch (f818bf40…).
🔑 Der Pin ist die Binary-SHA256 e93824f6…, und cloudflared bestätigt sie beim Start selbst
(Version 2026.6.1 (Checksum e93824f6…)) — im Log aller drei APs nachlesbar.
(b) docker save taugt seit Docker 25 nicht mehr als Quelle. Mit containerd-Image-Store schreibt
es OCI-Layout (blobs/sha256/, gzip-Layer); RouterOS will docker-v1 und meldet
no config found in manifest — klingt nach kaputtem Image, ist das Format.
(Konverter für den Fall, dass man doch ein Docker-Image braucht: tools/oci2docker.py, prüft die
Layer-Digests gegen rootfs.diff_ids.)
(c) /container/envs heisst auf ROS 7.24.1 list=, nicht name=. Mit name= kommt
bad parameter name bzw. unknown parameter name. Auch MikroMCPs manage_container_env benutzt
name= und ist damit für dieses Feld unbrauchbar.
4. Vier weitere Funde
- 🔴 Der
device-mode-Bestätigungs-Boot installiert KEINE Pakete. Auf ap1 lag die.npkschon bereit, alsdevice-modegesetzt wurde — der Stromzyklus hatcontainer: yesbestätigt und die Datei verbraucht, ohne zu installieren. Reihenfolge ist Pflicht: erst Paket-Reboot, danndevice-mode. (Nachholen ging per SSH, ohne zweiten Gang zum Gerät.) - 🟡
A - AVAILABLEin/system package printist ein Download-Katalog, kein Paket auf dem Gerät. Gegenprobe:crs326-corehat 2,9 MB frei von 16 MB, listet aberwifi-qcom(10,1 MB) undrose-storage(4,3 MB) als „available"; die Grössen sind arch-spezifisch.enablelöste einen Internet-Fetch aus — auf ap1/ap2 perdevice-mode=homegesperrt. Der.npk-Weg bleibt richtig. - 🟡 MikroMCPs
export_configexportiert unvollständig: 301 Bytes gegen 6,2 KiB bei direktem/export. Ein Rollback-Artefakt, das existiert und trotzdem fast leer ist — dieselbe Klasse wie „Lücke statt Fehlermeldung". Für Backups/export file=…per SSH. - ⚠️ WLAN-Abnahme nur teilweise belegbar:
main(3 Clients) undiot(27) haben frische Leases;media/untrusted/guesthatten schon vor dem Umbau null Clients. Kein Rückschritt, aber auch kein Beleg — nicht als „grün" buchen.
5. 🔴 Sicherheitsvorfall in dieser Session — Rotation nötig
Beim Suchen des Nautobot-Tokens hat eine unzureichende sed-Maskierung
(grep -n … | sed 's/:.*TOKEN/…/' | cut -c1-60) zwei Werte im Klartext ins Transkript geschrieben:
NAUTOBOT_SUPERUSER_API_TOKENNAUTOBOT_GITEA_TOKEN
beide aus docs/nas-vlan20/stacks/210-nautobot.yml. Als verbrannt behandeln → TP30.
Das ist exakt die Falle, die seit 2026-08-28 in der CLAUDE.md steht (der SHELLY_DEVICE_PW-Fall).
Merkregel, die offenbar noch nicht scharf genug formuliert war: ein Maskierungs-Muster, das auf
: ankert, matcht bei grep -n den Zeilennummer-Präfix statt den Wert. Sicher ist nur
sed -E 's/(TOKEN|PASSWORD|SECRET|KEY|PASS)=.*/\1=<redacted>/' — auf den Schlüsselnamen ankern,
nie auf ein Trennzeichen, das auch im Präfix vorkommt.
6. Repo-Zustand
- Branch
claude/nervous-williams-acf000ist hier hereingemergt. Konflikte aufgelöst:- Nummernkonflikt TP37:
mainhatte TP37 = Nautobot als Netzwerkdoku (User-Okay 08-30), der Branch TP37 = OOB-Mgmt. Letzterer ist auf TP38 umnummeriert. ⚠️ Braucht dein Okay — Nummernvergabe ist laut Konvention deine Entscheidung. - Drei CF-Rollback-Snapshots hatten denselben Dateinamen bei verschiedenem Inhalt
(
bf-mmv4/6 Regeln vs. v6/2 Regeln, analogbf-nas,bf-pve) — zwei Zeitpunkte, beide „vor-tp16.3-schnitt" genannt. Keiner verworfen: der ältere liegt jetzt als*-vor-hostname-schnitt.jsondaneben.
- Nummernkonflikt TP37:
- Neu:
tools/build-cfd-image.py,tools/oci2docker.py. mcp/mikromcp/config/routers.yamlmeldet weiterrosVersion: "7.24"für alle fünf (live 7.24.1) — kosmetisch, unangetastet gelassen.
7. Nächste Schritte
- Entscheidung zu Punkt 2 (sechs Drifts ins Soll heben) — vor dem Flip, sonst geht man mit erklärter, aber ungeklärter Drift in den Produktivpfad.
- §5 CNAME-Flip, einzeln mit Abnahme dazwischen, Testname zuerst (§5.1).
🔴
healthybeweist nur, dass der Connector mit Cloudflare redet — nicht, dass das Origin antwortet. Der Streckenbeweis bis Caddy ist §5.1. - §6 Abbau frühestens 7 Tage nach dem Flip.
- TP30: die zwei Tokens aus Punkt 5 rotieren.