Zwei Straenge, die sich dieselben Dateien teilen — deshalb ein Commit.
1) COMPLIANCE-DRIFTS BESEITIGT (User: "beseitige autonom alle") -> 68/68, 0 Drifts
Entfernt wurden die 4 verbliebenen `extra`-Drifts (der fuenfte, core 10.40.41.211,
war schon ueber TP19-vlan1-core-address gefallen):
- ap1 + ap2: Werks-defconf `/ip dns static router.lan -> 192.168.88.1`. Auf beiden
APs der einzige statische Eintrag, die IP existiert im Netz nicht. Der Core hat
sein eigenes, korrektes router.lan -> 10.40.99.1 (im Template, compliant).
- crs326-branch: Bring-up-Rest SVI vlan10 + 10.40.10.2, Adresse zuerst.
Richtung bewusst "am Geraet entfernen" statt "ins Template aufnehmen" — genau so
steht es seit 2026-08-13 im Switch-Zweig des Templates. Der frueher notierte
Vorbehalt "potenzielle Rettungspfade" ist per User-Entscheid aufgehoben; der
Mgmt-Fallback aus VLAN10 auf dem branch entfaellt damit (Rueckweg = MAC-Winbox am
selben Draht).
Weg: 3 manuelle GC-ConfigPlans, kein Direkt-Write. Vorher /system backup je Geraet.
Deploy gestaffelt — erst die APs, am Geraet gegengeprueft, dann branch.
Verifikation am GERAET, nicht am Job: DNS-Statics total=0 bei unveraenderten 28
bzw. 3 WLAN-Clients; branch nur noch vlan99 + 10.40.99.2/24; Ping vom Core 4/4.
Entscheidende Gegenprobe: /interface bridge vlan/export byte-identisch — `bridge`
steht dort statisch als tagged-Member von VLAN10, das Entfernen des SVI hat also
weder Traffic-Wirkung noch neuen Drift. Danach Backup -> Intended -> Compliance,
alle 4 Geraete mit frischem Success-Datum.
Neue API-Falle, die erklaert warum es bisher kein Skript gab:
POST /plugins/golden-config/config-plan/ ist 405 — das ViewSet ist read-only.
ConfigPlans entstehen nur ueber den Job "Generate Config Plans" (plan_type=manual
+ commands-TextVar). plan_type=missing erzeugt ausserdem nur add-Zeilen, also muss
alles Entfernende zwangslaeufig ein manueller Plan sein.
Neu: nautobot/gc-configplan.py — loest Device-UUIDs einzeln per Name auf und
assertet plan.device UND config_set gegen das Ziel (die alphabetische
Sortier-Falle aus TP21.1 kann damit nicht wiederkommen), verweigert config_sets
mit <<REDACTED>> (Regel 1) und print-Zeilen, kann gestaffelt deployen
(--deploy-ids) und kapselt Backup -> Intended -> Compliance (--refresh-compliance).
Dry-Run ist Default.
2) TP16.1: GATE OFFEN, Runbook ausfuehrungsreif, Governance-Ausnahme #4
Die Bedingung "gated bis TP21 den CRS326 abdeckt" ist seit der Adoption am
2026-08-13 erfuellt. §3 neu gemessen, §4.3 von Platzhalter auf echte Werte.
Die letzte inhaltliche Unbekannte hat sich erledigt: "Rueckweg-Routing TBD" —
der Core IST L3-Gateway aller VLANs, es braucht keine Zusatzroute. wg-hub liegt
auf demselben Geraet und ist damit direktes Vorbild statt fernes Muster.
Klarstellung, weil leicht zu verwechseln: das Mesh ersetzt die Tunnel NICHT. Es
loest nur den privaten Zugang (10.40.0.0/16 per IP, inkl. ICMP); die oeffentlichen
FQDNs bleiben auf cloudflared. Relevant dabei: die Route 10.40.0.0/16 zeigt auf
bf-pve — und der faehrt derzeit nur einen Connector.
Ausnahme #4 (User 2026-08-16): die WG-Zeilen des Mesh-Bring-ups auf crs326-core
duerfen direkt gesetzt werden. Grund ist strukturell, nicht bequem — TP22-Regel 1
schliesst jede <<REDACTED>>-Sektion vom Push aus, ein Privkey ist ueber Golden
Config gar nicht deploybar. Auflage: Backup vorher, intended config danach zurueck
nach Nautobot. Scope: nur dieser Bring-up.
Damit das ein einmaliger Bootstrap bleibt, ist das Secret-Handling-Design
dokumentiert: ein privater Schluessel ist Geraete-Identitaet, keine Konfiguration
(wie ein SSH-Hostkey). Der private Teil entsteht am Geraet und geht nie weg, nur
der oeffentliche kommt in die SoT und wird in die Peer-Configs gerendert.
Stufe 2 (nautobot-secrets-providers + Vault) lohnt bei 4 Geraeten und einem Key
nicht. Nebenbefund: die WG-Peers fm/dw stehen mit hartkodierten public-keys im
Jinja-Template — Public Keys sind Daten, keine Templatezeilen.
3) TP24 — USV aus TP15 herausgeloest (User-Entscheid)
Die DC-USV war der letzte offene Rest in TP15 und hat mit Switching/Routing
sachlich nichts zu tun (eigene Einkaufs-, Verkabelungs- und Elektrik-Logik).
TP15 ist damit inhaltlich zu. TP24 traegt jetzt 48V-Bus, MeanWell/LiFePO4,
Laufzeiten, DC-Eingangs-Tabelle und die 5 offenen Entscheidungen — darunter neu
die Standortfrage, die sich durch den Core-Umzug ins UG neu stellt.
4) DOKU-AUFRAEUM-SESSION A-E abgearbeitet
- Ist-Stand-Block neu geschrieben, live gegen die Geraete geprueft. Alte Fassung
als ausklappbare Historie, ⚠️-Provisorium entfernt.
- Reihenfolge-Abschnitt auf den echten Rest-Pfad TP5 -> TP6 eingedampft (Punkt 3
sagte noch "Jetzt: Omada-PVID-Fix").
- Stale ap1-als-Router-Aussagen in TP3/TP4/TP15/TP16.1/TP21/TP-R korrigiert —
fortgeschrieben, nicht ueberschrieben.
- CLAUDE.md: Mac mini .41.167 -> .20.167 (war stale, live per ARP bestaetigt),
branch-Uplink "sw1 GE8" -> "core ether8", ALLNET-/Omada-Gotchas als Historie.
- switch/ als Archiv gekennzeichnet (Geraet ausgebaut, Runner nicht ausfuehrbar).
- omada-mcp + CF-Ingress live gegengeprueft: beides sauber, Punkt abgehakt.
Nebenbefund, eingetragen aber nicht angefasst: das CF-Tunnel-HA ist degradiert
(bf-nas und bf-pve mit je nur einem Connector), und vier tote Alt-Tunnel tragen
VLAN1-Origins — darunter die Aufloesung des "unidentifizierten VLAN1-Geraets
.41.133" aus TP19 (es ist das coolify-Origin).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nimmt die 4 Live-Geräte (crs326-core/-branch, ap1, ap2) real unter Golden
Config: Backup -> Compliance -> intended -> kontrollierter Push. Damit greift
der Governance-Entscheid "Config exklusiv über Nautobot" operativ.
Secret-Leak geschlossen (Anlass, ungeplant gefunden)
Es gab keine ConfigReplace-Regeln, deshalb hatte der Backup-Job den
ap1-/export ungefiltert nach Gitea geschrieben: der live genutzte
WG-Hub-private-key und 6 WLAN-PSKs lagen dort im Klartext.
- nautobot/ingest-gc-scrubbing.py: 5 ConfigReplace-Regeln, Maske
"<<REDACTED>>". RouterOS quotet nur bei Bedarf (4 von 6 PSKs standen
unquotiert), daher Alternation mit der quotierten Variante zuerst --
\S+ ist greedy und würde bei einem PSK mit Leerzeichen den Rest
exponieren. Regex-Selbsttest läuft bei jedem Aufruf.
- Gitea-Repo neu angelegt (History-Rewrite verworfen: Gitea hält
unerreichbare Blobs bis zum server-seitigen gc). Verifiziert: 0
unmaskierte Secrets über alle 4 Geräte. User-Entscheid: nicht rotieren.
- push-gc-template.py: Pre-Push-Secret-Guard, --dry-run, -m, sha optional.
Template
- AP-Zweig (role == "Wireless AP"), datengetrieben aus ConfigContext
ap-common + local_config_context_data; ap1/ap2 differieren nur in 4
Werten. RadioProfile verworfen (hängt an einem Controller, den es seit
der CAPsMAN-Abschaffung nicht gibt).
- crs326-core-Zweig von Slash- auf /export-Form (Space-Form, Attribute
alphabetisch), stale disabled=yes aus der Cutover-Ära entfernt.
- Switch-Zweig für crs326-branch.
- Mgmt-Nummernplan korrigiert: ap2 und branch waren in den DNS-Statics
vertauscht, ap1 zeigte auf ein nicht existierendes .99.3.
Verbindlich: core .99.1 | branch .99.2 | ap1 .99.11 | ap2 .99.12.
Ergebnis: ap1 intended == Geräte-Ist (0 Drift), core 68/69 Zeilen
byte-identisch. 14 ComplianceRules, 51/56 compliant -- die 5 Restdrifts
sind echte Altlasten (Rettungspfade, Aufräumen gehört zu TP19).
Deploy (nautobot_config.py, Image gc9)
enable_plan/enable_deploy an. napalm-ros ist READ-ONLY: der Default-
Dispatcher wählt NAPALM (Platform trägt napalm: ros), Backup geht,
merge_config scheitert grundsätzlich mit leerer Fehlermeldung. Fix =
custom_dispatcher auf NetmikoMikrotikRouteros, in den Golden-Config-
Settings (nicht den Nornir-Settings). Pilot-Deploy: DNS-Statics auf dem
Core korrigiert, per Purge-vor-Add, weil plan_type=missing nur add
erzeugt und sonst Duplikate entstanden wären.
Governance-Regeln in docs/teilprojekte.md festgeschrieben: Pläne nur
feature-scoped (ein Voll-Push schriebe die Maske als PSK auf die APs),
AP-Template nie zeilenweise auf ein laufendes Gerät (vlan-filtering=no
reisst den Mgmt-Pfad ab).
CLAUDE.md: Power-Save-Fehldiagnose korrigiert
Der P750W war nicht im Power-Save, sondern schlicht ausgeschaltet; das
Ping-Symptom kam vom lokal mitlaufenden WARP-Client (cloudflared =
QUIC-Proxy, kein ICMP). Die Merkregel "DHCP-geht-aber-Ping-nicht =
ARP/Power-Save" ist damit widerlegt und entfernt; strukturell schliesst
TP16.1 diese ICMP-Lücke.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hardware-Tabelle + TP1: ALLNET Core-Switch als außer Betrieb markiert (2026-08-08,
User-Bestätigung) — durch crs326-core (L3-Router + Core-Switch) physisch abgelöst.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TP20: Postgres-16-LXC (105, pve, 10.40.20.20) provisioniert, UTF8/en_US.UTF-8,
wal_level=replica, DB+Rolle nautobot angelegt, End-to-End verifiziert. archive_mode
bewusst noch aus bis TP18/pgBackRest steht.
TP21: Nautobot-Stack (ghcr.io/nautobot/nautobot:3.1.7) als Portainer-Stack auf NAS
live (App+Worker+Scheduler+Redis), DB=platform-pg, API-Smoke-Test grün. Healthcheck-
gated Worker/Scheduler-Start ergänzt (Migration-Race-Condition beim Erstboot gefixt).
TP19.1: sw2 jetzt final auf 10.40.99.12 (statisch) — Christoph über Klickanleitung.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TP2.1 (sw2-Standalone-Recovery) von Christoph solo abgeschlossen. TP19-Live-Sweep
auf ap1 zeigt VLAN1 schon viel weiter zurückgebaut als dokumentiert (defconf-DHCP
bereits disabled, cudy1→VLAN10 umgenutzt, cudy2 tot) → neuer Unterpunkt TP19.1 für
den VLAN99-MGMT-Cutover. TP14.1-Rest obsolet (kein Omada-Re-Adopt mehr), TP14.3
DNS-Sweep fertig (nas/docker-Records auf ap1 korrigiert, omada/omada-mcp/fritzbox-
Records entfernt, da Controller von Christoph komplett gelöscht wurde). RouterOS-
Config-Backups (enthalten Live-WiFi-Passphrasen) neu gitignored.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
vmbr0.20 (kaputte Netzadresse statt Host-IP) auf 10.40.20.100/24 korrigiert,
Default-GW live geflippt (ifreload -a, kein Reboot). CF-Ingress bf-pve
(pve/j44d6tua-ssh) + ap1-DNS nachgezogen; dabei Alt-Bug gefunden und gefixt
(pve-mcp.bf.lan zeigte noch auf .41.173 statt .20.173).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- pve-mcp „Failed to connect" = mcp-pve 0.4.8 kann nur 1 MCP-Session
("Server already initialized") → Upgrade 0.6.1 (Per-Session), ✔ Connected.
omada-mcp war/ist gesund (frische Session-ID pro Init).
- Kollateral: VLAN20-Host-DNS auf NAS+LXC zeigte noch auf totes .41.254
→ docker-pull scheitert; LXC pct set .20.1, NAS Synology-DHCP-DNS-Falle.
Neuer Gotcha in CLAUDE.md.
- TP16 (neu, hochdringlich): FQDNs via CF „sehr unsicher" = #1033-Round-Robin
zurück; Live-Snapshot 2026-07-10: bf-Tunnel 2 statt 3 Connectoren, alle
frisch (2026.7.1), Origins nach VLAN20-Move erneut asymmetrisch zu auditieren.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Liwest hat die FritzBox dauerhaft gegen ein Arris-Kabelmodem getauscht
(2026-07-01). WAN läuft jetzt über den Core-Switch statt ether1, ap1
zieht die öffentliche Liwest-IP direkt. Telefonie entfällt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Root cause: ap2 (CAP, local forwarding) hatte bridge vlan-filtering=no →
datapath.vlan-id wurde nie getaggt → alle WLAN-Clients (main/media/iot/…)
egressten ungetaggt in VLAN1 → OG-iPhone-Drops beim Roaming ap1↔ap2.
Fix wie ap1: VLAN1 untagged=bridge,ether2 (Mgmt), 10/30/40/50/90 tagged
auf ether2 + wifi1/wifi2 als tagged-Member (nur Master-Radios sind
Bridge-Ports, CAPsMAN legt das auf dem CAP nicht an). As-built +
teilprojekte.md TP3.1 + CLAUDE.md-Gotcha. OG-Funktionstest offen (User).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DW/Geli on-site abgeschlossen (2026-06-27): Geli auf 10.95.10.0/24
renumbert, FB-WG single 10.95.10.1/24, alter FB↔FB-WG geswappt.
End-to-End verifiziert (macmini/Linz → Gelis 24/7-APs .246/.247,
echte LAN-IPs, kein 10.255.255.x-NAT-Leak). FM+DW live im Double-NAT.
Doku/Status von "🅿️ vertagt/geparkt" auf Ist-Stand gezogen, Bridge-Gate
an allen Stellen aufgelöst, stale 192.168.178-Referenzen bereinigt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ersetzt manuelles Referenzieren von Zusatzdateien beim Sessionstart.
HANDOVER.md als Archiv-Dokument markiert; teilprojekte.md bleibt kanonisch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>