Eine frische Session hat nach Core und CAPsMAN gefragt, weil die Datei sich selbst widersprach. Ursache war nicht fehlende Information, sondern dass bei Statuswechseln jeweils nur der neue Abschnitt geschrieben und der alte Header stehengelassen wurde: - TP3 trug im Header "beide hAP ax2 sind reine Standalone-APs, CAPsMAN abgeschafft", und sein Lesehinweis verwies als "Ist-Stand" auf den 08-08-Eintrag. Wer die WLAN-Frage hatte, landete zuerst dort -- und bekam die falsche Antwort. TP3 ist jetzt als vollstaendig historisch markiert und verweist auf TP28. - TP3.3 stand als "TODO (neue Session)", obwohl es seit 08-17 in TP25 aufgegangen ist. - TP28 selbst trug unter dem Header "KOMPLETT" noch einen Punkt "OFFEN -- das GC-Modell beschreibt weiter Standalone-APs" mit der stale Zahl 76/76. Das war mein Rest vom 18.: Header umgeschrieben, Punkte darunter nicht. - Die Abnahme in doku-cleanup-session.md verlangte woertlich "kein CAPsMAN" -- ein Kriterium, das den falschen Zielzustand beschreibt, bestaetigt genau die Session, die den ueberholten Stand wiedergibt. - Dazu HW-Refresh-Zeile und die ft-over-ds-Notiz in TP25 nachgezogen. Merkregel, die jetzt an drei Stellen im Dokument steht: bei einem Statuswechsel nicht nur den Header umschreiben, sondern die Punkte darunter mitziehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
288 KiB
BF-Netzwerk — Teilprojekte (kanonische Steuerung, Stand 2026-06-10)
Zweck: Das große Netz-Projekt in einzeln durchziehbare Teilprojekte (TP) zerlegt — jedes mit klarem Scope, aktuellen Entscheidungen, Abhängigkeiten und Status. Jedes TP ist so geschnitten, dass es eine frische Session mit sauberem Kontext straight abarbeiten kann. Architektur/Historie:
~/.claude/plans/ich-will-das-delegieren-atomic-sunrise.md.
Kanonisches VLAN-Modell (gültig — überschreibt ältere Tabellen)
| VLAN | Name | Subnetz (Ziel) | Zweck |
|---|---|---|---|
| 10 | MAIN | 10.40.10.0/24 | Trusted (Handy/Laptop/Apple Watch) |
| 20 | INFRA | 10.40.20.0/24 | NAS/VMs/Docker/HA |
| 30 | IOT | 10.40.30.0/24 | Smart-Home (HA-managed), Waage, Fitness-Tracker |
| 40 | MEDIA | 10.40.40.0/24 | Sonos, AppleTV, TV, VuPlus, Cast-Ziele (getauscht ggü. früher) |
| 50 | UNTRUSTED | 10.40.50.0/24 | Spielekonsole, eBook-Reader, Low-Trust-Internet |
| 90 | GUEST | 10.40.90.0/24 | nur Internet |
| 99 | MGMT | 10.40.99.0/24 | Switch/AP/Hypervisor-Mgmt |
| 100 | WAN | (Arris-Transfer) | zum Arris-Kabelmodem (Liwest, Bridge-Mode, Public-IP an ap1) |
IP-Blöcke: .1–10 Router/Gateways · .11–20 Switches/APs. GW je VLAN = .1 (crs326-core). |
|||
Mgmt (VLAN99, Ist 2026-08-16): core .99.1 · branch .99.2 · ap1 .99.11 · ap2 .99.12. |
|||
| (Historisch, überholt: „ap1=.1, ap2=.2 · ALLNET=.11, Omada=.12" — aus der Zeit vor dem Core-Cutover.) |
Ist-Stand (Kurz)
Stand 2026-08-18 — live gegen die Geräte geprüft (MikroMCP/REST), nicht aus der Doku abgeschrieben. (Die Fassung vom 2026-08-16 stand bis zum 18. hier und war an vier Stellen überholt — Standalone-APs, RouterOS-Versionen, „plain 1.1.1.1", 68/68. Wer diesen Block liest, liest ihn als Erstes: er wird ab jetzt bei jeder Änderung mitgezogen, nicht nur die TP-Abschnitte.)
- Alle vier MikroTik laufen auf RouterOS 7.24 (stable, 2026-08-17 von Christoph selbst gehoben, TP27),
RouterBOOT ebenfalls 7.24 auf allen vieren (
current-firmware=upgrade-firmware, geprüft 08-18). - L3 + WAN-Edge =
crs326-core(CRS326-24G-2S+, Technik UG): Routing, DHCP (7 Server, 54 Reservierungen), DNS, NAT, NTP-Server für den Standort und der WG-Hub (TP10, Peersfm/dw) laufen hier. Mgmt-SVI10.40.99.1(vlan99), Gateway.1je VLAN. WAN =vlan100— DHCP-Client hält die öffentliche Liwest-IP90.146.33.177/24direkt vom Arris (Bridge-Mode) → kein Double-NAT. DNS-Upstream = DoH zum CF-Gateway mitverify-doh-cert=yes(TP23 Stufe 1 ✅ 08-18);servers=1.1.1.1steht nur noch als Bootstrap für den DoH-Hostnamen. - 🔥 Die Firewall ist deny-by-default — in BEIDEN Ketten (TP5 E3/E4 ✅ 08-18).
TP10-seal-lanistdisabled; Mgmt-Input kommt nur noch aus VLAN10, von HA (8728), von Nautobot (22) und übercf-mesh. Ein neuer Dienst über eine VLAN-Grenze braucht ab jetzt eine explizite Regel. - L2-Branch =
crs326-branch(Technik OG): reiner L2-Switch, Mgmt10.40.99.2, Uplinkether1→ coreether8. - WLAN = CAPsMAN auf dem Core (TP28 ✅ 08-17, GC-Modell nachgezogen 08-18): ap1
10.40.99.11(an coreether15), ap210.40.99.12(an branchether24), beide reine CAPs —cap enabled=yes,discovery-interfaces=vlan99. Die APs halten keine eigene WLAN-Config mehr; Kanäle, SSIDs, Security und Steering kommen vom Manager. 802.11r/k/v aktiv,ft-over-ds=yes. - SSDP-Relay (TP7.1 ✅ 08-18): LXC 108
mcast-relayauf pve, zweibeinig10.40.10.21(VLAN10) +10.40.40.21(VLAN40) — dafür trägtcore ether13beide VLANs. Die macOS-Sonos-App findet damit ihr System; mDNS macht weiterhin der Core. - Ausgebaut / gelöscht: ALLNET-
sw1und Omada-sw2sind physisch weg (2026-08-08 bzw. 2026-07-23, in Nautobot Decommissioned); Omada-Controller +omada-mcpgelöscht (2026-07-16); FritzBox 6660 raus seit 2026-07-01 (Liwest-Tausch auf Arris). VLAN1 ist leer (/ip arpaufbridge= 0 Einträge, 08-18) — TP19 ist geschlossen;cudy1hängt stromlos an coreether11, physischer Ausbau ist hands-on. - Kontrolle / Governance: MikroMCP für Reads/Debug (alle 4 Geräte in der Registry), Config-Änderungen ausschließlich über Nautobot Golden Config (TP21/TP22 — Deploy-Pipeline scharf, 92/92 Compliance-Checks grün, 0 Drifts bei 23 Rules, Stand 2026-08-18).
📜 Historische Fassung (Stand bis 2026-08-08, Topologie vor dem Core-Cutover — bewusst erhalten, nicht als Ist lesen)
ALLNET-Core
.11(FW2.2.1, VLANs 10/20/30/40/50/90/99/100; GE1/GE2/GE8 Trunk; TP1 ✅ 2026-06-15). Omada-Switch.12(adopted, TP2 ✅ 2026-06-15; Trunk-ALL auf P1+P2, Access-Profile auf P3-P8; Profile noch PVID=1 bis Omada-PVID-Fix). Omada-Controller.175(DS923/macvlan, mbentley 6.2, 🟢 live). omada-mcp.176(pve-LXC, StreamableHTTP, 🟢 live, 84 read-Tools; Controller-API v2 intern via christoph@emsenhuber.com). 2× hAP ax² (7.23.1): ap1.1(ALLNET P1) — TP4 ✅ 2026-07-01: Router + WAN-Edge (VLAN-Subinterfaces, DHCP, DNS, NAT, Public-Edge). ap2.2(Omada P2 — Trunk). Edge-Cutover ✅ 2026-07-01: FB6660 physisch entfernt (Liwest-Kabelmodemtausch, kein Zurück), Arris-Kabelmodem im Bridge-Mode; WAN =sw1 gi16 Access VLAN100 → gi15 Trunk → ap1 ether2 → vlan100 auf bridge(NICHT ether1); ap1 hält Public-IP direkt (Liwest, kein CGNAT), Double-NAT weg. Telefonie war auf der FB und wird nicht weitergeführt. Vorarbeit: TP10-Kern durch (2026-06-27, WG-Hub live) → Bridge-Gate vorher gelöst. Runbook:routeros/wan-cutover-runbook.md. Kontrolle: MikroMCP (MikroTik) live · ALLNET = Klickanleitungen · Omada → Controller + omada-mcp 🟢.
Nächster Schritt (Stand 2026-08-18): die TP6-Prämisse messen, nicht CAKE bauen.
TP6 wird hier seit Monaten als „DAS Ziel" geführt, aber docs/call-quality-diagnosis.md hat den
Bufferbloat 2026-06-16 bereits gemessen (A/A+, „CAKE wäre marginal, nicht deployt"). Die Messung
stammt aus der FritzBox-Ära, der Edge ist seither getauscht — also einmal gegen den heutigen Edge
nachmessen und dann entscheiden. Blocker gibt es keine mehr. TP5 ist in der Nacht auf den 18. abgeschlossen worden (Etappe 3 + 4: deny-by-default in forward und input, MGMT isoliert, seal-lan abgeschaltet), TP23 Stufe 1 (DoH auf dem Core) ebenfalls. Nebenher offen, blockiert nichts: TP25 (Signal-Boden + Re-Walk), TP28-Rest (die fünf wifi-*-Features vom AP-Scope auf den Core umhängen — die einzigen verbliebenen Compliance-Drifts), TP7.1 (SSDP-Relay für die macOS-Sonos-App), TP16.3, TP24.
Vorherige Fassung (Stand 2026-08-14, überholt): „TP5 — Deny-by-default am Ende von
forward." Alles Davorliegende ist durch: CRS326-Bring-up + L3-Umzug ap1→crs326-core(TP15/TP21.1 ✅ 2026-08-08), WLAN-Neuprovisionierung ohne CAPsMAN (TP3 ✅ 2026-08-08), Nautobot-Plattform + Fleet-Adoption + Deploy-Pipeline (TP21/TP22 ✅ 2026-08-13). Danach TP6 (CAKE) = das Projektziel. Kleine Follow-ups nebenher: DoH-Cloudflare auf core, DC-USV (TP24, seit 2026-08-16 eigener TP). ⚪ Omada-PVID-Fix ist obsolet (User-Entscheid 2026-07-22 — Omada spielt seit der TP15-Korrektur keine Rolle mehr im Netz, nie mehr aufgreifen). Vorherige Fassung (Stand 2026-07-22, erledigt): „TP15 CRS326-Bring-up als neuer L3-Core, danach WLAN-Neuprovisionierung ohne CAPsMAN; TP5 folgt nach TP21/CRS326-Adoption." 🎯 Ziel: sauberes System „from scratch", keine Leichen/Altlasten. Migrations-Session-Endstand = VLAN1 + altes cudy-WLAN komplett weg (VLAN1 nur noch Mgmt,defconf-Client-DHCP zurückgezogen, cudy-Uplinks aufs Ziel-Client-VLAN getaggt oder cudy abgebaut). Unterpunkte/Aufräum-Liste bei Migration: (a) die Interim-Härtung ap2wifi1/wifi2 frame-types=admit-only-vlan-tagged(TP3.1, 2026-07-06) bleibt gültig — verschwindet automatisch mit VLAN1; (b)→ kein Provisorium mehr (2026-08-13, TP3.3): Steering ist fester Bestandteil des Golden-Config-Templates + ComplianceFeaturest-main rrm/wnm= reines Roaming-Provisoriumwifi-steering— es war die Neuprovisionierung, die es stillschweigend verloren hatte; (c)cudy1 = verbleibender aktiver VLAN1-Leak→ ERLEDIGT (User-bestätigt + verifiziert 2026-08-14): cudy1 ist offline.core ether11trägt kein Link (keinR-Flag), Nautobot-Status Offline (TP22 Schritt 5). Damit existiert kein aktiver VLAN1-Leak mehr; der Dual-DHCP-Race ausproject_vlan1_dhcp_incidentist Historie. Der formale Teardown (Gerät ausbauen, Doku/Inventar) bleibt TP19. ⚠️ HW-Constraint hAP ax²: 1 GB RAM, aber nur 128 MB Flash + KEIN USB → Container auf dem Router NICHT praktikabel. Folge: native RouterOS-Features bevorzugen (z.B. Built-in-mDNS statt Container); Container (mDNS-Reflector, BIND9-DNS, Omada-Controller) laufen auf NAS/pve, nicht am hAP. 🔒 Governance-Entscheid (User, 2026-07-16, ausgeweitet 2026-07-16): Config ausschließlich über Nautobot — keine Direkt-Changes mehr an einzelnen im Netz verstreuten Geräten. Ursprünglich als ap1/ap2-Config-Freeze bis TP21 formuliert, noch am selben Tag verallgemeinert: jede Netz-Gerätekonfiguration (Router, APs, künftig auch die CRS326-Switches) läuft ab jetzt exklusiv über Nautobot Golden Config (TP21), sobald das steht — keine ad-hoc MikroMCP-Writes/UI-Klicks mehr an Einzelgeräten. TP19.1 war die letzte Ausnahme (ap1-DNS-Fix + ap2/sw1/sw2-Mgmt-VLAN-Umzug, s.u.) — davon ist nur der risikolose ap1-Teil noch direkt gemacht worden, ap2 wurde bewusst auf „nach Nautobot" vertagt. Macht Nautobot + alle Prerequisites (TP18→TP20→TP20.1→TP21, jetzt auch Komodo) zum aktuell kritischen Pfad, vor TP5/TP6. Betrifft nicht Software-Migrationen auf NAS/pve (anderes Substrat) und die Frage, ob sw1/sw2 vor der CRS326-Ablösung noch angefasst werden (offen, s. TP15/TP19.1). ✅ Genehmigte Ausnahme (User, 2026-07-17): der zentrale CF-Tunnel-Zugang auf ap1 (TP16/TP16.1). Alle für den zentralen Cloudflare-Zugang auf ap1 notwendigen (Vor-)Arbeiten dürfen direkt via MikroMCP/CF-API gemacht werden, ohne auf Nautobot GC zu warten — konkret die nativen WireGuard-Mesh-Zeilen aus TP16.1 (und analoge cloudflared/WG-Anpassungen am ap1-Edge). Begründung: Remote-Erreichbarkeit ist die Voraussetzung, um überhaupt sicher am Netz zu arbeiten (Henne-Ei zu Nautobot). Scope-Grenze: Die Ausnahme gilt nur für ap1. Sobald der zentrale Zugang später auf die CRS326 wandert (TP15), gilt die Ausnahme dafür vorerst NICHT — CRS326-Config läuft dann regulär über Nautobot GC (oder braucht eine eigene, dann neu zu erteilende Ausnahme). Nachtrag der ap1-Ausnahmezeilen in die GC als Follow-up, sobald Nautobot steht. ✅ Genehmigte Ausnahme #4 (User, 2026-08-16): die WireGuard-Zeilen des Cloudflare-Mesh-Bring-ups aufcrs326-core(TP16.1). Dürfen direkt via MikroMCP/REST gesetzt werden. Begründung ist strukturell, nicht bequem: TP22-Regel 1 schließt jede Sektion mit<<REDACTED>>generell vom GC-Push aus, und/interface wireguardist genau so eine — ein privater Schlüssel ist über Golden Config nicht deploybar. Damit ist die frühere TP16.1-Zusage „CRS326-Zeilen laufen regulär über GC" gegenstandslos. Auflage: vorher/system backup, danach Ist-Stand als intended config zurück nach Nautobot. Scope-Grenze: nur der Mesh-Bring-up aufcrs326-core— nicht spätere WG-Änderungen, nicht andere Geräte, und sie verlängert sich nicht automatisch. Langfristige Auflösung = das Secret-Handling-Design in TP16.1 (Privkey ist Geräte-Identität, nicht Config). ✅ Genehmigte Ausnahme #2 (User, 2026-07-22): der CRS326-Bring-up (TP15). Die Grundkonfiguration beider CRS326 — Management-IP, Bridge, VLAN-Filtering, Trunks/Access-Ports — darf direkt via MikroMCP/Winbox gemacht werden. Begründung = Henne-Ei: Golden Config kann nicht auf ein Gerät pushen, das im Werkszustand keine erreichbare IP hat, und die GC-Templates existieren noch nicht (TP21 „offen: Templates/intended config"). Auflage: der so entstandene Ist-Stand wird anschließend als intended config nach Nautobot zurückgeschrieben, danach übernimmt GC — die Ausnahme deckt das Bootstrapping, nicht den Dauerbetrieb. Scope-Grenze: gilt für die beiden CRS326 im Bring-up. Sie hebt die Regel für ap1/ap2 nicht auf (deren Neuprovisionierung läuft weiterhin über GC) und verlängert sich nicht automatisch auf spätere CRS326-Änderungen. Damit ist die frühere Formulierung in TP16.1 („CRS326-Config läuft regulär über Nautobot GC oder braucht eine eigene, dann neu zu erteilende Ausnahme") erfüllt — dies ist diese Ausnahme.
Teilprojekte
TP1 — ALLNET Core-Switch finalisieren ▸ ✅ FERTIG (2026-06-15) → ❌ Gerät AUSSER BETRIEB (2026-08-08, durch crs326-core ersetzt)
- ✅ GE8 Trunk (native vlan1, tagged 10/20/30/40/50/90/99/100) — war bereits aktiv.
- ✅ VLAN 40 umbenannt: UNTRUSTED → MEDIA (
switch/cli/04-vlan50-media-untrusted.cli). - ✅ VLAN 50 angelegt + benannt: UNTRUSTED.
- ✅ GE1/GE2 (AP-Trunks) um VLAN 50 ergänzt; GE8 auto-includiert (Trunk).
- Ergebnis: Core trägt alle VLANs (10/20/30/40/50/90/99/100) an P1/P2/P8.
TP2 — Omada Access-Switch + Controller ▸ ✅ FERTIG (2026-06-15)
- ✅ Omada Controller 6.2.10.17 auf DS923 (macvlan
.175):omada/docker-compose.yml, Stack via Portainer endpointId=14. Wizard abgeschlossen (configured=true), Creds inmcp/omada/.env. - ✅ pve-mcp (samik081) in Claude Code eingetragen (
~/.claude/settings.json, SSE.173:3000). - ✅ omada-mcp live auf pve-LXC (
.126, endpointId=2), ipvlan-IP.176, Stack Id=200, URL in~/.claude/settings.json.- Transport: StreamableHTTP
http://10.40.41.176:3000/mcp(Health/health→ 200). Settings-Bug (doppelter Eintrag) behoben 2026-06-15. - Auth: Omada Open API Client-Credentials. Creds in
mcp/omada/.env. Token-Format:Authorization: AccessToken=<token>(nicht Bearer). OMADA_TOOL_CATEGORIES=all (alle 84 read-Tools aktiv; write für VLANs/Ports nicht im MCP implementiert → direkte Open API oder Controller-UI). - omadac_id=
adbef8fa…, site_id=6a2fe68e….
- Transport: StreamableHTTP
- ✅ VLANs im Controller: 1/10/20/30/40/50/90/99/100 — alle angelegt, Switch adopted (switchConsistent=true).
- ✅ Port-Plan (ES208G, alle 8 Ports konfiguriert):
Port Name Profil Gerät Status 1 uplink Trunk-ALL → ALLNET GE8 ✅ korrekt 2 ap2 Trunk-ALL hAP ax² #2 ✅ korrekt 3 Port3 Access-MAIN — (frei) ⚠️ PVID=1 4 dock/monitor Access-MAIN Docking-Station ⚠️ PVID=1 · Lifeline-Port, nicht anfassen 5 drucker Access-MAIN Drucker ⚠️ PVID=1 6 Port6 Access-MAIN — (frei) ⚠️ PVID=1 7 macmini Access-INFRA Mac mini ⚠️ PVID=1 · fixe IP 10.40.41.x, nicht anfassen 8 ds923+ Access-MAIN NAS (2. Port) ⚠️ PVID=1 · nicht anfassen - ⚠️ Profile-PVID-Constraint (bis TP4 offen): NAS, Mac mini und andere Geräte haben fixe IPs im
Bereich
10.40.41.x(VLAN-1-Subnetz der FritzBox). Solange diese nicht auf VLAN-10/20-Subnetze migriert sind, mussnativeNetworkId=Default(VLAN 1)in allen Access-Profilen bleiben — sonst kein DHCP, kein Internet für diese Geräte. Fix nach TP4. - ⚠️ Bekannter Fehler
untagNetworkIds(Analyse 2026-06-15 via Controller-API v2): Access-MAIN hatuntagNetworkIds=[VLAN1, VLAN20, VLAN10](3 untagged!) statt[VLAN10]. Access-INFRA hatuntagNetworkIds=[VLAN20, VLAN1]statt[VLAN20]. Geräte erhalten Frames aus mehreren VLANs ungetaggt → Inter-VLAN-Tests verfälscht. Fix erst sinnvoll nach TP4 zusammen mit PVID-Korrektur. - Sichere Testports (kein kritisches Gerät): P3, P5, P6.
- ✅ Portainer-Ablösung: Komodo empfohlen (einzige Option mit nativem MCP
mcp-server-komodo). Eigener Task. - Abh. erfüllt: TP1 (GE8 Trunk ✅).
- → TP4 wird vorgezogen: Alle VLANs im Controller definiert (status=false = kein Management-IP, normal). Traffic läuft noch auf VLAN 1 bis TP4 die L3-Interfaces + DHCP-Server je VLAN aktiviert.
TP2.1 — Omada-Switch (sw2/ES208G) → Standalone-Recovery (kein Controller) ▸ ✅ FERTIG (2026-07-16, User solo)
- Root Cause: beim VLAN20-Umzug des Omada-Controllers (TP14.1, 2026-07-10) ist die Controller↔sw2-Verbindung zerbrochen (sw2 seither „Disconnected", ursprünglich als reiner Mgmt-Loss vertagt). Beim Rettungsversuch hat der User versehentlich einen Werks-Reset am Switch ausgelöst. Ein anschließender Wiederherstellungsversuch (durch Claude) hat Teile der Config unbemerkt halluziniert — der damalige „wiederhergestellte" Stand war nicht vertrauenswürdig.
- Entscheidung (User 2026-07-15): Controller-Zustand als invalid betrachtet, sw2 komplett neu — diesmal OHNE Managementsoftware. Kein Omada-Controller-Re-Adopt, kein Omada-Ecosystem-Anschluss (s. TP15-Korrektur — Omada bekommt generell keine Rolle mehr, auch nicht WLAN). sw2 direkt über eigenes Web-UI konfiguriert, wie ein eigenständiger Switch.
- ✅ 2026-07-16 (User-Aussage): „voll durch, Funktionsweise erfolgreich getestet." Nach dem gescheiterten Claude-Versuch hat der User sw2 komplett allein neu aufgesetzt (Runbook
docs/tp2.1-omada-switch-standalone-runbook.mdals Playbook-Referenz, nicht Schritt-für-Schritt-Log). Keine formale Einzelschritt-Verifikation dieser Session (kein Port-für-Port-Protokoll, keine Live-Prüfung durch Claude) — Status beruht auf User-Bestätigung „es geht einfach", nicht auf eigener Nachkontrolle. - sw2 bleibt Solo: „bekommt nie Geschwister" — keine weiteren Omada-Geräte geplant. Interimslösung bis zur Ablösung durch CRS326 (TP15).
- Offen/nachzuziehen (nicht blockierend): finale Portbelegung + IP von sw2 in
docs/ip-plan.md/CLAUDE.md-Hardware-Tabelle nachtragen (aktuell dort noch „Adoption pending" — stale, aber Wert unbekannt, nicht geraten);omada/.secretsauf neue Standalone-Creds prüfen; ob Omada-Controller-Container jetzt komplett überflüssig ist. - Abh.: TP1 ✅ (VLAN-Trunk am Uplink). Verwandt: TP15 (löst sw2 mittelfristig durch CRS326 ab), TP14.1 (Auslöser).
TP3 — WLAN ▸ 📜 VOLLSTÄNDIG HISTORISCH — der Ist-Stand steht in TP28, nicht hier
🔴 Lesehinweis (überarbeitet 2026-08-19): dieser gesamte TP ist Geschichte, von der ersten bis zur letzten Zeile. Er beschreibt zwei überholte Zustände nacheinander — die CAPsMAN-Ära (Juni/Juli 2026) und danach den Standalone-Rebuild vom 2026-08-08. Beides gilt nicht mehr: seit TP28 (2026-08-17) läuft das WLAN wieder über CAPsMAN, mit
crs326-coreals Manager; ap1/ap2 sind reine CAPs ohne eigene WLAN-Konfiguration.⚠️ Bis 2026-08-19 trug dieser TP im Header „beide hAP ax² sind reine Standalone-APs, CAPsMAN abgeschafft" und der Lesehinweis verwies als „Ist-Stand" auf den 08-08-Eintrag. Wer die WLAN-Frage hatte, landete zuerst hier — und bekam die falsche Antwort. Genau daran ist eine frische Session am 2026-08-19 hängengeblieben. Für den aktuellen WLAN-Stand: TP28 lesen, für Funkparameter TP25. Der Wert dieses TPs sind die Gotchas (VLAN-Leck ohne
datapath, Bring-up-Fallen), nicht der Status.
- ✅ 5 sichtbare SSIDs live, beide APs, beide Bänder, je SSID→VLAN (wifi datapath vlan-id):
dirtyvader-main(10, WPA3-only, FT),-iot(30, nur 2,4 GHz, WPA2+3),-media(40, WPA2+3, FT=no wg. Sonos),-untrusted(50, WPA2+3),-guest(90, WPA2+3). Alt-SSIDsinstall*/BF-Main/wv*entfernt. Temp-PSK (User setzt echte). - ✅ CAPsMAN-Architektur: ap1=Manager+AP (lokale Radios), ap2=CAP (dynamisch via Provisioning,
remote-cap=Ok). Kernlektion: Der Manager kann seine eigenen Radios NICHT über CAPsMAN provisionieren → ap1 lokal zuweisen (Master viaset+ statische Slave-VAPs), ap2 zieht Master+Slaves dynamisch. Ein CAP hält keine Eigen-Config. - ✅ Kanal-Plan (non-DFS, überlappungsfrei): ap1 ch36/5180 + ch1/2412 · ap2 ch149/5745 + ch11/2462.
(Auto-Channel hatte beide APs auf 5500-DFS/2437 gelegt = Co-Channel → fix gepinnt. ap2-Kanaländerung braucht
remote-cap provision-Push.)bound-Problem damit obsolet/sauber gelöst. - ✅ Sonos-Migration abgeschlossen (2026-07-02): alle 10 Sonos auf
dirtyvader-media/VLAN 40 mit MAC-fest reservierten DHCP-Leases indhcp-v40. Household geschlossen, iOS-App findet alle Geräte (mDNS via Repeater). Inventar/IPs = SSoTdocs/sonos-inventar.md(IPs haben sich verschoben — Arc jetzt.199, Arbeitszimmer-Paar auf.191/.192). - Vertagt: hidden
dirtyvader-infra(20)+-mgmt(99) (Mgmt verkabelt). TP8: eine 802.1X-SSID (dirtyvader-secure) mit FreeRADIUS-Dynamic-VLAN → dann PSK-main/infraeinstampfen (Konsolidierung). - SSID-Strategie-Entscheid (Begründung): unterschiedl. WPA-Typ/Band erzwingen separate SSIDs; „alles in 1 SSID per Auth" nur via 802.1X (Geräte ohne EAP wie Sonos/TV/IoT brauchen ohnehin PSK) → Hybrid in TP8.
- Mesh = NEIN (beide APs wired-trunk → Loop-Risiko). DoH-Upstream = Cloudflare Gateway (seit TP4 aktiv).
- Abh. erfüllt: TP4 ✅ (L3/VLAN-Interfaces). Folge: TP8 (802.1X), Sonos-Migration.
- 🔄 CAPsMAN wird abgeschafft (User-Entscheid 2026-07-22) — WLAN-Neuaufbau from scratch. Anlass: WLAN dauerhaft instabil, besonders wenn beide APs laufen. Beide APs bekommen künftig eigenständige, von Nautobot Golden Config identisch generierte RouterOS-Configs statt Manager/CAP.
- Begründung (kein Widerspruch zu Nautobot, aber ein echter Reibungspunkt): CAPsMAN erzeugt auf dem CAP dynamische Objekte (
wifi13–22), die nie in dessen eigener Config stehen → Golden-Config-Compliance sieht auf ap2 faktisch nichts. Genau diese Halbheit war die Ursache von TP3.1 (CAPsMAN schriebdatapath.vlan-idnicht auf die Leitung und legte die tagged-Member am CAP nicht an). - Was NICHT verloren geht: 802.11r/k/v braucht kein CAPsMAN, sondern nur gleiche SSID/PSK/Mobility-Domain → Fast-Roaming bleibt. Preis: Radio-/Kanaländerungen sind zwei Deployments statt eines Provision-Pushes — mit Nautobot ohnehin ein Job-Run.
- Reihenfolge: WLAN-Neuprovisionierung erst nach dem CRS326-Bring-up (TP15), da Routing/DHCP/DNS vorher umziehen.
- ✅ DURCH (2026-08-08): beide APs als reine Standalone-APs neu provisioniert, CAPsMAN weg. ap1
10.40.99.11(an coreether15), ap210.40.99.12(an branchether24); Uplink geräteseitig aufether1(PoE-Port,poe-out=off) umgestellt, ether2 aus dem Trunk entfernt. 6 SSIDs (main WPA3+FT / infra/iot/media/untrusted/guest WPA2+3, iot nur 2,4 GHz, media FT=no); jede SSID mit eigenemdatapathbridge+vlan-id → das TP3.1-„cfg-main-2g ohne datapath"-Leck ist strukturell weg. Kanäle non-DFS ap1 ch36/ch1, ap2 ch149/ch11. Client-Test grün (VLAN10/30-Leases korrekt). Configsrouteros/.secrets/ap{1,2}-prov-base.rsc, PSKsrouteros/.secrets/wlan-psks.env, As-built → Nautobot vianautobot/ingest-ap-rebuild.py. Einheitliches Admin-PW auf allen 4 MikroTik (User-Vorgabe). Henne-Ei beim Bring-up: Werks-192.168.88.1über Core-Temp-Pfad (192.168.88.2+ masq, wieder entfernt) via scp+/import; Werks-Inline-Overrides auf wifi1/wifi2 mussten geleert werden (!configuration.ssid !security.*), sonst funkt die Main-VAP die Werks-SSID. Offen: DoH auf core (nur plain 1.1.1.1), breiterer CLAUDE.md-Gotcha-Cleanup (ap1-als-L3-Router-Referenzen sind überholt).
- Begründung (kein Widerspruch zu Nautobot, aber ein echter Reibungspunkt): CAPsMAN erzeugt auf dem CAP dynamische Objekte (
TP3.1 — ap2 VLAN-Trunk-Fix ▸ ✅ Config live (2026-07-01) — routeros/tp3.1-ap2-vlan.rsc
- Root Cause: ap2 (CAP, local forwarding) hatte
bridge vlan-filtering=no→datapath.vlan-idwurde nie auf die Leitung geschrieben → ALLE WLAN-Clients auf ap2 (main/media/iot/…) egressten ungetaggt in VLAN1 (defconf/10.40.41.x) statt ins Ziel-VLAN. Symptom: iPhone (VLAN10) im OG „verbunden, aber sporadisch kein WLAN-Symbol" — beim Roaming ap1↔ap2 sprang es VLAN10↔VLAN1 (Subnetz-Flip → Abbruch). Sonos-Terrasse landete auf ap2 fälschlich auf10.40.41.183. TP3 „ein CAP hält keine Config" gilt nur für Manager-Forwarding — hier local forwarding, daher braucht ap2 doch VLAN-Config. - ✅ Fix (wie ap1): ap2-Bridge
vlan-filtering=yes; VLAN1 untagged=bridge,ether2 (Mgmt), VLANs 10/30/40/50/90 tagged auf ether2. Da nur die Master-Radios wifi1(5G)/wifi2(2.4G) Bridge-Ports sind (Slave-VAPs forwarden über den Master), zusätzlich wifi1/wifi2 als tagged-Member je Client-VLAN (wifi1: 10/40/50/90, wifi2: 10/30/40/50/90). CAPsMAN legt diese auf dem CAP nicht automatisch an → manuell gesetzt. Danachremote-cap provision. - Lockout-Risiko gehandhabt: ap2-Mgmt (10.40.41.2) untagged VLAN1 blieb erhalten; kein Scheduler (device-mode=home) → Recovery = Power-Cycle OG. Ausgeführt im leeren-registration-table-Fenster.
- ⏳ Offen — funktionaler OG-Test durch User: Handy auf
dirtyvader-mainim OG → Lease mussdhcp-v10/10.40.10.xsein (nichtdefconf/10.40.41.x). Falls kein DHCP: Omada-Port-2-Trunk (tagged 10/30/40/50/90) prüfen. - Abh.: TP3 ✅, TP4 ✅ (Bridge-VLAN-Muster gespiegelt). Config ap2-lokal (nicht CAPsMAN-verwaltet).
- 🔁 Interim-Härtung 2026-07-06 (Migrations-Provisorium, fliegt mit VLAN1 raus): Symptom „kein DHCP auf
dirtyvader-main, Altnetz ebenso, nichts geändert". Diagnose via MikroMCP (ap1+ap2): Dual-DHCP-Race — dieselben Main-MACs (56:71:6C:22:E6:A9,F2:62:4C:E1:AF:09,C0:C7:DB:DE:71:BE) hielten gleichzeitig eine korrekte VLAN10-Lease (dhcp-v10/10.40.10.x) und eine VLAN1-Lease (defconf/10.40.41.18x);defconfunddhcp-v10boten parallel →offering ... without success+ Minutentakt-Flapping.bridge-ARP auf ap1 = 333 Einträge (flache VLAN1 lebt voll weiter; IoT/Shelly untagged auf10.40.41.2xx). Griff: auf ap2 die Master-Radio-Bridge-Portswifi1/wifi2vonframe-types=admit-allaufadmit-only-vlan-tagged— untagged Main/Slave-Frames werden verworfen statt in VLAN1 gedumpt (im Zielbild ohnehin korrekt, daher kein Rückbau nötig, verschwindet mit VLAN1).ether2bleibtadmit-all(VLAN1-Mgmt/Trunk, kein Lockout). Rollback:frame-types=admit-allauf beiden Ports. ⚠️ Rest-Leak bleibt: cudy1 (altes WLAN) bridged Clients weiter untagged in VLAN1 — nur per Switch-Port-Tag bzw. Alt-WLAN-Abbau (Migration) zu schließen, NICHT auf der MikroTik-Seite. Zusätzlichst-main rrm=yes wnm=yes(802.11k/v, behandelt nur das Roaming-Symptom). SSoT-Detail: Memoryproject_vlan1_dhcp_incident. - 🎯 ROOT CAUSE des ap1-Lecks gefunden (2026-07-22, live aus
/interface/wifi/configuration print) — es ist KEINframe-types-Problem:cfg-main-2g(SSIDdirtyvader-mainauf 2,4 GHz, gebunden an Master-Radiowifi2) hat überhaupt keinendatapath-Block — wederbridgenochvlan-id. Das 5-GHz-Pendantcfg-main-5g/wifi1taggt sauber nach VLAN 10, 2,4 GHz taggt gar nicht → egress ungetaggt in VLAN 1. Ein Client, der zwischen den Bändern derselben SSID wechselt, springt damit10.40.10.x↔10.40.41.x— Subnetzwechsel mitten in der Verbindung. Erklärt das Dual-DHCP-Race und das „verbunden, aber sporadisch kein WLAN" ohne jede Zusatzannahme. Fix nicht mehr direkt anwenden — geht mit der WLAN-Neuprovisionierung (CAPsMAN-Abschaffung, TP3) über Nautobot ein. Nebenbefund:cfg-infraexistiert auf ap1, wird von keinem Interface benutzt (deckt sich mit TP3.3), und ap1 funkt real auf ch36/ch1 — die Interfaces überschreiben das Channel-Profilch-5g(5745/ch149). - 🔴 Update 2026-07-15: gleiches Leck jetzt auf ap1 vermutet.
dirtyvader-main-Clients bekommen zeitweise10.40.41.x-IPs statt10.40.10.x— identisches Dual-DHCP-Race-Muster wie oben, aber die 2026-07-06-Härtung wurde nur auf ap2 gemacht. Nächster Schritt: gleicheadmit-only-vlan-tagged-Umstellung auf ap1s lokalen Main-Radio-Bridge-Ports (⚠️ NICHTether2anfassen — das ist ap1s Mgmt-/WAN-Trunk-Pfad). Diagnose+Fix-Schritte:docs/tp19-vlan1-cudy-teardown-runbook.mdPhase A (~30-60 Min). Diese Härtung ist wie die ap2-Variante ein Provisorium, das mit TP19s VLAN1-Abbau automatisch obsolet wird.
TP3.2 — WLAN Coverage / P750W-Discovery ▸ ✅ ABGESCHLOSSEN (2026-08-17, User-Test erfolgreich) — docs/wifi-p750w-coverage-and-map.md
- ✅ Brother P750W (VLAN30) gelöst: DHCP-
client-id-Fix (matcht über MAC → feste10.40.30.5); an ap1 gepinnt (geordnete wifi-access-listaccept w2-iot→ blanketreject, überlebt ap2-Re-Provision) — dozende Legacy-Clients nur am co-located-GW ap1 per ARP erreichbar, CAP ap2 nicht; mDNSvlan30inmdns-repeat-ifaces+5353 → in MAIN auffindbar. Druck+Selbsttest OK. Web-UIhttp://10.40.30.5/general/information.html. - ✅ Nebenbei:
multicast-enhance=enabled(iot+media), Guestft=yes, INFRA-SSID(20) angelegt (nur ap2), Steering-Profilst-main/neighbor-group=bf-mainauf beide Main-Configs. - Nomenklatur: dynamische ap2-CAP-Slaves (
wifi13–22) nicht praktikabel umbenennbar (name-formatunzuverlässig) → Map dokumentiert statt umbenannt. Backupsbf-ap{1,2}-pre-nomen-20260702.backup/.rscauf den Geräten. - ⏳ Offene Coverage-Arbeit → ausgelagert nach TP3.3 (Fortsetzung in neuer Session).
TP3.3 — WLAN Coverage-Kur ▸ 📜 IN TP25 AUFGEGANGEN (2026-08-17) — offene Arbeit steht dort, nicht hier
⚠️ Der Header sagte bis 2026-08-19 „🔜 TODO (Fortsetzung, neue Session)" — dieselbe Falle wie bei TP3: ein Status, der nicht mitgezogen wurde. Der Re-Walk und die Dead-Spot-Kartierung sind Schritt 5 von TP25 und zwar bewusst nach den Funkparameter-Fixes; die 802.11k/v-Reparatur ist am 2026-08-13 erledigt worden. Was hier steht, ist Begruendung und Messhistorie.
- ✅ BEHOBEN 2026-08-13, noch am selben Abend (User: „aus Zeitgründen zuerst 11k/v, der nächste Call steht an").
st-main(rrm=yes wnm=yes neighbor-group=bf-main) auf beiden APs wiederhergestellt und ancfg-main-5g/cfg-main-2ggehängt — via GC-ConfigPlan, bewusst nicht per Direkt-Write: der Push läuft so NAS→Kabel→AP und nicht über die WLAN-Verbindung, die man gerade umkonfiguriert./system backupje AP davor (ap{1,2}-pre-steering-20260813.backup). Gegengeprüft am Gerät (nicht am Plan-Status):st-main rrm=true wnm=true ng=bf-main, beide Main-Configs verweisen darauf.- ⚠️ Erwartete Nebenwirkung: alle Clients haben kurz reassoziiert (ap1 25→2, ap2 7→14 unmittelbar danach) —
steering=auf einerwifi configurationzu setzen re-applied die VAPs, auch die nicht angefassten. Nach ~2 Min eingependelt (ap1 15 / ap2 13, VLAN30 = 28 Hosts auf der Core-Bridge). Nicht während eines Calls machen. - ✅ In GC verankert: Steering steht jetzt im AP-Zweig des Templates (
st-main/bf-mainals Konstante — es gibt genau eine Roaming-Domain pro Standort) + neues ComplianceFeaturewifi-steering. Eine künftige Neuprovisionierung kann es damit nicht mehr stillschweigend verlieren — genau das war der Fehler vom 2026-08-08. - ⏳ Offen: der Praxistest. Dieselbe Route noch einmal gehen. Reißt es weiterhin ab, ist es echte Coverage → Dead-Spot-Kartierung.
- ⚠️ Erwartete Nebenwirkung: alle Clients haben kurz reassoziiert (ap1 25→2, ap2 7→14 unmittelbar danach) —
- 🔴 Der Befund (2026-08-13): Steering war auf BEIDEN APs weg.
/interface/wifi/steering= 0 Einträge auf ap1 und ap2 (live geprüft). Vor dem Rebuild warst-mainmitrrm=yes wnm=yes+neighbor-group=bf-mainauf beiden Main-Configs gesetzt (s. TP3.2 + TP3.1-Interim). Die Neuprovisionierung am 2026-08-08 ausrouteros/.secrets/ap{1,2}-prov-base.rschat es nicht wieder angelegt.- Wirkung: kein 802.11k (Neighbor Reports → der Client kennt die Nachbar-APs gar nicht) und kein 802.11v (BSS Transition → der AP kann den Client nicht wegschicken). Der Client bleibt am sterbenden AP kleben, bis die Verbindung zusammenbricht, und muss dann komplett neu scannen + assoziieren = harter Abriss statt Übergabe. Genau das Symptom „einmal durch die Wohnung, WLAN weg" (User-Erlebnis 2026-08-13 während eines Telegram-Videocalls, musste auf 5G ausweichen).
- ⚠️
ft=yesist KEIN Gegenbeweis (auf beiden APs gesetzt,ft-mobility-domainbeidseitig leer = gleicher Default, FT selbst also intakt). 802.11r macht die Übergabe schnell, sobald der Client sie beschließt — es bringt ihn nicht dazu, sie zu beschließen. Ohne 11k/v fällt die Entscheidung viel zu spät. „FT ist an" ≠ „Roaming funktioniert". - Reihenfolge-Konsequenz: Diese Regression vor der Dead-Spot-Kartierung beheben und dieselbe Route nachlaufen — sonst kartiert man Löcher, die in Wahrheit Roaming-Verhalten sind, und zieht daraus womöglich Hardware-/Platzierungs-Entscheidungen (s. „ap1 ins Sideboard"-Idee unten).
- Weg (Governance): Steering gehört ins GC-Template (
/interface/wifi/steering+steering=an der Main-Configuration) → feature-scoped Deploy. Kein Direkt-Write. Betrifftwifi-configuration(bereits Compliance-Feature) + ein neues Featurewifi-steering.
- 💡 Idee „ap1 ersetzt den Sideboard-Switch" (User 2026-08-13): ap1 hat 4 freie Ports (
ether2–5;ether3/4/5sind bereits Bridge-Ports mitpvid=1,ether2ist seit der ether1-Umstellung kein Bridge-Port mehr und müsste wieder aufgenommen werden) → die Wohnzimmer-Multimediageräte könnten direkt an ap1, der Smart-Managed-Switch entfiele. Technisch machbar (untagged VLAN40 wiecore ether2), aber platzierungsgebunden: ein Media-Sideboard ist RF-mäßig einer der schlechtesten AP-Standorte (geschlossen, Metallgehäuse der AV-Geräte, niedrig). User-Vorgabe: Platzierung hat Vorrang vor dem eingesparten Gerät. Entscheidung daher erst nach der Steering-Reparatur + Re-Walk. Problem: Kanten/Terrasse grenzwertig — Clients (iPhone/iPad) landen bei −76..−89 dBm und springen zwischen allen 4 Main-Radios (ap1-5G/2,4G ↔ ap2-5G/2,4G) → „0–1 Striche + häufiger Abriss"; Terrasse auch mittags schlecht. FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
Bereits geklärt/erledigt (nicht nochmal aufrollen):
- NICHT config-verursacht (ap1 kein Reboot, RF-Konfig unverändert). TX schon am AT-Max (18/15 dBm, EIRP-Deckel — kein Hebel).
- Kanalplan intern überlappungsfrei (ap1 ch1/ch36, ap2 ch11/ch149). Steering
st-main/neighbor-group=bf-mainauf beiden Main-Configs gesetzt (hilft Client-Entscheidung, macht Signal aber nicht stärker). - ap1-only ist vom Tisch (echte Funklöcher) → beide APs nötig, aber besser platziert.
Offene Arbeit:
- Dead-Spot-Kartierung (Tageslicht): User stellt sich in jeden Problempunkt (Terrasse zuerst, entfernte Räume,
dicke Wand) → je Punkt
registration-table+monitor(Signal je Radio/Band/AP). Zusätzlich Nachbar-WLAN-Scan/interface/wifi/scanje AP (störend — wirft Clients kurz ab) gegen Abend-Congestion. Output → SSoT-Doku. - Remediation nach Befund: Platzierung (ap2 Richtung Schwachseite umstellen / 3. AP / Outdoor-Unit / Kabelweg);
Roaming-Feintuning (802.11v
transition-Schwellen ab 7.21, Band-Overlap reduzieren); Kanalplan aus Scan nachziehen. - INFRA(20) auf ap1 ergänzen (fehlt — sendet nur auf ap2): lokaler
w2-/w5-infra-Slave analog w2-/w5-media. - Danach Re-Walk-Test (wie 2026-07-02, aber mit Kartierung als Baseline).
Sicherheitsnetz: Backups bf-ap{1,2}-pre-nomen-20260702.backup/.rsc auf den Geräten. Kontext-Memory project_wifi_coverage
ref_wifi_powersave_multicast. Abh.: TP3 ✅, TP3.1 ✅, TP3.2 ✅.
TP4 — Router-Cutover (hAP#1 = Router + WAN-Edge) ▸ ✅ FERTIG (2026-07-01) — ⚠️ Rolle seit 2026-08-08 auf crs326-core (TP21.1); alles unten beschreibt den damaligen ap1-Aufbau und gilt als Historie/Referenz, nicht als Ist
- ✅ Bridge VLAN-Filtering aktiviert (
vlan-filtering=yes); VLAN-Tabelle: VLAN1 untagged bridge+ether2, VLANs 10/20/30/40/50/90/99/100 tagged bridge+ether2. - ✅ VLAN-Subinterfaces: vlan10/20/30/40/50/90/99 auf bridge; je GW
.1(10.40.10.1 … 10.40.99.1). - ✅ DHCP: dhcp-v10…dhcp-v99 je auf eigenem VLAN-Interface, pools .100-.200, GW+DNS = VLAN-GW.
- ✅ DNS: RouterOS-nativ, allow-remote-requests=yes. Upstream seit 2026-06-16: DoH Cloudflare Gateway (
use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query, verify-doh-cert,servers=1.1.1.1als Bootstrap; FB-Upstream abgelöst). Statische Einträge für alle Infra-Hosts unterbf.lan(13 Einträge, Transition-IPs bis PVID-Fix).- ⚠️ Auto-Suffix
.lan(RouterOS-Einschränkung, kann nicht auf leer gesetzt werden) — TP5-Cleanup.
- ⚠️ Auto-Suffix
- ✅ NAT: srcnat masquerade out-interface=vlan100 (ap1 = Public-Edge; kein Double-NAT mehr). Fallback-Konfig für ether1 bleibt reversibel dokumentiert (
routeros/wan-cutover-runbook.md). - ✅ Routing-Tabelle: 0.0.0.0/0 via Liwest-Gateway auf vlan100; alle 7 VLAN-Subnetze als Connected-Routes aktiv.
- ✅ Edge-Cutover vollzogen (2026-07-01): FritzBox 6660 physisch weg (Liwest hat gegen ein Arris-Kabelmodem im Bridge-Mode getauscht — kein Zurück). WAN =
Arris → sw1 gi16 Access VLAN100 → gi15 Trunk → ap1 ether2 → vlan100 auf bridge(NICHT ether1). ap1 hält Public-IP direkt (Liwest, kein CGNAT). WAN-Input-Seal live (TP10-seal-Regeln: est/inv/dhcp/icmp/lan/wandrop iminput-Chain,list_firewall_rules2026-07-02 verifiziert). Telefonie war auf der FB und wird nicht weitergeführt (User-Bestätigung 2026-07-02). - DNS-Entscheidung (Technitium und externer BIND verworfen): RouterOS-DNS als Resolver, keine DHCP→DNS-Auto-Registrierung (soweit möglich). Infra-Hosts als statische
/ip dns static-Einträge unterbf.lan; dynamische Clients bewusst ohne Namen. Filtering/DNSSEC via DoH-Upstream (TP3). HA: 2. Resolver auf ap2, statische Einträge beidseitig pflegen. - Abh.: TP1 ✅. TP3-Abhängigkeit entfällt (WLAN läuft weiterhin über FB bis TP3).
- Ermöglicht jetzt: PVID-Fix in Omada-Profilen (MAIN→PVID10, INFRA→PVID20), untagNetworkIds-Bereinigung, DHCP-Reservierungen für NAS/macmini/pve auf neue VLAN-Subnetze migrieren.
TP5 — Firewall & Inter-VLAN-Policy ▸ ✅ DURCH (2026-08-18): deny-by-default in BEIDEN Ketten scharf · + E5 (2026-08-19) — 📋 docs/tp5-deny-by-default-runbook.md
📌 „DURCH" heißt nicht „abgeschlossen". E5 (MAIN→IOT) kam einen Tag nach dem Drop — unter deny-by-default braucht jeder neue Dienst über eine VLAN-Grenze seine Regel. Weitere Etappen sind normaler Betrieb, kein Rückschritt. Der Weg dahin ist immer derselbe: erst den Drop-Log lesen, dann die Regel schreiben.
-
✅ ETAPPE 5 (2026-08-19):
MAIN → IOTaufgemacht —routeros/tp5-e5-main-iot.rsc, Backupcore-pre-tp5-e5-main-iot-20260819.backup, Compliance danach 92/92, 0 Drifts.- Auslöser (User): Brother P750W und die Shellys aus VLAN10 nicht erreichbar. Der Drop arbeitete
korrekt — es gab schlicht nie eine
vlan10→vlan30-Zeile. Offen waren nurMAIN→MEDIA,MAIN→INFRA,MAIN→MGMT; IOT fehlte als einziges Paar in der Liste. - 🔴 Merkregel: der Drucker fällt mit
udp/161auf, NICHT mit631. Im Drop-Log stehen 40 Zeilen SNMP nach10.40.30.5und kein einziges IPP — macOS fragt zuerst den SNMP-Status ab und bricht ab, bevor es überhaupt zu IPP kommt. Wer nur 631 whitelistet, repariert nichts. - Log-Matrix
in:vlan10 out:vlan30: 497 ICMP · 489udp/5353· 489udp/137· 237udp/3722(Apple-Continuity →.30.201) · 40udp/161. Quellen:.10.183(1596 Zeilen, Sweep über alle 254 Adressen),.10.180(118),.10.82(38). - Entscheid (User): voll einbahnig, kein Portfilter. MAIN steht zu INFRA/MEDIA/MGMT ohnehin
ungefiltert offen — und INFRA hält NAS, Proxmox und Nautobot, also deutlich mehr Wert als die
Shellys. MAIN→IOT eng zu filtern wäre Symbolik, kostet aber bei jedem neuen IoT-Gerät eine Runde
Fehlersuche. Der Sicherheitswert sitzt in der Gegenrichtung:
IOT→MAINbekommt bewusst keinacceptund bleibt gedroppt; Antworten laufen überdefconf: accept est,rel,untracked. - Abnahme am Gerät (von
10.40.10.82, also der Quelle aus dem Log):.30.5ICMP 0 % Loss,snmpget sysName.0→P750W, tcp/631+9100+80 offen;.30.202/.203/.221HTTP 200..30.201bleibt still — kein Firewall-Thema mehr (die Regel ist ungefiltert), Gerät aus. - ⚠️ Bewusste Nebenwirkung: der Subnetz-Sweep von
.10.183läuft ab jetzt durch statt im Drop-Log aufzulaufen. Betriebsneutral, aber der Log wird an dieser Stelle leiser — nicht mit „Problem gelöst" verwechseln, wenn später jemand die Log-Rate als Metrik liest. - 🔧 Werkzeug-Fix nebenbei:
gc-manual-plan.py --assertURL-encodet die Query jetzt. Ein Kommentar mit Leerzeichen (TP5-E5: MAIN->IOT) warfhttp.client InvalidURL— nach dem erfolgreichen Deploy, d.h. der Change war durch und nur die Gegenprüfung crashte. Das ist die schlechtere Reihenfolge: man steht mit einem Traceback da und weiß nicht, ob es gewirkt hat.
- Auslöser (User): Brother P750W und die Shellys aus VLAN10 nicht erreichbar. Der Drop arbeitete
korrekt — es gab schlicht nie eine
-
✅ ETAPPE 3 + 4 DURCH (2026-08-18, nachts).
forwardundinputenden jetzt mitdrop, die Log-Regel steht in beiden Ketten davor und protokolliert weiter, was der Drop frisst. Artefakte:routeros/tp5-etappe2-nachtrag.rsc,-etappe3-drop.rsc,-etappe4-input-mgmt.rsc,-etappe4-nachtrag-discovery.rsc(+ die beiden autorevert-abbestellen-Plaene). Backupscore-pre-tp5-{nachtrag,etappe3,etappe4}-20260818.backup.- 🔴 Das 70-Sekunden-Ergebnis aus Etappe 2 (die Log-Regel sei verstummt) war falsch. Ueber
dreieinhalb Stunden gemessen liefen 119 Zeilen auf, in vier Gruppen — drei davon haetten den
Drop zum Ausfall gemacht:
Zeilen Was Warum es die Whitelist nicht traf 92 Matter udp/5540, SwitchBot.30.227→ HAdie E2-Regel IOT->INFRA Diensteist TCP-only18 10.40.20.31→.99.{2,11,12}:22der Netmiko-Deploy kommt vom nautobot-worker, nicht vom Web-Container.20.30, auf den die E2-Regel lautete (deren Zaehler stand auf 0)8 .99.x:8728→ HARueckrichtung des Mgmt-Pfads, nach Conntrack-Ablauf als new1 Shelly .30.225:80→ HAgleiches Muster ➡️ Merkregel: ein Zaehlerstand ueber 70 Sekunden ist keine Messung. Und wer den Deploy-Pfad whitelistet, muss die IP des Workers nehmen, nicht die des Web-Containers. - 🔴 Fund in Etappe 4, der erst spaeter zugeschlagen haette: die CAPs finden ihren Manager per
Layer-2-Discovery.
/interface/wifi/capauf ap1 zeigtdiscovery-interfaces=vlan99undcurrent-caps-man-address: 04:F4:1C:B4:17:76%vlan99— eine MAC, keine IP. Der input-Drop verwarf MNDP (udp/5678); bestehende CAPWAP-Sitzungen liefen alsestablishedunbeeindruckt weiter, kaputt gewesen waere es erst beim naechsten AP-Reboot. Geschlossen mitTP5-E4: MNDP discovery(LAN) +TP5-E4: CAPsMAN capwap(nur vlan99). - 📌
inputist der riskantere Teil, nichtforward: der Core ist DNS- und DHCP-Server fuer alle sieben VLANs, und beides lief allein ueberTP10-seal-lan. Reihenfolge deshalb zwingend Ersatzregeln →seal-lan disabled=yes→ Drop.seal-lanwurde abgeschaltet, nicht geloescht (schnellerer Rueckweg, und der Auto-Revert greift genau dort an). - ✅ Nebeneffekt wie vorhergesagt: die 5
TP5: mDNS in vlanXX-Input-Regeln sind endlich scharf (vlan30 = 87, vlan20 = 13 Pakete binnen Minuten; sie standen seit dem 2026-08-14 auf 0). - 🎯 Abnahme am Geraet:
forward-Drop 11 Pakete in 15 Minuten — ausschliesslich die eigene pve→branch:22-Sonde;input-Drop nur Broadcast-Rauschen (MNDP auf VLAN1-nativ, NetBIOS 137/138 aus VLAN20, SSDP-Announcements einer Sonos aus VLAN40). Haus im Normalbetrieb: 23 Leases, 30 WLAN-Clients, beide CAPsOk, WAN steht. Funktionstest: Shelly aus INFRA200, Internet301, MacBook erreichbar,branch:22von pve aus zu (korrekt). Und der Pfadbeweis: ein GC-Deploy auf ap2 lief MIT scharfem Drop durch. - 🛟 Auto-Revert-Scheduler (10 min, Name ohne Bindestrich) lief vor jedem der beiden Schnitte und wurde nach bestandener Abnahme per eigenem Plan abbestellt.
- 🔜 Bleibt offen: die DNS-Bypass-Sperre — sie gehoert bewusst nicht hierher, sondern an das Ende von TP23 (Stufe 6), wenn die Ausnahme-Oberflaeche nachweislich traegt.
- 🔴 Das 70-Sekunden-Ergebnis aus Etappe 2 (die Log-Regel sei verstummt) war falsch. Ueber
dreieinhalb Stunden gemessen liefen 119 Zeilen auf, in vier Gruppen — drei davon haetten den
Drop zum Ausfall gemacht:
-
✅ ETAPPE 2 DURCH (2026-08-17) —
routeros/tp5-etappe2-whitelists.rsc, ConfigPlan86fbd528, Backupcore-pre-tp5-etappe2-20260817.backup.- Basis waren 43.027 Logzeilen aus dem Fenster 2026-08-16T17:21 → 2026-08-17T14:05 (Kollektor
10.40.20.18), also ~21 Stunden echter Nutzverkehr statt der 10-Minuten-Stichprobe von Etappe 1. Die vollständige Matrix:Paar Zeilen Dienste (Ziel:Port, absteigend) vlan20 → vlan9920.682 8728auf branch (7468) / ap1 (7468) / ap2 (5731) = HA-mikrotik-Integration ·:22je 8 = Nautobot-Netmikovlan10 → vlan208.082 macmini udp/37226234 (Continuity) · NAS66901578 · Nautobot8080137 · AirPlay700069 · pve-mcp300022 · HA958316 · pve:2212 · macmini49152/udp 59107je 8 · NAS:224 · Ollama114342vlan20 → vlan107.123 Rückrichtung Continuity (eigene Flows je Richtung) vlan20 → vlan306.238 HA pollt ~22 Shellys auf tcp/80vlan30 → vlan20306 .30.249→ HA8123(203) · macmini49152(1)vlan10 → vlan30237 nur udp/3722→.30.201= das iPhone im IOT-SSID (D2)vlan10 → vlan99214 Arbeitsplatz .10.82→ branch/ap1/ap2:22/:80/:443cf-mesh → *137 100.96.0.1→ Nautobot8080(62) · NAS6690(46) · macmini/NAS/branch/ap1/ap2:22· pve8006· pve-mcp3000vlan10 → vlan1017 same-VLAN mDNS 5353(vom Repeater auf dem Core)vlan40/vlan50/vlan900 ➡️ D6 bestätigt: Internet-only-Pinning ist risikofrei. out:bridgekommt nicht mehr vor (VLAN1-Rückbau hält). - Entscheidungen (User 2026-08-17): D1 = MAIN→INFRA pauschal (MAIN ist das Trusted-VLAN; 13 Einzelports
wären eine Wartungsfalle, die bei jedem neuen Dienst still bricht). D4 = MGMT named sources — MAIN komplett
- HA
.20.105:8728+ Nautobot.20.30:22+cf-mesh, Rest drop. D5 = beobachtetes8123+ MQTT als Absicht; Influx8086NICHT (nie beobachtet, der Weg läuft über HA).
- HA
- 🎯 ABNAHME am Gerät bestanden: 11 Regeln (
*1B–*25) existieren,disabled=false, alle vor der Log-Regel (place-before, sonst wäre das Gate unten nicht messbar), Selbstprotokolltp5e2: ENDE whitelist-regeln=11. Und der Zähler der Log-Regel steht: 54.129 bei 14:17:06 und unverändert bei 14:18:13; die letzte Zeile im Kollektor ist14:17:16— genau der Deploy-Zeitpunkt. Die Regel ist also verstummt. - ⚠️ Aber das ist noch KEIN Freibrief für Etappe 3. 70 Sekunden Stille sind keine Aussage — das Runbook verlangt bewusst „einige Tage", weil Geräte existieren, die einmal pro Woche funken (Backup-Jobs, Drucker-Discovery). Gate für Etappe 3: mehrtägiges Fenster ohne neue Zeilen.
- 📌 Zwei Dinge müssen VOR dem Drop passieren: (a) D2 — iPhone
.30.201ins MAIN-SSID umhängen (Hands-on Christoph); solange es im IOT-SSID hängt, killt der Drop die 237udp/3722-Flows. Eine Whitelist darauf wäre instabil, weil iOS pro SSID eine eigene Private Address vergibt. (b)seal-lanverengen (D4input-Teil), was zugleich die 5 toten mDNS-input-Regeln scharf schaltet.
- Basis waren 43.027 Logzeilen aus dem Fenster 2026-08-16T17:21 → 2026-08-17T14:05 (Kollektor
-
✅ ABNAHME DES VLAN1-RÜCKBAUS BESTANDEN (2026-08-16):
out:bridge= 0. 10-Minuten-Messfenster nach dem Wiederanschalten, Logdatei vorher geleert. Vorher warenvlan20 → bridge76 % des gesamten Inter-VLAN-Verkehrs. Die Rate fiel von ~166 auf ~34 Zeilen/min — der Rückbau hat das Log auf echten Nutzverkehr eingedampft. Wiederaufnahme überrouteros/tp5-etappe1-resume.rsc(GC, Backupcore-pre-tp5-resume-20260815.backup). -
📊 Beobachtete Matrix, 339 Zeilen / 10 min — das Arbeitsmaterial für Etappe 2:
Paar Zeilen was genau vlan20 → vlan99126 HA 10.40.20.105→10.40.99.2:8728+10.40.99.11:8728(je 67) = der Management-Pfadvlan20 → vlan3085 HA → IoT: .30.211:80(44),.30.8:10081(22),.30.244:8080Nuki (22),.30.5:631Drucker (4)vlan10 → vlan2065 Arbeitsplatz → INFRA vlan20 → vlan1061 INFRA → MAIN vlan10 → vlan102 mDNS 10.40.10.183:5353 → 10.40.10.82:5353— s.u. -
🔑 D4 ist damit belegt, nicht mehr geschätzt: der Management-Pfad ist HA (
10.40.20.105), das über seine viermikrotik-Integrationen8728auf branch/ap1/ap2 pollt (core.99.1erscheint nicht, weil dasinputist, nichtforward). Dazu MikroMCP vom Arbeitsplatz. Ohne Whitelist sperrt der spätere Drop die Verwaltung des eigenen Netzes aus. -
⚠️ Neuer Merkposten für Etappe 3 — same-VLAN-Verkehr erreicht die
forward-Kette:vlan10 → vlan10, unicast mDNS zwischen zwei MAIN-Clients, erzeugt vom mDNS-Repeater auf dem Core. Zwei Pakete in 10 Minuten, harmlos — aber ein blanker Drop am Kettenende würde sie treffen und damit Discovery innerhalb von MAIN beschädigen. Zusammen mitaccept out-interface-list=WANdie zweite Regel, die bekannt ist und nicht aus dem Log wiederentdeckt werden muss. -
✅ D2 vollzogen: iPhone ist im MAIN-SSID,
10.40.30.201steht im ARP auffailed. -
✅ Etappe 1 ausgerollt 2026-08-14 (über Nautobot GC, manual Config Plans; Backups
core-pre-/post-tp5-etappe1-20260814.backup). Auf dem Gerät:forward-Regelaction=log log-prefix="TP5-WOULD-DROP"am Kettenende, Syslog-Actiontp5syslog→ Kollektor10.40.20.18:514(syslog-ng-Containertp5-syslogauf dem Docker-LXC, Logs/opt/tp5-syslog/log/, 10-Minuten-Cron kappt bei 500 MB — der LXC hat nur ~2,5 GB frei).firewallist aus dem Memory-Ring genommen (topics=info,!firewall), sonst wäre der On-Box-Log tagelang unbrauchbar. Blockiert nichts. Artefakte:routeros/tp5-etappe1-log-lauf.rsc, Push-Werkzeugnautobot/gc-manual-plan.py. Compliance danach 16/17 (der eine Rotpunktip-address= bekannte VLAN1-Bring-up-IP10.40.41.211aus dem TP22-Backlog, keine neue Drift). -
🔴 Fund aus dem Log-Lauf, der Etappe 3 bestimmt: die Regel fing anfangs auch allen Internet-Verkehr (
out:vlan100, ~¼ der Zeilen in einer ruhigen Minute, unter Last mehr). Die Log-Regel steht deshalb jetzt aufout-interface-list="!WAN". Konsequenz für den späteren Drop: er darf NICHT bare ans Kettenende — davor gehörtaccept out-interface-list=WAN, sonst ist das ganze Haus offline. Diese Whitelist-Zeile ist damit bekannt und muss nicht aus dem Log wiederentdeckt werden. -
🔍 Erste Befunde nach 60 s (Rate nach Einengung ~166 Zeilen/min): 76 % des Inter-VLAN-Verkehrs ist
vlan20 → bridge, also INFRA nach VLAN1 — ein Monitoring-Host10.40.20.151scrapet ~10 tote/alte10.40.41.x-Ziele, HA.20.105zieht auf10.40.41.100:8006(pve unter seiner alten VLAN1-Adresse, real.20.100),.20.107auf10.40.41.10:8080. Das ist TP19-Material, das TP5 gerade sichtbar macht. Weiter:vlan20 → vlan99:8728(MikroTik-API auf branch/ap1/ap2 = der Management-Pfad selbst, muss in die Whitelist, betrifft D4),vlan20 → vlan30(HA → Drucker.30.5:631, Shelly, Nuki.30.244:8080),vlan10 ↔ vlan20(Synology Drive6690, Apple-Continuityudp/3722). -
✅ D2 entschieden (User 2026-08-14): iPhone wird ins MAIN-SSID umgehängt. Faktenlage war:
10.40.30.201, dynamische Lease, HostnameiPhone, MAC12:99:A6:AC:B0:CB= iOS Private Wi-Fi Address, aktiv aufdirtyvader-iotmit 748 MB rx. Die statische Reservierung10.40.10.196„iPhone" (andere private MAC — iOS vergibt pro SSID eine eigene) belegt, dass es dasselbe Telefon ist. Umhängen ist die Hands-on-Aufgabe von Christoph (SSID am Gerät wechseln +dirtyvader-iotvergessen lassen); technisches Argument: eine Whitelist auf eine rotierende Private MAC wäre ohnehin instabil. -
📋 Session-Runbook liegt (2026-08-14):
docs/tp5-deny-by-default-runbook.md— Ist-Stand live erhoben, beobachtete Inter-VLAN-Flow-Matrix (conntrack + Counter), 6 offene Entscheidungen (D1–D6), 4 Etappen mit Absicherung, Verifikation + Rollback. Kernansatz: Etappe 1 ist ein reiner Log-Lauf ohne Blockierung (action=logans Ende vonforward) — die Whitelist wird aus dem Log abgeleitet, nicht am Schreibtisch geraten. Drei Funde, die vorab eine Entscheidung brauchen: ein iPhone sitzt in VLAN30, ein ICMP-Dauersweep von.10.82auf alle Shellys, und vlan99 ist Mitglied derLAN-Liste (→seal-lanerlaubt Mgmt-Input aus jedem VLAN). VLAN50/90 tragen null Inter-VLAN-Verkehr → Internet-only-Pinning ist dort risikofrei. -
Deny-by-default + least-privilege (Ziel). MAIN→INFRA nur Whitelist-Dienste; MAIN↔MEDIA allow (+mDNS); UNTRUSTED/GUEST nur Internet; MGMT isoliert; Router-input gehärtet.
-
⚠️ Gerätewechsel beachten (2026-08-14 nachgetragen): der ✅-Block unten war ursprünglich auf ap1 verifiziert (2026-07-02) — ap1 ist seit 2026-08-08 Werksreset und reiner AP. Die Regeln sind beim Core-Cutover (TP21.1) mitgewandert, waren am neuen Gerät aber nie gegengeprüft. Am 2026-08-14 auf
crs326-corelive nachverifiziert (list_firewall_rules, chainsforward13 Regeln /input12 Regeln): alle unten gelisteten Regeln existieren, sind enabled, tragen ihreTP5:/TP10-seal--Kommentare und zählen Traffic. Merkregel: nach jedem Rollenwechsel eines Geräts gilt eine Verifikation vom Vorgänger nicht weiter. -
✅ Bereits live (ap1 2026-07-02 → re-verifiziert auf
crs326-core2026-08-14):forward accept vlan10↔vlan40— TP5: MAIN↔MEDIA (AirPlay/Sonos)forward accept vlan20↔vlan40— TP5: INFRA↔MEDIA (HA↔Sonos)input accept udp/5353 vlan10/vlan20/vlan30/vlan40— mDNS-Repeater (TP7-Anschluss)forward accept vlan90↔vlan40+input accept udp/5353 vlan90— GUEST→MEDIA (Sonos/Cast), permanent (TP7.2, 2026-07-03)- WAN-Input-Seal komplett (TP10-seal-est/inv/dhcp/icmp/lan/wandrop + WG-Hub UDP/51821 accept)
-
⏳ Offen: Deny-by-default am Ende von
forward(live bestätigt 2026-08-14: dieforward-Kette endet nachTP5: MEDIA->GUESTohne Drop → alles nicht explizit Erlaubte läuft durch); UNTRUSTED/GUEST auf Internet-only pinnen; MGMT isolieren; IoT→INFRA-Whitelist bauen. -
🔍 Befund beim Re-Verify (2026-08-14) — die 5
TP5: mDNS in vlanXX-Input-Regeln sind derzeit tot: sie stehen hinterTP10-seal-lan(in-interface-list=LAN, action=accept), das jeden LAN-Input schon vorher annimmt → Counter aller 5 mDNS-Regeln stehen auf 0 Pakete, währendseal-lan3,5 Mio. zählt. Kein Fehler und nichts zu tun — sie sind die Vorbereitung auf genau den Schritt, der noch aussteht: sobald der Router-inputgehärtet wird (seal-lanverengen/entfernen), werden sie scharf. Falle für die TP5-Session: erstseal-lanverengen, DANN testen — vorher beweist ein grüner mDNS-Test gar nichts, weil er überseal-lanläuft. -
📌 Ausgangslage für die Umsetzung (Live-Stand
crs326-core, 2026-08-14):forward= defconf (est/rel/untracked accept · fasttrack · drop invalid · drop WAN !dstnat) → 2× TP10-WG → 6× TP5-Holes (MAIN↔MEDIA, INFRA↔MEDIA, GUEST↔MEDIA), kein abschließender Drop.input= TP10-seal komplett (est/inv/dhcp/icmp/lan/wandrop) + WG-Listen 51821 + 5× mDNS. Der Deny-by-default-Griff ist damit eine Regel am Ende vonforwardplus die Whitelists davor — nicht ein Umbau der Kette. ⚠️ Governance: läuft über Nautobot GC (ip-firewall-*-Features aus TP22), nicht per Direkt-Write; vorher/system backup(TP22-Regel 3). ⚠️ Rettungspfad: ein zu früh gesetzter Drop killt Mgmt/DHCP/DNS quer durchs Haus — Reihenfolge Whitelists zuerst, Drop zuletzt, unddevice-modeauf core erlaubt scheduler → Auto-Revert-Scheduler als Sicherung ist hier möglich (anders als auf den hAPs). -
🔊 Im Paket enthalten (User-Vorgabe 2026-08-14): der macOS-Sonos-Client-Fix. Ist-Stand: iOS-App findet alles (mDNS via Repeater ✅), HA steuert/gruppiert sauber (Sonos-Panel, via static hosts +
advertise_addr, TP7.2 ✅) — nur die macOS-Desktop-App findet die Sonos-Umgebung nicht. Ursache ist bekannt und keine Firewall-Frage: die Desktop-App entdeckt per SSDP (UDP 1900), und RouterOS reflektiert nur mDNS, kein SSDP → die Discovery quert die VLAN-Grenze MAIN(10)→MEDIA(40) nicht. Dieforward accept vlan10↔vlan40-Regel ist bereits offen und hilft hier nicht, weil das Problem vor dem Verbindungsaufbau liegt. Fix = SSDP-Reflector (TP7.1) auf NAS/pve (nicht am Router — kein Flash) mit Bein in vlan10 + vlan40, plusinput accept udp/1900auf den bedienten VLANs. TP7.1 wird damit aus „vorgemerkt" in dieses Arbeitspaket gezogen und ist mit der Deny-by-default-Arbeit gemeinsam zu testen (sonst prüft man zweimal dieselbe Strecke). -
IoT→INFRA-Rückmeldung (deine Frage): IoT darf aktiv zu INFRA-Diensten initiieren — Firewall-Allow IoT→INFRA NUR auf MQTT (1883/8883), HA-API, InfluxDB (8086) o.ä.; Antworten via established/related; IoT→MAIN bleibt deny. So pusht ein Sensor Daten an HA/MQTT/Influx, ohne dass IoT „frei" ist.
-
Abh.: TP4 ✅ (L3-Basis, Rolle inzwischen auf
crs326-core), TP14.5 ✅ (Freigabe-Gate), TP22 ✅ (GC-Deploy-Pipeline = der vorgeschriebene Weg für den Push). Keine offenen Blocker mehr — TP5 ist der kritische Pfad. Folge: TP6 (CAKE). Hängt dran: TP5.1 (DNS-Redirect/Torch für Low-Trust).
TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt
- Kontext (2026-07-08/09): Airfryer „airschreier" (Philips/Versuni, ESP,
10.40.30.180) bekam per DHCP-Option 6dns 1.1.1.1als Override, weil das OTA-Update über den ap1-DoH-Gateway-Pfad nicht durchging (DoH-Latenz beim primitiven ESP-Stack — kein Content-Block, via Gateway-Logs bewiesen, s.memory/ref_esp_ota_doh_not_block). Nebenwirkung: public 1.1.1.1 = anonymer Consumer-Resolver ≠ accountgebundener Gateway-DoH (px35ynlol3.cloudflare-gateway.com) → DNS-Sicht auf das Gerät weg, Gerät umgeht zudem die Filterung. - (a) DNS-Redirect statt Geräte-Override (der dauerhafte Fix): dst-nat „UDP/53 (+TCP/53) von Low-Trust-Src → auf einen plain Resolver umbiegen" gibt Logging zurück UND funktionierendes OTA (kein langsamer DoH-Pfad fürs Gerät). Redirect-Ziel-Optionen: (i) ap1-Resolver mit nicht-DoH-Upstream für dieses Src-Set, (ii) direkt public 1.1.1.1 (dann nur Flow-Logging), (iii) eigener plain-Resolver. Sauberer als „Gerät verschwindet auf 1.1.1.1". Verortung: Teil des UNTRUSTED-Internet-only-Pinnings (TP5-„Offen"); Entscheidung v50-DNS-Policy (gefiltert vs. plain) hängt dran.
- (b) Live-Torch als Ad-hoc-Observability: DNS ist bei direktem 1.1.1.1 blind, Flows nicht (NATen über ap1).
torchaufvlan30/vlan50gefiltert auf die Geräte-IP zeigt Ziel-IPs live (Versuni → AWSeu-west-1IoT erkennbar). Voraussetzung: Gerät aktiv. Merkregel: Airfryer nur online wenn er kocht → Capture ans Einschalten koppeln. - Abh.: UNTRUSTED-Move des Airfryers (Kandidat, s. VLAN50) + TP5-Deny-by-default. Kein Blocker.
TP6 — QoS/CAKE + Call-Quality-A/B-Test ▸ 🟠 PRÄMISSE PRÜFEN, BEVOR gebaut wird (2026-08-18)
- 🔴 Der Widerspruch, der zuerst aufzulösen ist: dieser TP wird seit Monaten als „DAS Ziel" geführt —
aber
docs/call-quality-diagnosis.mdhat den Bufferbloat bereits gemessen und kommt zum gegenteiligen Schluss. Wörtlich in dessen Ergebnistabelle:CAKE / QoS | kein Bufferbloat-Spielraum | ❌ nicht deployt (wäre marginal), und im Kopf: TP6 „hat sich als Nicht-QoS-Problem entpuppt". Messwerte (2026-06-16): 3 Flows = 10,3 Mbit Upload gesättigt · idle 12 ms · Vollast avg 17,5 ms / max 26 ms → A/A+. Bei solchen Zahlen holt CAKE nichts mehr. - ⚖️ Was das relativiert: die Messung stammt aus der FritzBox-Ära. Seither ist der Edge komplett
getauscht (Arris im Bridge-Mode, NAT und Queuing liegen auf
crs326-core). Die Leitung ist dieselbe, das Pufferverhalten des neuen Edge ist ungemessen. - ➡️ Erster Schritt ist deshalb keine Konfiguration, sondern eine halbe Stunde Messen: Bufferbloat-Test gegen den heutigen Edge. Kommt wieder A/A+ heraus, ist TP6 erledigt statt offen und der kritische Pfad ist leer. Kommt es schlechter heraus, ist die Ursache neu und CAKE ist die Antwort darauf — dann aber mit einer Zahl als Begründung.
- 🔎 Fasttrack ist auf dem Core faktisch tot — und das ist kein Entwurf, sondern ein Unfall
(Befund 2026-08-18): die Regel
defconf: accept est,rel,untrackedsteht vordefconf: fasttrack, also wird Fasttrack nie erreicht. Live: 32.979.171 Pakete auf der accept-Regel, 0 auf der Fasttrack-Regel, 0 von 445 Verbindungen fasttracked.- Herkunft:
ap1hatte die Reihenfolge vor dem Cutover richtig (Fasttrack zuerst, wie im MikroTik-defconf). Umgedreht wurde sie beim handgebauten Core-Aufbau (TP21.1). - Für TP6 ist das günstig: Fasttrack umgeht die Queues, CAKE braucht sie — ein Konflikt, den man sonst erst auflösen müsste, existiert hier gar nicht.
- ✅ ENTSCHIEDEN (Christoph, 2026-08-19): der Zustand bleibt — und gilt ab jetzt als Absicht, nicht
als Unfall. Begründung: bei ~10 Mbit WAN kostet der Verzicht nichts (die Core-CPU trägt den
Forward-Pfad ohnehin, 32,9 Mio Pakete sind der Beleg), und für CAKE ist er die bequemere Ausgangslage.
Damit ist auch die TP21-Warnung „das Re-Baseline hat den Fehler zum Soll erklärt" aufgelöst: die
Reihenfolge in der SoT ist jetzt gewollt. Sie war es bei der Aufnahme nur nicht.
- ⚠️ Gegenbedingung, unter der neu bewertet wird: wenn Inter-VLAN je auf Gigabit soll (NAS ↔ MAIN läuft geroutet über dieselbe 800-MHz-CPU), ist der Verzicht teuer. Die Messung dafür steht aus — und sie, nicht die WAN-Zahl, ist die Vorbedingung jeder Neubewertung.
- ⚠️ Ungemessen ist der Preis: ohne Fasttrack läuft jedes geroutete Paket durch die volle Kette samt Conntrack, auf der Core-CPU. Für 10 Mbit WAN irrelevant, für Inter-VLAN-Transfers (NAS ↔ MAIN, Synology Drive) möglicherweise nicht. Das ist messbar und sollte gemessen werden, bevor jemand die Reihenfolge „repariert".
- 🔴 Und es steht seit 2026-08-18 als ABSICHT in der SoT: das Re-Baseline
(
ingest-core-firewall.py --apply) hat die Reihenfolge unverändert nach Nautobot geschrieben, Ruleip-firewall-filtermitconfig_ordered=true.Entscheidung nötig: Reihenfolge korrigieren (Fasttrack lebt wieder) · Fasttrack-Regel entfernen (ehrlich: wir nutzen sie nicht) · so lassen und hier begründet stehen lassen.→ entschieden am 2026-08-19, s. oben: so lassen. Damit stimmen SoT und Absicht wieder überein — bisher stimmten sie nur zufällig überein.
- Herkunft:
- 📋 Runbook liegt bereit:
docs/tp6-praemisse-messrunbook.md(2026-08-19). Es reproduziert die Methode von 2026-06-16 (3 Flows + 24 Pings idle/Last), misst erstmals auch die Download-Richtung (die 2026-06-16 nie gemessen wurde — beim asymmetrischen Kabelanschluss die wahrscheinlichere Problemseite), und trägt das Abbruchkriterium vor der Messung: A/A+ → TP6 wird geschlossen statt gebaut. Enthält außerdem den Bau-Kontext für den Fall B, damit er nicht neu recherchiert wird — vor allem:/queuefehlt im GC-Template und hat keine ComplianceRule (dieselbe blinde Stelle, die TP26 für/ip firewall filtergeschlossen hat), eine handgesetzte Queue wäre also driftend und ungeschützt. - 📌 Nicht im Repo dokumentiert und deshalb Teil der Messung: die tatsächliche Liwest-Linerate. Die „~10 Mbit" stammen aus der Sättigungsmessung von 2026-06-16, nicht aus einem Tarifdatenblatt. Ohne diese Zahl ist die übliche CAKE-Vorgabe „85–95 % Linerate" geraten.
- Abh.: TP5 ✅ (keine Blocker mehr). Vorgelagert: die Messung oben.
TP7 — Media-Discovery (mDNS) für VLAN 40 ▸ ✅ FERTIG (2026-07-02) — docs/tp7-mdns.md
- ✅ Built-in mDNS-Repeater aktiv — Live-Stand
crs326-core(verifiziert 2026-08-14):mdns-repeat-ifaces=vlan10,vlan20,vlan30,vlan40,vlan90→ MAIN/INFRA/IOT/GUEST ↔ MEDIA. Reversibel (Feld leeren). 📌bridge(=VLAN1) ist nicht mehr dabei — mit dem VLAN1-Retirement erwartbar und korrekt, war aber nie nachgezogen. Historische Fassung (ap1, bis 2026-08-08):…,vlan90,bridge—bridge=VLAN-1 seit TP7.2 2026-07-03. Realbestand: MAIN=iOS-Client + MacBook, INFRA=Home Assistant, MEDIA=10× Sonos (siehedocs/sonos-inventar.md). - ✅ Funktional durchgetestet (2026-07-02): iOS-Sonos-App (vlan10) und Home Assistant (vlan20) finden die
9 online-Sonos per
_sonos._tcp.local.(Bonjour) automatisch. Household nicht mehr gesplittet. - ✅ TP5-Anschluss live:
forward accept vlan10↔vlan40+forward accept vlan20↔vlan40+input accept udp/5353auf vlan10/20/30/40 sind gebaut (mit „TP5:"-Kommentar), damit Discovery + Steuerung + Streaming ohne Umwege gehen. - ⚠️ SSDP/Cast (UDP 1900) bewusst NICHT gebaut (bräuchte Reflector-Container auf NAS/pve; hAP hat kein USB/Flash). Konsequenz: macOS-Desktop-Sonos-App nutzt SSDP → quert die VLAN-Grenze NICHT und findet die Sonos nicht. iOS-App (mDNS) und HA-Integration decken den Nutzungsbedarf ab; Spotify Connect läuft über Cloud.
- Abh.: TP4 ✅, TP5 (Sonos-Holes) ✅ live.
TP7.1 — SSDP-Relay (macOS-Sonos-App über VLAN-Grenze) ▸ ✅ LÄUFT (2026-08-18) — User-bestätigt: „sonos ist da!"
- ✅ Umsetzung: eigener LXC 108
mcast-relayauf pve (Ubuntu 24.04, 1 Kern, 256 MB,onboot), zweibeinig:eth0= 10.40.10.21 (VLAN10),eth1= 10.40.40.21 (VLAN40), Default-Route nur über VLAN10, kein IP-Forwarding. Dazucore ether13(pve-Port) umtagged vlan10, vlan40erweitert (routeros/tp7.1-core-ether13-trunk.rsc). Software:alsmith/multicast-relayals systemd-Unitmulticast-relay.service.--noMDNSist Pflicht: mDNS reflektiert bereits der Core (TP7). Zweimal zu reflektieren erzeugt Duplikate.--ssdpUnicastAddr 10.40.10.21ist ebenfalls noetig — die Sonos antworten auf einen M-SEARCH per Unicast, und diese Antworten muessen zurueckgereicht werden.
- 🔑 Warum zwei Beine zwingend sind (Christophs Frage „vlan40 sollte keinen relay benoetigen?!?"):
SSDP ist link-lokales Multicast mit TTL 1. Der M-SEARCH des MacBooks verlaesst VLAN10 nie, die
ssdp:alive-NOTIFYs der Sonos verlassen VLAN40 nie. Ein Relay kann nur kopieren, was es selbst hoert — es muss Mitglied beider Broadcast-Domaenen sein. Routing hilft wegen TTL 1 nicht, undforward accept vlan10<->vlan40ist laengst offen: es scheitert vor dem Verbindungsaufbau, an der Entdeckung. Dass AirPlay funktionierte, passt genau ins Bild — das ist mDNS. - 🎯 Beweis im Log:
[Sonos Discovery] Relayed 268 bytes from 10.40.10.183:49358 on eth0 [ttl 64] to 255.255.255.255:1900 via eth1/10.40.40.21— echte Suchrufe beider Macs (.10.183,.10.82). - ⚠️ Falle beim Selbsttest: ein M-SEARCH vom Relay-Host selbst wird nicht weitergereicht (Loop-Schutz: das Werkzeug ignoriert eigene Quelladressen). Mein synthetischer Test meldete deshalb 0 Antworten, waehrend die App bereits funktionierte. Aus dem Relay heraus laesst sich der Relay nicht pruefen — entweder am echten Client testen oder am Log mitlesen.
- Keine Firewall-Arbeit noetig: der Relay spricht in beiden VLANs jeweils lokal; das trifft die
forward-Kette nicht. - 📌 Status-Update 2026-08-14: Symptom vom User erneut bestätigt — iOS-App ✅, HA-Sonos-Panel ✅ (steuern/gruppieren), macOS-Desktop-App findet die Umgebung nicht. Damit ist das Bild vollständig: alles, was mDNS spricht, funktioniert; nur der SSDP-Weg fehlt. Der Fix wird Bestandteil des TP5-Pakets (gemeinsamer Test mit Deny-by-default statt zweimal dieselbe Strecke prüfen). ⚠️ Nicht als Firewall-Problem fehldiagnostizieren:
forward accept vlan10↔vlan40ist längst offen — es scheitert an der Discovery, nicht am Datenpfad. - Bedarf: macOS-Desktop-Sonos-App auf VLAN 10 findet die Sonos in VLAN 40 nicht (Discovery per SSDP UDP 1900, RouterOS reflektiert kein SSDP). iOS-App + HA decken den Alltag ab, aber User will die Desktop-App nutzen.
- Lösung: kleiner SSDP-Reflector-Container mit Bein je Ziel-VLAN. Auf NAS oder pve (nicht am hAP, 128 MB
Flash + kein USB). Kandidaten:
bkupreck/ssdp-repeater,scyto/multicast-relay, oder eigenes Python-Skript. - Scope: vlan10 ↔ vlan40 (MacBook → Sonos). Optional vlan20 ↔ vlan40 falls HA je SSDP-Discovery brauchen sollte (aktuell nicht — HA nutzt zeroconf/mDNS).
- Anschluss TP5:
input accept udp/1900auf den bedienten VLANs (falls Router-lokal reflektiert wird) bzw. Container-Port-Freigaben je Bein. - Alternative (verworfen): macOS-Client temporär in VLAN 40 hängen (unpraktikabel für Alltagsnutzung).
- Abh.: TP7 ✅. Kein Blocker für TP5-Deny-by-default.
TP7.2 — HA↔Sonos static-host binding + VLAN1/GUEST-Discovery ▸ ✅ FERTIG (2026-07-03) — docs/sonos-inventar.md
- Root Cause (widerlegt frühere Doku): HA-
media_player.*-Sonos alleunavailable. HA sitzt nicht auf VLAN 20, sondern noch auf10.40.41.105(VLAN-1-Transfernetz, IP-Migration steht aus). Der mDNS-Repeater deckte VLAN 1 nicht ab, und die HA-Sonos-Integration ist SSDP-abhängig (manifest dependencies:[ssdp], soco 0.31.1) → quert die VLAN-Grenze nicht. Die alten „HA nutzt mDNS/zeroconf, fixed 2026-07-02"-Notizen waren falsch. - ✅ HA-Fix (discovery-unabhängig):
sonos: media_player: hosts:mit allen 11 Sonos-IPs +advertise_addr: 10.40.41.105inconfiguration.yaml(Backup.bak-sonos-20260703).advertise_addrfixt die UPnP-Event-Callbacks trotz HA-Multi-Homing (.105/172.16.0.18/docker). Core-Restart → alle 6 Online-Zonenidle/playing(Wohnzimmer-Push verifiziert = Callbacks OK). Terrasse.198offline = kein Entity (kommt beim Einschalten). Kurzes Flapping direkt nach Restart = Settling, danach stabil. - ✅ Nebeneffekt: mit
bridgeim Repeater (s.u.) meldet HA jetzt „Automatic discovery is working, hosts not needed" — die statischen Hosts sind also Redundanz (Gürtel+Hosenträger), bleiben aber als Absicherung. - ✅ VLAN 1 (temp) + GUEST (perm) Discovery/Reach (User-Wunsch 2026-07-03):
- mDNS-Repeater erweitert →
mdns-repeat-ifaces=vlan10,vlan20,vlan40,vlan30,vlan90,bridge(VLAN-1-untagged=bridge). - Firewall:
input accept udp/5353 vlan90+forward accept vlan90↔vlan40(ganzes MEDIA, beide Richtungen; User-Wahl). VLAN 1/bridgebrauchte nichts (schon viaTP10-seal-lan+ permissiver Forward). - Bewusst in Kauf: flacher Repeater → Guests sehen auch MAIN/INFRA/IOT-mDNS-Announcements (Discovery-Leak; echte Verbindungen regelt TP5-Deny-by-default).
- mDNS-Repeater erweitert →
- Offen/später: HA→VLAN 20 (IP-Migration nach Omada-PVID-Fix) → dann nur
advertise_addrauf neue IP; macOS-Desktop-App weiter via SSDP-Reflector TP7.1. Abh.: TP7 ✅, TP5-Holes ✅.
TP8 — Identity & Access-Control ▸ research-gated
- RADIUS = FreeRADIUS auf der NAS (✏️ User-Manager v5 kann KEIN LDAP → openldap nur via FreeRADIUS anbindbar).
- EAP-TLS (Zert) je Gerät + dynamische VLAN-Zuweisung (RADIUS-Attribut
Tunnel-Private-Group-ID). Einfachste Heim-Alternative: pro VLAN eine SSID mit WPA3-PSK (kein RADIUS) — Abwägung Komfort vs. Admin-Aufwand. - Abh.: TP3. (Research erledigt, s. TP-R.)
TP9 — Gateway-/Router-HA ▸ ❌ OBSOLET (User-Entscheid 2026-08-08)
- ❌ Verworfen (User-Begründung 2026-08-08, „ganz klar nein"): am
crs326-coreführt ohnehin nie ein Weg vorbei — er ist der unumgängliche L3-Durchleitungspunkt. Ein zweites Gerät / VRRP beseitigt diesen SPOF nicht, sondern baut nur zusätzliche Sollbruchstellen ein (2× Config-Sync für DHCP/DNS/Firewall/NAT, Split-Brain-Risiko, VRRP-Eigenfehler) → netto ein Zuverlässigkeits-Verlust, kein -Gewinn. Die Frage ist nicht „Aufwand vs. Nutzen", sondern „mehr Fehlerquellen einbauen?" → nein. DR-Weg = Config-Backup-Restore (+ ggf. AP-Reprovisionierung). VRRP-Skizze unten = nur noch historische Recherche. - „Was, wenn ap1 ausfällt?" → VRRP löst Gateway-Failover je VLAN ~gratis (kreuzweise Master/Backup). ⚠️ Haken (nicht Last): DHCP/Firewall/NAT/DNS müssen auf BEIDEN APs identisch gepflegt sein, sonst „Gateway up, Internet tot". Empfehlung: VRRP nur für MAIN/INFRA, sonst ap2 als Kalt-Ersatz + Backup. DHCP/DNS schon redundant (Split + 2 Resolver).
- Abh.: TP4. (Research erledigt, s. TP-R + Config-Skizze im Report.)
TP10 — Multi-Site VPN ▸ ✅ KERN DURCH (2026-06-27) — beide WG live auf ap1-Hub (docs/tp10-vpn-migration.md)
Details/Cutover/Gotchas/Eckdaten →
docs/tp10-vpn-migration.md(Single Source of Truth). Research:docs/research/vpn-comparison.md.
- ✅ KERN DURCH (2026-06-27) + EDGE-CUTOVER (2026-07-01): beide AVM-Tunnel → 2× WireGuard mit Hub auf ap1 migriert. Live:
peer fm(10.101.0.0/24, bidirektional, myfritz-Endpoint) undpeer dw(10.95.10.0/24, CGNAT-Dial-in) mit frischem Handshake + Traffic. Public-Edge direkt — ap1 hört UDP/51821 aufvlan100(Edge-Cutover 2026-07-01), keine FB-Portfreigabe mehr, kein Double-NAT. FM-IPsec gekillt, Gelis alter FB↔FB-WG sauber geswappt. - ✅ DW/Geli on-site verifiziert (2026-06-27): Geli auf
10.95.10.0/24renumbert, FB-WG single10.95.10.1/24, Keepalive 25, Endpointbf4…:51821. End-to-End von macmini/Linz → Gelis 24/7-APs10.95.10.246/.247sauber (echte LAN-IPs, kein10.255.255.x-NAT-Leak). - 💡 Root Cause (FM-PoC bewiesen): FB masqueradet WG, wenn die Interface-
Addresseine Transfernetz-IP ist → muss die FB-LAN-IP sein (AVM Proxy-ARP). War der Schlüssel zum sauberen LAN-LAN. - Hub:
wg-hub(UDP 51821, KeyP/bzt…, MTU 1412, keine IF-IP). Endpoint = DDNSbf4.emsenhuber.net:51821(Cloudflare, DNS-only → Public-IP). Apply gebündelt inrouteros/tp10-cutover-apply.rsc. - ✅ Permanenter Edge-Cutover durch (2026-07-01) — Details in TP4 (WAN via sw1 vlan100, ap1 = Public-Edge, WAN-Input-Seal live). BF-FB-eigenen WG-Server 51820 entfällt (FB physisch weg).
- Offen: DDNS-Auto-Updater für
bf4.emsenhuber.netauf NAS/pve, damit der A-Record der Public-IP folgt (falls Liwest sie tauscht). Aktuell manuell in Cloudflare gepflegt.
TP11 — Monitoring & Mgmt-Control-Plane ▸ research-gated
- MikroMCP + omada-mcp + SNMP/icinga-mikrotik, RoMON, NTP, E-Mail-Alerts, Netwatch. → Teil von
docs/research/routeros-capabilities.md. - CF-Tunnel #1033 Track A ✅ live (2026-06-30): Round-Robin-1033er über 3 asymmetrische Connectors behoben
durch Reduktion auf pve-only Connector (NAS + macmini scheiterten an pve-lokalen/stalen Origins). SSoT:
docs/cf-tunnel-mapping.md. Track B/C läuft über TP14 (Ingress bereits v116 .41→.20 für NAS; pve-Connector→VLAN20 via TP14 Session B = #1033-Zielbild).
TP12 — IPv6 (intern + extern, 3 Standorte) ▸ research-gated
- Konzept für FM/BF/DW. → TP-R.
TP13 — „Botschafts-WLANs" ▸ 🔜 VORBEREITET (2026-08-08), fun/low-prio
- Idee: eine/mehrere Broadcast-only-SSIDs als „schwarzes Brett" an die Funk-Nachbarschaft — der SSID-Name ist die Botschaft (z.B.
Kanal-11-bitte-freihalten,WLAN-Tuning-siehe-Portal). Optional ein offenes WLAN mit Captive-Portal auf eine statische Info-HTML (Kanalabsprache, Auto-Kanalwechsel-Bitte). Leitgedanke: wer die SSID sieht, kann auch stören → die Infoseite erreicht genau die Zielgruppe. Technik (jetzt einfach, da WLAN standalone seit TP3-Rebuild): reine Namens-SSIDs = zusätzliche⚠️ Überholt 2026-08-19, in zwei Punkten:/interface/wifiSlave-VAPs auf wifi1/wifi2 mit eigenerconfiguration(nurssid=, kein Security/Datapath)- (a) WLAN ist seit TP28 nicht mehr standalone. SSIDs entstehen am Manager
crs326-core(9configuration-, 6datapath-Objekte, 4provisioning-Zeilen — live gelesen 08-19). Das ist für TP13 sogar einfacher: ein Deploy statt zwei. - (b) 🔴 „kein Security" ist ein offenes WLAN — genau das, was der Rechtsvorbehalt unten ausschließen will. Richtig ist eine SSID mit WPA2/WPA3-PSK, den niemand kennt: sie beacont den Namen, ist aber nicht beitretbar.
- Captive-Portal-Variante (RouterOS-Hotspot, isoliertes VLAN,
walled-garden) bleibt als Option bestehen — s. Rechts-Gate unten.
- (a) WLAN ist seit TP28 nicht mehr standalone. SSIDs entstehen am Manager
Umsetzungs-Skizze: … Beacon-SSIDs in→ diese Dateien sind für den WLAN-Teil Historie (die CAPs sind auf dierouteros/.secrets/ap{1,2}-prov-base.rscergänzen …cap-Zeile eingedampft). Aktuelle Umsetzung:docs/tp13-botschafts-wlan-runbook.md(2026-08-19).- 🔴🔴 Die Falle, die dort ausführlich steht: ein Slave-VAP ohne explizite
vlan-idam Manager landet ungetaggt inbridge— weil der CAP vom Manager-Datapath nur dievlan-idübernimmt. Das ist dasselbe Leck wie TP3.1 (cfg-main-2gohne datapath) und dieselbe Mechanik wie der 14-h-Ausfall vom 08-18. Die Botschafts-SSID braucht deshalb einen Datapath mit totemvlan-id— PSK und toter Datapath, nicht eines von beidem. - ✅ VAP-Budget geprüft (live 08-19), unkritisch:
max-interfaces=16je Radio, belegt sind 4 (5 GHz) bzw. 5 (2,4 GHz). Die Grenze ist Airtime, nicht die Zahl — jeder VAP beacont eigenständig. Empfehlung: genau eine SSID, auf 2,4 GHz (mehr Reichweite = mehr Nachbarn, und 5 GHz bleibt für Nutzverkehr frei).
- 🔴🔴 Die Falle, die dort ausführlich steht: ein Slave-VAP ohne explizite
- ⚠️ Recht vor Scharfschalten prüfen (User privat, AT): offenes WLAN + Portal berührt Impressumspflicht/Störerhaftung — reine Namens-SSIDs ohne offenen Zugang sind unkritisch (kein Fremd-Datenverkehr); im Zweifel nur die Beacon-Variante.
- Abh.:
TP3-Rebuild ✅ (Standalone-APs — SSID-Änderung = 1 Deploy/GC-Job)→ TP28 ✅ (CAPsMAN auf dem Core) + TP22 ✅ (GC-Deploy-Pipeline). SSID-Änderung = ein Deploy auf den Core; Direkt-Edit am Gerät ist durch den Governance-Entscheid ausgeschlossen.
TP14 — Host/Container-IP-Migration VLAN1→VLAN20 (Docker-Cutover NAS+pve) ▸ ✅ DURCH (2026-07-13; live re-verifiziert 2026-08-08) — docs/nas-vlan20/RUNBOOK.md, Handoff docs/nas-vlan20/handoff/
- ✅ ABGESCHLOSSEN — Migration komplett (Live-Check 2026-08-08 vom core: NAS
.20.10, pve.20.100, Docker-LXC.20.126, platform-pg.20.20, Nautobot.20.30alle 0% Loss). Alle Hosts + Container auf VLAN20. TP14.4 (CF-Access-Token-Rotation) = kleiner, nicht-blockierender Standalone-Follow-up (CF/TP11-Umfeld); TP14.5 war nie ein eigener Change (nur ein Reihenfolge-Gate) → erfüllt, TP5 damit entblockt. - ✅ NAS (DS923, ep14) migriert (2026-07-09/10): Docker von
default_external(macvlan .41) auf einvlan20-Macvlan (10.40.20.0/24, gw .1, parentovs_eth0); DSM-Cutover.20.10; Portainer-Endpoint.20.10:9001. Root-Cause der Dauerfehler = Portainer Config-Only-Macvlan-Falle (Driver:null, kein Container-Attach) + Macvlan-Parent-Exklusivität (default_externalmuss weg fürvlan20) +default_internal(172.18) weg. Container laufen auf.20.x. - ✅ CF-Ingress v116 (2026-07-10): 6 NAS-Origins .41→.20 (SSoT
docs/cf-tunnel-mapping.md§8);vw200 via Tunnel = pve→VLAN20-Routing steht (502 direkt nach Ingress-PUT = transient). - ⚠️ Abh./Reihenfolge: verzahnt mit Omada-PVID-Fix/IP-Migration (Reihenfolge #3); Sessions = Sub-TPs TP14.1–14.5, sequenziell A→B→C→(D jederzeit)→E, keine parallelen Branches (geteilte Live-Infra). Anschlussstatements:
docs/nas-vlan20/handoff/README.md. - ✅ TP14.1 (Session A) durch 2026-07-10: alle ep14-Container auf vlan20 + pve-mcp neu; nur Omada-Inform-Adresse offen (Controller-UI-Task, s.u.).
- ✅ TP14.2 (Session B) durch 2026-07-10: pve-LXC (400/
docker) auf VLAN20 (.20.126, ipvlanparent=veth20); omada-mcp/adguard→.20.x; CF-Connector jetzt VLAN20 = #1033 gelöst. Nächste Session = TP14.3 (Session C, dormante Stacks + Referenz-Sweep ap1-DNS). - ✅ Netz-Abgleich 2026-07-11 (live via MikroMCP/pve-mcp): NAS
.20.10, Mac mini.20.167, pve-LXC.20.126alle reachable auf VLAN20 (+ Container.20.xpopuliert;iobroker .107/ccu .232/z2m .106/vw .127jetzt auch VLAN20). Sonst in VLAN1 (bridge) nur noch: sw1.11/sw2.12/ap2-Mgmt.2(Switch-/AP-Mgmt, interim bis MGMT-VLAN99) + Streu-Clients übers cudy-Alt-WLAN (MacBook.182, iPhone.186, SwitchBot.184, Sonoff) + die 16 VLAN1-Shellys (TP17).defconf/pool-v1-DHCP aufbridgeläuft noch (VLAN1 aktiv). - ✅ pve-Host-Mgmt → VLAN20 (2026-07-13): letzter verbliebener Host-Umzug.
vmbr0bleibt VLAN1.41.100(ohne Default-Route, interim), neuesvmbr0.20(bereits vorbereitet, aber mit kaputteraddress 10.40.20.0/24vorgefunden) korrigiert auf10.40.20.100/24→ifreload -alive (ifupdown2, kein Reboot, LXC 400 durchgehend unbeeinflusst) → Default-GW auf10.40.20.1geflippt. SSH-Key-Auth bestätigt auf.20.100. Nachgezogen: ap1-DNS (pve.bf.lan→.20.100; dabei Fund+Fix eines Alt-Bugs:pve-mcp.bf.lanzeigte noch auf.41.173statt.20.173), CF-Tunnelbf-pveIngress (pve+j44d6tua-SSH-Hostname .41.100→.20.100, PUT viaCF_API_TOKEN, Smoke 200/200), CLAUDE.md,docs/ip-plan.md.~/.claude.jsonwar schon sauber.
TP14.1 — Session A: NAS fertigstellen ▸ ✅ DURCH (2026-07-10); Omada-Inform/sw2 VERTAGT
- ✅ Alle ep14-Container auf vlan20 redeployed + verifiziert running/.20.x (via Portainer-Stack-Redeploy, Env preserved, Volumes intakt): oc-stack(112 → prometheus
.151/node-exporter.154/grafana.109), default(72 → hms-mqtt.124), nginx(101 → dashboard-web.148), oc-central(160 → qdrant.159), oc-charlie(158 →.162+cf), oc-johnny2(150 →.161+cf), gitea(111 →.157, DB.20.23:3306erreichbar ✓), drawio(107 →.139, intern; CF-CNAME war eh gelöscht). - ✅ pve-mcp NEU als Stack (id 202, vlan20-only
.20.173), verbunden mit Proxmox.41.100(v9.0.11) — ⚠️ StreamableHTTP am Root-Pfad/, NICHT/sse(mcp-pve v0.4.8,MCP_TRANSPORT=http).~/.claude.jsonmcpServers.pve-mcpNEU angelegt{type:http, url:http://10.40.20.173:3000/}(war vorher gar nicht drin) → wirkt nach Claude-Code-Restart. - ✅ Tunnel-Smoke (CF-Ingress v116 zeigte schon auf
.20): gitea 200, grafana 302, vw 200 — Origins existieren jetzt real. - ⚠️ alertmanager
.153: korrekt an vlan20, aber crash-loop wegen PRE-EXISTING Config-Bug (${TELEGRAM_CHAT_ID}-Literal in/etc/alertmanager/alertmanager.yml→ int64-Parse-Fehler; Alertmanager macht kein Env-Substitution). NICHT migrationsbedingt, braucht echte chat_id. Out-of-scope. - ⚠️ openclaw-DB
10.40.41.122:3306down (shared MariaDB, pre-existing; Bots kamen trotzdem hoch).DB_HOST-Env unverändert gelassen.OLLAMA_BASE_URL=.41.167=Mac-mini bleibt korrekt.41(migriert nicht → kein Blanket-Env-.41→.20!). - ⚪ OBSOLET (2026-07-16) —
omada-controller Inform-Adresse + sw2 re-adopt: ursprünglich vertagt (2026-07-10, Controller-Login schlug fehl). Gegenstandslos seit TP2.1: der Controller-Login-Ausfall eskalierte zum Werks-Reset von sw2, User hat daraufhin entschieden, sw2 dauerhaft standalone ohne Controller zu betreiben — und den Omada-Controller-Container samt omada-mcp am 2026-07-16 komplett gelöscht (overkill für 1 Switch auf der Abschussliste, s. TP15/CRS326). Kein Re-Adopt mehr vorgesehen. - 🐞 Gotcha gefunden: Portainer-Stack 111 (gitea) hatte den
vlan20-Networks-Block auskommentiert (Vorsession-Artefakt) → Container landete aufgitea_default/172.18. Fix = Redeploy mit Disk-Filedocs/nas-vlan20/stacks/111-gitea.ymlals Override.
TP14.2 — Session B: pve-Docker-LXC (.126) → VLAN20 ▸ ✅ DURCH (2026-07-10) (ipvlan)
- ✅ ep2-Container auf
vlan20: omada-mcp.20.176(OMADA_BASE_URL→.20.175), adguard_bf1.20.16, adguard_fm2.20.17— alle running/reachable (health 200, adguard 302). Transf. Filesdocs/nas-vlan20/stacks/{195-adguard,200-omada-mcp}.yml. - ✅ LXC 400 (
docker) net0 →tag=20, ip=10.40.20.126/24, gw=10.40.20.1(⚠️ Retag brauchte Christoph — Tokenclaude@pam!claudehat keinVM.Config.Network; UI-Edit, dann Reboot via API mitVM.PowerMgmt). Portainer wandert aufhttps://10.40.20.126:9443. - 🐞 Gotcha: in-Container-Iface heißt jetzt
veth20, NICHTeth0(UI setzte Name analog net1=veth16) → Dockervlan20=ipvlanparent=veth20(nicht eth0 wie im Runbook). cloudflared(host)/portainer(bridge) unberührt. - ✅ CF-Connector
db713b30jetzt in VLAN20 (Tunnelbf.emsenhuber.nethealthy/8 conns) = löst TP11-Track-B/C (#1033-Zielbild). Ingressportainer.41.126→.20.126. Smoke: portainer/gitea/vw 200, grafana 302. - ✅ Refs nachgezogen:
mcp/portainer/.env(PORTAINER_URL),~/.claude.json(omada-mcp.20.176), CLAUDE.md,docs/ip-plan.md,docs/cf-tunnel-mapping.md. Next = TP14.3 (Session C, dormante Stacks + Referenz-Sweep ap1-DNS). - ✅ Live-Smoke re-verifiziert 2026-07-10: alle 6 VLAN20-IPs ping OK + dienstseitig grün — Portainer
.20.126:9443HTTP 200 (LXC 400 running, net0veth20 tag=20 gw/ns=.20.1), omada-mcp.20.176→Controller.20.175v6.2.10.17 (HTTPS :8043 200), pve-mcp.20.173liefert Proxmox-Config, adguard.20.16/.20.17HTTP :80 302→login (nicht HTTPS/:3000).
TP14.2a — pve-mcp Single-Session-Fix + VLAN20-Host-DNS ▸ ✅ (2026-07-10)
- pve-mcp „Failed to connect": Ursache = mcp-pve v0.4.8 kann im HTTP-Transport nur eine MCP-Session (ein globaler
StreamableHTTPServerTransport,sessionIdGeneratorgesetzt) → erster Client nach Boot belegt den Slot, jeder weitere Init (neue Claude-Code-Session,claude mcp list-Healthcheck, Reconnect) =400 "Server already initialized". omada-mcp NICHT betroffen (frische Session-ID pro Init → Per-Session-Transport). Fix = Upgrade auf 0.6.1 (Per-Session-Map,serverFactory()je Session, gleiche Env-Vars = Drop-in); Stack 202 neu deployed, Container.20.173= 0.6.1,Connected to Proxmox VE 9.0.11,tools/listliefertpve_*, Claude Code ✔ Connected. 3× init hintereinander = 3× 200 mit verschiedenen session-ids (verifiziert). - Kollateral-Fund — VLAN20-Host-DNS kaputt (beide Docker-Hosts): nach dem VLAN20-Umzug zeigten NAS und pve-LXC
/etc/resolv.confnoch auf totes.41.254→docker pullghcr.io scheitert (EAI_AGAIN/ 5s-Resolver-Timeout; Egress zu ghcr-IP140.82.x:443= OK 31 ms, also nur Resolver tot, nicht Egress). Fixes: LXC.20.126→pct set 400 --nameserver 10.40.20.1(Christoph). NAS → DSM-„Allgemein"-DNS war.20.1, ABER die Netzwerkschnittstelle zog DNS per DHCP und überschriebresolv.conf; Fix = Schnittstelle „DNS manuell"10.40.20.1(Christoph) → NAS pullt wieder direkt. Merkregel Synology: GUI-DNS ≠ wasdockerdliest (Quelle/etc/resolv.conf, per DHCP überschreibbar). Workaround solange NAS-DNS tot:docker save(LXC, hat DNS) → gzip (191-MB-tar reißt am Portainer-Agent-Socket-Proxy „context canceled"; ~70 MB gz geht) → PortainerPOST /endpoints/14/docker/images/load→ Stack-RedeploypullImage:false. Gotcha: laufende Container frieren den127.0.0.11-Upstream zum Erstellzeitpunkt ein (Recreate nötig; für pve-mcp egal — Proxmox per IP.41.100). Memoryref_pve_mcp_singlesession_and_vlan20_dns.
TP14.3 — Session C: Dormante Stacks vlan20-tauglich + Referenz-Sweep ▸ ✅ Referenz-Sweep durch (2026-07-16); dormante Stacks weiter bewusst nicht deployt
- ✅ Dormante Stacks bereitgestellt (2026-07-11):
transform.pyauf core(43)/openclaw(92)/openclaw2(97)/oc20260307(119)/openspeedtest(74)/speedtest_tracker(80)/technikscheiss(42) →.new.yml+.orig.ymlindocs/nas-vlan20/stacks/(gitignored). Nicht deployt (User: „im Bedarfsfall später", Container-Zukunft ungewiss). 42/43 warendefault_internal→ jetzt vlan20-only (DHCP-.20.x). ⚠️ Deploy-Caveats: externe Refs bewusst NICHT umgeschrieben (DB_HOST=.41.122[pre-existing tote openclaw-DB, in 80+119],OLLAMA_BASE_URL=.41.129,REDIS_URL=.41.111in 119); Kollision43-corewill.20.23= gitea-DB-IP (nicht gleichzeitig deploybar). - ✅ Referenz-Sweep
.41→.20(2026-07-16, im Rahmen der TP19-Backup-Vorbereitung live gefunden + gefixt): ap1/ip dns statichatte nochnas.bf.lan→.41.10unddocker.bf.lan→.41.126stale — korrigiert auf.20.10/.20.126(MikroMCPmanage_dns_entry, dry-run+apply). Zusätzlich per User-Entscheid Omada-Controller + omada-mcp komplett gelöscht (overkill für 1 Switch auf der Abschussliste) → DNS-Einträgeomada.bf.lan/omada-mcp.bf.lanentfernt statt migriert.fritzbox.bf.lan(totes Gerät, physisch weg seit 2026-07-01) ebenfalls entfernt.docs/ip-plan.md+ CLAUDE.md nachgezogen. - ✅ ERLEDIGT/GEGENSTANDSLOS (live geprüft 2026-08-16):
~/.claude.json(omada-mcp-Eintrag verwaist), CF-Ingress-Rest (omada/omada-mcp-Hostnames, ungeprüft)~/.claude.json:omada-mcpist nicht mehr als MCP-Server registriert (mcpServersenthält ihn nicht). Er steht nur noch indisabledMcpServerseiniger Projekt-Scopes — ein reiner Merkposten „bewusst aus", keine Verbindungsversuche, kein Handlungsbedarf.- CF-Ingress: alle 9 Tunnel durchgesehen (
cfd_tunnel+/configurations) — kein einzigeromada-Hostname mehr. Sauber.
- ↪️ Shelly-Geräte-Übersiedelung ausgegliedert → TP17 (die ~26 IoT-Shellys sind eine eigenständige WLAN-Migration, nicht Teil des Docker-Ref-Sweeps).
TP14.4 — Session D: CF-Access-Profil für Claude ▸ 🔜 TODO (nicht cutoff-kritisch)
- CF-Token „claude code mcp" hat jetzt
Access: Service Tokens: Write+Read→claude-mcprotieren (POST …/access/service_tokens/{id}/rotate) →CF_ACCESS_CLIENT_ID/_SECRETinmcp/cloudflare/.env(chmod600). Memoryref-cf-access-claude-profile. - 📋 Runbook:
docs/tp14.4-cf-access-token-runbook.md(2026-08-19). Ist-Stand verifiziert:mcp/cloudflare/.enventhält bisher wederCF_ACCESS_CLIENT_IDnoch_SECRET— es ist nichts halb erledigt. 🔴 Das Secret wird nur bei der Rotation ausgegeben, wer es nicht sofort schreibt, muss erneut rotieren. Abnahme = ein Aufruf mit den Headern (antwortet) und einer ohne (403) — der Erfolgsfall allein beweist nichts, der Hostname könnte aufbypassstehen.
TP14.5 — Session E: Freigabe-Gate → TP5-Firewall ▸ ✅ ERFÜLLT (2026-08-08) — kein eigener Change
- Gate „TP14.1–14.3 durch (alle Origins/Connectoren in VLAN20)" ist erfüllt → TP5 (Deny-by-default) ist entblockt. Reines Reihenfolge-Gate, kein eigener Change.
TP15 — HW-Refresh: Switching + Router ▸ ✅ ABGESCHLOSSEN (2026-08-08) — Bring-up beider CRS326 + Branch-Tausch (2026-07-23) und Core-Tausch/L3-Umzug (2026-08-08, Durchführung s. TP21.1) sind durch — docs/hw-refresh-requirements.md, Memory project_mikrotik_commit_nautobot_gc
🔌 Scope-Änderung 2026-08-16 (User-Entscheid): die DC-USV ist aus diesem TP herausgelöst und heißt jetzt TP24. Sie war der letzte offene Rest hier, hat mit Switching/Routing sachlich nichts zu tun und trägt eigene Entscheidungen (Elektrik, Batterie, Standort). TP15 ist damit inhaltlich zu. Vorherige Header-Fassung (Stand 2026-08-05, überholt): „🟢 CRS326-Bring-up + Branch-Tausch DURCH (2026-07-23); Core-Tausch/L3-Umzug vorbereitet, Cutover-Config materialisiert (2026-08-05), Cutover = nächstes Wartungsfenster."
- ✅ BRING-UP BEIDER CRS326 + BRANCH-TAUSCH gegen sw2 — DURCH (2026-07-23, Claude via REST unter Governance-Ausnahme #2). Ablauf/As-built:
- Zugriffsweg (Henne-Ei gelöst): Erst-Reihenfolge war core zuerst (User-Korrektur — core hängt an sw1 und ist der L2-Pfad, über den branch überhaupt erreichbar wird; branch war isoliert). Zugriff auf die Werks-
192.168.88.1über temporäre ap1-Zweit-IP192.168.88.2/24+ srcnat-Masquerade192.168.88.0/24(beideTP15-temp, nach Bring-up wieder entfernt — Rückweg nötig, weil die Werks-Box keine Route zu VLAN10 hat). Config dann komplett per REST (/system/scriptPUT+run), kein Winbox-Paste. Winbox-MAC-Connect scheiterte reproduzierbar („macconnection sync timeout" über WLAN/quer durch den Fabric — braucht selben Draht). - Identitäten am Gerät verifiziert (nicht nur Doku):
core= sw-id 4W04-URHT, MAC04:F4:1C:B4:17:76, SerialHKA0AREXJFM, PWX9…;branch= sw-id RGZJ-UK0T, MAC04:F4:1C:B4:15:58, SerialHKA0AJJA52F, PWPHR…(ap2 hängt an branch ether24 — bridge-host bestätigt = definitiv branch). PWs in~/.secrets/credentials.env. - branch = produktiv, volle SOLL-Portbelegung (User-manuell erhoben, maßgeblich): ether1 Uplink-Trunk→sw1 #8 (native VLAN1 + tagged 10/20/30/40/50/90/99, kein 100), ether2+ether8 = NAS 2×tagged-VLAN20 (zwei unabhängige Links), ether3 Drucker/VLAN10, ether4 Dock/VLAN10, ether5+ether6 Sonos/VLAN40, ether7 Mac mini/VLAN20, ether24 ap2-Trunk; ether9–23+sfp disabled. vlan-filtering=yes. Mgmt
10.40.99.13(VLAN99) erreichbar über sw1 #8 (+ VLAN1-Temp.41.213während Bring-up). Post-Swap-Abnahme grün: NAS.20.10, Mac mini.20.167(VLAN20), Dock.10.194(VLAN10), Sonos.40.191/.40.192(VLAN40). - core = grundkonfiguriert, NICHT produktiv (bleibt an sw1 #12): identity/vlan-filtering/volle VLAN-Tabelle, ether1 Uplink, ether2 Temp-Downlink (war Config-Pfad für branch), Mgmt
10.40.99.11(VLAN99, erreichbar erst wenn sw1 #12 99T trägt) + VLAN1-Temp.41.211. Port-Layout ab ether3 tentativ (final in Core-Swap-Session). - Beide in MikroMCP
routers.yaml(crs326-core/-branch, ENVROUTER_CRS326_*in~/.claude.json— live erst nach MCP-Neustart, diese Session lief alles per REST-curl). Nautobot modelliert + GraphQL-verifiziert (nautobot/ingest-crs326-ports.py): branch Active + volle Ports + primary_ip4.99.13; core Planned + tentatives Layout; sw1 verifizierte 16-Port-Belegung (löst „UNVERIFIZIERT"); sw2 → Decommissioning. - 🐞 Gotchas festgehalten: (1) Kabel ether3↔ether5 waren beim Umstecken vertauscht → ein AZ-Sonos landete als Access-VLAN10 in
10.40.10.190und blutete via SonosNet nach VLAN40 (= Dual-Homing-Muster,project_dual_homing_slowness_incident) → Kabeltausch gefixt, beide AZ-Sonos jetzt sauber VLAN40 (.191/.192bound). (2) RouterOS-Script-policy-Feld per REST wählerisch → weglassen (admin-Default = volle Policy). (3) Disable-Regex mit^…$-Ankern griff nicht →[find name!="ether1" and …]nutzen. (4) REST-PUT-Antwort mit mehrzeiligemsourceist kein sauberes JSON → ID separat via?.proplist=.idholen. (5) Claude-Code-Auto-Mode-Classifier blockt Device-Config-Writes per Bash (Reads ok) →autoMode.allow-Regel in.claude/settings.local.jsonnötig (kann Claude sich nicht selbst setzen).
- Zugriffsweg (Henne-Ei gelöst): Erst-Reihenfolge war core zuerst (User-Korrektur — core hängt an sw1 und ist der L2-Pfad, über den branch überhaupt erreichbar wird; branch war isoliert). Zugriff auf die Werks-
- ✅ ERLEDIGT 2026-08-08 (Durchführung + Recovery s. TP21.1).
🔜 Als Nächstes (eigene Session, Übergabe): Core-Tausch = L3-Umzug(Routing/DHCP/DNS/CF-Mesh von ap1 → crs326-core) — Vollausfall-Fenster, s.docs/tp15-core-swap-session-handoff-prompt.md. Danach WLAN-Neuprovisionierung (TP3, CAPsMAN-Abbau).Finaler Mgmt-Renumber dann: branch⚠️ Anders gekommen (Ist seit 2026-08-08, live bestätigt): core.99.13→.99.12, core bleibt.99.11..99.1· branch.99.2· ap1.99.11· ap2.99.12. - ✅ Core-Swap VORBEREITET (2026-07-23, reine Prep-Session, kein Netz-Eingriff): ap1s Live-L3-Config vollständig gelesen (MikroMCP) und als staged Config materialisiert →
routeros/tp15-core-l3-staged.rsc(alles Betriebsumlenkendedisabled=yes, im Cutover in einem Rutschenable; ~50 Reservierungen + WG-Privkey bewusst erst im Fenster maschinell von ap1 geholt statt abgetippt). Runbook/Rollback/Verifikation im Plan. 3 Fenster-Start-Entscheide festgelegt: (1) WG-Hub (TP10 FM/DW-VPN) migriert MIT — war im Handoff-Prompt übersehen, hängt an ap1s Public-Edge und kann dort nicht bleiben; (2) Governance = frische Direkt-Ausnahme #3 (REST/MikroMCP), danach intended→Nautobot; (3) Rettungspfad = iPhone-Hotspot. - ✅ Nautobot-Modell + Golden-Config-Template für L3-Cutover vervollständigt (2026-08-05):
crs326-corejetzt Rolle Router, alle VLAN-SVIs (vlan10/20/30/40/50/90/99/100) + Gateway-IPs (.1) modelliert;nautobot/mikrotik_routeros.j2(Giteabf-golden-config) erzeugt fürcrs326-coredie vollständige staged L3-Konfig (Interface-Lists, GW-IPs, WAN-DHCP, DHCP-Server/Pools, DNS, NAT, Firewall, WG-Hub) und für alle anderen MikroTik-Geräte nur die Identität. Git-Sync + Generate Intended Config erfolgreich getestet; intended config fürcrs326-coreliegt in Nautobot vor.- ✅ ap1-Cutover-Daten exportiert + in Cutover-Config eingebaut (2026-08-05): 54 statische DHCP-Leases aus ap1 (
dhcp-v10/v20/v30/v40) nachrouteros/ap1-leases-to-core.rscüberführt; WG-Hub-Privkey von ap1 geholt und in die lokale Cutover-Configrouteros/tp15-core-cutover-intended.rsceingesetzt (der WG-Privkey landet NICHT im Git-Template — Secret). - 🐞 Prep-Gotchas: (a) MikroMCP kann core noch nicht schreiben —
ROUTER_CRS326_CORE_*im MCP-Prozess nicht geladen (jeder Zugriff „Missing environment variable") → vor dem Fenster MCP neu starten oder REST-curl gegenhttp://10.40.41.211/rest. (b) Mgmt-.99.11tot (sw1 #12 trägt kein 99T), nur VLAN1-Temp.41.211erreichbar. (c) WG-Hub: Privkey von ap1 mitnehmen (sonst FM/DW-Reconfig nötig). (d) core-vlan99 wird GW.1; Bring-up-.11dadurch redundant (Fenster-Reconcile). (e) VLAN1 raus: Hybrid-VLAN1-Drops sw1 GE3/7/10 beim Umstecken einem echten VLAN zuordnen oder stilllegen. - ✅ WG-Endpoint-Frage geklärt (2026-07-23): Spokes adressieren den Hub über
bf4.emsenhuber.net:51821= CF-A-Record (proxied=false, TTL 120, aktuell90.146.35.38). Kein Updater auf ap1 → nichts zu migrieren;bf4folgt der IP manuell (offener TP10-Follow-up). Zieht core am WAN eine neue IP (Lease sticky, eher nicht), viaCF_API_TOKENnachziehen:bf4-Record + Access-Policybf4-home-ip(90.146.35.38/32). Chance: core ist nichtdevice-mode=home→ scheduler/fetch gehen →bf4-DDNS-Auto-Updater dort bauen (schließt TP10-Follow-up). - 📋 Session-Handover für die Cutover-Session:
docs/tp15-core-swap-session-handover.md(Einstieg + Pre-Window-Checkliste + Kurz-Runbook; Original-Auftrag bleibtdocs/tp15-core-swap-session-handoff-prompt.md).
- ✅ ap1-Cutover-Daten exportiert + in Cutover-Config eingebaut (2026-08-05): 54 statische DHCP-Leases aus ap1 (
- 📦 2× CRS326-24G-2S+RM werden morgen (2026-07-17) geliefert, Produktivsetzung spätestens Montag 2026-07-20 (User-Entscheid 2026-07-16). Sequenzierung ggü. Nautobot geklärt: TP20+TP21 werden bis dahin fast-getrackt (TP18/Komodo als Blocker entfernt, s. TP20) — Ziel ist, dass Nautobot vor der CRS326-Produktivsetzung steht und die Switches direkt als Nautobot-verwaltete Geräte adoptiert werden, statt erst von Hand konfiguriert und später importiert. sw1/sw2-VLAN99-Umzug (TP19.1) läuft parallel dazu on-demand, unabhängig davon.
- 🧭 Grundsatzentscheid (2026-07-14, korrigiert 2026-07-15): reines MikroTik-Ecosystem — Routing + Switching + WLAN. Omada bekommt KEINE Rolle (weder Switching noch WLAN — der ursprüngliche „Omada=WLAN"-Satz war ein Fehlschluss beim Dokumentieren, User-Korrektur 2026-07-15: „WLAN war NIE von Omada die Rede"). Begründung Switching: Projektziel #1 CAKE nur RouterOS/OpenWrt/OPNsense (Omada-Gateway kann kein CAKE) → Switching = MikroTik CRS. WLAN bleibt auf hAP ax² (
/CAPsMAN— CAPsMAN am 2026-08-08 abgeschafft, Standalone aus der Golden Config; die Hardware-Aussage gilt), kein EAP-Kauf, Coverage-Fix bleibt Platzierungsfrage (TP3.3). Verworfene Vollvarianten (Omada-only, MikroTik-only) samt Begründung + Ansible/Nautobot-Recherche → Memory. Anlass der Korrektur: Omada-Controller↔sw2-Link beim VLAN20-Umzug (TP14.1) zerbrochen, versehentlicher Werks-Reset bei Rettungsversuch, fehlerhafter Wiederherstellungsversuch → sw2 wird standalone neu eingerichtet, s. TP2.1. - 🛒 Switches: 2× CRS326-24G-2S+RM bestellt (2026-07-14 — CSS326-Fehlbestellung storniert → CRS). 24×1G + 2×SFP+, lüfterlos, DC-input (USV-tauglich). Lösen ALLNET-Core (sw1) + Omada-ES208G (sw2, s. TP2.1 — Solo/Interim bis CRS-Tausch) + Cudy ab.
- ✅ CRS = RouterOS-fähig → in-model: MikroMCP-Write + Nautobot Golden Config (TP21) managen auch die Switches, nicht nur den Router → config-as-code deckt den ganzen Kabel-Fabric. (SwOS-Boot bliebe als Fallback möglich, aber nicht genutzt.)
- ⚠️ kein PoE (Sonoff/PoE-Verbraucher via Injektor, falls nötig).
- 📶 WLAN bleibt hAP ax² — kein Hardware-/Ecosystem-Wechsel; die Hardware-Aussage gilt unverändert.
⚠️ Die Betriebsart hat zweimal gewechselt, letzter Stand ist CAPsMAN: CAPsMAN abgeschafft
(2026-07-22/08-08, TP3-Rebuild → Standalone-APs) → wieder eingeführt am 2026-08-17 (TP28), Manager
ist
crs326-core, ap1/ap2 sind reine CAPs. Wer hier nur bis zum ersten Pfeil liest, baut auf einem überholten Stand auf. Coverage-Schwachstellen (P750W-Fall, Terrasse/Kanten) bleiben Platzierungs-/Roaming-Thema von TP3.3, nicht durch neue Hardware gelöst. - 🧭 Router-HW final (User-Entscheid 2026-07-22): kein RB5009. Kein Zukauf einer dedizierten Router-HW.
- 🔄 KORREKTUR (User-Entscheid 2026-07-22, später am selben Tag): der CRS326-Core WIRD der neue L3-Router. Die frühere Fassung dieser Zeile („Router bleibt dauerhaft ap1/ap2, L3/CAKE/Firewall bleiben auf ap1") ist damit überholt. Routing, DNS und DHCP wandern vollständig von ap1 auf
crs326-core; ap1/ap2 werden zu reinen Access Points. Auch der CF-Mesh-Endpoint terminiert dort (s. TP16.1, war schon vorher auf CRS326 retargetet — passt jetzt konsistent zusammen). Damit entfallen diedevice-mode=home-Einschränkungen des hAP (kein scheduler/fetch) für die Router-Rolle. Reihenfolge (User): erst Switches aufsetzen und in Betrieb nehmen, danach WLAN-Neuprovisionierung der APs. Betroffen/nachzuziehen: TP4 (Router-Rolle), TP5/TP6 (Firewall + CAKE landen auf dem CRS326), TP21 (Scope-Grenze). - 📍 CRS326 Live-Stand (2026-07-22, via MNDP von ap1): beide Geräte sind bereits am Netz und laufen — RouterOS 7.19.5, Werkszustand.
crs326-core= MAC04:F4:1C:B4:17:76(software-id4W04-URHT),crs326-branch= MAC04:F4:1C:B4:15:58(RGZJ-UK0T). ⚠️ Beide auf Werks-IP192.168.88.1im selben L2-Segment = IP-Konflikt → beim Bring-up nur eines nach dem anderen adressieren, Unterscheidung ausschließlich per MAC. Die frühere Notiz „Uplink-Port bislang ungenutzt/down" ist überholt. Standorte:crs326-core= „Technik UG" (virtueller Technikbereich im UG/Diele, KEIN Keller),crs326-branch= „Technik OG". - 🔌 PoE-Anschluss der APs (User-Vorgabe 2026-07-22): Verkabelung/Portbelegung bleibt sonst unverändert; ap1/ap2 sollen künftig aber am PoE-Port hängen. PoE selbst ist noch kein Thema, die Config soll es aber schon vorsehen.
- ✅ Port =
ether1. RouterOS nummeriert Interfaces ab 1 (ether1…ether5), nieether0— die Unix-Konventioneth0gilt hier nicht. Auf dem hAP ax² istether1der PoE-Port (live bestätigt:/interface/ethernet/poelistet ausschließlichether1). - ⚠️ Aber: passives PoE 18–28 V, NICHT 802.3af/at. Ein normaler 802.3af/at-Switch oder -Injektor speist den hAP ax² nicht. Es braucht einen passiven PoE-Injektor (MikroTik-Standard). Dazu passend: der CRS326 hat gar kein PoE (bereits dokumentiert) → Strom kommt ohnehin aus einem Inline-Injektor zwischen Switchport und AP, nicht aus dem Switch.
- ⚠️ Config-Konsequenz: ap1s Trunk liegt heute auf
ether2→ wandert bei der Neuprovisionierung aufether1. Undether1steht aktuell aufpoe-out=auto-on(der hAP kann über denselben Port auch Strom abgeben) — beim Umbau auf „ether1 = versorgter Uplink" musspoe-outauf diesem Portoffgesetzt werden, sonst speisen Injektor und AP gegeneinander.
- ✅ Port =
- 🔋 DC-USV → ausgelagert nach TP24 (2026-08-16). Inhalt unverändert gültig (MeanWell LRS-150-48 + DDR-120-48 + LiFePO4 20 Ah, ~€190, 48-V-Bus; die CRS326 haben passenden DC-Input) — steht ab jetzt dort, samt der offenen Entscheidungen (Mac mini/Inverter, Bus-Standort nach dem Core-Umzug, Batteriegröße, Shutdown-Signalisierung).
- ✅ Standort-/Ablösungs-Mapping final (User 2026-07-22) — sauberes 1:1:
Bereich heute wird abgelöst durch Technik UG (virtueller Bereich in der Diele, kein Keller) sw1 (ALLNET, 16 Ports) crs326-core (= neuer L3-Router) Technik OG sw2 (ES208G, 8 Ports) + ap2 + cudy2 crs326-branch Wohnzimmer Sideboard ap1 — (bleibt, wird reiner AP) Kapazität unkritisch: 16+8 belegte Ports heute gegen 2× 24 GbE + 2× SFP+ künftig. Vollständig in Nautobot gepflegt (alle 8 Devices haben einen Bereich). - 📻 cudy-Hardware (User 2026-07-22): beide sind Cudy WR3600E V1.0, Firmware
2.3.15-20250905-191956.cudy1= Technik UG, am Core#11, aktiv als Übergangs-WLAN (elektrosmog.c,10.40.10.246) — und Christophs aktueller WLAN-Pfad.cudy2= Technik OG, außer Betrieb (Nautobot-StatusDecommissioning), wird nicht reaktiviert. - ⚠️ Etappe 1 (Erstzugriff auf die CRS326) ist NICHT kritisch (User 2026-07-22): Werkszustand, Gerät steht griffbereit neben ihm → der IP-Konflikt auf
192.168.88.1wird physisch/seriell aufgelöst, kein Lockout-Szenario. - ✅ Portplan-Widerspruch AUFGELÖST (User 2026-07-22): am Core ist
#15 = ap1und#11 = cudy1. Damit gilt die TP4-Variante (gi16Arris/VLAN100 →gi15Trunk → ap1ether2);switch/cli/03-trunk-ap-ports.cli(gi1 = ap1 / gi2 = ap2) ist STALE — die Datei bezeichnet sich selbst als „provisorisch, 2026-06-09" und wurde vom Edge-Cutover am 2026-07-01 überholt. Nicht mehr als Quelle verwenden.- Zielport nach dem Tausch: ap1 wandert auf
crs326-corePort 4 (User-Vorgabe). Gleichzeitig wandert ap1s Uplink geräteseitig vonether2aufether1(PoE-Port, s.o.). - ⚠️ Nach wie vor NICHT vom Gerät gelesen: die restliche sw1-Belegung.
switch/state-backups/sw1-running-config-20260716-*.txtsind 214-Byte-Fehlschläge (Incorrect User Name!!, toterclaudecode-Login),switch/cli/running-PRE.txtist Pre-TP1.gi16(Arris) undgi8(Trunk → sw2) stehen in Nautobot daher explizit als „UNVERIFIZIERT" markiert.
- Zielport nach dem Tausch: ap1 wandert auf
- 🔴 Betriebliches Kernrisiko (Analyse 2026-07-22): der Core-Tausch ist KEIN Switch-Tausch, sondern ein Vollausfall.
crs326-coreersetzt sw1 und wird gleichzeitig L3-Router — und an sw1 hängt auf#15ap1, also Gateway, DHCP, DNS und der WAN-Trunk fürs gesamte Netz. Core-Tausch und L3-Umzug sind damit faktisch dasselbe Ereignis und brauchen ein geplantes Ausfallfenster. → Reihenfolge-Entscheid (User 2026-07-22):crs326-branchzuerst (gegen sw2, Technik OG),crs326-corein einer eigenen, späteren Session. - 🛟 Rettungspfade liegen günstig auf verschiedenen Switches: Christophs Notebook hängt per WLAN über cudy1 → Core
#11; der kabelgebundene Plan B (Dock/Monitor Arbeitszimmer) hängt am sw2/Branch (P4). Beim Branch-Tausch stirbt also der Kabelweg, das WLAN überlebt. (Beim Core-Tausch stirbt beides — s. Kernrisiko oben.) - Hinweis: die A/B/C/D-Switch-Varianten in
hw-refresh-requirements.mdsind durch die CRS326-Beschaffung überholt (Doc = Recherche-Archiv + USV/Energie-Referenz). - Abh.: TP14 ✅ (IP-Migration). Verzahnt: TP20 (Platform-DB), TP21 (Nautobot GC), TP2.1 (sw2-Standalone-Recovery).
TP16 — CF-Tunnel: Round-Robin killen + reziprokes HA ▸ ✅ KERN UMGESETZT (2026-07-10) — ⚠️ HA aktuell degradiert (Live-Befund 2026-08-16) — docs/cf-tunnel-mapping.md §10, #1033
- 🟠 BEFUND 2026-08-16 (beim Doku-Aufräumen live über die CF-API erhoben, kein Eingriff): das reziproke HA läuft nur noch auf einem von drei Tunneln.
bf-mm= 2 Connectoren (je 4 conns) ✅ ·bf-nas= 1 Connector (3 conns) 🟠 ·bf-pve= 1 Connector (4 conns) 🟠.- Bedeutung: die Dienste hinter
bf-nas(gitea, grafana, pve-mcp, vw, ds-bf, nautobot) undbf-pve(pve, ccu, iobroker, z2m25, portainer, hass, ha-mcp) hängen jeweils an einem einzigen cloudflared-Prozess. Fällt dessen Host aus, sind sie weg — genau der Zustand, den TP16 beseitigt hat. Kein530/Round-Robin-Problem (das bleibt strukturell gelöst), sondern Redundanzverlust. - Bekanntes Muster: identisch zum Incident vom 2026-07-16 (macmini-Connectoren flappten unter QUIC → Fix
TUNNEL_TRANSPORT_PROTOCOL=http2). Diesmal sind die macmini-Connectoren oben (bf-mm hat 2), es fehlt je ein Gegenstück auf NAS/pve. Nächster Schritt (eigene Session): auf NAS und pve nachsehen, welcher der beiden cloudflared-Container nicht läuft, und ob es derhttp2-Konventionsfall ist.
- 🧹 Nebenbefund beim selben Sweep — Alt-Tunnel mit VLAN1-Origins (alle
down, 0 Connectoren, daher aktuell harmlos):openclaw(→10.40.41.147/.148/.139),coolify(→10.40.41.133),johnny2,TeilzeitCharlie. ⚠️openclawbeanspruchtn8n.emsenhuber.net, das produktiv aufbf-mmläuft — käme der Tunnel je wieder hoch, entstünde exakt das alte Round-Robin-Muster auf diesem Hostname. Empfehlung: die vier toten Tunnel löschen (user-gated, Löschen ist nicht umkehrbar) — gehört fachlich zu TP19 (VLAN1-Retirement:.41.133war eines der „unidentifizierten VLAN1-Geräte" aus TP19 B1.2 — hiermit als coolify-Origin identifiziert).
✅ Umgesetzt (2026-07-10, eigene Session): reziprokes 3-Tunnel-HA live (bf-nas
70d6a4cf/ bf-pvef7fdf3a6/ bf-mm7a322261), 6 Connectoren (2/Host, je Fremdhost), 19 FQDNs Loop-Smoke 0×530, HA per Host-Ausfall-Sim bewiesen. Round-Robin-#1033 strukturell weg. As-Built =docs/cf-tunnel-mapping.md §10. Schritt 5 Access-Strang:— 🔴 GESTRICHEN (User-Constraint 2026-08-14, s. TP16.2). Verbleibend offen:vwbypass→geschützt via WARPhass/ha-mcp400/403;gateway-dw(WG→404) klären.
-
Symptom (User): FQDNs über CF werden sporadisch / „sehr unsicher" aufgelöst = #1033-Muster zurück („jeden 3. Schuss eine Niete"). User hat alle 3 cloudflared-Images + Container aktualisiert/neu gestartet.
-
✅ Root-Cause endgültig (User-Diagnose bestätigt): macvlan/ipvlan-Host-Isolation. Ein cloudflared-Connector ist blind für macvlan/ipvlan-Container auf seinem EIGENEN Host (Linux-Kernel-Regel), erreicht aber Fremdhost-L2 + co-lokierte Bridge-Container. Mehrere Connectoren auf EINEM Tunnel = geteilter Ingress + CF-Round-Robin → jede Origin, die auf dem Host eines Connectors liegt, fällt bei ~1/N aus. Strukturell, nicht durch „Origins fixen" heilbar. Bsp:
omada .20.175/pve-mcp .20.173/gitea .20.157/grafana .20.109= NAS-macvlan → vom NAS-Connector NICHT erreichbar. -
Invariante: innerhalb EINES Tunnels ist kein Route→Connector-Pinning möglich (alle Connectoren teilen Ingress, CF round-robined). „Ausgewählte Routen für ausgewählte Connectoren" = getrennte Tunnel.
-
Ziel-Design (HA): reziproke Per-Host-Tunnel — jeder Host-Dienst wird von den Connectoren der ANDEREN Hosts bedient (nie vom eigenen):
Tunnel (= Dienste eines Hosts) Connectoren auf HA pve-Dienste NAS + macmini 1 abdrehbar NAS-Dienste (omada/pve-mcp/gitea/grafana/…) pve + macmini 1 abdrehbar macmini-Dienste ( .20.167)pve + NAS 1 abdrehbar 3 Tunnel, jeder Host fährt 2 cloudflared → Host-Ausfall ⇒ jeder Tunnel ≥1 Connector = voll HA. Voraussetzung: jede Origin L2-erreichbar.
-
Ist-Inventory (live 2026-07-10, s.
cf-tunnel-mapping.md §9): Ingress v119, 24 Hostnames, 2 live Connectoren. DOWN/stale:pbs .20.135,nginx-bf .41.123(noch VLAN1!),hermes+hermes-geli .20.167. Zu klären (Host/Netz):vw .20.127/ccu .20.232/iobroker .20.107/z2m25 .20.106— ggf.vw/ccuauf VLAN20-macvlan heben.gateway-dw(192.168.178.1) = WG-Sonderfall. -
CF-Access-Strang (verzahnt, s. TP11 Track-B):
hass-400 in der HA-iPhone-App = CF-Access davor (Companion-App kann Access-Login nicht) → Fix ohne Passthrough: iPhone in WARP enrollen (Device-Identity erfüllt Access; „Warp Login App" existiert bereitsallow:christoph).⚠️🔴 Überholt (2026-08-14):vw= aktuellbypass(öffentlich!) → von bypass auf geschützt heben.vwBLEIBT bypass — harter User-Constraint, Härtung stattdessen über TP16.2. „Passthrough-Hosts sind die kritischen" (User). -
Umsetzungs-Reihenfolge (für die eigene Session): (1) Reachability-Matrix je Host (pve/NAS/macmini → jede Origin, read-only) BEVOR gruppiert wird; (2) Interim-Sofortfix: bf-Tunnel auf pve-only (pve erreicht alles außer gateway-dw) → 0×1033, reversibel; (3) reziprokes 3-Tunnel-HA bauen (CNAMEs re-pointen, 6 Connectoren, Token je Tunnel; NAS/macmini-Alt-Token entfernen); (4) tote Origins bereinigen; (5) Access-Strang (WARP + vw); (6) Loop-Gegentest.
-
Abh.: TP14.1/14.2 ✅. Verwandt: TP11 (CF-Tunnel-Track-B/C + Access), #1033. SSoT:
docs/cf-tunnel-mapping.md. Memoryproject_cf_tunnel_1033. -
✅ Incident 2026-07-16 (User unterwegs, WARP „spinnt", keine BF-IPs mehr) ▸ Public-FQDN-Teil gefixt: macmini-Connectoren (
cloudflared-bfnas/-bfpve) flappten live unter QUIC/UDP (Docker-Desktop-Bridge-NAT) →bf-nas/bf-pvevon 2 auf 1 Connector degradiert (HA faktisch weg, nicht down). Fix: beide aufTUNNEL_TRANSPORT_PROTOCOL=http2umgestellt (rollend, 0 Downtime), wieder voll HA. Konvention: macmini-Connectoren künftig immerhttp2. ICMP-Befund (getrennt, strukturell): TCP über die WARP-Route ging überall, ICMP nicht (fm 36 %/bf 100 %/dw 100 % Loss) — cloudflared ist QUIC-Proxy, kein WireGuard. Kurz als „bf-pve-Route wegen USV" notiert (Commit1c1a676) → REVIDIERT (Begründung invertiert: bf-pve-Connectoren laufen auf NAS+macmini, nicht pve). Details:docs/cf-tunnel-mapping.md §13. → Richtungswechsel für Private Access = TP16.1.
TP16.1 — Private Access via native Cloudflare Mesh (WireGuard) auf crs326-core ▸ ✅ ABGESCHLOSSEN (2026-08-17) — docs/tp16.1-warp-mesh-native-crs326.md
- ✅ Kernergebnis: ICMP ist repariert. Privater Zugang unterwegs läuft über natives WireGuard auf
crs326-corestatt cloudflared-QUIC — 0 % Ping-Loss auf alle BF-VLANs, vorher 100 %. Genau das Symptom aus dem Incident 2026-07-16, das dieses TP ausgelöst hat. Öffentliche FQDNs unberührt auf dem 3-Tunnel-HA (TP16). Compliance 68/68. - ✅ §4.0 erledigt 2026-08-17: Mesh-Node angelegt.
bf-core-mesh=d1da7c8a-2736-4cbb-8af1-32db5393fb9c, Register-Token inmcp/cloudflare/.env(CF_MESH_REGISTER_TOKEN, gitignored). ➡️ Die seit 2026-07-17 offene Free-Plan-Frage ist beantwortet: der Free-ZT-Plan erlaubt Cloudflare Mesh — der LXC-Fallback ist vom Tisch. - 🔑 Der Weg dahin war ein Token-Problem, kein Plan-Problem (kostete 2 Anläufe). Der alte User-Token hatte zwei fehlende Permissions (§4.0 und §4.1 —
devices/settingswar schon lesend403). Ersetzt durch einen account-owned Token (9984078812bc…, ⏰ gültig bis 2027-01-09). Zwei Fallen, beide sehen aus wie „Token kaputt": (1) Account-Tokens verifizieren an/accounts/{id}/tokens/verify— am alten/user/tokens/verifymelden sie1000 "Invalid API Token", während alle echten Endpoints 200 liefern; (2) Dashboard-Fehler"Account tag in access policy must match tag in request uri"= eine Zone-Permission (DNS) steckt in der Policy-Zeile mit Account-Ressourcen → braucht eine eigene Zeile. Verifiziertes Soll-Set + Permission-IDs indocs/tp16.1-…md§4.0. Merke: Dashboard sagt „Edit", API sagt „Write". - ✅ §4.1–§4.4 durchgezogen 2026-08-17 (User-Freigabe „jetzt durchziehen"). Prereqs:
use_zt_virtual_ip=true, Device-Profil „Cloudflare Mesh" (4d3c0f57…), Split-Tunnel auf beiden Profilen korrigiert (100.64.0.0/10→/11+100.112.0.0/12). Gerät:cf-meshaufcrs326-core, Mesh-IP100.96.0.6/32, Peer162.159.193.2:2408, Handshake steht, Route100.96.0.0/12 → cf-meshaktiv; Backuppre-tp16.1-mesh-20260817.backupvorher (Auflage #4 ✅). CF meldet Node healthy. §4.4: Weg A hat funktioniert — der befürchtete vnet-Gotcha trat NICHT ein,10.40.0.0/16zeigt jetzt aufbf-core-meshstattbf-pve(Rollback = 1 PATCH zurück,bf-pveunangetastet). - ⚠️ Zwei Werkzeug-Fallen, real getroffen (gehören in jede künftige WG-Arbeit): (1) MikroMCPs
manage_wireguard_interfacekann grundsätzlich keinen privaten Schlüssel annehmen — RouterOS erzeugt ihn selbst; bei CF Mesh kommt er aber von CF → Key per SSH mit Interpolation aus der gitignoreten.envsetzen, nicht über das Tool. (2)manage_wireguard_peerschreibtendpoint: "IP:Port"komplett inendpoint-addressund lässtendpoint-port=0→ kein Handshake, sieht aus wie ein Firewall-Problem, ist ein Parameter-Bug. Nach jedem Peer-Addprint detailgegenlesen. Auchpersistent-keepalivefehlt dem Tool. - ✅ §4.5 ABNAHME BESTANDEN 2026-08-17 (MacBook am Hotspot, WARP connected): Ping 0 % Loss auf
10.40.10.1/10.40.20.105/10.40.99.12/10.40.20.10/10.40.99.1(47–63 ms) — vorher 100 %. TCP mit echtem Datenfluss (pve 8006 → 200, Nautobot → 302,ssh macmini→ ok). FQDN-Smoke gitea/hass/pve/nautobot/vw → 200/200/302/302/200 ⇒ cloudflared-Public-Teil unberührt. - ✅ Auflage Ausnahme #4 erfüllt: Ist-Stand als intended config zurück nach Nautobot → zuerst 65/68 (drei
extra-Drifts = die Mesh-Zeilen), Zeilen byte-genau aus dem Backup ins Jinja-Template, Push nachbf-golden-config, Repo-Sync → 68/68, keine Drifts. Privkey bleibt draußen (<<REDACTED>>-Maske wie beiwg-hub). ⚠️ Push-Gotcha: Nautobot schreibt Backups+intended in dasselbe Repo →git pull --rebasevor jedem Push, sonstrejected (fetch first). - ✅ Mgmt-ACL via GC ausgerollt 2026-08-17 (Nachlauf, alle 4 Geräte) —
72/72 compliant. Neue Compliance-Featureip-service(match_config=/ip service,config_ordered=false) → 17→18 Regeln, 68→72 Checks. Sollzustand einheitlich im Template:ssh/www/winbox/api=address=10.40.0.0/16,100.96.0.0/12,ftp/telnet/api-ssl=disabled=yes. Ablauf regelkonform: Backups auf allen Zielen →--job mgmt-acl --apply --no-deploy→ gestaffelter Deploy (ap2 zuerst, am Gerät gegengeprüft, dann ap1/branch/core) → Geräte-Gegenprobe → Compliance.- 🔎 Der Befund war das Gegenteil der Erwartung: ich hatte „branch/ap1/ap2 sperren den Mesh aus" befürchtet — tatsächlich hatten sie gar keine Address-Beschränkung (ssh/www/winbox/api/ftp/telnet komplett offen), und die dynamischen Einträge zeigten
REMOTE 100.96.0.1, waren also längst per Mesh erreichbar.winboxwar auf ALLEN vier unbeschränkt, auch am Core. Aus dem Erreichbarkeits-Fix wurde damit eine Härtung. - ⚠️ Scope-Erweiterung, bewusst und meldepflichtig:
ftp/telnet/api-sslwurden auf branch/ap1/ap2 abgeschaltet (Klartext bzw. ungenutzt; der Core hatte das bereits). Begründung: die Alternative wäre gewesen, „telnet aktiv" als Sollzustand in die SoT zu schreiben. Nichts hier nutzt telnet/ftp — der ALLNET-Telnet-Runner ist Archiv, das Gerät ausgebaut. - 📌 Schreibweise (Falle):
/ip service set ssh …mit dem Dienstnamen, NICHT[find name=ssh]— letzteres trifft auch den dynamischen Verbindungs-Eintrag und quittiert mitfailure: this is configured elsewhere.
- 🔎 Der Befund war das Gegenteil der Erwartung: ich hatte „branch/ap1/ap2 sperren den Mesh aus" befürchtet — tatsächlich hatten sie gar keine Address-Beschränkung (ssh/www/winbox/api/ftp/telnet komplett offen), und die dynamischen Einträge zeigten
- 🔴🔴 DIE FALLE DIESES TPs —
/ip servicesperrte das Router-Mgmt aus dem Mesh aus (Core, vor dem Rollout oben): Direkt nach dem WARP-Connect warcrs326-coremgmt-tot: MikroMCPConnection lost before handshake, SSHkex_exchange_identification: Connection reset, REST 502 — bei gleichzeitig verlustfreiem Ping auf dieselbe IP, und alle Hosts hinter dem Core normal. Ursache:/ip service ssh,www address=10.40.0.0/16, der Mesh-Client kommt aus100.96.0.0/12. ICMP kennt keine Service-ACL. Undnc -zmeldet „offen", weil der CF-Gateway-Proxy den TCP-Handshake terminiert — ein TCP-Connect ist über WARP KEIN Reachability-Beweis. Fix:address=10.40.0.0/16,100.96.0.0/12. Merkregel: wer per Mesh ans Netz kommt, ist noch lange nicht am Router. ⚠️ Fürcrs326-branch/ap1/ap2noch OFFEN — deren eigene/ip service-ACLs sind ungeprüft. Entscheidender Diagnose-Schritt war der Banner-Grab vom macmini (nc 10.40.99.1 22→SSH-2.0-ROSSSH): von innen gesund ⇒ Pfad/ACL, nicht Gerät. Fehlspuren, die man sich sparen kann: MTU (die großen Pings scheitern am WARP-Client-utunMTU 1380, nicht ancf-mesh) und SSH-Session-Erschöpfung. - ✅ Schalter „Allow all Cloudflare One traffic to reach enrolled devices" — recherchiert 2026-08-17, ENTSCHIEDEN: bleibt AUS. Laut CF-Settings-Referenz ist es ein globales Device-Client-Setting („Global device client settings"), alle Pläne, alle OS, Client-Mode „Traffic and DNS". Funktion: es lässt Traffic aus Mesh/WAN zu den eingebuchten Geräten hin — also Zugriff auf Device-IPs. Das ist die Client↔Client-Richtung und für unseren Fall (Gerät → Mesh-Node →
10.40.0.0/16) nicht nötig; der Mesh läuft bewiesenermaßen ohne. Kein API-Feld (in Spec,devices/settings-PATCH und Profil-GET gegengeprüft), und die CF-Docs nennen keinen Menüpfad. ⚠️ Die Docs widersprechen sich: die Mesh-Get-Started-Seite nennt es eine Profil-Einstellung, die Settings-Referenz eine globale. Nach User-Vorgabe („im Zweifel ohne Schalter") nicht gesetzt — nichts gebaut, nichts geklickt. Erst relevant, wenn ein Zugriff auf ein Endgerät (statt auf das Netz) gebraucht wird. - 📌 Bleibt gültig: die HA-Degradierung der öffentlichen Tunnel (TP16,
bf-pvefährt nur einen Connector) wird davon nicht geheilt — eigener offener Punkt. Und für TP5 vormerken: bei deny-by-default braucht der Mesh explizitforward accept 100.96.0.0/12 ↔ 10.40.0.0/16. - ✅ Gate erfüllt (2026-08-16): die Bedingung „gated bis TP21 den CRS326 abdeckt" ist eingelöst —
crs326-coreist seit 2026-08-08 der produktive L3-Router und seit 2026-08-13 in Nautobot adoptiert (68/68 compliant). Runbook §3 neu gemessen, §4.3 von Platzhalter auf echte Werte gezogen. - 🧭 Erwartung geraderücken (wichtig, weil leicht zu verwechseln): das Mesh ersetzt die CF-Tunnel NICHT. TP16.1 löst ausschließlich den privaten Zugang (unterwegs →
10.40.0.0/16per IP, inklusive ICMP) und tauscht dort den cloudflared-QUIC-Proxy gegen natives WireGuard auf dem Core. Die öffentlichen FQDNs bleiben auf dem 3-Tunnel-HA aus TP16. Beide Stränge laufen nebeneinander — die HA-Degradierung aus TP16 (2026-08-16) wird davon nicht geheilt und bleibt ein eigener offener Punkt. - 📌 Live-Befunde 2026-08-16 (read-only erhoben, kein Eingriff):
warp_connector=[], aber der GET antwortet (kein 403) → die Free-Plan-Frage entscheidet sich erst amPOST(§4.0).CF_API_TOKENistactive; ob er die separate Permission „Cloudflare One Connector: WARP" trägt, zeigt genau dieser POST — dort schlug es am 2026-07-17 mit10000fehl.use_zt_virtual_ip: false→ Unique-Device-IP muss weiterhin eingeschaltet werden. Gateway-Proxy TCP+UDP sind an.- Nur EIN Device-Profil (Default). Der „auf beiden Profilen"-Hinweis im Runbook meint also: Default jetzt, Mesh-Profil sobald es existiert — es gibt kein zweites, auf dem man etwas übersehen könnte.
- Split-Tunnel-Exclude enthält unverändert
100.64.0.0/10(verschluckt die Mesh-Overlay-Range) → der §4.1.4-Schritt bleibt nötig. - Die vnet-Route
10.40.0.0/16(5546dcb6…) zeigt weiter aufbf-pve— der Fallback steht. ⚠️ Aberbf-pvefährt derzeit nur einen Connector, der private Pfad hängt also an einem einzelnen cloudflared-Prozess. - ✅ Die letzte inhaltliche Unbekannte ist weg: „Rückweg-Routing TBD" hat sich erledigt, weil der Core L3-Gateway aller VLANs ist — es braucht keine Zusatzroute. Und
wg-hub(TP10) liegt auf demselben Gerät, ist also direktes Vorbild statt fernes Muster.
- ✅ GOVERNANCE-AUSNAHME #4 (User, 2026-08-16): die WG-Zeilen für den Mesh-Bring-up auf
crs326-coredürfen DIREKT gesetzt werden (MikroMCPplan_changesdryRun →apply_plan). Begründung — es ist kein Bequemlichkeits-, sondern ein struktureller Grund: TP22-Regel 1 schließt jede Sektion, die<<REDACTED>>enthält, generell vom GC-Push aus, und/interface wireguardist genau so eine Sektion. Ein privater Schlüssel ist über Golden Config also gar nicht deploybar — die frühere Zeile „CRS326-Zeilen laufen regulär über Nautobot GC" trägt nicht mehr. Auflage (wie Ausnahme #2): Ist-Stand danach als intended config zurück nach Nautobot; vorher/system backup(Regel 3). Scope-Grenze: nur der Mesh-Bring-up aufcrs326-core— nicht spätere WG-Änderungen, nicht andere Geräte. - 🔑 Damit die Ausnahme ein einmaliger Bootstrap bleibt — Secret-Handling-Design (Runbook §4.3): ein privater Schlüssel ist Geräte-Identität, keine Konfiguration (wie ein SSH-Hostkey). Regel: der private Teil entsteht am Gerät und verlässt es nie; nur der öffentliche geht in die SoT und wird in die Peer-Configs gerendert. RouterOS kann das nativ (
/interface wireguard adderzeugt den Privkey selbst). Compliance bleibt grün, weil dieConfigReplace-Maske aus TP22 Schritt 0 byte-identisch zu der im Template ist. ⚠️ Vorbehalt: bei CF Mesh erzeugt CF das Schlüsselpaar — dann fällt die On-Device-Erzeugung weg, das Prinzip („nie in Git, nie in der intended config") hält trotzdem. Stufe 2 (nautobot-secrets-providers+ Vault, Wert erst bei der Plan-Erzeugung einsetzen) lohnt bei 4 Geräten und einem Key nicht — eigener TP nach TP18/TP20.1. - 🧹 Sofort fälliger Modellierungs-Nachzug, unabhängig vom Mesh: die WG-Peers
fm/dwstehen mit hartkodiertenpublic-key="…"im Jinja-Template. Public Keys sind Daten, keine Templatezeilen — gehören nach Nautobot und von dort gerendert. - ⚠️ Für TP5 vormerken: sobald deny-by-default greift, braucht der Mesh-Verkehr explizit
forward accept 100.96.0.0/12 ↔ 10.40.0.0/16— heute passiert er nur, weil dieforward-Kette ohne Drop endet. - ⏭️ Was die Scharfschalt-Session macht:
POST warp_connector(Plan-Gate) → account-weite Prereqs (Unique Device IP, Split-Tunnel auf beiden Profilen) →wgcf-connector-Token → 4 WG-Zeilen auf dem Core → Route5546dcb6…umhängen (vnet-Gotcha, Weg A/B) → Ping-Abnahme. Trifft alle Live-WARP-Geräte mit einem kurzen Reconnect → Zeitpunkt user-gated. - ✅ Update (User-Entscheid 2026-07-22): Ziel-Device für den WG-Mesh-Node ist jetzt der CRS326 Core-Switch statt ap1 — konsistent mit dem TP15-Endstand (kein RB5009) — ⚠️ die damalige Klammer „Router bleibt ap1/ap2 rein für L3/WLAN" ist seit dem Core-Cutover 2026-08-08 überholt: L3 liegt auf
crs326-core, ap1/ap2 sind reine APs. Der Retarget auf den Core war damit im Ergebnis richtig, nur anders begründet als hier notiert und TP21s "ganzer Kabel-Fabric via RouterOS"-Modell (CRS326 ist ohnehin RouterOS-fähig und wird Nautobot-verwaltet). Reine Ziel-Doku-Änderung — das Scharfschalten bleibt weiterhin eine eigene, spätere Session und bleibt gated, bis TP21 den CRS326 als Device abdeckt. Keine neue Governance-Ausnahme: die bestehende ap1-Ausnahme (s. Ist-Stand-Zeile 31) gilt explizit nicht automatisch für den CRS326 — CRS326-Konfiguration soll regulär über Nautobot GC laufen, sobald TP21 so weit ist. Die CRS326 selbst sind aktuell noch Werkszustand (physisch bereits mit dem aktuellen Core verkabelt, aber die betreffende Uplink-Port bislang ungenutzt/down) — konkrete Management-IP/Interface-Zuordnung für den CRS326 als L3/WG-Endpoint ist noch nicht getroffen (TBD nach TP15-Bring-up). - Trennung: Public FQDNs bleiben auf cloudflared-3-Tunnel-HA (TP16); Private Access (unterwegs →
10.40.0.0/16per IP inkl. ICMP) wandert vom cloudflared-QUIC-Proxy auf einen nativen WireGuard-Mesh-Node auf dem CRS326 Core-Switch. - Warum CRS326-nativ: Cloudflare Mesh spricht WireGuard, RouterOS kann natives WireGuard (TP10-Hub auf ap1 ist einer, Muster überträgt sich) → Mesh-Node = WG-Peer zu CF-PoP, kein Container/TUN/LXC/neue HW. Verlagert die Rolle vom Router (ap1, der weiterhin Public-Edge + WLAN-Anker bleibt) auf den Core-Switch, der als zentraler Kabel-Fabric-Knoten ohnehin alle VLANs sieht. RouterOS-Container-Weg bleibt tot (kein
/dev/net/tun-Passthrough auf JEDER Router/Switch-HW) — daher weiterhin natives WireGuard, kein Container-Ansatz. - Verworfen: WG-Roadwarrior (User will keine Extra-App/Profil je Gerät), alle Helper-Host-ZT-Anbieter (SPOF-Verletzung).
- Warum heute nur Konzept: TCP-Pfad funktioniert (nur ICMP-Komfort fehlt), und die CF-Prerequisites sind account-weit (Unique-Device-IP, Split-Tunnel-Exclude, Device-Profile) → treffen Live-WARP-Geräte (1× kurzer Reconnect) → nicht unter Zeitdruck. Zusätzlich jetzt gated durch den Retarget: CRS326-Bring-up (Management-IP, VLAN-Filtering) muss erst stehen.
- Nächste Session (nach CRS326-Bring-up): Plan-Probe
POST warp_connector(Free-Plan-Gate; sonst LXC-Fallback) → account-weite Prereqs →wgcf-connector-Token→WG-Config → 4 WG-Zeilen auf dem CRS326 → Subnetz-Route + vnet-Route5546dcb6…von bf-pve umhängen (Rollback trivial) → Verifikation (Ping verlustfrei). Team-Domainemsenhuber.cloudflareaccess.com. Governance „Config nur via Nautobot" → CRS326-Zeilen regulär via TP21/GC, sobald das Device dort adoptiert ist. - ✅ Recherche-Härtung 2026-07-17 (Primärquellen animmouse + offizielle CF-Docs + OpenAPI-Spec, alles verifiziert, gilt unabhängig vom Zielgerät): (1) Produkt heißt seit 2026-04-14 offiziell Cloudflare Mesh (API-Pfade bleiben
warp_connector, im Spec bestätigt inkl. Token- und sogar HA-Endpoints); (2) ICMP-Proxy ist bereits AN (User-Korrektur: fm-Ping10.101.0.0/24beweist es — kein To-Do; mein „fehlt" war ein Fehlschluss aus dem API-Spec, das Flag ist Dashboard-only); (3) Split-Tunnel-Exclude auf beiden Device-Profilen (Default + Mesh); (4) vnet-Gotcha beim Route-Umzug („virtual networks only for cloudflared") → Weg A PATCH, Weg B DELETE+POST dokumentiert; (5) v4-only-Entscheid (Mesh-IPv6-site-to-site laut Guide broken, NAT66-Gefrickel nicht nötig); (6) keepalive 1m statt 25s ok. Alles indocs/tp16.1-warp-mesh-native-crs326.md§2/§4 eingearbeitet (Config-Block dort als Platzhalter markiert, IP/Interface TBD). - Abh.: TP16 ✅ (Public-Teil), TP10 ✅ (WG-Grundmuster, jetzt als Vorbild statt Direktziel), TP15 (CRS326-Bring-up), TP21 (Nautobot-Adoption des CRS326, Voraussetzung fürs Scharfschalten). SSoT:
docs/tp16.1-warp-mesh-native-crs326.md,docs/cf-tunnel-mapping.md §14.
TP16.2 — Härtung der öffentlich erreichbaren Dienste (bypass-Strang) ▸ 📋 KONZEPT (2026-08-14), Umsetzung offen
- 🔴 HARTER CONSTRAINT (User 2026-08-14):
vwwird NICHT WARP-/Access-geschützt. Gilt dauerhaft, nicht „vorerst". Begründung (technisch belastbar, nicht Bequemlichkeit): die Bitwarden-Clients (Browser-Extension, Mobile, Desktop) können den interaktiven Access-Login nicht durchführen — dasselbe Muster, das die HA-Companion-App auf400laufen lässt. Ein Passwortmanager hinter einem Client, den man im Notfall (fremdes Gerät, Neuinstallation, Handyverlust) nicht installieren kann, ist ein Aussperr-Risiko gegen den eigenen Schlüsselbund — und damit gefährlicher als das, wovor die Maßnahme schützen soll. Die frühere TP16-Schritt-5-Absicht „vw von bypass auf geschützt heben" ist damit gestrichen. - Ziel stattdessen: Schutz erhöhen, ohne Clients zu brechen — gilt für alle bypass-Dienste (
vw,hass,gitea). - ✅ Schicht 0 — bereits vorhanden, nicht unterschätzen: keine offenen Ports, alles ausschließlich über CF-Tunnel (3-Tunnel-HA, TP16), TLS terminiert an der Edge, DDoS-Schutz. Der Origin ist nicht direkt erreichbar. Das ist bereits mehr als bei den meisten Selfhostern.
- ✅ Schicht 1 — chirurgisch: Access nur auf die Pfade, die kein Client anfasst. CF Access wertet die spezifischere Application zuerst → man kann eine zweite Access-App auf
vw.emsenhuber.net/admin*legen (echte Policy) und den Host im Übrigen auf bypass lassen. Das Admin-Panel wird ausschließlich per Browser bedient — dort funktioniert der Access-Login einwandfrei, während/api,/identityund/notifications(die Client-Pfade) unberührt bleiben. Kein Client bricht, das wertvollste Ziel ist weg.- Alternativ noch härter: Admin-Panel ganz aus (
ADMIN_TOKENleer lassen) und nur bei Bedarf temporär aktivieren. - Analog für
gitea:/admin*+ Registrierung path-scoped schützen (Git-über-HTTPS mit Token bleibt offen).
- Alternativ noch härter: Admin-Panel ganz aus (
- ✅ Schicht 2 — App-eigene Bremsen (kostenlos, sofort): Vaultwarden hat Rate-Limits per Default an (
LOGIN_RATELIMIT_SECONDS=60,LOGIN_RATELIMIT_MAX_BURST=10, dazuADMIN_RATELIMIT_*) → Werte prüfen/verschärfen;SIGNUPS_ALLOWED=false,INVITATIONS_ALLOWED=false,SHOW_PASSWORD_HINT=false, 2FA erzwingen. HA hatip_ban_enabled+login_attempts_threshold. Gitea: Registrierung aus. - ✅ Schicht 3 — Edge-Regeln (CF), wirkt für alle Dienste gemeinsam: WAF-Custom-Rules + Rate Limiting gezielt auf die Login-Endpunkte (
/identity/connect/tokenbei vw,/auth/loginbei HA,/user/loginbei Gitea); optional Geo-/ASN-Filter. ⚠️ Free-Plan-Kontingente vorher im Dashboard prüfen (nicht belegt). - ✅ Schicht 4 — ein Mechanismus für alle: CrowdSec (oder fail2ban) mit Cloudflare-Bouncer. Bans landen dann an der Edge statt erst am Origin. Vaultwarden hat ein offizielles Fail2Ban-Setup-Wiki (Log-Muster für Login und Admin-Panel).
- 🔴 Voraussetzung für Schicht 2–4, und der eigentliche Knackpunkt: die echte Client-IP muss am Origin ankommen. Hinter dem CF-Tunnel sieht die Anwendung sonst nur die IP des cloudflared-Containers → jede IP-Sperre bannt den Tunnel statt den Angreifer = Selbstaussperrung aller Nutzer, und Rate-Limits greifen ins Leere. Genau dieser Defekt ist bereits offen dokumentiert: HAs
trusted_proxiesfehlen.20.10/.20.167(TP16,hass-400-Strang). ➡️X-Forwarded-For/CF-Connecting-IPsauber durchreichen ist Schritt 1 dieses TPs, alles andere baut darauf auf. - Reihenfolge: (1) Client-IP-Weitergabe fixen (inkl. HA
trusted_proxies) → (2)/admin-Pfade path-scoped schützen → (3) App-Limits + 2FA → (4) Edge-Rules → (5) CrowdSec/fail2ban mit CF-Bouncer. - Abh.: TP16 ✅ (Tunnel-HA). Verwandt: TP20.1 (vw wandert auf Platform-Postgres — DB-HA ≠ Access, getrennt halten), TP23 (dessen WARP-Managed-Network-Idee ist durch diesen Constraint entlastet:
vwverlangt keine Device-Identity, also kollidiert „WARP zuhause aus" nicht mehr mit dem Access-Strang).
TP17 — Shelly-Übersiedelung VLAN1 → VLAN30 (IOT) + shelly-mcp ▸ ✅ KOMPLETT (User-Bestätigt 2026-08-13): alle Shellys auf VLAN30 — Geräte-PW (TP17.2) weiterhin bewusst zurückgestellt — mcp/shelly/, Runbook docs/tp17-shelly-go-runbook.md
- ✅ Abschluss 2026-08-13 (User-Bestätigt): auch die zuletzt offenen saisonalen Shellys (s1/s2/s3/s12) sind inzwischen umgeklemmt — alle Shellys auf
dirtyvader-iot/VLAN30, kein VLAN1-Shelly-Rest mehr. Migration-Teil von TP17 damit vollständig abgeschlossen. - ✅ GO durchgezogen 2026-07-13 (16 Shellys VLAN1→VLAN30, 0 Fehler): Pilot s26 + Welle A (s4–s9) + Welle B (s10/11/13/15/17/19/20/21/25) → alle auf
dirtyvader-iot/10.40.30.<octet>verifiziert (SSID+IP+rssi). Mit den 6 Vorab-Migrierten (s14/16/18/22/23/24) = 22/26 auf VLAN30; VLAN1-Sweep.180-250= 0 Shellys. Restliche 4 saisonal ausgesteckte (s1/s2/s3/s12) inzwischen ebenfalls migriert (s.o.). - 🔧 Anker-Verfahren (User-Idee, statt sta1-Backup): je Gerät vor dem sta-Write die geräteeigene AP-Funktion aktiviert (
WiFi.SetConfig ap.enable— Firmware verlangt WPA2, kein offenes AP → PSK=IOT-PSK, live/kein Reboot) = Notanker, falls VLAN30-Join scheitert (Gerät bleibt überShelly*-<mac>-AP erreichbar, kein physischer Reset). Nach Verify alle 22 AP-Anker wiederdeanchort. Runner:mcp/shelly/migrate.py(migrate/deanchor/auth/table, Dry-Run default, stoppt bei erstem Fehler, reuseddiscover.py). - ✅ HA-Cross-Check nach Batch: einzige
unavailableShelly-Entities = s12 (saisonal aus) — alle 22 migrierten reconnecten via mDNS/zeroconf (TP7-Repeater vlan30↔vlan20-HA) auf neuer.30.x-IP, Entity-IDs unverändert (keyt per MAC). Inventarinventory/bf.csv.41→.30 nachgezogen (22 Zeilen, Section→IOT). - ⚠️ Coverage-Flag:
s4 kueche_mikrowelleverbindet mit rssi −93 (Metallgehäuse), hat aber verifiziert — grenzwertig, im Auge behalten. s7 Tiefkühl −85. Rest gut (−26…−81). - ✅ Eco-Mode-Policy (2026-07-13, PROVISORISCH): eco senkt CPU-Takt + WiFi-TX-Leistung → eco AN für RSSI ≥ −80 (Energie-Win, TX irrelevant), eco AUS für < −80 (Uplink-Headroom): s4/−91, s7/−88, s17/−81, s18/−79…−82, s19/−86 → 17× ON / 5× OFF, live via
Sys.SetConfig device.eco_mode(kein Reboot). s4 (Küchen-Sockel/Metall, −91, fix) bewusst eco-OFF = schwächster Link. ⏳ 2. Eval nötig nach TP3.3 (WLAN-Ausrichtung/Aufbau ändert RSSI → Grenzfälle neu bewerten; User 2026-07-13). - ✅ HA-Referenz http vs https geklärt (2026-07-13): HA speichert
configuration_urlfür alle 22 Shellys bereitshttp://10.40.30.x:80(Integration korrekt + neue IPs übernommen). Das „https" ist client-seitig (Mixed-Content-Upgrade, wenn HA selbst über https/Tunnel geöffnet) — kein HA-Fix möglich/nötig, Shelly-SSL bewusst NICHT (CPU/Energie, IoT-Netz). ⚠️ Rand-Fund: 1 HA-Shelly-Device zeigt auf10.95.10.206(Fremd-Subnetz, nicht BF) → separat prüfen. - ⏳ Rest (nicht mehr Migration, s. TP17.2/TP19): (1) einheitliches Geräte-PW → zurückgestellt als #TP17.2 (Kosmetik). (2) Nicht-Shelly-Mover + cudy-Teardown + VLAN1-Client-Retirement → läuft in TP19. (3) DNS/ip-plan Restfeinschliff (mit TP19).
TP17.2 — einheitliches Geräte-Passwort (Shelly SetAuth) ▸ ⏸️ ZURÜCKGESTELLT (Kosmetik, User 2026-07-13)
- Was: je Gerät
Shelly.SetAuth(Useradmin, realm-individuellerha1= sha256("admin::"), einheitliches Klartext-PW) viamcp/shelly/migrate.py auth --go.SHELLY_DEVICE_PWliegt inmcp/shelly/.env(gesetzt, len 13). Runner + Digest-Auth-Fallback in_rpcfertig. - Warum zurückgestellt: rein kosmetisch/Härtung; bricht die HA-Shelly-Integration, bis pro Config-Entry (22×) das Credential neu eingetragen ist → disruptiv, kein Mehrwert im abgeschotteten IOT-VLAN. Erst nach dem Netz-Teardown (TP19) neu bewerten.
- Ziel: ~26 Shellys (aktuell untagged VLAN1
10.40.41.2xx, weil auf alt-WLAN cudy, s. TP3.1/project_vlan1_dhcp_incident) auf SSIDdirtyvader-iot(VLAN30,w2-iot, WPA2/WPA3-mixed, PSK74c9L283$669) umklemmen → DHCPdhcp-v30/pool-v30 (live). Kein netzseitiger Move möglich (anderes WLAN) → per-Gerät WiFi-Reconfig. - User-Entscheide (2026-07-11): (1) volles
shelly-mcpbauen (reusable, nicht nur Skript); (2) Pilot 2–3, dann Rest; (3) DHCP-Reservierungen je MAC in VLAN30 (stabile IPs für HA/ioBroker/DNS). - ✅ Recon durch (
mcp/shelly/discover.py, read-only /shelly-Sweep): 16 live, alle Gen3/Gen4 (uniforme RPC-APIWiFi.SetConfig, auth=off — kein Gen1-Sonderfall). 10 „offline" = weihnachten_* (s1/s2/s3, saisonal ausgesteckt Juli) + s12/s14/s16/s18/s22/s23 (aus/DHCP-drift). ⚠️ Inventar-Fix: s6 (kueche_kuehlschrank,.213) MAC falsch erfasst (0c:72:74:36:90:9e) → reald0:cf:13:d8:18:fc. s24 hat gar keine MAC. - Mechanismus je Gerät: Gen2+ RPC
WiFi.SetConfig {sta:{ssid,pass,enable}}→ Reboot → landet.30.x. ⚠️ Risiken: falsches PSK → AP-Mode (physischer Reset); Gerät kurz offline; HA/ioBroker-Refs brechen bis re-pointed; WPA3-mixed ggf. zickig auf alter FW; ap1 2,4-GHz-Masterwifi2running:false→ Coverage v.a. via ap2 prüfen. - ✅ Live-Abgleich 2026-07-11 (go-ready): (a)
shelly-mcp(server.py) fertig — discover/get/set_sta/verify/reservation_plan, PSK in.envgesetzt (noch nicht als MCP registriert, optional). (b) Alle VLAN30-DHCP-Reservierungen liegen (.30.2xx, Oktett erhalten, außerhalb Pool.100–.200); s6-Reservierung.30.213MAC gefixt (falsch0C:72…9E→ realD0:CF:13:D8:18:FC). (c) IOT-SSID live verifiziert: ap1w2-iotrunning:true, 8 Clients −26…−68 dBm (ap1-wifi2-„running:false" ist kosmetisch). (d) Migration bereits ~5/26 durch: s14/16/18/22/23 seit ~2,5 d stabil auf reservierten.30.221/.223/.225/.202/.203(+.30.204unbekannt, evtl. s24) → Pilot faktisch bestanden. - ✅ HA-Cross-Check 2026-07-11 (alle IPv4-Geräte in HA): Shellys deckungsgleich;
.30.204= Shelly „Bad/Spiegelschrank" (Plus RGBW PM,14:33:5c:d8:2d:7c) = vmtl. s24 → 6 statt 5 schon migriert. Netzweite Aufstellung + VLAN1-Leerstand-Analyse im Runbook: nach TP17 + pve-Host→VLAN20 + Christophs Endgeräte→VLAN10 ist VLAN1 endgeräte-frei; es bleiben nur Switch-/AP-Mgmt (sw1/sw2/ap2 → VLAN99-Cutover, eigener Schritt) + 1 unidentifiziertes Gerät.41.246(morgen klären). Nicht-Shelly-VLAN30-Mover (User-bestätigt): ✅ SwitchBot floor-lamp.41.184+ ✅ Twinkly-Girlande.30.228(beide 2026-07-16 übersiedelt, s. TP19) + Creality Ender (fehlt noch, off). Withings schon übersiedelt; Tasmota existiert nicht mehr (kein aktives Gerät → stale HA-Eintrag). EOS-Smartwatches/eBook-Reader später + von Christoph selbst (eBook eher VLAN50). - Scope-Erweiterung (User 2026-07-11): je Gerät 3 Änderungen — WLAN→
dirtyvader-iot+ IP (.41.2xx→.30.2xx) + einheitliches Geräte-Passwort (Shelly.SetAuth, Useradmin, realm-individueller ha1 → Toolset_authinserver.pynachrüsten). PW entschieden: eigenes Shelly-Admin-PW (getrennt vom WLAN-PSK) →SHELLY_DEVICE_PWin.env(Christoph liefert Wert). HA-Entities unverändert (keyt per MAC). HA-Entities bleiben unverändert (HA keyt per MAC). Projektion TP17.1 (experimentell, nachrangig): Gen4 (~11 St.) auf Thread/Matter flashen (Firmware-Verfügbarkeit + Thread-Border-Router offen) — Konflikt mit „Entities unverändert" (Matter = neue Entities) → erst WiFi-Migration stabilisieren. - ✅ Reservierungs-/Pool-Konvention (User 2026-07-11): alle Shellys bekommen statische IP (
10.40.30.<octet>, gw/dns.30.1) + in-pool DHCP-Reservierung als Backup.pool-v30auf.100-.250erweitert (Reservierungen jetzt in-pool);set_staaufstatic=trueumgestellt; s24-Inventar +.30.204-Reservierung angelegt. Vollständiger HA-MAC-Scan: 2 verpasste Media-Geräte Apple TV 4K + Philips TV (aus, → VLAN40) — vor cudy-Abschuss VLAN verifizieren; Apple TV = vmtl. Thread-Border-Router (TP17.1)..41.246/.247 = cudy1/cudy2(Teardown-Ziele). Tasmota bestätigt tot. - Offene Schritte (morgen, „nur noch go", Runbook
docs/tp17-shelly-go-runbook.md): die 16 verbliebenen VLAN1-Shellys (s4–s11, s13, s15, s17, s19–s21, s25, s26 auf10.40.41.2xx) perWiFi.SetConfig→dirtyvader-iotumklemmen (Batch, je Gerät.30.xverifizieren) → Geräte-PW setzen → HA/ioBroker-Re-Point → SwitchBot/Tasmota/3. Nicht-Shelly → saisonale s1/s2/s3/s12 beim nächsten Einstecken → cudy-Alt-WLAN abbauen → DNS/Inventar/ip-plannachziehen. - Abh.: SSID/VLAN30 (TP3/TP4 ✅), DHCP-v30 ✅. Verwandt:
project_vlan1_dhcp_incident(cudy-Rest-Leak), TP5 (IOT-Firewall danach). Memoryproject_shelly_migration_tp17.
TP18 — Souveräner Objektspeicher (Garage, Multi-Site, S3-Cold-Tier) ▸ 🔜 KONZEPT (2026-07-12)
- Auslöser: 9-TB-Syno-Backup-Volume zu 2/3 voll; reine Daten ~3 TB, Tendenz steigend, „schlagartiger" Bedarf nicht ausgeschlossen. „Wenn skalieren, dann jetzt Syno-Nachfolger mitdenken."
- Kriterien (User-priorisiert): (1) keine Fremd-Abhängigkeit / kein Cloud-Lock-in (Cloud-Opex abschreckend); (2) Multi-Site BF/FM/DW; (3) HA (Standort-Verlust überlebbar); (4) billig/teuer trennen — Variante „kalt = Objektspeicher, heiß = lokal" genügt (kein Hot/Cold innerhalb des Stores nötig); (5) horizontal + vertikal skalierbar; (6) S3-API als Branchenstandard, den jedes Backup-Tool spricht.
- Entscheid Engine = Garage (Deuxfleurs, Rust): einziger Kandidat, der geo-verteilt über offenes Internet/WAN latenztolerant ist (CRDT-Metadaten, eventually consistent) → passt aufs 3-Keller-Modell BF/FM/DW. Ceph verworfen (will Sub-ms-LAN, Single-Cluster-über-WAN = Anti-Pattern; zu schwer, ~1 GB RAM/TB). MinIO (AGPL + Console/Feature-Abbau 2025) und SeaweedFS (kann Hot/Cold + Erasure-Coding, aber komplexer, Multi-Site async) = Fallback, falls später feingranulares Tiering / EC-Effizienz bei zweistelligen TB dominant wird.
- Entscheid Disk-Layout = JBOD, KEIN RAID. Redundanz gehört in eine Schicht: Garage RF=3 über 3 Sites ist die Redundanz. RAID 1 darunter = Doppelt-Bezahlen (3 Sites × 2 Mirror = 6× roh für 1× nutzbar, absurd). RAID 0 verworfen (1 Platte tot = ganzer Node-Rebuild über WAN). JBOD = jede Platte eigenes Garage-Data-Dir (v1 Multi-HDD): Failure-Domain = 1 Platte, Rebuild nur deren Anteil, kein Kapazitätsverlust. Merksatz: distributed store = „just a bunch of disks", Redundanz ausschließlich über die Sites.
- Was man dafür bezahlt: Plattentod triggert Re-Replikation über WAN (durch Upload-BW gedeckelt). Bei ~3 TB/Site tolerabel; wenn Bedarf „schlagartig" auf zweistellige TB springt → mehr/kleinere Platten (Blast-Radius) oder 4. Node, ggf. Wechsel auf SeaweedFS-EC.
- Dimensionierung (Planungsanker 10 TB nutzbar; heute 3 TB unique / 6 TB Backup-used): RF=3 → 30 TB roh gesamt = 1 volle Kopie ~10 TB/Site (provisionieren ~16 TB roh/Site: 2 Platten = halber Blast-Radius + Headroom). Linear skalierend.
- Kostenmodell (Annahmen: HDD neu CMR ~€18/TB · recert ~€10/TB · Strom €0,25/kWh · Lean-Node Mini-PC/pve 12 W + 2 HDD ~20–28 W):
- Capex kumulativ (3 Sites): Platten €540 (recert) – €900 (neu) + Nodes €400 (BF=pve €0; FM/DW je Mini-PC
€200) = **€600–1.300**. Vergleich: ein resilienter Syno-Nachfolger für 10 TB = €1.000–1.600 capex ohne Geo-HA → Garage-3-Node gleich teuer/billiger mit HA. - Opex kumulativ: ~€135–185/J Strom — aber getrennt gerechnet: FM/DW laufen über fremde Zähler, auf Christophs Zähler landet nur der BF-Node ≈ €50–60/J (Gegenleistung: er hostet deren Kopie, reziprok wie TP16).
- JBOD-vs-RAID1-Ersparnis: Strom bloß €9–22/J (Christophs Zähler) → kein Entscheidungsgrund; der Hebel ist Capex ~€900 (nicht gekaufte Spiegelplatten) + architektonische Korrektheit. (Reicht nicht für ein BW-Upgrade €120–240/J, taugt aber als Seed für HW-Rückstellungen.)
- Capex kumulativ (3 Sites): Platten €540 (recert) – €900 (neu) + Nodes €400 (BF=pve €0; FM/DW je Mini-PC
- Konzeptioneller Bruch (Syno-Nachfolger): Kein großes resilientes NAS mehr nötig — die kollektive 3-Site-Redundanz ist die Garantie. Syno-Rolle splittet: Hot/SMB/VM-Disks bleiben lokal (Syno oder ZFS auf pve, klein/schnell); Backup/Cold wandert in Garage über BF/FM/DW → das 9-TB-Volume wird aufgelöst statt ersetzt (aus 1 SPOF werden 3 geo-redundante Kopien). Backup-Tool (restic/Kopia) sprechen S3 nativ.
- Impacts auf Bestand (Kurz): (a) Storage-Redundanz-Philosophie kippt — weg von SHR/RAID pro NAS, hin zu 3× JBOD; (b) Backup-Kette Hyper-Backup/SMB → S3-Bucket umstellen; (c) Container-Host-System (TP14) kriegt Garage als LXC/Container je Site, aber auf rohen Platten, nicht auf bestehenden SHR-Volumes; (d) Upload-BW wird Durchsatz-/Rebuild-Limit; (e) HW-Planung verzahnt mit TP15 (Node-HW, pve-Standort) und TP24 (Stromversorgung je Site), FM/DW brauchen je 1 Node.
- Startpfad (inkrementell/reversibel): ① BF zuerst — Garage-Container auf pve, 2 HDDs JBOD, Backups lokal auf Bucket (sofort Nutzen, noch keine Redundanz). ② FM/DW nachziehen (Mini-PC + 2 Platten), RF→3, ab jetzt geo-redundant+HA. ③ Syno entlasten (Backup-Last abgeben).
- Offen (Modell scharfstellen): realer Strompreis; ob FM/DW eigene Nodes stellen oder Christoph HW hinstellt; Backup-Tool-Wahl (restic vs Kopia); ob heißes Zeug künftig auf ZFS/pve statt Syno.
- Abh.: TP10 (WG-Multi-Site = Transport, Upload-BW-Constraint), TP14 (Container-Hosts), TP15 (Node-HW) / TP24 (Stromversorgung), Muster von TP16 (reziprokes Per-Host-HA). Kein Blocker für laufende TPs. SSoT dieser Session.
TP19 — cudy-Teardown + VLAN1-Client-Retirement ▸ ✅ GESCHLOSSEN (2026-08-18) — docs/tp19-vlan1-cudy-teardown-runbook.md
- ✅ Abschluss-Sweep 2026-08-18, alles live gegengeprueft (reine Reads):
- VLAN1 ist leer:
/ip arpaufbridge= 0 Eintraege, 0 reachable. Nicht Restverkehr, sondern gar nichts. Der Dual-DHCP-Race ausproject_vlan1_dhcp_incidenthat damit endgueltig keine Quelle mehr. - Prometheus: kein einziges
10.40.41.x-Ziel mehr. Aktiv sindlocalhost:9090, n8n (.20.167:5678), grafana (.20.109:3000); die uebrigen acht Jobs sind auskommentiert. Der in der alten Restliste genannte Punkt ist damit verifiziert erledigt, nicht nur behauptet. - Interim-Kruecken sind weg:
/interface bridge portauf ap2 hat keinen Port mit eingeschraenktenframe-typesmehr — die TP3.1-Haertungadmit-only-vlan-taggedist beim Rebuild verschwunden. Nichts abzuraeumen.st-mainist seit TP3.3 fester Templatebestandteil. - DNS-Statics zeigen ausschliesslich auf
.99.x/.20.x, kein.41.x. - cudy1:
core ether11ohne Link seit 2026-08-08 19:33, in Nautobot Offline. cudy2 tot.
- VLAN1 ist leer:
- 🔜 Was NICHT mehr TP19 ist (bewusst dorthin verschoben, wo es hingehoert, statt den TP offen zu halten):
- Der physische Ausbau von cudy1 — Hands-on-Aufgabe, blockiert nichts, kein Netzeffekt.
- Die 4 toten CF-Tunnel (
coolify,openclaw…) — das sind Karteileichen in der Cloudflare-Config, kein Netzthema → TP16. - HA-Portainer
setup_retry(docker system dfauf ep14 braucht 33–120 s, struktureller Plattformnachteil) → Monitoring-Thema, TP11. Aussichtsreichster Weg bleibt ein eigener Portainer-Benutzer ohne Zugriff auf ep14.
- 📌 Nebenbefund beim Abschluss, sofort behoben: der Standort hatte keine funktionierende Zeitquelle.
ap1/ap2 zeigten per NTP auf
10.40.99.1, wo kein Server lief (status=waiting), branch hatte gar keinen eingetragen. ap2 war dadurch 17 Stunden versetzt — aufgefallen, weil ein Logeintrag von 04:57 als2026-08-17 12:19gestempelt wurde. Der Core ist jetzt NTP-Server (routeros/tp19-ntp-core-als-zeitquelle.rsc, inkl. der noetigeninput-Regel — ohne die waere der Server seit Etappe 4 eingeschaltet und trotzdem unerreichbar gewesen), branch ist Client (routeros/tp19-ntp-branch-client.rsc).- 🔎 Die Wurzel lag eine Ebene tiefer: auch der Core hatte keinen NTP-Client
(
enabled: no, keine Server) beiuse-local-clock: no. Ein Server ohne eigene Synchronisation liefert Stratum 16, das jeder Client verwirft — die Anfragen kamen also an (die Firewall-Regel zaehlte) und wurden trotzdem nicht brauchbar beantwortet. Der Standort hatte damit an keiner Stelle eine funktionierende Zeitsynchronisation; dass drei von vier Uhren stimmten, war Restglueck vom letzten manuellen Stellen. Behoben mitrouteros/tp19-ntp-core-client.rsc(time.cloudflare.com,at.pool.ntp.org) → Coresynchronized. - 🔴 Und der letzte Schritt war der unauffaelligste: der Server hielt Stratum 16 fest. Er war
eingeschaltet worden, waehrend sein eigener Client noch unsynchronisiert war — RouterOS
bewertet das nicht von selbst neu. Die Anfragen kamen an (die Firewall-Regel zaehlte mit),
wurden aber unbrauchbar beantwortet, und alle drei Clients blieben auf
waiting. Einenabled=no/enabled=yesnach der Synchronisation hat es geloest. Der entscheidende Test dorthin: branch einmal aufat.pool.ntp.orgzeigen lassen — es synchronisierte in 20 Sekunden. Damit war bewiesen, dass der Client heil ist und der Server schweigt, statt weiter im Nebel zu stochern. ✅ Endstand: alle vier Geraetesynchronized. (ap2s Uhr musste einmalig von Hand gestellt werden — 17 h liegen ueber der NTP-Panic-Schwelle, so weit springt kein Client von selbst.) - ✅ Governance nachgezogen (2026-08-18): NTP steht jetzt im GC-Template (Core als Quelle
mit oeffentlichem Upstream, branch/APs als Clients auf
10.40.99.1), wird per DHCP-Option 42 (ntp-server=je Netz, Christophs Vorschlag) an alle Clients ausgeliefert — nicht nur an die MikroTik-Flotte — und ist mit der neuen ComplianceRulesystem-ntpdrift-ueberwacht. Das war exakt der blinde Fleck, den TP26 fuer/ip firewall filtergeschlossen hat.
- 🔎 Die Wurzel lag eine Ebene tiefer: auch der Core hatte keinen NTP-Client
(
- ✅ Live-Nachprüfung 2026-08-16 (MikroMCP + CF-API, reine Reads):
cudy1ist tot, nicht nur „offline gemeldet":core ether11steht aufrunning=false, letzter Link-Down 2026-08-08 19:33, seither kein Link. Die Formulierung „aktiver VLAN1-Leak" ist damit endgültig hinfällig — der Dual-DHCP-Race hat keine Quelle mehr. Offen bleibt nur der physische Ausbau + Inventar/Doku.crs326-corehat keine VLAN1-IP mehr:/ip/addresslistet nur noch die 7 SVIs + die WAN-DHCP-Adresse — die Bring-up-Altlast10.40.41.211ist weg. Damit fällt einer der 5 Compliance-Drifts aus TP22 raus, sobald wieder Backup → Intended → Compliance gelaufen ist (die Compliance vergleicht gegen das letzte Backup, nicht gegen das Gerät — s. TP22-Falle).- ✅
crs326-branch-Interim ERLEDIGT (2026-08-16):10.40.10.2+ SVIvlan10über einen GC-ConfigPlan entfernt (s. TP22). Mgmt läuft über.99.2;/interface bridge vlanblieb byte-identisch, es gibt also weder einen Traffic- noch einen Drift-Effekt. .41.133identifiziert (war TP19 B1.2 „unidentifiziertes VLAN1-Gerät"): es ist das coolify-Origin aus dem gleichnamigen, seit Monaten toten CF-Tunnel. Ebenso.41.147/.148/.139aus dem totenopenclaw-Tunnel. Keine aktiven Geräte — Karteileichen in der Cloudflare-Config, nicht im Netz. Aufräumen = die 4 toten Tunnel löschen (user-gated, s. TP16-Nebenbefund).
- ✅ VLAN1-Adressen abgeräumt (2026-08-15) — der Weg dorthin —
docs/vlan1-rueckbau-howto-manuelle-schritte.md:- pve
10.40.41.100weg (/etc/network/interfaces:vmbr0voninet staticaufinet manual, Adresszeile raus; angewendet perip addr delohneifreload -a, damit die Bridge nicht durchgetreten wird). Nachher nur nochvmbr0.20, keine41.0/24-Route, alle 9 Gäste weiterrunning, Storage aktiv. Backup/root/interfaces.bak-tp19-20260815-183045. - Core
10.40.41.211weg über Nautobot GC (routeros/tp19-core-vlan1-address-remove.rsc). Mgmt.99.1+10.40.10.1intakt. Compliance damals 17/17 grün — der TP22-Backlog-Punkt „crs326-core 10.40.41.211" entfällt. (Zahl inzwischen überholt: nach TP16.1 sind es 72/72 Checks.) - HA zeigt auf
10.40.20.100(User), ioBroker korrigiert (User). - Prometheus bereinigt. Der pauschale
41→20-Ersatz war eine Falle: nurgrafana(.20.109) undn8n(.20.167:5678) liefern echte Metriken.giteahat/metricsgar nicht aktiviert,vaultwardengibt 404,portainer /api/statusliefert JSON statt Prometheus-Format,node/alertmanager/qdrantsind exited,piholeist abgewählt → 8 Jobs +alerting:-Block auskommentiert, 3 aktive Ziele, alleup. - 🔴 NAS-Falle:
prometheus.ymlgehört65534:65534, das Verzeichnisadm.christoph→cat > dateischeitert still („Permission denied"), während eincpdaneben klappt. Schreiben persudo tee+md5sum-Gegenprobe, nie der Shell-Erfolgsmeldung trauen.
- pve
- ⏳ OFFEN: HA-Portainer-Integration bleibt auf
setup_retry—docker system dfauf nas-bf ist zu langsam. Aus dem HA-Debug-Log:PortainerTimeoutError … GET /api/endpoints/14/docker/system/df→ConfigEntryNotReady. Die Integration ruftsystem dffür jede Umgebung bei jedem Update auf.- Container-Manager-Neustart am 2026-08-15 durchgeführt (
/usr/syno/bin/synopkg stop|start ContainerManager— Binary nicht im sudo-PATH; DSM meldet den Status danach weiterhin falsch alsstop). Alle 14 Container aus der Baseline zurück, zusätzlich kamhms-mqtthoch (Restart-Policyalways, lief vorher nicht). - ✅
hms-mqttstillgelegt (2026-08-16, User: „wird bald platt gemacht"). Es war bereits beendet; entscheidend war die Restart-Policyalways→no(docker update --restart=no), sonst wäre es beim nächsten Daemon-Neustart wiedergekommen. Ein bloßesdocker stophätte hier nicht gehalten. - ✅ Der Hänger ist damit weg:
system dfbeendet sich wieder (vorher rc=124 nach Ausgabe der Tabelle). ❌ Aber es bleibt viel zu langsam und schwankt: 33 s → 92 s → 3× >120 s. - 🔑 Wo die Zeit hingeht (gemessen):
images -q84 ms ·ps -aq95 ms ·volume ls -q65 ms ·system df33–92+ s. Also vollständig in der Größenberechnung (du-artiger Durchlauf der overlay2-/Volume-Verzeichnisse auf NAS-Platten) — ein struktureller Plattformnachteil, kein Defekt. Die Mengen sind harmlos (25 Images/13 GB, 10 Volumes/79 MB). - Aussichtsreichster Weg: eigener Portainer-Benutzer für HA ohne Zugriff auf ep14 → die Integration sieht die langsame Umgebung gar nicht. User-gated (Benutzer + Token anlegen). Alternativen: nichts tun (stört nichts) · Images aufräumen (6,98 GB reclaimable, Erfolg offen) · ep14 aus Portainer nehmen (schlechter Tausch).
- ⚠️ Zwei widerlegte Zwischenthesen, nicht wieder aufgreifen: die tote Umgebung
odroid-m1war es nicht (entfernt, Symptom blieb, alle übrigen Endpoints ≤0,16 s); und es ist kein Größenproblem der Images.
- Container-Manager-Neustart am 2026-08-15 durchgeführt (
- ✅ Restliste aus dem TP5-Log-Lauf — ABGEARBEITET (Abnahme 2026-08-16:
out:bridge= 0 über 10 min, Rate von ~166 auf ~34 Zeilen/min gefallen; im 43k-Zeilen-Log vom 08-17 kommtout:bridgenicht mehr vor). Wert dieses Eintrags = die Diagnosemethode, nicht der Stand. Der Log-Lauf hatte gezeigt, dass 76 % allen Inter-VLAN-Verkehrs aus VLAN20 nach VLAN1 (out:bridge) ging, obwohl dort nichts mehr antwortete (alle Ziele im ARPfailed/incomplete). Verursacher waren Konfigurationen, die nie nachgezogen wurden:prometheus(10.40.20.151, NAS) scrapet 10 tote Ziele:10.40.41.109:3000·.126:9443·.127:80·.147:5678·.149:3000·.152:3001·.153:9093·.154:9100·.159:6333·.23:80.10.40.20.105zieht auf10.40.41.100:8006= pve unter seiner alten VLAN1-Adresse (real10.40.20.100).10.40.20.107auf10.40.41.10:8080(NAS alt).- 📌 Umzugsregel: das letzte Oktett bleibt gleich, nur
41→20— belegt für grafana (.109), vaultwarden (.127), Portainer (.126). Für.23/.147/.149/.152/.153/.154/.159existiert kein laufendes VLAN20-Gegenstück (anderswo oder tot;alertmanagerist seit TP14.1 als kaputt notiert) → diese Ziele gehören geprüft und dann aus Prometheus entfernt, nicht umgeschrieben.
- ⚠️ Kein Firewall-/Portproblem (2026-08-14 geprüft, nachdem beim Umstellen ein Timeout auftrat):
pveproxylauscht auf*:8006,pve-firewallist disabled, keine iptables-Regel, kein/etc/default/pveproxy.https://10.40.20.100:8006antwortet aus VLAN10 und VLAN20 mit HTTP 200 in ~0,06 s. Wer hier einen Timeout sieht, sucht an der falschen Stelle — undtimeoutgibt es auf macOS nicht, eintimeout bash -c '… /dev/tcp/…'-Test meldet deshalb falsch-negativ. - ⚠️ Eskaliert 2026-07-15 (historisch — durch den WLAN-Rebuild 2026-08-08 gegenstandslos): der unter TP3.1 dokumentierte VLAN1-Leak trat damals auch auf ap1/
dirtyvader-mainauf — die ap-seitige Interim-Härtung (TP3.1) milderte das Symptom, die endgültige Lösung ist hier, TP19: VLAN1 physisch weg = kein Leck mehr möglich. - 🟢 cudy-Stand (User 2026-07-16): cudy1 (
.41.246) auf10.40.10.246umgehängt — bewusst kein Abbau-Ziel mehr, dient als Standalone-WLAN-Sender während der Umstellungsphase (nicht Teil des Teardowns, extern vom User selbst umkonfiguriert). cudy2 (.41.247) wird nicht mehr reaktiviert — faktisch tot, ARP-Sweep bestätigt keine Präsenz mehr auf VLAN1. B2.2 („cudy1/cudy2 stromlos/Reset/ausbauen") ist damit erledigt/gegenstandslos (cudy2 aus, cudy1 schon migriert statt abgebaut). - 🟢 Live-Sweep 2026-07-16 (ap1, vor geplantem Teardown): VLAN1 ist bereits viel weiter zurückgebaut als dokumentiert:
defconf/pool-v1-DHCP-Server ist bereitsdisabled=yes(Export bestätigt) — B2.4 („defconf zurückziehen") ist de facto schon erledigt, Ursprung/Zeitpunkt dieser Änderung nicht aus dieser Session bekannt (nicht in dieser Doku protokolliert).- ARP auf
bridge(VLAN1): nur noch 2 „reachable"-Hosts —sw1(.41.11, by design, bleibt bis MGMT-VLAN99) undpve-Interim-Fallback (.41.100) (B1.5-Aufräumziel, noch offen — Host-seitige Änderung auf pve, nicht Router). Alle anderen ~20 ARP-Einträge sind stale/„failed" (Cache-Reste längst migrierter Hosts wie macmini/.20.167, NAS/.20.10, grafana/.20.109 etc.), keine aktive Kommunikation mehr. - B1.1 MacBook (Claude-Sandbox-Client) bereits sicher migriert: aktive DHCP-Leases nur noch auf
dhcp-v20(10.40.20.101) unddhcp-v10(10.40.10.187), keinedefconf-Lease mehr. ⚠️ Dual-Homed über 2 VLANs gleichzeitig (project_dual_homing_slowness_incident-Muster) — funktional ok, aber im Auge behalten. - B1.2 unidentifizierte Geräte
.41.133/.41.198: kein ARP-Eintrag mehr vorhanden — entweder migriert oder abgeklungen, gelten für den Teardown als nicht mehr blockierend. - ⚠️ B1.3 (Media→VLAN40) und B1.4 (saisonale Shellys) nicht in diesem Sweep verifiziert — weiterhin offen, kurz vor dem finalen Cutover gegenchecken.
- Backup-Stand vor Cutover (2026-07-16): nur ap1 gesichert (Binary
bf-ap1-pre-vlan1-teardown-20260716.backupauf dem Router + lokaler Exportrouteros/state-backups/ap1-export-20260716-pre-vlan1-teardown.rsc). ap2 nicht gesichert, aber unkritisch: bewusst ausgesteckt (User-bestätigt 2026-07-16, kein Ausfall) — kein Backup nötig, solange es aus bleibt. sw1 nicht per Telnet gesichert (claudecode-Login 2× deterministisch abgelehnt), aber kein Blocker: User macht sw1-Änderungen ohnehin direkt im UI/CLI selbst (effizienter als über den Claude-Runner, gemeinsame Entscheidung) — Telnet-Automation für sw1 ist hier kein Muss. - Ziel (Kapstein der Segmentierung, s. Zeile 27): altes cudy-WLAN weg + VLAN1 als Client-Netz stilllegen (
defconf/pool-v1-Client-DHCP zurückziehen, ✅ bereits disabled). Nicht VLAN1 komplett: Switch-/AP-Mgmt (sw1.11/sw2.12/ap2.2) bleiben by design in VLAN1 (statisch, kein DHCP nötig) bis zum separaten MGMT-VLAN99-Cutover (eigener TP).cudy1/cudy2 =— cudy1 migriert auf.41.246/.247(Teardown-Ziele).10.246(Reuse statt Abbau), cudy2 tot/nicht reaktiviert (s.o.). - 🎯 User-Gate (Update 2026-07-14): Shelly ist wieder da (kein Blocker mehr) — SwitchBot ist KEIN Prereq mehr, funktioniert laut User erst NACH VLAN1-Retirement (Reihenfolge ggü. 2026-07-13 umgedreht) → wandert in die Teardown-Nachlese. TP19 damit direkt startbereit. Twinkly nebenher (saisonal).
- Verlorene Shelly — IDENTIFIZIERT via HA 2026-07-13 (User-Hinweis „du siehst ihn im HA"): HA-Device
shellyplugsg3-e4b063e41ab8, Modell = Shelly Plug S Gen3, MACe4:b0:63:e4:1a:b8, HA-device_id7a21e8f3349e6660f8b35974fc989a7b. NICHT im 26er-Inventar (Spare/Küchen-Steckdose, die Christoph beim Einrichten verbockt hat; er nannte sie „küche s20", aber s20=98:a3:16:7c:5f:ecläuft sauber auf.30.206— Verwechslung). KEIN AP-Mode, nicht tot: assoziiert am Altnetzelektrosmog.c(cudy → untagged VLAN1-L2), aber mit bogus-IP10.95.10.206(Fremd-Subnetz, User-Fehler) → unrouting-bar, daher weder in VLAN1/30-Sweep noch normal per IP erreichbar, aber per MAC in HA/WiFi-Table sichtbar. Der.219/s12-Verdacht war Sackgasse (s12 nur saisonal aus). - Update 2026-07-14: Shelly wieder da (User-Meldung) — Live-Status (noch bogus-IP
10.95.10.206oder inzwischen normal erreichbar?) zu Sessionbeginn per HA/ARP verifizieren; Recovery-Plan unten ggf. obsolet, falls sich das Gerät selbst erholt hat. - Recovery-Plan (falls beim Verify noch nötig): ap1 bekommt temporäre Zweit-IP
10.95.10.1/24auf der Bridge →10.95.10.206per L2 erreichbar → einWiFi.SetConfig {sta: ssid=dirtyvader-iot, pass=IOT-PSK, static, ip=10.40.30.<frei>}+Shelly.Reboot→ Gerät kommt auf VLAN30 hoch → temp-IP entfernen. Danach.30.x-Reservierung + Inventar (MACe4:b0:63:e4:1a:b8) + eco-Policy. Umgeht die „blutige Nase" (IP am Gerät ändern während man drauf hängt = Verbindungsverlust) — vom Router aus in einem Rutsch. Christophs manueller Direkt-Versuch (AP-IP auf 10.40.30 „verdrehen") war genau deshalb gescheitert. - ✅ SwitchBot floor-lamp
.41.184(b8:f8:62:09:f2:04) → erfolgreich auf VLAN30 übersiedelt (2026-07-16, Christoph via App/BLE), Res..30.227.
- Verlorene Shelly — IDENTIFIZIERT via HA 2026-07-13 (User-Hinweis „du siehst ihn im HA"): HA-Device
- Prereqs-Status (live nachgezogen 2026-07-16, s. Live-Sweep oben):
- ✅ Christophs Endgeräte → VLAN10/20 erledigt: MacBook-Air (
c0:c7:db:de:71:be, Claude-Sandbox-Client) hat aktive Leases nur noch aufdhcp-v10/dhcp-v20, keinedefconf-Lease mehr. iPhone.41.186nicht im aktuellen Sweep erneut geprüft (zuletzt off/asleep) — kurz vor Cutover gegenchecken. - ✅ 2 unidentifizierte VLAN1-Geräte (
.41.133/.41.198) aus dem ARP verschwunden — kein aktueller Eintrag mehr, gelten als nicht mehr blockierend (entweder migriert oder abgeklungen). - ⏳ Media → VLAN40 weiterhin offen: Apple TV 4K + Philips TV nicht in diesem Sweep verifiziert.
- ⏳ Saisonale Shellys s1/s2/s3/s12 weiterhin offen — nicht blockierend, kann übersprungen werden (Re-Onboarding-Aufwand akzeptiert).
- ⏳ pve-Interim-IP
.41.100weiterhin aktiv/reachable — Host-seitiger Cleanup auf pve selbst noch offen (nicht Router-Config).
- ✅ Christophs Endgeräte → VLAN10/20 erledigt: MacBook-Air (
- Teardown-Sequenz (angepasst an den Live-Stand): VLAN1-Client-Sweep ist schon fast leer (nur sw1-Mgmt + pve-Interim reachable) →
defconf/pool-v1 ist bereits disabled → cudy-Abbau entfällt (cudy1 umgenutzt statt abgebaut, cudy2 tot) → ✅ SwitchBot + Twinkly erledigt (2026-07-16) → verbleibt: Media-Check (B1.3), pve-.41.100abräumen (B1.5), Interim-Krücken bewerten (ap2frame-types=admit-only-vlan-tagged,st-main rrm/wnm), Inventar/ip-plan/DNS.41→Zielfinal. - Abh.: TP14 ✅ (Hosts raus aus VLAN1), TP17 ✅ (Shellys raus). Verwandt:
project_vlan1_dhcp_incident(cudy-Dual-DHCP-Leak), TP5 (Deny-by-default danach sauberer). SSoT hier +docs/tp19-vlan1-cudy-teardown-runbook.md. Folge: TP19.1.
TP19.1 — VLAN99-MGMT-Cutover (sw1/sw2/ap2-Mgmt VLAN1 → VLAN99) ▸ ✅ ERLEDIGT (2026-08-14 nachgezogen) — alle lebenden Geräte auf VLAN99, die beiden Rest-Punkte gegenstandslos
- ✅ Abschluss-Nachtrag 2026-08-14 (Status-Korrektur, kein neuer Change): der Header stand noch auf „ap2 vertagt, sw1 offen" (Stand 2026-07-16) — beides ist durch spätere TPs eingelöst bzw. gegenstandslos geworden, ohne dass es hier nachgetragen wurde. Ist-Stand: core
.99.1· branch.99.2· ap1.99.11· ap2.99.12— jedes lebende Netzgerät hat sein Mgmt auf VLAN99. sw1/sw2 existieren nicht mehr (physisch ausgebaut, in Nautobot per TP22 Schritt 5 auf Decommissioned). Damit ist TP19.1 vollständig; offen bleibt nur der VLAN1-Client-Teil, und der gehört zu TP19 (Hauptteil), nicht hierher. - Scope: die einzigen Dinge, die TP19s Hauptteil bewusst in VLAN1 belässt — sw1 (
.41.11), sw2, ap2-Mgmt (.41.2) — auf VLAN 99 (MGMT,10.40.99.0/24) umziehen. Erst danach ist VLAN1 wirklich komplett weg, nicht nur als Client-Netz. - User-Entscheid (2026-07-16): kein eigenständiges TP-Nummer — bewusst als Unterpunkt von TP19 geführt („VLAN1 killen"), nicht als TP22 o.ä.
- ✅ ap1-Teil erledigt (2026-07-16): ap1 brauchte keinen funktionalen Umzug (vlan99-Interface/GW
.99.1läuft schon seit TP4) — nur der kosmetische DNS-Static-Nachtragap1.bf.lan10.40.41.1→10.40.99.1war offen, per MikroMCP erledigt (dry-run→apply,manage_dns_entry). - ✅ sw2-Teil erledigt (2026-07-16, Christoph selbst über die Klickanleitung): sw2 jetzt auf
10.40.99.12(statisch, planmäßiger Zielwert ausip-plan.md) — per Ping verifiziert. Zwischenzeitlich war das Gerät kurz auf einer dynamischen10.40.99.200-Lease aufgetaucht (unklare Ursache, s. Memoryproject_tp20_tp21_fasttrack_20260716), jetzt aber sauber auf der geplanten statischen Adresse.CLAUDE.md/ip-plan.mdnachgezogen. - ✅ ap2-Teil erledigt (2026-08-08, im TP3-Rebuild) — die Vertagung wurde wie geplant eingelöst. ap2-Mgmt liegt auf
10.40.99.12(VLAN99), gesetzt bei der Standalone-Neuprovisionierung, nicht isoliert von Hand;primary_ip4in Nautobot per TP22 Schritt 5 nachgezogen. Derap2.bf.lan-DNS-Static wurde im TP22-Pilot-Deploy (2026-08-13, GC-ConfigPlan) von10.40.41.2auf.99.12gezogen. Ursprüngliche Vertagungs-Begründung zur Historie: - 🔜
ap2-Teil bewusst vertagt(User-Entscheid 2026-07-16): erst NACH Nautobot (TP21). Nautobot übernimmt dann in einem Rutsch ap1 + ap2 + die neuen CRS326-Switches (TP15) als config-as-code-Fleet — der ap2-Mgmt-VLAN-Umzug wird also nicht mehr isoliert von Hand gemacht, sondern Teil der Nautobot-Erstadoption.ap2.bf.lan-DNS-Static bleibt bewusst auf10.40.41.2bis dahin. - 🔒 TP19.1 war die letzte Ausnahme vom ap1/ap2-Config-Freeze — der jetzt (2026-07-16) zur generellen Regel ausgeweitet wurde (s. Governance-Entscheid oben): jede Gerätekonfiguration künftig ausschließlich über Nautobot, keine direkten Änderungen mehr an einzelnen im Netz verstreuten Geräten. Der ap1-DNS-Fix oben war die letzte direkte MikroMCP-Write-Aktion unter der alten (engeren) Regel.
- ⚪ sw1-Teil GEGENSTANDSLOS (2026-08-14 festgestellt): Christoph hat sich für „auf CRS326 warten" entschieden — sw1 wurde am 2026-08-08 durch
crs326-coreersetzt und physisch ausgebaut (Nautobot: Decommissioned, TP22 Schritt 5). Ein Mgmt-VLAN-Umzug für ein nicht mehr existierendes Gerät entfällt ersatzlos.switch/ui-guides/02-vlan99-mgmt-cutover.mdist damit historisch (nie ausgeführt, nicht mehr ausführbar — der Telnet-Runnerswitch/insgesamt nur noch Archiv). Ursprünglicher Stand zur Historie: Klickanleitung fertig, Ausführung on-demand (User-Entscheid 2026-07-16), nicht blockierend. - Bereits vorbereitet:
docs/ip-plan.mdPhase 2 hat schon einen Entwurf (ap2→10.40.99.2, sw1→10.40.99.11, „Lockout-Risiko, sorgsam", sw1 zuletzt). - Abh.: TP19-Hauptteil (VLAN1-Client-Retirement) — logisch danach, da VLAN99 als eigenes Mgmt-Netz erst dann wirklich nötig wird, wenn VLAN1 sonst leer ist. sw1-Teil braucht sw1-Telnet-Zugriff (User macht sw1-Changes direkt, s. Feedback-Memory) — Lockout-Risiko am größten bei sw1 (einziger Netzpfad zu sw2 hängt am Uplink).
TP20 — Platform-Datenbank (Postgres Precious-Tier + MariaDB Tier-2) ▸ ✅ Plattform live (2026-07-16) — Nautobot-DB angelegt, vw-Migration (TP20.1) offen — Memory project_mikrotik_commit_nautobot_gc
- ✅ Platform-Postgres live (2026-07-16): LXC 105 auf pve,
platform-pg.bf.lan/10.40.20.20, Ubuntu 24.04 (native PG16-Paket, kein PGDG-Repo nötig — bewusste Abweichung von der sonstigen Debian/community-scripts-Konvention der übrigen pve-LXCs, aus PG16-Verfügbarkeitsgründen). Cluster mit--locale en_US.UTF-8 -e UTF8neu initialisiert (Erstinstallation lief inC/SQL_ASCII, für Nautobot ungeeignet, korrigiert).wal_level=replicagesetzt;archive_modebewusst noch NICHT an — ohne pgBackRest/Garage-S3 (TP18) zum Prunen würde archivierte WAL unbegrenzt wachsen und die kleine 8GB-Disk füllen; wird nachgezogen sobald TP18 steht. Rolle+DBnautobotangelegt,pg_hba.conferlaubtscram-sha-256aus10.40.20.0/24. End-to-End-Verbindungstest (Netzwerk, nicht nur localhost) erfolgreich. Creds inpostgres/.secrets(gitignored,chmod 600). - Auslöser: Mehrere Dienste brauchen zentrale DB (Nautobot-SoT [TP21], Vaultwarden, HA-Recorder). Grundsatzentscheid statt Nautobot-Insellösung — „wir skalieren schneller als wir schauen können" (User).
- ⚠️ Abh.-Korrektur (User 2026-07-16): TP18 (Garage-S3) ist KEINE Vorbedingung mehr — „hat mit dem Netz nichts zu tun", transitiv aus der TP21-Kette entfernt. pgBackRest→Garage-S3 (s.u.) wird nachgezogen sobald Garage existiert, blockiert aber nicht mehr den Start.
wal_level=replica/archive_modekönnen mit einem Platzhalter/lokalen Archive-Ziel hochgezogen werden, produktives Off-Site-PITR kommt später. - ⚠️ Komodo-Abh. (s. TP2/Memory
project_komodo_tp_pending) vorerst zurückgestellt: Komodo selbst existiert noch nicht als laufendes System — kann also nicht „darüber" deployt werden. Entscheidung (Claude, 2026-07-16, transparent statt stillschweigend): Postgres-LXC + Nautobot-Stack werden jetzt direkt gebaut (LXC/Docker-Compose), Komodo adoptiert sie später — gleiches Muster wie bei den CRS326 (Hardware/Stack zuerst lauffähig, Management-Layer zieht nach). Sag Bescheid, falls das nicht gewünscht ist. - 🔍 Ressourcen-Check 2026-07-16 (live geprüft, SSH):
- pve (10.40.20.100): 4 vCPU, 15 GB RAM total, ~12 GB belegt, nur ~2-3 GB frei, 3 GB bereits im Swap — eng! Größter Verbraucher: HAOS-VM (
haos, vmid 100) mit ~8,2 GB aktiv von 10 GB Limit. Disk unkritisch (94 GB Root, 85 GB frei). - Mac mini (10.40.20.167): 10 CPU, 24 GB RAM, nur ~1,9 GB "wired" (nicht reklamierbar) — deutlich mehr echter Headroom als pve trotz "23G used"-Anzeige (macOS-Cache-Artefakt). Docker läuft bereits dort (n8n, n8n-redis, cloudflared×2, gitea-mcp, portainer_agent).
- NAS nicht geprüft (kein funktionierender SSH-Zugriff von hier aus mit den vorhandenen Keys/User) — für diese beiden Stacks laut TP20/TP21-Plan ohnehin nicht Zielhost.
- ✅ Entschieden (2026-07-16): Postgres-LXC auf pve, Nautobot-App-Stack auf NAS (nicht Mac mini) — NAS hat mehr Headroom (~12 GB verfügbar) und hostet bereits Gitea (Nautobots Git-Backend für Golden-Config-Templates), kürzere Wege als Mac mini. Deploy-Weg: Portainer-Stack auf ep14, analog dem bestehenden Muster (
docs/nas-vlan20/stacks/*.yml), Basis = offiziellesnautobot-docker-compose(github.com/nautobot/nautobot-docker-compose), nicht von Null gebaut. Wird als separate Session angestoßen (parallel zum Postgres-LXC-Aufbau auf pve). - Nachtrag (2026-07-16, nach Aufräumen): pve hat sich entspannt — nach Abschalten mehrerer mittelfristig eh stillzulegender Services (User) jetzt 6,7 GB frei, 0 Swap (vorher 2-3 GB frei, 3 GB Swap). Postgres-LXC passt entspannt.
- RAM-Upgrade-Idee (32GB-Stick) zurückgestellt (User 2026-07-16): Intel N100 (pve-CPU) ist offiziell auf max. 16 GB spezifiziert + Single-Channel; ein dokumentierter Fall mit demselben Corsair-Modul auf vergleichbarer N100-Hardware endete in Memtest86-Fehlern, stabil erst nach Rückbau auf 8GB. Empfehlung: 16GB als Decke für diese Kiste behandeln statt auf einen Settings-Fix zu hoffen. User rechnet ohnehin mittelfristig mit einem HW-Tausch für pve — gehört ggf. in TP15s HW-Refresh-Scope, noch nicht formal aufgenommen.
- pve (10.40.20.100): 4 vCPU, 15 GB RAM total, ~12 GB belegt, nur ~2-3 GB frei, 3 GB bereits im Swap — eng! Größter Verbraucher: HAOS-VM (
- ✅ 2-Tier (User 2026-07-14):
- Tier-1 „Platform-Postgres" (precious): EIN Postgres-Cluster, getrennte DBs für Nautobot (hier provisioniert) + Vaultwarden (Onboarding = TP20.1). PG 16 (Nautobot-Matrix-safe; Nautobot unterstützt kein MariaDB, nur PG/MySQL-8 → Postgres ist gesetzt, nicht optional).
- Tier-2 (Bestand): HA-Recorder bleibt MariaDB (Write-Churn, andere Zuverlässigkeitsklasse, single-site). (Vaultwarden liegt heute ebenfalls auf MariaDB → wandert per TP20.1 nach Tier-1.) Engine-Split fällt sauber entlang der Tier-Grenze.
- ✅ Single-Site-first (User 2026-07-14): jetzt nur BF-Primary („gehostet wird vorerst auf der bf-site", 2026-07-16 reconfirmed). Nimmt das 2-Site-Quorum/Split-Brain-Problem (bräuchte 3. Witness) vom Tisch. ABER replication-ready ab Tag 1:
wal_level=replica,archive_mode=on(Ziel vorerst lokal/Platzhalter, s.o.) — späterer Standby =pg_basebackup, kein Primary-Umbau/Restart. pgBackRest→Garage-S3 folgt nach TP18, nicht mehr Blocker. - Substrat: Postgres in LXC auf pve (DB-Klasse, nicht Docker).
- Scope TP20 = Plattform: Cluster hoch, Tiering, Backup/PITR, Nautobot-DB anlegen. vw-Migration + Cross-Site-HA = TP20.1 (ausgelagert).
- Offene Sub-Steps: PG-Version final (16 vs 17); Rollen/DB-Anlage Nautobot; pgBackRest-Bucket in Garage folgt nach TP18 (nicht mehr Blocker, s.o.).
- ⚠️ Komodo-Abh. (User 2026-07-16) vorerst zurückgestellt, s.o.: ursprünglich als Blocker gedacht (TP20 + neue Softwarepakete über Komodo statt direkt/Portainer), aber Komodo existiert noch nicht lauffähig und hat keine eigene TP-Nummer (nur unter TP2/TP11 erwähnt) → entkoppelt, um die Montag-Deadline zu halten. Komodo-TP-Nummer weiterhin zu klären, aber nicht mehr auf dem kritischen Pfad für TP20-Start.
- Abh.: keine harten Blocker mehr (TP18 entfernt, Komodo entkoppelt). Blockt weiterhin TP21 + TP20.1.
TP20.1 — Vaultwarden → Platform-Postgres + Cross-Site-HA ▸ 🔜 KONZEPT (2026-07-14, ausgelagert aus TP20)
- Ziel:
vw(.20.127, heute MariaDB) auf den Precious-Tier holen und das eigentliche User-Ziel erfüllen: DB-Replikation über 2 Sites (Standort-Verlust überlebbar). - Phase 1 — Migration (single-site): vw MariaDB→Postgres (Export → Import in Tier-1-DB
vaultwarden→DATABASE_URLumstellen → verifizieren). Danach ist vw precious + im pgBackRest/PITR-Schirm von TP20. (Alternative verworfen: vw auf MariaDB lassen + MariaDB-Repl — zugunsten EINER Replikations-/Backup-Mechanik im Precious-Tier.) - Phase 2 — Cross-Site-Standby:
db-platform-standby-LXC am 2. Standort →pg_basebackup/Streaming-Replication über WG (TP10) → manuelles Promote-Runbook. Repliziert den ganzen Tier-1-Cluster (vw = HA-Ziel, Nautobot bekommt Gratis-DR-Kopie). Patroni + 3. Witness nur, falls später Auto-Failover statt manuellem Promote gewünscht. - Verwandt/Abgrenzung: vw ist auch in TP16 offen (CF-Access:
bypass→WARP-geschützt) — DB-HA ≠ Access, getrennt behandeln. Reziprokes 2-Site-Muster analog TP16/TP18. - Abh.: TP20 (Tier-1 Postgres muss stehen), TP10 (WG-Transport für Phase-2), TP18 (Backup-Schirm). Kein Blocker für TP21.
TP21 — Nautobot Golden Config (config-as-code Control-Plane) ▸ 🟢 Plattform + Datenmodell + Templates live
- 🔴 BETRIEBSBEFUND 2026-08-18: der Stack hat sich zweimal in einer Nacht selbst umgebracht — Ursache
war der Image-Healthcheck, nicht Celery.
nautobot-workerund-schedulererben aus dem Image einenHEALTHCHECK, der alle 10 snautobot-server health_checkstartet — einen kompletten Django-Bootstrap (~250 MB). Unter Last dauert ein Lauf >2 min, die Aufrufe stapeln sich also unbegrenzt (neun gleichzeitig gemessen, aeltester 2:16 alt). Ergebnis: Speicher alle →proc_fork.c:189 Failed to fork(). errno=[12/Cannot allocate memory]im NAS-Syslog um 23:48:47 → eine Minute spaeter raeumt DSM den Stack ab (sauberesdocker stop, daher ExitCode 0 bzw. 137 nach Grace — kein Kernel-OOM,OOMKilled=false). Dasselbe Muster schon um 19:35.- Behoben im Stack (
docs/nas-vlan20/stacks/210-nautobot.yml, Portainer-Stack 203):healthcheck: disable: trueauf worker+scheduler,--concurrency=2 --max-tasks-per-child=100,mem_limitje Container, Web-Healthcheck-Timeout 5s → 15s. Load fiel von 73,5 auf 5,8. - ⚠️
cpus:geht auf Synology NICHT — der Kernel hat keine CFS-Quota, der Stack-Deploy bricht mitNanoCPUs can not be setab. Nurmem_limitverwenden. - 📌 Nichts haengt an dieser Health:
restart=unless-stoppedstartet bei Exit neu, nicht bei unhealthy, und keindepends_onwartet auf den Worker. Der Web-Container behaelt seinen billigen curl-Check — das ist das Signal, dasservice_healthynutzt. - 🎯 Strukturell bleibt es eng: Nautobot teilt sich die DS923+ (4 Kerne) mit einer VMM-VM, Active Backup und ~14 weiteren Containern. Der Stack bleibt vorerst dort (User-Entscheid 2026-08-18); ein groesserer Server ist gedanklich bereits vorgemerkt.
- Behoben im Stack (
- 🔴 Die Kehrseite des Re-Baselines, am eigenen Leib gelernt (2026-08-18):
ingest-core-firewall.pyerklärt den Ist-Stand zum Soll — es prüft nicht, ob der Ist-Stand sinnvoll ist. Beim Lauf nach TP5 E3/E4 ist damit die kaputte Fasttrack-Reihenfolge des Core als Absicht in den Config-Context gewandert (s. TP6). Der Warnhinweis im Skriptkopf („nur nach einer bewusst durchgeführten, verifizierten Änderung laufen lassen") ist also notwendig, aber nicht hinreichend: die Änderung war bewusst, die Umgebung, die mitgeschrieben wurde, hat aber niemand angesehen. Merkregel: nach dem ersten Re-Baseline einer Sektion deren Diff einmal ganz lesen, nicht nur die Zeilen, die man selbst angefasst hat.- ✅ Nachtrag 2026-08-19: der konkrete Fall ist aufgelöst — Christoph hat entschieden, die Fasttrack-Reihenfolge so zu lassen (Begründung in TP6). Der Eintrag in der SoT ist damit nachträglich korrekt. Die Merkregel bleibt trotzdem gültig: dass ein versehentlich mitgeschriebener Zustand sich hinterher als brauchbar herausstellt, ist Glück, kein Verfahren.
- 🔧 Zwei echte Template-Fehler, beim Re-Baseline 2026-08-18 gefunden (beide gepusht):
/ip service set … **address=**→ RouterOS 7.23/7.24 exportiertavailable-from=. Das erzeugte vier Dauer-Drifts (ap1/ap2/branch/core), bei denen das Geraet recht hatte und das Soll falsch war — und ein Push haette auf 7.24 auflaufen koennen.hw-offloadgehoert in die SKIP-Liste voningest-core-firewall.py: die REST-API meldet es auf der defconf-fasttrack-Regel,/exportschreibt es nicht → ewige Falsch-Drift auf genau einer Regel.- Ergebnis: 71/76 compliant; die verbleibenden 5 sind der TP28-Rest (
wifi-*auf dem Core). (App 2026-07-22, Basisdaten + Git-Backend + L3-Core-Template 2026-08-05, ap1/ap2 As-built 2026-08-08); Device-Adoption/Compliance-Push ausgelagert → TP22 — Memoryproject_mikrotik_commit_nautobot_gc
- Ziel: modellierter Control-Plane über den MikroTik-RouterOS-Kern: GUI-SoT + Config-Compliance/Drift + intended-config + Push. Ergänzt MikroMCP (interaktiv/Debug), ersetzt es nicht (deklarativ/DR/Compliance). Aus User-Recherche 2026-07-14: MikroTik in Golden Config erstklassig (
mikrotik_routeros+_api, Nornir/NAPALM, backup+deploy). - Scope-Grenze (Fassung 2026-08-16, nachgezogen): RouterOS in-model =
crs326-core(L3-Router) +crs326-branch(L2) + ap1/ap2 (reine APs) — alle 4 Geräte sind seit TP22 adoptiert, Golden Config deckt damit den ganzen Fabric inkl. WLAN. Es bleibt nichts außerhalb: der frühere Vorbehalt „außerhalb bleibt Omada-WLAN" ist gegenstandslos, seit der Omada-Stack gelöscht (2026-07-16) und CAPsMAN abgeschafft (2026-08-08) ist.Vorherige Fassung (überholt): „RouterOS in-model = Router (ap1/ap2, dauerhaft — kein RB5009) + beide CRS326-Switches (RouterOS-Boot) → Golden Config deckt den ganzen Kabel-Fabric. Außerhalb bleibt nur Omada-WLAN (eigener Controller, spielt aber laut TP15-Korrektur ohnehin keine Rolle mehr)."
- 🔒 Wird zum alleinigen Config-Weg für Netzgeräte (Governance-Entscheid 2026-07-16, s. oben): ab hier keine ad-hoc MikroMCP-Writes/Switch-UI-Klicks mehr auf Dauer — Nautobot managed den Fleet.
- ✅ Nautobot-Stack live (2026-07-16), auf NAS statt Mac mini (Ressourcen-Check hatte Mac mini vorgeschlagen, dann auf NAS umentschieden — mehr Headroom + Gitea-Co-Location, s. TP20-Log): Portainer-Stack
nautobot(Id 203, ep14), 4 Container —nautobot(App/API,10.40.20.30:8080),nautobot-worker(Celery),nautobot-scheduler(Celery Beat),nautobot-redis. Bildghcr.io/nautobot/nautobot:3.1.7(offizielles Image direkt, nicht dasnautobot-docker-compose-Repo — das ist eininvoke/Poetry-getriebenes Dev-Tooling-Repo ohne eigenständigedocker-compose.yml, für einen Portainer-String-Stack ungeeignet; bewusste Abweichung, dokumentiert statt stillschweigend). DB = Platform-Postgres (10.40.20.20, TP20). Compose-Dateidocs/nas-vlan20/stacks/210-nautobot.yml(gitignored, wie alle NAS-Stack-Files).- 🐛 Gotcha beim ersten Deploy: alle 3 Nautobot-Container liefen initial gleichzeitig
migrate(Standard-Entrypoint-Verhalten) → Race-Condition,IntegrityErroraufpg_type. Fix:nautobot-Service kriegt einenhealthcheck(curl .../health/),nautobot-worker/nautobot-schedulerstarten erst beidepends_on: nautobot: condition: service_healthy— serialisiert die Migration sauber auf einen Container. DB dafür einmalDROP+CREATE(sauberer Neustart, kein Datenverlust — war eh leer). - ✅ End-to-End verifiziert:
/api/status/mit Token 200, Nautobot-Version 3.1.7, alle 4 Container laufen. Superuseradminangelegt, Creds im Stack-File (gitignored) +postgres/.secrets(DB-Seite). - ⚠️ Bekannt offen, nicht blockierend: kein HTTPS/Reverse-Proxy vor Nautobot (Django-Security-Warnings beim Start, erwartet für internen HTTP-only-Betrieb auf VLAN20 — analog anderen internen Diensten); Celery-Worker-Registrierung beim allerersten Start nicht sofort sichtbar (
celery-workers-running:0initial), unkritisch, braucht kurz zum Einpendeln.
- 🐛 Gotcha beim ersten Deploy: alle 3 Nautobot-Container liefen initial gleichzeitig
- PoC-Pfad (angepasst an die Montag-Deadline):
Nautobot-Stack hoch✅ → ap1 + ap2 in einem Rutsch adoptieren (ap2 bekommt dabei gleich seinen VLAN99-Mgmt-Umzug aus TP19.1, s.o. — nicht isoliert vorher) → sobald CRS326 verkabelt sind, direkt als Nautobot-verwaltete Geräte adoptieren statt erst manuell konfigurieren → Compliance/Drift + Templates/intended für VLAN-/Firewall-Standards danach. - ✅ Basisdaten-Ingest durchgeführt (2026-07-22) — Ist-Zustand, nicht Zielzustand (User-Entscheid: „wir gehen vom status quo aus"). Quelle = ap1 live via MikroMCP. Skript-Muster idempotent (get-or-create + Delta-PATCH).
- Locations: neuer LocationType
BereichunterSite;BF → Technik UG(crs326-core, crs326-branch, ap2) undBF → Wohnzimmer Sideboard(ap1). - Devices: ap1 = Rolle Router (Ist am 2026-07-22 — ⚠️ seit der Adoption 2026-08-13 ist ap1 in Nautobot Wireless AP und
crs326-coreder Router, s. TP22), ap2 = neue Rolle Wireless AP + Status Offline, beide CRS326 Platform RouterOS nachgetragen (fehlte → hätte jeden GC-Job auf ihnen verhindert) + Werks-MAC/software-id incomments. Neu als Übergangs-Devices ohne Platform (nie GC-fähig, bewusst):sw1(ALLNET),sw2(ES208G),cudy1. - IPAM: VLAN-Group
BF+ 9 VLANs (1 Deprecated, 10/20/30/40/50/90/99/100 aktiv) + 8 Prefixes, jeweils an ihr VLAN gebunden. VLAN100/WAN bewusst ohne Prefix (öffentliches Liwest-/24, gehört uns nicht). - ap1-Interfaces (26): ether1-5, bridge, lo, wg-hub, vlan10-100, wifi1/wifi2, 7 VAPs — inkl. MACs,
ether2als Trunk (untagged VLAN1 + tagged 10-100), VAPs als Access-Ports auf ihrem VLAN. 9 Gateway-IPs an ihren Interfaces. Platzhalter-Interfacemgmtauf ap1 gelöscht (existiert real nicht). - WLAN: logischer Controller
bf-wlan(kein CAPsMAN —controller_devicebewusst leer, die Control-Plane ist Nautobot GC) + GruppeBF-WLAN-APs(ap1+ap2) + 6 WirelessNetworks mit VLAN-Bindung + 2 RadioProfiles (2,4 GHz ch1 / 5 GHz ch36, Domain AT). - 🐞 API-Gotcha:
tagged_vlanswird vom REST-Serializer in Detail-/List-Views alsnullzurückgegeben, obwohl korrekt gespeichert — Verifikation nur über GraphQL verlässlich. Kostet sonst eine Stunde Fehlersuche an einem Nicht-Problem. Ebenso: Relationen kommen per Default ohnedisplay(?depth=1nötig), undVLANGroup/Prefix/VLANbrauchen passendecontent_typesam LocationType, sonst 400. - ✅ CRS326-Core L3-Device-Modell + Ports angelegt (2026-08-05):
crs326-corejetzt Rolle Router, alle VLAN-SVIs (vlan10/20/30/40/50/90/99/100) + Gateway-IPs.1(außer vlan100) in Nautobot; Portbelegung vianautobot/ingest-crs326-ports.pyaktualisiert.crs326-branchbleibt Switch mit Mgmt-IP.99.13(Zielrenumber.12im Cutover-Fenster). - ⚠️ Offen/nachzutragen: exaktes Modell von sw1 + cudy1 (aktuell
… (Modell TBD)); Standort von sw1/sw2/cudy1 (hängen anBFstatt an einem Bereich);ap2s→ ✅ erledigt (TP22 Schritt 5):primary_ip4zeigt noch auf das tote10.40.41.210.40.99.12.
- Locations: neuer LocationType
- ✅ Git-Backend an Gitea angebunden (2026-08-05): Repository
bf-golden-config(jinja_templates/mikrotik_routeros.j2) sync-t in Nautobot; Generate Intended Config fürcrs326-coreerfolgreich, intended config in GC-Tabelle vorhanden.- ✅ Lokale Cutover-Config materialisiert:
routeros/tp15-core-cutover-intended.rscenthält die aus Nautobot gerenderte Config plus die 54 ap1-Leases und den WG-Hub-Privkey (lokales Fenster-Artefakt, nicht im Golden-Config-Repo).
- ✅ Lokale Cutover-Config materialisiert:
- ↪️ Adoption + Compliance-Push → ausgelagert nach TP22 (eigener TP, User-Entscheid 2026-08-08): ap1/ap2/crs326-Adoption, RouterOS-Nornir-Dispatcher,
enable_deploy, WG-Privkey/PSK-Secret-Handling. TP21 selbst = Plattform + Datenmodell + Templates (steht). Datenmodell-Nachträge (branch/core-Ports final, sw1 außer Betrieb, cudy1) laufen in TP22 mit. - Abh.: TP20 (Postgres muss stehen), Gitea ✅, RouterOS-Fleet (core/branch/ap1/ap2).
TP21.1 — Core-Cutover-Recovery (ap1 → crs326-core als L3-Router) ▸ ✅ NETZ WIEDER LIVE (2026-08-08); Aufräum-Todos offen
Kern-Erkenntnis (wichtig gegen Doku-Verwirrung):
crs326-coreIST jetzt der produktive L3-Router. Der Core-Cutover (TP15) wurde faktisch vollzogen — ap1 wurde plattgemacht/getrennt, core hat Routing/DHCP/DNS/NAT/WG-Hub übernommen. core-Mgmt =10.40.99.1(vlan99-SVI) bzw. same-subnet-Fallback10.40.10.1(RouterOS-Version 7.19.5 identifiziert das Gerät zweifelsfrei als CRS326, nicht als hAP/ap1). Die CLAUDE.md-Zeile „core grundkonfiguriert, NICHT produktiv" ist damit überholt.
- Verlauf: Ausgangssymptom war ein L3-Ausfall-Eindruck (kein DHCP, „kein Routing nach .20.x"). Ursache = unvollständiger Cutover: core hatte L3-SVIs + Firewall, aber es fehlten DHCP-Server, WAN-Egress, WG-Hub und der DNS-Resolver-Upstream. ap1 (bisher alleiniges L3-Gerät) war bereits Werksreset + getrennt.
- ✅ DHCP wiederhergestellt aus letztem ap1-Backup (
routeros/ap1-pre-core-cutover-20260806-073616.rsc): 7 Server (dhcp-v10…v99) + 8 Networks + 54 statische Reservierungen + Optiondns 1.1.1.1. Reproduzierbar inrouteros/tp21-core-dhcp-from-ap1.rsc. Legacy VLAN1 (pool-v1/defconf) + tote omada-inform-Option bewusst weggelassen. - ✅ WAN/Internet: dhcp-client auf
vlan100→ Liwest-Public-IP90.146.33.177gebunden (Arris hängt physisch an core.vlan100), NAT-Masqueradeout-interface-list=WAN, Default-Route korrekt; die self-pointing Blackhole-Route0.0.0.0/0 via 10.40.99.1entfernt. disabled-Falle beachtet: die ap1-Masquerade-Regelnout-interface=bridge/=ether1sinddisabled=yesund wurden NICHT übernommen. - ✅ WG-Hub (TP10) neu aufgebaut:
wg-hub(listen 51821, Privkey ausrouteros/ap1-wg-hub.privkey, Hub-Pubkey unverändert) + Peersfm/dw+ Routen. Beide Tunnel handshaken (dw + fm live). Reproduzierbar (Privkey redacted) inrouteros/tp21-core-wan-wg-restore.rsc. - ✅ DNS gefixt: core hatte
allow-remote-requests=no+ leeren Upstream → Client-DNS tot UND Hub konnte myfritz (FM-Endpoint) nicht auflösen. Fix =allow-remote-requests=yes+servers=1.1.1.1(plain, weil corecerts=0→verify-doh-certunmöglich). Das entsperrte auch FM. - ✅ Identity auf
crs326-coregesetzt (war fälschlich „ap1" — genau diese Altlast stiftete Verwirrung).mcp/mikromcp/config/routers.yamlauf Zielschema: core.99.1, branch.99.2, ap1.99.11, ap2.99.12(wirkt nach MCP-Neustart; danach core via routerIdcrs326-core). - ✅ disabled/invalid-Falle bereinigt (User-Hinweis „keine disabled-Falle?"): (a) die 2 TP10-WG-Forward-Regeln (
allow from/to WG spokes) warenI=invalid, weil aus dem ap1-Backup mit der stale Interface-ID*1Dübernommen → aufin/out-interface=wg-hub(per Name) korrigiert; (b) 2 inaktive WG-Route-Leichen (gateway="", aus einem früheren Cutover-Versuch vor Existenz von wg-hub) entfernt, nur die aktivengateway=wg-hubbleiben. Finaler Sweep sauber: filter-invalid=0, nat-invalid=0, routes-inactive=0, if-disabled=2 (nur ungenutztesfp-sfpplus1/2, gewollt). - ✅ Backups:
core-pre-dhcp-restore-20260808.backup(vor Eingriff) +core-post-tp21-recovery-20260808.backup(nach allen Fixes neu gezogen) auf dem Gerät. - ℹ️ branch ist gesund (L2, forwardet), Mgmt
10.40.99.2(+ temp— die Temp-IP ist am 2026-08-16 entfernt worden) — via core-MNDP bestätigt. Das in Winbox-MAC gesehene „0.0.0.0" ist der bekannte Discovery-Artefakt (Gerät hat auf dem Discovery-VLAN keine IP), kein echtes Problem.10.40.10.2 - 🔜 TODO (Aufräum-Liste, spätere Session — danach WLAN-Neuprovisionierung):
- DoH-Cloudflare-Gateway auf core wiederherstellen (aktuell nur plain 1.1.1.1, keine Filterung/Account-Bindung): CA-Bundle importieren →
use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes(Referenz-Config liegt auf ap1). - Intended config nach Nautobot zurückschreiben (die Direkt-Writes liefen unter der CRS326-Cutover-Governance-Ausnahme).
- branch
192.168.88.1-Rest verifizieren (Bootstrap Rev 4 entfernt es in Zeile 70; via MCP noch nicht gegengeprüft, weil Registry-Umstellung MCP-Neustart braucht). - ✅ core
ether4GEKLÄRT (2026-08-13) — es ist das Wohnzimmer-Sideboard (Smart-Managed-Switch, nur VLAN40-Multimedia), und der Port ist der falsche. Symptom war „TV meldet, LAN funktioniert nicht".- Ursache = VLAN-Mismatch, kein Kabeldefekt:
ether4hatpvid=40(untagged rein → VLAN40 ✓), ist in VLAN40 aber tagged-Member (untagged sindether2/ether3/ether5) → alles raus ist 802.1Q-getaggt und der untagged Switch/TV verwirft es. Einseitige Kommunikation. - Belege: TX 3,4 GB / 16 M Pakete gegen RX 452 KB / 1.338 Pakete, 0 stabil gelernte MACs; TV-Lease
10.40.40.11(70:AF:24:B8:C9:86) bound, last-seen 1h54m, gleichzeitig ARP-Statusfailed— ein Gerät, das nachweislich sendet, aber nicht antwortet. Der bound-Lease ist kein Gegenbeweis: beim Einschalten macht der TV einen INIT-REBOOT-REQUESTauf seine alte IP, RouterOS quittiert mit ACK und markiert bound — das ACK muss den Client nie erreichen. - Herkunft:
ether4war als ap1-Uplink-Trunk vorbereitet („ap1 wandert #15→#4"); ap1 blieb aufether15, in den übrigen Trunk-Port wanderte das Sideboard-Kabel. - ✅ BEHOBEN 2026-08-13 — am Port, nicht am Kabel (User-Vorgabe): „Patchfeld 1–10 ist durchnummeriert und komplett gepatcht, die Nummerierung wird nicht wegen einer Config geändert." Richtig so — die Portnummer ist physische Infrastruktur. Also
ether4sauber auf untagged VLAN40 gezogen statt das Kabel zu verschieben. - Ausgeführt via Nautobot-GC-ConfigPlan (
plan_type=manual, 6 Zeilen, change_control_idTP21.1-4 …), nicht per Direkt-Write — Governance gewahrt. Vorher/system backup=core-pre-ether4-vlan40-20260813.backup(Regel 3).ether4aus den Tagged-Listen von VLAN 10/20/30/40/50/90 entfernt + als untagged-Member zu VLAN40 ergänzt.pvid=40stand bereits — das war nie das Fehlende. Verifiziert:vlan40 untagged=ether2,ether3,ether4,ether5,tagged=ether1,ether8,ether15; vlan99 (Mgmt) und vlan100 (WAN) unangetastet. Damit ist auch der Flood-Leak aus IoT/INFRA/MAIN zum Wohnzimmer-Switch weg. - ✅ End-to-End-Beweis ERBRACHT (2026-08-14, live via MikroMCP auf
crs326-core) — der TV war am 08-13 tatsächlich nur im Standby. Alle vier Kriterien grün:ping 10.40.40.11= 5/5, 0 % Loss (avg 563 µs); ARPcomplete=true/status=delayaufvlan40(vorherfailed);/interface/bridge/hostlernt70:AF:24:B8:C9:86aufether4, VID 40;ether4rx-unicast=6.909/ 3,0 MB RX (am 08-13 noch 1.338 Pakete / 452 KB → der Downstream lebt jetzt). DHCP-Leasetvweiterhin bound aufdhcp-v40. Damit ist TP21.1 Punkt 4 vollständig abgeschlossen und die Diagnose „tagged Egress auf einem untagged Port" ist end-to-end bestätigt (SSoT-Merkregel:ref_tagged_egress_oneway_port). - 🔴 INCIDENT + Lehre (2026-08-13): Der erste Deploy lief gegen das FALSCHE GERÄT (ap1 statt core). Ich hatte 4 Device-UUIDs mit einer Sammelabfrage geholt und die Reihenfolge angenommen; die Nautobot-REST-API sortiert aber alphabetisch →
ap1, ap2, crs326-branch, crs326-core. Der ConfigPlan trug damit ap1.- Schaden: keiner. RouterOS wies jedes
setab (invalid value for argument interface), weilether8/13/15auf einem 5-Port-hAP nicht existieren; die Ablehnung ist pro Kommando atomar → kein Teilzustand. ap1 nachgeprüft: VLAN-Tabelle vollständig, 25 WLAN-Clients, Mgmt.99.11. Das war Glück, kein Können — bei einem auf beiden Geräten gültigen Kommando (z.B.tagged=ether1) hätte es ap1s VLAN-Tabelle zerlegt. - Regel daraus: Device-UUIDs IMMER einzeln per Name auflösen, nie aus einer Sammelabfrage positional zuordnen — und vor dem Deploy
plan.device.displaygegen den Zielnamen assert'en (im Skript jetzt so gemacht). - Bestätigt zum zweiten Mal: der Deploy-Job meldete
SUCCESSund der PlanCompleted, obwohl auf dem Gerät nichts ankam. Weder Job- noch Plan-Status sind ein Wirksamkeitsnachweis — nur die Gegenprüfung am Gerät zählt. Der Fehl-Plan wurde gelöscht (irreführender Datensatz).
- Schaden: keiner. RouterOS wies jedes
- ✅ Lücke geschlossen (2026-08-13, User: „compliance rules! die Änderung machen wir"):
/interface bridge port+/interface bridge vlansind jetzt für alle drei Geräteklassen im Template und als ComplianceFeatures scharf — s. TP22.
- Ursache = VLAN-Mismatch, kein Kabeldefekt:
ap1/ap2Neuprovisionierung (WLAN-Rebuild, eigene Session) — ap1 ist Werksreset; danach greifen die.99.11/.99.12-Registry-Einträge.
- DoH-Cloudflare-Gateway auf core wiederherstellen (aktuell nur plain 1.1.1.1, keine Filterung/Account-Bindung): CA-Bundle importieren →
TP22 — Device-Adoption + Golden-Config Compliance-Push (RouterOS-Fleet) ▸ ✅ DURCH (2026-08-13), Compliance-Backlog abgearbeitet 2026-08-16 → 68/68, 0 Drifts — alle 5 Schritte erledigt (Schritt 4 per Entscheid „keine Secret-Injection"); aus TP21 ausgelagert 2026-08-08
- Ziel: die 4 Live-Geräte (crs326-core, crs326-branch, ap1, ap2) real unter Nautobot Golden Config nehmen — Backup → Compliance/Drift → intended → Push (
enable_deploy). Damit greift der Governance-Entscheid „Config exklusiv über Nautobot" operativ. Macht die aktuellenrouteros/.secrets/*.rsc-Handoffs mittelfristig überflüssig. - Stand aus TP21: Plattform + Datenmodell + Git-Template + intended-config für core stehen; ap1/ap2 als reine APs zurückgeschrieben (
nautobot/ingest-ap-rebuild.py, 2026-08-08).enable_plan/enable_deployinnautobot_config.pynoch bewusst aus (pull/read-only). - ✅ Schritt 0 DURCH (2026-08-13) — Backup-Scrubbing + Repo-Neuanlage. Vorgezogen aus Schritt 4, weil ohne Scrubbing jedes weitere Backup Secrets geleakt hätte.
- 🔴 Root-Cause-Fund: Es gab keine ConfigReplace/ConfigRemove-Regeln → der Backup-Job vom 2026-07-22 hatte den ap1-
/exportungefiltert nach Gitea geschrieben.backups/ap1.cfgenthielt im Klartext den damals wie heute live genutzten WG-Hub-private-key (bei der Core-Recovery unverändert aufcrs326-coreübernommen, damit FM/DW-Spokes matchen) und 6 WLAN-PSKs. - ✅ 5 ConfigReplace-Regeln (Platform RouterOS) via
nautobot/ingest-gc-scrubbing.py(Dry-Run-Default, Regex-Selbsttest bei jedem Lauf):10-wifi-passphrase,20-wireguard-private-key,30-preshared-key,40-password,50-secret→ Maske"<<REDACTED>>". Gegen den echten Export kalibriert: RouterOS quotet nur bei Bedarf (4 von 6 PSKs standen unquotiert), deshalb Alternation("(?:[^"\\]|\\.)*"|\S+)mit der quotierten Variante zuerst (\S+ist greedy und würde bei einem PSK mit Leerzeichen den Rest exponieren). Replace normalisiert immer auf die quotierte Form → Maske ist formunabhängig byte-identisch (Voraussetzung für das Template in Schritt 1). Negativtest:public-key=wird nicht maskiert (sonst bräche der WG-Peer-Block). - 🐞 Blocker nebenbei gefunden + gefixt: Nautobot hatte das ALTE Router-Passwort. Der erste Backup-Lauf meldete Job-
SUCCESS, schrieb aber nichts —backup_last_attempt_datesprang,backup_last_success_datenicht (GC meldet Job-Erfolg auch bei Geräte-Fehlern; nur das Success-Datum je Gerät zählt). Ursache:NAUTOBOT_ROUTEROS_PASSWORDim Stack war 12 Zeichen aus der Zeit vor der PW-Vereinheitlichung (2026-08-08, 32 Zeichen, identisch auf allen 4 MikroTik). Fix = Stack-Env nachgezogen + Stack 203 redeployed; Datei zusätzlich aufchmod 600(Backup.bak-20260813). - ✅ Gitea-Repo
admin/bf-golden-configgelöscht + neu angelegt (User-Entscheid: Repo neu, nicht rotieren — History-Rewrite verworfen, weil Gitea unerreichbare Blobs bis zum server-seitigengcbehält). Struktur + Template + README wiederhergestellt. Vollscan aller Blobs der neuen History: 0 unmaskierte Secrets (die 6 Regex-Treffer sind 5× README-Doku der Feldnamen + 1× der Template-Platzhalter). Nautobot-GitRepository re-synct, End-to-End-Backup ins frische Repo verifiziert (112 Z., 6/6 PSKs maskiert). - 📌 Risiko-Akzeptanz (User 2026-08-13): keine Rotation. Faktenlage: Repo
private=true, anonymer Zugriff 404. Aber Gitea hängt auf CF-bypassam Internet undha-xstateist ein Service-Account mit Gitea-Admin (kann jedes private Repo lesen) → Lesbarkeit für 2 Accounts, nicht fürs Internet. Trigger für nachträgliche Rotation: ändert sich die Gitea-Exposition oder derha-xstate-Account → WG-Key rotieren (FM/DW-Klickanleitungrouteros/fritzbox-wg-lanlan-klickanleitung.md). - ⚠️ DR-Konsequenz: ein maskiertes Backup ist kein Wiederherstellungs-Artefakt. Restore hängt weiter an
~/.secrets/,routeros/.secrets/*undrouteros/ap1-wg-hub.privkey(alle gitignored).
- 🔴 Root-Cause-Fund: Es gab keine ConfigReplace/ConfigRemove-Regeln → der Backup-Job vom 2026-07-22 hatte den ap1-
- ✅ Schritt 1 DURCH (2026-08-13) — AP-Zweig im Golden-Config-Template.
- Datenmodell = ConfigContext (
nautobot/ingest-ap-configcontext.py). Verworfen: Wireless-RadioProfile(haengt überControllerManagedDeviceGroupan einem Controller — den gibt es seit der CAPsMAN-Abschaffung bewusst nicht mehr; ein Fake-Controller wäre Modellschuld), CustomFields (skalieren nicht), Ableitung aus VAP-Descriptions (SSID nur als Freitext → stille Brüche). Angelegt: ConfigContextap-common(Scope Role Wireless AP + Platform RouterOS, weight 1000) mitzones/radios/Site-Konstanten +local_config_context_dataje AP mit nur den 2 Kanalnummern. Frequenz wird im Template gerechnet (5000+5*ch/2407+5*ch) statt gespeichert. - Cross-Check im Skript: die
zones-Tabelle wird gegen die 11 real modellierten VAP-Interfaces (Name-Präfix +untagged_vlan) validiert, Divergenz = Abbruch → ConfigContext und DCIM können nicht auseinanderlaufen. - Template: neuer Zweig
{% elif obj.role.name == "Wireless AP" %}(rollen-, nicht namensbasiert). Scope bewusst nur die compliance-verwalteten Sektionen (channel/datapath/security/configuration/bridge-vlan/vlan99/ip-address/route) — nicht die ganze Config: defconf-Boilerplate (ipv4/ipv6-Firewall,/disk,/tool mac-server) und die VAP-Zeilen bleiben draussen, weil deren MACs gerätevergeben und in Nautobot nicht modelliert sind. Die früheren „Ausnahmen" fallen aus den Daten heraus: IOT hatbands:["2g"]→ landet automatisch nur aufwifi2; VLAN1/VLAN99 stehen als literale Zeilen ausserhalb der Schleife (VLAN99 aufbridge, NICHT auf die Radios — sonst Mgmt over-the-air). - 🔑 Formatregel gelernt: gegen den echten
/exportschreiben, nicht gegen die.rsc. RouterOS sortiert Attribute alphabetisch und schreibtft-over-dsnur beift=yes; die handgesetzte.rschat abweichendes Padding/Reihenfolge. Referenz-Export:routeros/state-backups/ap1-gc-backup-scrubbed-20260813.cfg. RouterOS exportiert CRLF, Jinja rendert LF — GC normalisiert das korrekt (die schon vorher grünesystem-identity-Compliance war der Beleg). - ✅ Abnahme: ap1 Intended == Geräte-Ist, 0 Drift (33 Zeilen, zeilenweise identisch); ap2 unterscheidet sich in exakt den 4 erwarteten Werten (identity, 5180↔5745, 2412↔2462,
.99.11↔.99.12). - ✅ Mitgenommen: WG-Privkey-Platzhalter im core-Zweig auf dieselbe Maske
"<<REDACTED>>"vereinheitlicht (sonst Dauer-Diff, sobald eine Feature auf/interface wireguardliegt); DNS-Statics korrigiert (s. Nummernplan unten).routeros/push-gc-template.pygehärtet: Pre-Push-Secret-Guard (verweigert den PUT bei unmaskierten Werten),--dry-runmit Diff,-mstatt hartkodierter Commit-Message,shaoptional (sonst 404 nach Repo-Neuanlage).
- Datenmodell = ConfigContext (
- ✅ Schritt 2 DURCH (2026-08-13) — Adoption + Backup/Compliance grün, 20/20.
- SecretsGroup „RouterOS Nornir" an
crs326-core+crs326-branchgehängt (ap1/ap2 hatten sie schon) — einheitliches Admin-PW seit 2026-08-08 macht eine Gruppe für alle 4 ausreichend. - Datenmodell-Korrekturen vorgezogen (technisch Voraussetzung):
crs326-coreStatus Planned → Active (ist der produktive L3-Router),crs326-branchprimary_ip4.99.13→.99.2(live verifiziert). - ✅ Backup über alle 4 erfolgreich, Sichtprüfung: 0 unmaskierte Secrets (ap1/ap2 je 6 PSKs maskiert, core WG-Privkey maskiert, branch secret-frei).
- ✅ 4 neue ComplianceFeatures (
wifi-channel,wifi-datapath,wifi-security,wifi-configuration, alleconfig_ordered=false) + die bestehendesystem-identity→ 20/20 compliant über alle 4 Geräte. - ⚠️ Bewusst noch KEINE Features für
bridge-vlan/ip-address/ip-route: ComplianceRules gelten pro Platform, nicht pro Rolle — und dercrs326-core-Zweig ist in Slash-Form geschrieben (/ip/address add …), was den Export (Space-Form,/ip address add …) nicht matcht → das gäbe permanenten Falsch-Drift auf dem Core. Follow-up: core-Zweig auf Export-Form umstellen, dann diese Features nachziehen. Die wifi-Features sind unkritisch, weil core/branch keine WLAN-Hardware haben (beide Seiten leer = compliant).
- SecretsGroup „RouterOS Nornir" an
- ✅ Follow-up DURCH (2026-08-13) —
crs326-core-Zweig auf/export-Form. Der Zweig war als staged Cutover-Skript geschrieben (Slash-Form/ip/address, plusdisabled=yes-Flags aus der Vorbereitungszeit) und matchte den Export nicht → er hätte platform-weite ComplianceRules dauerhaft rot gefärbt. Jetzt Space-Form + alphabetische Attribute,disabled=yesentfernt (core ist seit 2026-08-08 produktiv), VLAN-Tabelle als Jinja-Konstante, GW-IPs weiter datengetrieben. Ergebnis: 68 von 69 Zeilen byte-identisch zum Gerät. Zusätzlich Switch-Zweig fürcrs326-branch(Mgmt-Layer) ergänzt — vorher fiel branch auf „nur/system identity" durch und meldete legitime Config als Drift. 9 weitere ComplianceFeatures (interface-list/-vlan/-wireguard, ip-address/-pool/-dhcp-server/-dns/-firewall-nat/-route); beiip-dhcp-serverbewusst drei spezifische Präfixe statt/ip dhcp-server, sonst fingen die 54 dynamischenlease-Zeilen mit. - ✅ Schritt 3 DURCH (2026-08-13) — Deploy-Pipeline scharf, Pilot erfolgreich.
- Image
3.1.7-gc9auf der NAS gebaut (/volume1/docker/nautobot-image), Stack 203 retaggt. ⚠️ Falle: ein bereits vorhandenesgc7trug dieselben Flags; ein Build ohne geänderte Quelldatei zieht den Docker-Cache und liefert eine identische Image-ID — immer gegen die Flags im fertigen Image verifizieren.scpauf die NAS schlug fehl („Connection closed"), Übertragung perssh 'cat > datei'. - Jobs sind in Nautobot zusätzlich einzeln freizuschalten (
enabled=true): die Plugin-Flags machen sie nur verfügbar. - 🔴 Kernbefund:
napalm-rosist ein READ-ONLY-Treiber. Der Default-Dispatcher wählt NAPALM (weilPlatform.network_driver_mappingsnapalm: rosenthält) → Backup (get_config) geht,merge_configscheitert grundsätzlich, mit leerer Fehlermeldung (E1015 … ``). **Fix:** in den Golden-Config-Settings (nicht in den Nornir-Settings!)custom_dispatcher: {"mikrotik_routeros": "nornir_nautobot.plugins.tasks.dispatcher.mikrotik_routeros.NetmikoMikrotikRouteros"}— dieser Dispatcher pusht vianetmiko_send_config`. Danach lief der Deploy sofort. - ⚠️ Gescheiterter Deploy = sauberer Fehlschlag: das Gerät blieb beim NAPALM-Versuch vollständig unverändert (kein Teilzustand). Zusätzlich meldet der Deploy-Job
SUCCESS, obwohl der Plan aufFailedsteht — wie beim Backup gilt: nur der Objekt-Status zählt, nicht der Job-Status. - ✅ Pilot-Deploy: die DNS-Statics auf dem Core. Vorher
/system backup(core-pre-tp22-first-deploy-20260813.backup). ⚠️config_seteines generierten Plans ist schreibgeschützt, undplan_type=missingerzeugt nuradd— das hätte Duplikate ergeben (ap1.bf.langleichzeitig auf.99.3und.99.11). Deshalb manueller Plan mit Purge-vor-Add. Ergebnis verifiziert:ap1→.99.11,ap2→.99.12,branch→.99.2, weiterhin 11 Einträge, keine Duplikate. Compliance 51/56.
- Image
- ✅ Schritt 5 DURCH (2026-08-13) — Datenmodell-Nachträge,
nautobot/ingest-tp22-datamodell.py. Quelle war durchgehend das Gerät, nicht die Doku:bridge/port(pvid),bridge/vlan(tagged/untagged),bridge/host(gelernte MACs je Port+VID) plus ARP/DHCP-Leases zur Identifikation der Gegenstellen.crs326-core: von 5 auf 26 Ports. Vorher waren 3 davon als „GEPLANT (tentativ)" modelliert undether1zeigte auf das totesw1 #12. Belegt (MAC-hart):ether8→crs326-branch,ether13→pve.20.100,ether14→Sonoff.30.250,ether15→ap1,ether16→Arris/WAN,ether5/ether6→Sonos Schlafzimmer.195/.193. Die Trunk-Sets sind exakt wie am Gerät übernommen, inkl. Schiefstände (z.B. trägtether1kein VLAN20/99) — bewusst nicht geradegezogen.crs326-branch:ether1-Zielsw1 #8→crs326-core ether8;ether5/ether6= Sonos Arbeitszimmer (aktuell kein Link, die Schlafzimmer-Paare hängen am Core);ether9–23+sfp waren als „disabled" modelliert, sind live aber enabled (Bootstrap Rev4) → korrigiert.- Standort-Fehler gefunden:
crs326-branchundap2standen in Nautobot auf Technik UG, real Technik OG (die Doku war richtig, das Modell falsch) → korrigiert. - Status-Endzustände: sw1/sw2/cudy2 → Decommissioned (physisch ausgebaut; „Decommissioning" heißt Prozess läuft). Nautobot liefert diesen Status mit, aber nur für
circuits.circuit→content_typesumdcim.deviceerweitert statt einen zweiten gleichnamigen anzulegen.cudy1→ Offline (coreether11hat kein Link; der endgültige Teardown bleibt TP19). sw1s 4 Duplikat-Ports (gi8/gi11/gi15/gi16nebenGE*) entfernt. - ✅ Compliance-neutral verifiziert: Generate-Intended + Compliance über alle 4 Geräte neu gelaufen → weiterhin 51/56 mit exakt denselben 5 bekannten Drifts. Grund: der core-Zweig des Templates iteriert nur Interfaces mit Präfix
vlanund hält die Bridge-VLAN-Tabelle als Jinja-Konstante. Umkehrschluss als Dauerregel: dievlanXX-Descriptions auf dem Core sind NICHT kosmetisch — sie landen alscomment=in der intended config. - 🔍 Nebenbefund, halbkonfigurierte Ports (NICHT angefasst, gehört zu TP19/TP5):
core ether11(cudy1) hatpvid=10ohne VLAN10-Membership → funktionslos;core ether3hatpvid=1bei untagged-VLAN40-Membership;core ether2ist gleichzeitig statisches untagged-Member von VLAN1 und VLAN40;branch ether9–23tragenpvid=20ohne jede Membership. Alles Bring-up-Reste, betriebsneutral (kein Link), aber sie gehören in die VLAN1-Aufräumrunde.
- ✅ Nachtrag 2026-08-13 — Compliance-Abdeckung erweitert auf 68 Checks (63/68 grün; seit 2026-08-16 68/68). Drei neue ComplianceFeatures, alle auf Anhieb grün:
wifi-steering(/interface wifi steering) — sichert die TP3.3-Reparatur ab.bridge-port+bridge-vlan(/interface bridge port//interface bridge vlan) — der L2-Layer war bis dahin komplett unüberwacht: der core-Zweig emittierte gar keine Bridge-Sektion, der AP-Zweig nur die VLAN-Tabelle ohne Ports. Jetzt für alle drei Geräteklassen im Template.- 🔑 Bewusst als Literal-Block, nicht aus DCIM abgeleitet. Der As-built trägt akzeptierte Schiefstände (
core ether3ist untagged-Member von VLAN40, hat aberpvid=1;core ether2hängt zusätzlich in VLAN1;branch ether9–23habenpvid=20ohne Membership). Würde manpvidausuntagged_vlangenerieren, meldete die Compliance genau diese bekannten Altlasten als Dauerdrift. Der Literal-Block liefert das, was hier gebraucht wird: Drift-Erkennung gegen den Ist-Zustand. - ⚠️
/interface bridgeselbst bleibt außen vor — trägt die gerätespezifischeadmin-mac, wäre pro Gerät verschieden und ist kein Fleet-Standard. - 🐞 Falle dabei: Compliance vergleicht gegen das letzte BACKUP, nicht gegen das Live-Gerät. Nach dem Steering-Deploy meldete sie erst Drift auf
wifi-configuration/wifi-steering, weil das Backup vom Nachmittag stammte. Reihenfolge nach jeder Geräteänderung: Backup → Intended → Compliance.
- ✅ Compliance-Backlog ABGEARBEITET (2026-08-16, User-Auftrag „beseitige autonom alle Compliance-Drifts") — Ergebnis: 68/68, 0 Drifts.
- Was entfernt wurde (alle vom Typ
extra, also am Gerät vorhanden und in der intended config bewusst nicht vorgesehen): ap1+ap2/ip dns static 192.168.88.1 router.lan(Werks-defconf, zeigte auf eine IP, die es im Netz nicht gibt — der Core hat sein eigenes, korrektesrouter.lan → 10.40.99.1);crs326-branchvlan10 "TEMP Mgmt VLAN10"+10.40.10.2(Bring-up-Interim). Der fünfte Drift,crs326-core10.40.41.211, war schon vorher über den ConfigPlanTP19-vlan1-core-addressgefallen. - Richtung der Beseitigung bewusst „am Gerät entfernen", nicht „ins Template aufnehmen" — das entspricht der Absicht, die im Switch-Zweig von
mikrotik_routeros.j2seit 2026-08-13 schriftlich steht („Bewusst NICHT emittiert … gehoeren entfernt"). Die frühere Zurückhaltung („potenzielle Rettungspfade") ist mit dem User-Entscheid vom 2026-08-16 aufgehoben; der Mgmt-Fallback aus VLAN10 entfällt damit, Rückweg im Notfall = MAC-Winbox am selben Draht. - Weg: 3 manuelle GC-ConfigPlans (
TP22-drift-aps-defconf-dns,TP22-drift-branch-temp-vlan10), Governance gewahrt — kein Direkt-Write. Vorher/system backupje Gerät ({ap1,ap2,branch}-pre-drift-cleanup-20260816.backup). Deploy gestaffelt: erst die beiden APs, am Gerät gegengeprüft, dann branch. - 🔑 Neue Falle gelernt:
POST /plugins/golden-config/config-plan/ist405 Method Not Allowed— das ViewSet ist read-only. ConfigPlans entstehen ausschließlich über den JobGenerate Config Plans(beiplan_type=manuallandet dercommands-TextVar alsconfig_setauf jedem ausgewählten Gerät). Das erklärt, warum es bis dahin kein Skript gab und alle 17 Vorgänger-Pläne per Hand entstanden sind. - ✅ Verifikation am Gerät, nicht am Job: ap1/ap2
list_dns_entries→total: 0bei unveränderten 28 bzw. 3 WLAN-Clients; branch/interface vlan→ nurvlan99,/ip address→ nur10.40.99.2/24,pingvom Core 4/4 mit 0 % Loss./interface bridge vlan/exportbyte-identisch zu vorher — die Gegenprobe darauf, dass kein neuer Drift entsteht (bridgesteht dort statisch als tagged-Member von VLAN10, unabhängig vom SVI). DanachBackup → Intended → Compliance, alle 4 Geräte mit frischem*_last_success_date. - 🛠️ Tooling neu:
nautobot/gc-configplan.py— legt manuelle Pläne über den Job an, löst Device-UUIDs einzeln per Name auf und assertetplan.device.displayundconfig_setgegen das Ziel (die alphabetische Sortier-Falle aus TP21.1 kann damit nicht wiederkommen), verweigert jedesconfig_setmit<<REDACTED>>(Regel 1) und jedeprint-Zeile, kann gestaffelt deployen (--deploy-ids) und kapselt die ReihenfolgeBackup → Intended → Complianceals--refresh-compliance. Dry-Run ist Default.
- Was entfernt wurde (alle vom Typ
- 🔒 GOVERNANCE — verbindliche Deploy-Regeln (festgeschrieben 2026-08-13, VOR dem Scharfschalten von
enable_deploy):- Config Plans werden ausschliesslich feature-/manual-scoped erzeugt, NIEMALS als „full intended". Ein Voll-Push schriebe wörtlich
passphrase="<<REDACTED>>"auf die APs (= alle WLAN-Clients raus, inkl. ~26 Shellys) bzw.private-key="<<REDACTED>>"auf den Core (= WG-Hub tot, FM/DW-Spokes weg). Jede Sektion, die<<REDACTED>>enthält (/interface wifi security,/interface wireguard), ist vom Push generell ausgeschlossen. - Das AP-Template wird NIE zeilenweise auf ein laufendes Gerät gepusht. Die Provisionierung setzt zwischenzeitlich
vlan-filtering=no→ das reisst den vlan99-Mgmt-Pfad ab, die restlichen Zeilen kämen über dieselbe SSH-Session nie an (halb konfigurierter AP). Voll-Reprovisionierung ausschliesslich per Datei-Upload +/import(routeros/.secrets/ap{1,2}-prov-base.rsc). Verschärfend:device-mode=homeblockt auf den hAPsscheduler/fetch→ die übliche Auto-Revert-Absicherung steht dort nicht zur Verfügung; der VLAN1-untagged-Rettungspfad darf nie wegoptimiert werden. - Vor jedem Push ein
/system backupauf dem Zielgerät. Das GC-Backup ist wegen des Scrubbings kein vollwertiges Restore-Artefakt.
- Config Plans werden ausschliesslich feature-/manual-scoped erzeugt, NIEMALS als „full intended". Ein Voll-Push schriebe wörtlich
- ✅ Schritt 4 ENTSCHIEDEN (User 2026-08-13): Variante (a) — keine Secret-Injection, bleibt wie es ist. Ursprünglich geplant war „WLAN-PSKs + WG-Privkey via Nornir-Secrets injizieren"; die Governance-Regel 1 (unten) hat das überholt: Sektionen mit
<<REDACTED>>sind vom Push generell ausgeschlossen, die Secrets werden also nie gebraucht. Konsequenz, bewusst akzeptiert: Secrets bleiben dauerhaft außerhalb von Modell und Push, DR läuft weiter über~/.secrets/+routeros/.secrets/*+routeros/ap1-wg-hub.privkey; „Gerät vollständig aus dem Modell wiederherstellbar" gilt nur ohne Secrets. Die verworfene Alternative (b) hätte Regel 1 aufweichen müssen — ein Render-Fehler hätte dann WLAN bzw. WG-Hub abgeschossen. Damit ist TP22 inhaltlich abgeschlossen. - Schritte: (1) AP-GC-Template:
mikrotik_routeros.j2umrole == "Wireless AP"-Zweig erweitern (Bridge/vlan-filtering/ether1-Trunk/vlan99-Mgmt/6 SSIDs ohne PSK/L3) → APs komplett aus GC generierbar; (2) Nornir/NAPALM-Adoption aller 4 (SecretsGroup „RouterOS Nornir"; einheitliches Admin-PW seit 2026-08-08 vereinfacht das), Backup/Compliance-Job grün; (3)enable_plan+enable_deployscharf — erst Dry-Run/Plan, dann kontrollierter Push; (4) Secret-Handling WG-Privkey (core) + WLAN-PSKs (bleiben aus dem Git-Template, via Nornir-Secrets injizieren); (5) Datenmodell-Nachträge: branch/core-Ports final, sw1 (außer Betrieb) + cudy1-Status. - Nutzen: Drift-Erkennung + reproduzierbarer Rebuild jedes Geräts aus dem Modell.
- Abh.: TP21 ✅ (Plattform/Modell/Templates), TP20 ✅, einheitliches Admin-PW ✅. Danach ist der kritische Pfad frei für TP5 (Deny-by-default) → TP6 (CAKE).
TP23 — DNS-Policy & Self-Service-Ausnahmen ▸ ⏳ STUFE 1 DURCH, STUFE 2 VORBEREITET (2026-08-18)
- ✅ Stufe 1 — DoH auf dem Core scharf (
routeros/tp23-stufe1-doh-core.rsc), schliesst zugleich TP21.1 TODO 1.use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query,verify-doh-cert=yes.servers=1.1.1.1bleibt als Bootstrap fuer den DoH-Hostnamen stehen.- 🔑 Die alte Begruendung „core hat kein CA-Bundle, verify also unmoeglich" war zu pessimistisch.
Es braucht kein Bundle, sondern genau einen Root: die Kette ist
Leaf → GTS WE1 → GTS Root R4, importiert wurde nur R4 (~1 KB, gueltig bis 2036) — bei 2,8 MB freiem Flash ist das der Unterschied zwischen geht und geht nicht. Fingerprint lokal und am Geraet gegengeprueft (349dfa40…3c7d). - 📌 Der Zertifikatsimport steht bewusst nicht im GC-Template: er braucht die Datei am Geraet
und ist einmaliger Bootstrap, kein Sollzustand. Im Template steht nur die
/ip dns set-Zeile. - ⚠️ Der Deploy meldete FAILURE, obwohl alles sass.
/certificate importgibtfailed: 0aus, und der Job scannt den Geraete-Output stumpf nach dem Wort. Wieder ein Beleg fuer die TP22-Regel: Job-Status ist kein Wirksamkeitsnachweis, nur die Gegenpruefung am Geraet zaehlt.
- 🔑 Die alte Begruendung „core hat kein CA-Bundle, verify also unmoeglich" war zu pessimistisch.
Es braucht kein Bundle, sondern genau einen Root: die Kette ist
- ⏳ Stufe 2 — AdGuard eingerichtet, aber bewusst NICHT scharf geschaltet (User-Vorgabe 2026-08-18).
adguard_bf1(10.40.20.16) macht bereits DoH zum selben CF-Gateway. Ergaenzt wurden: conditional upstreams[/bf.lan/]10.40.20.1und[/40.10.in-addr.arpa/]10.40.20.1(ohne die zweite Zeile wuerden interne Reverse-Lookups zu Cloudflare abfliessen), sechs CIDR-Client-Gruppen (ein VLAN = eine Gruppe) und die permanente Ausnahmegruppedns-bypass-exempt(aktuell10.40.10.183). Abnahme perdig:core.bf.lan→10.40.99.1,nas.bf.lan→10.40.20.10, extern ueber DoH. BackupAdGuardHome.yaml.bak-tp23-20260817.- Kein DHCP-Scope wurde angefasst — alle sieben liefern weiter
10.40.X.1aus. Das Scharfschalten ist damit spaeter ein reiner DHCP-Change; die passende Firewall-Zeile (TP5-E2: LAN->AGH dns (Vorrat)) steht bereits, damit dabei die scharfe Firewall nicht angefasst werden muss. - ⚠️ AGH schreibt die YAML beim Start neu (eigene Schluesselreihenfolge, Kommentare weg,
time_zone: Local→UTC). Wer die Datei patcht, muss danach am laufenden Stand pruefen, nicht am eigenen Entwurf.
- Kein DHCP-Scope wurde angefasst — alle sieben liefern weiter
- 🔜 Offen bleiben Stufe 3–6 (zweite AGH-Instanz, per-Lease Option 6, HA-Buttons, und zuletzt die Bypass-Sperre). Ausdruecklich keine HA/zweite Instanz (User 2026-08-18).
- Auslöser: sobald gefiltertes DNS scharf ist, gehen einzelne Seiten/Dienste kaputt. Es braucht Ausnahmen ohne Admin-Eingriff — per User/Client/Gruppe/global, temporär oder permanent, mit Oberfläche. Bedarf ist belegt, nicht vermutet: der bisherige Workaround war „Client von Hand auf
1.1.1.1stellen", regelmäßig (User 2026-08-14). - 🔴 Zentrale Reihenfolge-Regel: genau dieser Workaround IST der DNS-Bypass, den TP5 schließen will → erst der Ersatz, dann die Sperre. Ohne funktionierende Ausnahme-Oberfläche verliert u.a. der Entwicklungsrechner samt Agenten-Toolchain seinen Ausweg — und DNS-Blocks äußern sich dort nicht als klare Meldung, sondern als diffus kaputte Build-Umgebung.
- Zwei Befunde, die die Architektur bestimmen:
- DoH ist nicht das Problem. Clients sprechen plain mit dem lokalen Resolver, der macht DoH nach oben — die empfohlene Auflösung des DoH/Split-Horizon-Konflikts,
bf.lanbleibt heil. Was Seiten blockiert, ist die Policy. ➡️ Nie einen „DoH aus"-Schalter bauen, sondern Policy-Ausnahmen. - Identität existiert nur dort, wo die Client-IP sichtbar ist. Router-DoH aggregiert alle Clients hinter einer Quelle — CF sieht nur den Core. Per-User-Identität bei CF verlangt einen Agent (WARP; bei NextDNS/ControlD deren CLI) → auf Shelly/Sonos/TV unmöglich. RouterOS kann keine per-Client-Ausnahme (keine DNS-Views;
/ip dns staticwirkt domain-weit — verifiziert). ➡️ Ein lokaler Resolver mit Client-Policy ist unvermeidbar.
- DoH ist nicht das Problem. Clients sprechen plain mit dem lokalen Resolver, der macht DoH nach oben — die empfohlene Auflösung des DoH/Split-Horizon-Konflikts,
- ✅ Architektur-Entscheid: Filter zentral bei CF, Identität + Ausnahmen lokal. Die Filterliste bleibt vollständig bei Cloudflare (Core via DoH, unterwegs via WARP); lokal wird nie eine Filterliste vorgehalten, nur die Diffs. Vorteile: kein RAM-Thema auf dem Core (eine Adlist kostet ~1,9 KB/Domain, 50k ≈ 95 MB — Konkurrenz mit Conntrack/DHCP/WG), eine Policy-Quelle statt zweier, gleiche Regelbasis zuhause wie unterwegs.
- ✅ Resolver-Wahl: AdGuard Home (läuft bereits,
10.40.20.16). Vergleich gegen die realen Anforderungen:- Pi-hole disqualifiziert: spricht kein DoH → bräuchte cloudflared/unbound als Sidecar (vierte QUIC-Komponente neben den drei TP16-Connectoren). Dazu belegtes Bruchrisiko v5→v6 (FTL/API/Web neu, Docker-Env-Variablen tot).
- AGHs „keine Gruppen"-Schwäche verschwindet hier, weil Clients als CIDR eintragbar sind →
10.40.30.0/24= die IoT-Gruppe. Die VLAN-Segmentierung ist bereits die Policy-Grenze. Dazu natives DoH, per-Device-ID auch bei wechselnder IP, „Unblock for this client", API + HA-Integration. - Technitium = ernsthafte Alternative (autoritativer DNS + DHCP + Apps,
networkGroupMap); seine IP/Subnet-Bindung trifft uns kaum, weil die IPs per Reservierung faktisch statisch sind. Neubewertung legitim (die TP4-Ablehnung galt einer anderen Frage) — sinnvoller Anlass wäre, DNS und DHCP zusammenzuführen. Eigener TP, nicht dieser. - Verworfen: eigene Self-Service-UI bauen · per-Device-DoH via NextDNS/ControlD (Agent-Zwang, bricht
bf.lan) · Umbrella ($30–45/User/Jahr) · Cloudflare verlassen (wirft TP16/TP16.1 weg) · Adlist auf dem Core.
- Zuweisung ist nativ möglich:
/ip/dhcp-server/leasehat die Propertydhcp-option(verifiziert) → Option 6 pro Lease, bei 54 Reservierungen ein Konfigurationsschritt. (Nebenfund: Leases habenaddress-lists→ automatische Aufnahme in eine Firewall-Liste, direkt nützlich für die TP5-JIT-Gruppe.) - ✅ WARP im LAN abschalten — Mechanismus: Cloudflare „Managed Networks". Der Client sucht bei jedem Netzwechsel einen selbst gehosteten TLS-Endpunkt, prüft dessen SHA-256-Fingerprint und zieht ein Device-Profil, das WARP deaktiviert. Beacon auf NAS/pve, nicht auf den Core (
certs=0). Beseitigt die ICMP-Falle vom 2026-08-13 (ref_warp_local_icmp_trap) an der Wurzel.- ✅ Kollision aufgelöst (2026-08-14): die frühere Sorge war, dass TP16-Schritt 5
vwauf WARP-geschützt hebt und damit „WARP zuhause aus" bricht. Der User-Constraint aus TP16.2 streicht genau das —vwbleibt bypass und verlangt nie Device-Identity. Damit steht der Managed-Networks-Weg frei. Rest-Risiko nur für Dienste, die künftig doch Device-Identity verlangen sollten → dann Access-Policy zusätzlich auf die Heim-IP (bf4-home-ipexistiert bereits). - ✅ Kein Verlust beim Fremdnetz-Zugriff: FM/DW laufen über den WG-Hub (TP10), nicht über WARP. Managed Networks schaltet nur im Heimnetz ab.
- ⚠️ Free-Plan-Verfügbarkeit des Features nicht belegt → im Dashboard gegenprüfen. Holzhammer-Alternative (WARP-Endpunkte per Firewall sperren) nicht empfohlen: bricht still, Client probiert Transport-Fallbacks, trifft auch Gäste.
- ✅ Kollision aufgelöst (2026-08-14): die frühere Sorge war, dass TP16-Schritt 5
- Umsetzung in Stufen — Sperre zuletzt:
- DoH auf dem Core scharf → schließt TP21.1-TODO 1 (heute plain
1.1.1.1); CA-Bundle nötig. - WARP-Managed-Network (Beacon auf NAS/pve) → WARP zuhause aus.
- AGH in den Pfad, zweite Instanz + Config-Sync, beide per DHCP als DNS 1 + 2.
- Client-Gruppen per CIDR (ein VLAN = eine Gruppe); per-Lease Option 6 nur für Abweichler.
- HA-Buttons für temporäre Freigaben + JIT (AGH-API, RouterOS-REST, CF-API), RouterOS-
schedulerals Backstop, damit Ablauf auch ohne HA greift. - 🔴 Erst jetzt (in TP5): DNS-Bypass sperren — Vorbedingung: Freigabe über HA funktioniert nachweislich, und die permanente Ausnahmegruppe
dns-bypass-exempt(Entwicklungsrechner + Build-/Agent-Tooling) steht. Dann: nur Resolver dürfen 53/853 nach außen (schließt Geräte, die eigene Resolver hardcoden — Smart-TV mit8.8.8.8ist der Klassiker).
- DoH auf dem Core scharf → schließt TP21.1-TODO 1 (heute plain
- Grenzen, offen benannt: ein Resolver im Datenpfad ist unvermeidbar (zwei Instanzen federn ab, ⚠️ AGH hat kein natives HA → Config-Sync ist Betriebsaufwand, sonst gilt nach Failover eine andere Policy) · keine Blockseite bei HTTPS (gilt für jede DNS-Filterlösung, auch Umbrella) · CF-Log-Retention 24 h im Free-Plan — laut User ausreichend, weil Ausnahmen JIT entstehen und ältere Fälle reproduziert werden.
- ⚠️ 802.1X löst die IoT-Identität NICHT: Consumer-IoT (Shelly, Sonos) hat keinen 802.1X-Supplicant; der Standardweg ist MAB = wieder MAC-basiert → kein Identitätsgewinn gegenüber der DHCP-Reservierung. TP8 bleibt richtig, aber als Sicherheitsthema (dynamische VLAN-Zuweisung, kein MAC-Spoofing bei Managed-Geräten), nicht als DNS-Identitätsquelle.
- Abh.: TP21.1 TODO 1 (DoH auf core), TP5 (Firewall/Bypass-Sperre — Reihenfolge s.o.), TP16 Schritt 5 (Access-Kollision), TP16.1 (falls WARP zuhause bleiben soll), TP8 (nur Sicherheit). Kein Blocker für TP5 → TP6, aber TP5 darf die Bypass-Sperre nicht vorziehen.
TP24 — Unterbrechungsfreie Stromversorgung (DC-USV, 48V-Bus) ▸ 🔜 KONZEPT — aus TP15 herausgelöst (User-Entscheid 2026-08-16) — docs/hw-refresh-requirements.md §9
-
Warum ein eigener TP: Die USV hing bisher als Unterpunkt in TP15 (HW-Refresh Switching/Router) mit. TP15s Kernauftrag — CRS326-Beschaffung, Bring-up, Core-Tausch — ist seit 2026-08-08 durch; die Stromversorgung ist als einziger Rest übrig geblieben und hat mit Switching sachlich nichts zu tun. Sie ist ein eigenständiges Infrastruktur-Thema mit eigener Einkaufs-, Verkabelungs- und Entscheidungslogik (Elektrik, Batterie, Standort) und blockiert nichts auf dem kritischen Pfad. Darum eigener TP.
-
Was es ist (Begriffsklärung): eine Pufferbatterie für die Netz-/Infrastruktur-Hardware — keine klassische AC-USV mit 230-V-Steckdosen. Ein 48-V-Gleichspannungsbus versorgt die Geräte direkt an ihrem DC-Eingang; die Batterie hängt am selben Bus und übernimmt bei Netzausfall ohne Umschaltlücke. Der Umweg AC→DC→AC→DC (und damit dessen Dauerverlust) entfällt.
-
Zielbild (Aufbau, unverändert gültig aus der TP15-Recherche):
Teil Typ Preis Wirkungsgrad Netzteil MeanWell LRS-150-48 (150 W, 48 V) ~€30 ~88 % DC-USV-Modul MeanWell DDR-120-48 (120 W) ~€80 ~95 % (pass-through) Batterie LiFePO4 12,8 V / 20 Ah (256 Wh) ~€50 — DC-DC 12 V MeanWell SD-100A-12 (100 W, für NAS/pve) ~€30 ~85 % Summe ~€190 230 V AC → LRS-150-48 → 48-V-Bus →Switches direkt ·→ DC-DC 12 V →DS923/pve ·→ DDR-120-48 →LiFePO4. -
Warum 48 V: PoE-Technik arbeitet nativ mit 44–57 V (kein Wandler nötig), höhere Spannung = kleinere Ströme = weniger Leitungsverlust, und 48 V ist der Telecom-/USV-Standard.
-
Laufzeit (256 Wh): ~2,5 h bei 100 W reiner DC-Last · ~5,5 h wenn nur Switch + PoE (45 W) · ~2 h wenn ein Inverter für den Mac mini mithängt.
-
Effizienz-Argument (der eigentliche Grund für DC statt AC): eine AC-USV verheizt bei 100 W Dauerlast ~25–40 W (≈ €66–105/Jahr), die DC-Variante
5–12 W (≈ €13–32/Jahr) — bei praktisch gleicher Anschaffung (€190 vs. €150–250). Der Mehrpreis amortisiert sich über den Dauerbetrieb. -
✅ DC-Eingang vorhanden (geprüft):
crs326-core+crs326-branch(12–57 V, DC-Jack) · ap1/ap2 hAP ax² (12–57 V, alternativ PoE-in). ⚠️ Adapter/Sonderfall: DS923+ (externes 12 V/7 A, 4-Pin Mini-Fit JR) · pve/N100 (12 V Hohlstecker) · Mac mini hat gar keinen DC-Eingang (eingebautes Netzteil → nur über Inverter). -
Offene Entscheidungen (aus TP15 mitgenommen, unverändert offen):
- Mac mini auf USV? Braucht einen Inverter (~15–20 % Verlust + Komplexität). Vorfrage: läuft er überhaupt 24/7? Wenn nein, reicht ein Graceful-Shutdown-Script auf USV-Warnung.
- Standort/Verkabelung: Der Bus soll laut Skizze im Arbeitszimmer/Technik OG sitzen — der L3-Core steht aber in Technik UG. Entweder zweiter Zweig nach unten oder Bus dorthin, wo der Core steht. Diese Frage ist durch den Core-Umzug neu zu stellen (die Skizze stammt aus der Zeit, als oben der Verteiler geplant war).
- Arris-Kabelmodem: vorentschieden auf Grid (muss ohnehin am Netz bleiben, DC-Zweig nach unten wäre Aufwand für ~1–2 W).
- Batteriegröße: 20 Ah als Startwert; 50 Ah wenn die gepufferte Last über Switch+AP hinaus wächst.
- Monitoring/Shutdown: wie meldet die USV einen Netzausfall an NAS/pve (Signalkontakt vs. nichts)? Ohne das gibt es kein sauberes Herunterfahren, nur Durchhalten bis die Batterie leer ist.
-
Nutzen konkret: bei Stromausfall bleiben Core-Switch, Branch-Switch und beide APs online → Netz, WLAN und der WG-Hub überleben (der WAN-Uplink nur, solange auch der Arris Strom hat, s. Entscheidung 3). Für NAS/pve zählt vor allem das kontrollierte Herunterfahren statt des harten Abschaltens.
-
Abh.: keine harten. TP15 ✅ (die zu versorgende Hardware steht und hat DC-Eingänge). Verwandt: TP18 (Garage-Nodes brauchen je Site eine Stromversorgung), TP11 (USV-Zustand ins Monitoring). Kein Blocker für TP5/TP6.
-
Historie: war bis 2026-08-16 Unterpunkt von TP15 („🔋 DC-USV: MeanWell LRS-150-48 + DDR-120-48 + LiFePO4 20Ah (~€190), 48V-Bus; CRS326 DC-input passt"). Vollständige Recherche inkl. Schaltbild, Effizienzvergleich und Gerätetabelle:
docs/hw-refresh-requirements.md §9(+ §10 D/E/F für die offenen Fragen).
TP25 — WLAN-Stabilisierung ▸ ⏳ Funkparameter + Drift-Erkennung durch; offen nur noch Messarbeit — Sammel-TP für Christophs Beobachtungen 1–6
Restliste (Stand 2026-08-18): Fund A–D ✅ · Drift-Luecke ✅ (mit TP28, 92/92) · offen: Fund E (
access-listmitsignal-range-Boden — ⚠️ gehoert jetzt auf den Manager, nicht mehr auf die APs) · Fund F (5:05-Takt bei IoT-Trennungen, am Manager nachmessen — die AP-Tabellen sind unter CAPsMAN leer) · Re-Walk + Dead-Spot-Kartierung (hands-on). Alles drei ist Messarbeit gegen die korrigierte Basis, keine Konfigurationsarbeit mehr. Warum eigener TP: Christoph hat am 2026-08-16/17 sechs konkrete Beobachtungen gemeldet und ausdrücklich einen TP dafür verlangt. Sie hängen alle an derselben Ursache-Klasse (Funkparameter, die nicht nach Manual gesetzt sind), gehören also zusammen. TP25 übernimmt den offenen Rest von TP3.3 (Re-Walk, Dead-Spot-Kartierung) — dieselbe physische Arbeit, doppelt geführt wäre Unsinn. TP3.2/TP3.3 bleiben als Historie stehen. User-Randbedingung (2026-08-17, wörtlich): „ich weigere mich einen anderen access point zu kaufen solange ich nicht das gefühl habe, wir haben alles aus dem ap rausgeholt." Das ist die Abnahmebedingung dieses TPs — keine Hardware-Empfehlung, bevor die Parameter stimmen.
- ⚠️ Ausgangslage: Drift ist bestätigt, aber NICHT die Ursache. Christoph hat am 08-16/17 selbst an den APs
gespielt („drift ist garantiert. es hat vorher aber auch nicht funktioniert"). Der Audit unten ist gegen den
Ist-Stand gefahren (
/interface/wifi/export+/interface/wifi/monitor+ Log, beide APs, 2026-08-17 14:01). Zwei der Funde sind älter als die Experimente und stammen aus der TP3-Neuprovisionierung.
🔴 Fund A — 2,4 GHz läuft auf 40 MHz, obwohl das Profil 20 MHz sagt (Beobachtung 4)
- Christophs Frage war berechtigt, aber der Adressat ist ein Override, keine Entscheidung. Das Channel-Profil
ist korrekt:
add band=2ghz-ax frequency=2412 name=ch-2g width=20mhz. Überschrieben wird es inline am Radio:set [find default-name=wifi2] channel.band=2ghz-ax .skip-dfs-channels=10min-cac .width=20/40mhz→ das Inline-Override gewinnt gegen das verlinkte Profil.monitorbeweist es: ap12412/ax/Ce, ap22462/ax/eC—Ce/eC= 40 MHz. Niemand hat 20/40 „gewählt"; es ist genau die Override-Klasse, die CLAUDE.md für den TP3-Bring-up schon dokumentiert („Werks-Inline-Overrides auf wifi1/wifi2 überschreiben das verlinkte Profil") — damals nur fürconfiguration.ssid/security.*bereinigt, fürchannel.*nie. - Warum 40 MHz auf 2,4 GHz falsch ist (Manual-Ebene, nicht Geschmack): es gibt nur 3 überlappungsfreie
20-MHz-Kanäle. ap1 belegt mit
2412/Ce≈ 2402–2442, ap2 mit2462/eC≈ 2442–2482 → die beiden APs decken zusammen praktisch das ganze Band ab. Jeder Nachbar-AP überlappt zwangsläufig einen von beiden. Dazu halbiert 40 MHz die spektrale Leistungsdichte → ~3 dB weniger Reichweite bei gleicher Sendeleistung. Und der Nutzen ist null: IoT-Clients sind fast alle 20-MHz-only. Das ist die „miserable Reichweite" aus Beobachtung 4. - Fix: die Inline-
channel.*-Overrides aufwifi1/wifi2leeren (!channel), damit die Profile greifen. Nebenbefund:skip-dfs-channels=10min-cacaufwifi2ist bedeutungslos — im 2,4-GHz-Band gibt es keine DFS-Kanäle. Copy-Paste-Spur, harmlos, gehört trotzdem raus.
🔴 Fund B — ap2 sendet auf 5 GHz mit 9 dBm statt 18 dBm (Beobachtungen 1+2)
- Gemessen: ap1
wifi1tx-power: 18, ap2wifi1tx-power: 9— bei identischer Hardware und identischem Profil. 9 dB Unterschied = Faktor ~8 in der Leistung, ap2s 5-GHz-Zelle hat grob ein Drittel des Radius von ap1. - ✅ BEHOBEN 2026-08-17: ap2s 5-GHz-Radio läuft jetzt mit 18 dBm (
5220/ax/Ce/I). Messreihe am Gerät:Zustand Kanal tx-power ap2 vorher 5745/ax/Ceee(80 MHz, ohne/I)9 ap2 nach Frequenzwechsel 5220/ax/eeCe/I(80 MHz, mit/I)9 ⬅️ unverändert! ap2 nach Breitenkorrektur 5220/ax/Ce/I(40 MHz)18 ✅ ap1 durchgehend 5180/ax/Ceee/I→5180/ax/Ce/I18 → 18 - 🔴 Ehrliche Korrektur: meine erste Begründung war falsch, und die zweite auch nicht vollständig.
Ich hatte die 9 dBm auf ETSI-Band C (ch149 ohne
/I-Flag) zurückgeführt. Widerlegt: der Wechsel ins Indoor-Band bei gleicher Breite ließ die Leistung auf 9 dBm. „80 MHz kostet generell Leistung" trägt auch nicht — ap1 fuhr 80 MHz im selben Band mit 18 dBm. Der Fix ist gemessen, der Mechanismus ist es nicht. - 🔬 Kohärente Resthypothese (nicht bewiesen, aber testbar): es sind zwei Effekte, je einer pro Kanal —
(a)
5745/Ceee= ETSI-Band-C-Limit (die erste Theorie gilt für diesen Kanal weiter), und (b)5220/eeCe= das Kontrollkanal liegt nicht am Blockanfang (eeCestattCeee), was das Radio derated. Das würde ap1s5180/Ceee=18 und ap2s5220/eeCe=9 gleichzeitig erklären. Diskriminierender Test: ap2 testweise auf5180/Ceee— 18 dBm ⇒ Hypothese (b) trägt; 9 dBm ⇒ es ist gerätespezifisch (dann ist ap2s Radio der Verdächtige, relevant für die Hardware-Frage!). Nicht nötig für den Betrieb, aber vor einem Hardwarekauf wissenswert. - ⚠️ Die TP3-Notiz „Kanäle non-DFS ap1 ch36/ch1, ap2 ch149/ch11" hatte trotzdem keinen tragenden Grund — s. eigener Absatz „Herkunft der ch149-Notiz" unten.
- 🎯 Der Fix löst Fund B und C in einem Zug — und er ist nicht offensichtlich: unter ETSI Austria existiert
im Indoor-Band (5180–5240) nur ein einziger 80-MHz-Block (
5180/Ceee= ch36–48). Zwei APs können dort also nicht beide 80 MHz fahren, ohne sich zu überlappen — genau deshalb ist ap2 überhaupt auf 5745 gelandet. Mit 40 MHz gehen beide sauber ins Indoor-Band:AP neu Kanäle Leistung Belegung ap1 5180/Ce36+40 18 dBm 5170–5210 ap2 5220/Ce44+48 18 dBm 5210–5250 Beide /I-freigegeben (aus der Radio-Tabelle bestätigt), überlappungsfrei, +9 dB für ap2.
🔴 Fund C — 80 MHz auf 5 GHz kostet Reichweite, die hier fehlt (Beobachtung 1)
ch-5g width=20/40/80mhz, laufend5180/ax/Ceeebzw.5745/ax/Ceee= 80 MHz. Dieselbe Sendeleistung auf die vierfache Bandbreite verteilt kostet ~6 dB effektiven SNR am Zellenrand gegenüber 20 MHz, ~3 dB gegenüber 40 MHz. In einer 2-AP-Wohnung mit Terrasse ist Spitzendurchsatz das falsche Optimierungsziel — Randabdeckung und Stabilität sind das richtige.- Beleg, dass genau das das Terrassen-Symptom ist: ap1-Log, Telefon steht still im Halter:
-81→ roamt auf 2,4 GHz-82→ zurück-83→disconnected, connection lost, signal strength -88. −88 dBm ist unter der Nutzbarkeitsschwelle. Das ist kein Roaming-Problem (Christoph sagt selbst „ich red da nicht mal von roaming"), sondern Link-Budget — und dagegen hilft Breite runter, nicht drehen.
🔴 Fund D — w2-iot trägt einen unzulässigen Channel-Override auf einem Slave-VAP (Beobachtung 3)
- ap1:
add channel.band=2ghz-n .width=20mhz configuration=cfg-iot … master-interface=wifi2 name=w2-iot - ap2:
add channel.width=20mhz configuration=cfg-iot … master-interface=wifi2 name=w2-iot - Ein Slave-VAP teilt das Radio des Masters und kann keinen eigenen Kanal haben. Auf ap1 erzwingt das
Override zusätzlich
2ghz-n, während der Masterwifi2auf2ghz-axläuft — ein Band-Mismatch zwischen Master und Slave ist keine unterstützte Konfiguration. Das ist der Mechanismus hinter „alle SSIDs sind da,-iotbeharrlich nicht, und plötzlich ist es wieder da": der VAP fällt aus der Beacon-Rotation und kommt bei einem Re-Apply zurück. - 📌 Und es ist der Beweis für Beobachtung 6: die beiden APs sind hier nicht identisch (ap1 mit Band+Width, ap2 nur Width). Eine generierte Config kann das nicht produzieren — das ist Handarbeit, und zwar auf genau dem Objekt, das keine Handarbeit verträgt.
🟠 Fund E — keine access-list, also kein Signal-Boden gegen klebende Clients (Beobachtung 2)
/interface/wifi/access-listist auf beiden APs leer. Damit gibt es keinensignal-range-Boden — ein Client darf hängen bleiben, bis die Verbindung zusammenbricht, statt frühzeitig abgestoßen zu werden. Das ist der Standard-RouterOS-Griff gegen genau dieses Symptom.- Beleg für das Kleben: ap2-Log, Client
56:71:6C:22:E6:A9flappt in 22 Minuten sechsmal zwischenwifi1↔wifi2bei −62…−83 dBm. Und:F2:62:4C:E1:AF:09@wifi2 disconnected, not responding, signal strength -47— Abbruch bei ausgezeichneten −47 dBm. Beides zusammen = Band-Oszillation ohne Steering-Politik, nicht schlechte Abdeckung. - ⚠️ Nebenbefund: die TP3.2-Access-List, die den P750W an ap1 pinnte („überlebt ap2-Re-Provision"), ist beim Rebuild 2026-08-08 verlorengegangen — im Export beider APs steht keine einzige Access-List-Zeile. Laut CLAUDE.md ist der Pin nicht mehr nötig (L3-GW liegt auf dem Core), der Verlust war aber unbemerkt.
ft=yes ft-over-ds=nowar korrekt für den damaligen Standalone-Betrieb (over-DS braucht ein Inter-AP-Protokoll) — kein Fund, nur zur Abgrenzung festgehalten. 📌 Seit TP28 gilt das nicht mehr: unter CAPsMAN istft-over-ds=yesaktiv, weil der Manager genau dieses Inter-AP-Protokoll mitbringt.
🟡 Fund F — IoT-Clients trennen exakt alle ~5:05 bei gutem Signal (offen, präzise vermessen)
12:55:29 connected -59 → 13:00:36 disconnected -59 (5:07)
13:17:27 connected -63 → 13:22:32 disconnected -63 (5:05)
13:35:32 connected -60 → 13:40:37 disconnected -59 (5:05)
13:57:31 connected -59 → 14:02:35 disconnected -58 (5:04)
- −59 dBm ist ein gutes Signal. Eine auf 3 Sekunden reproduzierbare 5-Minuten-Periode ist ein Timer, kein Funk.
- 🚫 Ausdrücklich NICHT die alte Power-Save-Merkregel wiederbeleben — die ist am 2026-08-13 als Fehldiagnose
zurückgezogen worden (
ref_wifi_powersave_multicast, Drucker war schlicht aus). Dieser Befund ist ein anderer: vier saubere Messpaare mit konstanter Periode. - Kandidaten + der Test, der sie trennt: (a) periodischer VAP-Re-Apply durch Fund D → prüfen, ob ap2
(ohne Band-Override) dieselbe Periode zeigt; (b) DHCP-Lease/Renew-Interaktion →
lease-timeder beiden MACs (38:A5:C9:C0:73:1E,38:A5:C9:BC:33:31) gegen die Periode legen; (c) das Gerät selbst mit 5-min-Duty-Cycle → dann bleibt es nach Fund-D-Fix unverändert. Erst nach dem Fund-D-Fix erneut messen — sonst misst man zwei Effekte übereinander.
🧭 Beobachtung 5 — „alle Welt sagt CAPsMAN, nur wir sagen Nautobot GC. Hilfe oder Last?"
- Klare Antwort: es sind keine Alternativen, sie lösen verschiedene Probleme. CAPsMAN = Runtime-Control-Plane
fürs WLAN (ein Ort für Radio-Settings, sofortiger Push, dynamische VAPs). Nautobot GC = Config-as-Code-SoT
- Drift-Erkennung über die ganze Flotte (Core, Branch, beide APs). Man kann beides haben; das Reibungspunkt ist nur, dass CAPsMANs dynamische Objekte für GC unsichtbar sind (der Grund von 2026-07-22, und der gilt).
- 🔎 Aber eine Begründung von damals hält der Prüfung nicht stand. Der Entscheid nannte als ersten Grund „WLAN dauerhaft instabil, besonders wenn beide APs laufen". Das WLAN ist nach dem Standalone-Rebuild weiterhin instabil — die These „CAPsMAN war die Ursache" ist damit empirisch geschwächt. Die Funde A–E sind Funkparameter; CAPsMAN hätte sie weder verursacht noch geheilt. Der Rebuild hat ein Symptom umgezogen, keine Ursache beseitigt.
- Wo GC hier tatsächlich Last war: es hat diesen Drift nicht verhindert. Die Compliance deckt
wifi-steeringab (seit TP3.3), aber offensichtlich nicht die Channel-/Inline-Override-Fläche — sonst wären Fund A und D als Drift aufgeschlagen. Das ist eine Lücke im Feature-Set, kein Argument gegen GC. - Ehrliches Urteil (meine Empfehlung): GC als SoT behalten — es ist das Einzige, was Hand-Tuning davon
abhält, sich still zu akkumulieren, und genau das ist hier passiert. Aber: GC ist kein WLAN-Tuning-Werkzeug.
Der Ausweg ist nicht CAPsMAN, sondern die Parameter einmal nach Manual richtig zu setzen und dann mit einer
Compliance-Feature auf
/interface/wififestzunageln. Bei genau 2 APs ist der Kanal-/Leistungsplan eine Einmalentscheidung, kein Laufzeitproblem — der Hauptvorteil von CAPsMAN greift hier also kaum. (Wenn ein dritter AP dazukäme, wäre die Abwägung neu zu führen.)
🔎 Herkunft der ch149-Notiz (Christophs Frage 2026-08-17: „wie kam es zu dieser Notiz?")
- Nachverfolgt bis Commit
03f328f, 2026-06-18, CAPsMAN-Ära. Wortlaut der Commit-Message: „Kanal-Plan non-DFS/überlappungsfrei: ap1 ch36+ch1, ap2 ch149+ch11 (Auto-Channel hatte beide APs auf 5500-DFS/2437 gelegt = Co-Channel)". - 🎯 Das gelöste Problem war Co-Channel, nicht DFS. Auto-Channel hatte beide APs auf denselben Kanal gelegt; der Fix war, überhaupt zu pinnen. Dass die Wahl auf 36/149 fiel, ist das FCC-Standardpaar aus jedem Tutorial — „non-DFS" wurde als Begründung nachträglich mitgeschrieben, war aber nie eine geprüfte Anforderung. Christophs Einschätzung ist damit belegt: es gibt keinen Grund, Frequenzbänder auszunehmen.
- 📌 Und ein Detail, das die Sache entschärft:
skip-dfs-channels=10min-cacschließt DFS gar nicht aus. Es überspringt nur Kanäle, die die 10-Minuten-CAC brauchen (Wetterradar-Band 5600–5650). Der Rest des DFS-Bands bliebe nutzbar. Ausgeschlossen wurde DFS in Wahrheit durch das hartefrequency=-Pinning — wo nichts ausgewählt wird, wirkt kein Skip. (Die Overrides sind mit Schritt 2 ohnehin weg.) - Konsequenz für den Kanalplan: das DFS-Band 5500–5700 ist eine echte Option und liegt bisher brach —
11 zusätzliche Kanäle, in ETSI ohne
/I-Beschränkung. Preis: CAC-Wartezeit beim Start und im Radar-Fall ein erzwungener Kanalwechsel (30 min Sperre). Bei Christophs aktuellem Symptombild (Abbrüche) wäre ein radar-getriggerter Wechsel unangenehm — deshalb jetzt nicht, aber es ist der Reservekanalraum, falls ein dritter AP dazukommt und 40 MHz nicht mehr reicht.
📡 Beobachtung 4b — „könnte 2ghz-g nicht besser zu IoT passen?"
- Verfügbar auf diesem Radio (
/interface/wifi/radio):2ghz-g:20mhz·2ghz-n:20mhz,20/40mhz·2ghz-ax:20mhz,20/40mhz. - ❌ Für Reichweite bringt es nichts.
band=setzt die höchste angebotene Generation, nicht die einzige — ein2ghz-ax-AP ist rückwärtskompatibel, g/n-Clients assoziieren normal. Und ein schwacher Client fällt über die Ratenadaption von selbst auf die robusten niedrigen Raten.bandändert weder Sendeleistung noch Empfängerempfindlichkeit. - ✅ Für Interoperabilität ist der Gedanke aber richtig. Billige ESP-/Realtek-IoT-Stacks haben
dokumentierte Probleme mit 802.11ax-Beacons (HE-Capabilities, PMF).
2ghz-nnimmt die HE-Elemente aus dem Beacon und kann Assoziationswackler beheben — ein Kompatibilitäts-, kein Abdeckungsargument. - 🎯 Pointe: genau dieser Instinkt steckte schon im Fehler.
channel.band=2ghz-naufw2-iot(Fund D) war exakt der Versuch, IoT ein legacy-freundlicheres Band zu geben. Die Absicht war richtig, der Mechanismus falsch —bandist eine Eigenschaft des Radios, nicht eines Slave-VAPs. Alle 2,4-GHz-SSIDs teilenwifi2. - Empfehlung, falls Fund F (5-Minuten-Takt) nach dem Override-Fix bleibt:
wifi2global auf2ghz-n— die saubere Version dessen, was der Override wollte. Kostet real nichts (kein 2,4-GHz-Client hier braucht ax-Raten,dirtyvader-mainauf 2,4 GHz ist ohnehin Fallback).2ghz-gNICHT als ersten Schritt: die 20-MHz-Bindung ist richtig, aber 54 Mbit/s-Deckel und kein HT für alle 2,4-GHz-Clients ist ein echter Verlust ohne Zusatznutzen gegenübern.gist die Eskalationsstufe, nicht der Einstieg.
🏠 Deckenmontage-APs — bringen sie einen echten Vorteil? (Christophs Überlegung 2026-08-17)
- Der Gewinn liegt in Platzierung und Antennendiagramm, nicht im Silizium. Ein cAP ax ist dieselbe Chip-Generation und ebenfalls 2×2 wie der hAP ax² — mehr Rohleistung gibt es nicht. Was er gibt: ein nach unten optimiertes Diagramm, freie Sichtlinien von der Decke, PoE-Montage ohne Möbel davor.
- 🔴 Aber die Entscheidung wäre heute blind gewesen. Vor dieser Session lagen ~9 dB auf ap2 brach (Fund B), 2,4 GHz verschenkte ~3 dB an 40 MHz (Fund A) und der 5-GHz-Zellenrand ~3 dB an 80 MHz (Fund C). Hardware zu kaufen, um Fehlkonfiguration zu kompensieren, ist der teuerste Weg. Genau das deckt sich mit Christophs eigener Randbedingung („nicht kaufen, bevor alles aus dem AP raus ist").
- ✅ Jetzt ist der Boden gelegt (beide APs 18 dBm, überlappungsfrei, 20 MHz auf 2,4). Die Entscheidung gehört an den Re-Walk (Schritt 5). Bleiben danach Dead Spots — Terrasse, Kanten —, dann ist es ein Platzierungsproblem, und Deckenmontage ist die richtige Antwort. Dann stellt sich aber zuerst die billigere Frage: reicht Umhängen der vorhandenen APs? „Drehen hat nicht geholfen" passt zu einer Abschattung, die Drehen nicht behebt — Versetzen schon.
- 📌 Falls es auf drei APs hinausläuft, wird die CAPsMAN-Abwägung neu geführt (s. Beobachtung 5): bei 3 APs ist koordinierte Kanal-/Leistungsverwaltung erstmals ein Laufzeit- und nicht mehr ein Einmalproblem. Und der diskriminierende Test aus Fund B (ist ap2s Radio gerätespezifisch schwach?) gehört vor einen Kauf.
📋 Umsetzungsreihenfolge (alles via GC, gestaffelt, ap2 zuerst)
- ✅ Fund D DURCH (2026-08-17) —
channel.*-Overrides vonw2-iotauf beiden APs entfernt.w2-iotist danach auf ap1 und ap2BR(bound + running) → Beobachtung 3 strukturell erledigt. Dateien:routeros/tp25-schritt2-fix-overrides-ap2.rsc,routeros/tp25-schritt1-3-ap1.rsc. - ✅ Fund A DURCH (2026-08-17) — Inline-
channel.*aufwifi1/wifi2geleert. 2,4 GHz läuft jetzt auf 20 MHz (2412/axbzw.2462/ax, keinCe/eCmehr), tx-power 15 dBm. ap1 ch1 / ap2 ch11 = überlappungsfrei mit Platz für ch6 in der Nachbarschaft. - ✅ Fund B+C DURCH (2026-08-17) —
ch-5gaufwidth=20/40mhz; ap15180/ax/Ce/I, ap25220/ax/Ce/I, beide 18 dBm (ap2 vorher 9). Zellen benachbart, überlappungsfrei (5170–5210 / 5210–5250).- 🔴 GOTCHA, der zwei Deploys gekostet hat:
/interface/wifi/set <if> !channellöscht die Inline-Sub-Property-Overrides NICHT — es wirft nicht, es tut nichts. Danach standchannel.widthunverändert da, obwohl Profil undconfigurationkorrekt auflösten. Richtig ist einzeln:!channel.width !channel.band !channel.skip-dfs-channels. Dasselbe Muster wie der bekannte!configuration.ssid !security.*-Griff aus dem TP3-Bring-up — nur nie aufchannel.*angewandt. - ⚠️ Zwischenzustand war schlechter als der Ausgangszustand: weil die Breite noch auf 80 MHz stand, rutschte ap2 mit der neuen Frequenz in denselben 80-MHz-Block wie ap1 (beide ch36–48) = genau die Co-Channel-Lage, die 2026-06-18 wegkonfiguriert werden sollte. Merke: bei Kanalarbeit Breite VOR Frequenz ändern, sonst erzeugt man auf dem Weg eine Kollision.
- 🔴 GOTCHA, der zwei Deploys gekostet hat:
- 🔜 Fund E —
access-listmitsignal-range-Boden je AP; Schwellen erst nach dem Re-Walk festlegen. (Hinweis aus der P750W-Historie:/interface/wifihat keindisconnect-timeout/keepalivemehr — das gab es nur im altenwireless-Paket, AX-Radios können nicht zurück. Der Signal-Boden ist damit der einzige verbleibende Griff gegen klebende Clients.) - Re-Walk + Dead-Spot-Kartierung (der übernommene TP3.3-Rest) — erst jetzt, gegen die korrigierte Basis. Vorher gemessene Werte sind wertlos.
- ⏳ Drift-Lücke — Teil 1 GESCHLOSSEN, Teil 2 offen und jetzt exakt vermessen (2026-08-17).
- ✅ Der akute Teil ist zu: die neuen Werte stehen in der SoT (
nautobot/ingest-ap-configcontext.py:radios[5g].width20/40/80mhz→20/40mhz,DEVICE_CHANNELS[ap2][5g]149→44), Config-Context gepatcht, dann Backup → Intended → Compliance → 72/72, keine Drifts. Damit kann ein künftiger Deploy die Fixes nicht mehr zurückdrehen. (Bemerkenswert:widthfür 2,4 GHz stand dort die ganze Zeit korrekt auf20mhz— die SoT war richtig, nur das Gerät hat sie nicht befolgt. Der Beweis, dass das Problem der Inline-Override war und nicht die Datenlage.) - ✅ ERLEDIGT 2026-08-18 (mit dem TP28-GC-Umbau). Die
wifi-*-Features haengen jetzt am Core, die APs sind auf diecap-Zeile eingedampft, und drei neue Rules (wifi-capsman,wifi-provisioning,wifi-cap) decken den Rest ab. 92/92 compliant. Die unten beschriebene Luecke auf/interface wifiist damit gegenstandslos: ein CAP hat keine Inline-Overrides mehr. Der historische Befund bleibt als Begruendung stehen: - 🔴 Der Erkennungsteil bleibt offen. Die 18 Compliance-Rules abgefragt — es fehlen genau zwei Sektionen:
vorhanden fehlt /interface wifi channel·… configuration·… datapath·… security·… steering/interface wifi(die Interface-Sektion)/ip firewall nat/ip firewall filter - Folge 1 (WLAN): die fünf
wifi-*-Features decken nur die Profilobjekte ab. Die Inline-Overrides leben in/interface wifi— deshalb sind Fund A und D seit dem 2026-08-08 unentdeckt geblieben, obwohl die Flotte durchgehend „compliant" meldete. Genau die Lücke, die ich unter Beobachtung 5 vermutet hatte; sie ist jetzt belegt, nicht vermutet. Erschwerend: die VAP-MAC-Adressen sind gerätespezifisch (Template Zeile ~220 nimmt sie bewusst raus), eine Rule auf diese Sektion braucht also erstlocal_config_context_dataje AP. - 📋 Vorarbeit
/ip firewall filter(2026-08-17, Reconnaissance — vor dem Template-Bau nötig):crs326-core25 Regeln (defconf + TP10 + 6 TP5-Holes + 11 TP5-E2 + Log-Regel) ·crs326-branch0 ·ap1/ap2je 12 defconf-Regeln (Werksreste: input-seal, fasttrack, ipsec-Zeilen, sogar „accept to local loopback (for CAPsMAN)" — inert, weil die APs nicht routen, aber vorhanden). ➡️ Zwei Entscheidungen, bevor die Rule scharf gemacht wird, sonst meldet sie sofort flächendeckend Drift: (a) APs: die 12 defconf-Regeln als Sollzustand ins Template schreiben oder sie abräumen (sie tun nichts — ein reiner AP hat keineforward-Kette zu schützen). Empfehlung: abräumen, sonst schreibt man Werksmüll als Absicht in die SoT — dasselbe Argument wie beitelnetin TP16.1. (b) branch: 0 Regeln ist der korrekte Sollzustand und muss im Template auch als leer gerendert werden. - ✅ Folge 2 — GESCHLOSSEN (2026-08-17, TP26):
/ip firewall filterhat jetzt eine Compliance-Rule. Vorher gab es nurip-firewall-nat; „72/72" sagte über die Firewall gar nichts. Jetzt 76/76 (eine neue Rule × 4 Geräte).config_ordered=true— bei Firewallregeln ist die Reihenfolge semantisch. Damit ist TP5 Etappe 3 entblockt.
- ✅ Der akute Teil ist zu: die neuen Werte stehen in der SoT (
- ⚠️
steering=/Channel-Änderungen re-applien alle VAPs und werfen jeden Client kurz raus (TP3.3 am 2026-08-13 gemessen: ap1 25→2, ap2 7→14). Nicht während eines Calls deployen./system backupje AP vorher. - Abh.: TP22 ✅ (GC-Deploy-Pipeline). Übernimmt den offenen Rest von TP3.3, verwandt TP3.2 (Coverage-Doku
docs/wifi-p750w-coverage-and-map.md). Kein Blocker für TP5/TP6 — läuft parallel.
TP16.3 — cloudflared-Reduktion: was der Mesh als Datenpfad kann (und was nicht) ▸ ⏳ RECHERCHE DURCH (2026-08-17), Umsetzung offen
Christophs Frage (2026-08-17): „recherchiere, ob unser neuer wg-tunnel/cf mesh als datenpfad für die server/services genutzt werden kann. die containerpflicht als offizieller weg ist für mich unlogisch."
- ✅ Die Container-„Pflicht" gibt es für den privaten Zugang tatsächlich nicht — und wir nutzen sie schon nicht mehr.
CF-Docs (Mesh↔Tunnel-Vergleichstabelle) sind eindeutig: Mesh = bidirektional, L3/L4, TCP+UDP+ICMP, jeder
Teilnehmer bekommt eine Mesh-IP, Connector =
warp-clioder ein nativer WireGuard-Peer (unser Fall). Tunnel = inbound zum Origin, Veröffentlichen von Hostnames, Connector =cloudflared, Protokolle HTTP/S·TCP·SSH·RDP·SMB über WebSocket geproxied. Für „Server hinter dem Node erreichbar machen, die keinen Client laufen lassen können" nennen die Docs ausdrücklich CIDR-Routes auf dem Mesh-Node als den Weg — wörtlich für „servers, databases, printers, IoT devices". - 🎯 Das ist bei uns seit TP16.1 bereits scharf: die vnet-Route
10.40.0.0/16zeigt aufbf-core-mesh(§4.4, Weg A). Der gesamte private Datenpfad läuft schon über natives WireGuard auf dem Core, ohne jeden Container. Und er ist im TP5-Log-Lauf belegt, nicht vermutet: 137 Zeilenin:cf-mesh, Quelle100.96.0.1→ Nautobot.20.30:8080(62×), NAS.20.10:6690(46×), macmini:22, NAS:5000/:5001/:443/:22, pve.20.100:8006, pve-mcp.20.173:3000, branch/ap1/ap2:22. Christophs Instinkt war richtig. - 🔴 Wo die Container-Pflicht echt ist — und warum sie nicht willkürlich ist: für einen öffentlichen
Hostname, den jemand ohne WARP im Browser aufruft, braucht es einen Reverse-Proxy an der Edge. Das ist
cloudflared. Achtung Verwechslungsfalle: Mesh kennt seit 2026-07-02 ebenfalls Hostname-Routes, und die können auch public hostnames — aber das ist Egress: „route that hostname's traffic through the node and egress via the node's public IP". Es veröffentlicht nichts. Wer das verwechselt, baut den Public-Strang ab und ist überrascht. - ✅ Der reale Gewinn ist trotzdem groß, weil die meisten Dienste keinen öffentlichen Hostname brauchen.
Kriterium: hat der Dienst einen Client, der keinen interaktiven Access-Login kann? (dieselbe Logik wie der
TP16.2-Constraint bei
vw)Muss öffentlich bleiben (cloudflared) Grund Kann auf Mesh-only vwBitwarden-Clients, harter TP16.2-Constraint pve,nautobot,portainer,grafanahassCompanion-App (400-Muster) pve-mcp,ha-mcp,gitea-mcp,ds-bfn8neingehende Webhooks von Dritten ccu,iobroker,z2m25giteaGit-Clients / CI von außen — zu prüfen → Für die rechte Spalte ist der Mesh funktional gleichwertig und operativ einfacher (keine Ingress-Zeile, kein Connector-Paar, keine HA-Frage). Sie erreicht man ohnehin schon per privater IP. - 📌 Zwei Nebeneffekte, die den Fall stärken: (1) die TP16-HA-Degradierung (
bf-nas/bf-pveje nur ein Connector) verliert an Gewicht, sobald nur noch die vier Public-Dienste an cloudflared hängen — weniger Dienste pro SPOF; (2) ICMP + beliebiges UDP gehen über den Mesh und über cloudflared grundsätzlich nicht (der QUIC-Proxy war genau die Lücke aus TP16.1). - ⚠️ Grenzen, ehrlich benannt: (a) der Mesh-Weg setzt WARP auf dem Client voraus — für Christophs eigene Geräte gegeben, für Gäste/Fremdgeräte nicht; (b) IPv6-CIDR-Routes brauchen MASQUE und funktionieren mit einem WireGuard-Device-Profil nicht — deckt sich mit dem v4-only-Entscheid aus TP16.1, wäre aber ein Blocker, falls TP12 später v6 über den Mesh wollte; (c) es bleibt eine Cloudflare-Abhängigkeit — der Mesh ersetzt cloudflared, nicht Cloudflare.
- Vorgeschlagener Umsetzungsschnitt (klein anfangen, reversibel): einen Dienst der rechten Spalte als Probe
aus dem CF-Ingress nehmen (Kandidat:
nautobot— nur Christoph nutzt es, im Mesh-Log mit 62 Treffern der am häufigsten per Mesh angefasste Dienst, und ein Fehlschlag kostet nichts Produktives), eine Woche fahren, dann entscheiden. Rollback = eine Ingress-Zeile zurück. - 📋 Runbook:
docs/tp16.3-nautobot-mesh-only-runbook.md(2026-08-19) — der Schnitt oben, ausführbar ausformuliert: Vorbedingungen (Mesh-Route, Zugriff über10.40.20.30:8080mit WARP von außerhalb), Ingress-PUTüberCF_API_TOKEN(nicht über den CF-MCP, der ist read-only), Rollback aus der gesicherten Config.- 🔴 Der Abnahmepunkt, den man übersieht: Nautobot ist nicht nur Web-UI, sondern die
Deploy-Pipeline. Nach dem Schnitt gehört ein Job-Lauf zur Abnahme, nicht nur ein Browser-Aufruf
— der Netmiko-Deploy kommt von
10.40.20.31(nautobot-worker), nicht von.20.30. - ⚠️ Beim Kürzen des
ingress-Arrays muss die Catch-all-Regel die letzte bleiben, sonst greift der Ingress für alle übrigen Hostnames nicht mehr.
- 🔴 Der Abnahmepunkt, den man übersieht: Nautobot ist nicht nur Web-UI, sondern die
Deploy-Pipeline. Nach dem Schnitt gehört ein Job-Lauf zur Abnahme, nicht nur ein Browser-Aufruf
— der Netmiko-Deploy kommt von
- Abh.: TP16.1 ✅ (Mesh live), TP16 (Public-Strang + dessen HA-Degradierung), TP16.2 (der
vw-Constraint liefert das Entscheidungskriterium). ⚠️ Berührt TP5: der Mesh-Verkehr braucht bei deny-by-default eine expliziteforward-Zeile — s. TP5 Etappe 2.
TP26 — /ip firewall filter unter Drift-Kontrolle ▸ ✅ DURCH (2026-08-17)
Nachgetragen 2026-08-18. TP26 existierte bis dahin nur als zwei Commits und eine
.rsc— ohne Abschnitt in dieser Datei. Genau die Lücke, die eine frische Session nicht finden kann.
- Auslöser: vor TP26 gab es eine ComplianceRule auf
/ip firewall nat, aber keine auf/ip firewall filter. Die vielzitierte „72/72 grün" sagte über die Firewall damit gar nichts — und das ausgerechnet, während TP5 den Deny-by-default vorbereitete. Der Drop wäre die einzige Regel im Netz gewesen, die niemand überwacht. - ✅ Rule
ip-firewall-filterangelegt,config_ordered=true— bei Firewallregeln ist die Reihenfolge semantisch, nicht kosmetisch. Ergebnis damals: 76/76. Damit war TP5 Etappe 3 entblockt. - ✅ Zweiter Teil: die defconf-Firewall auf beiden APs abgeräumt (
routeros/tp26-ap-firewall-cleanup.rsc). ap1/ap2 trugen je 12 Werksregeln — input-seal, fasttrack, ipsec-Zeilen, sogar „accept to local loopback (for CAPsMAN)". Inert, weil ein reiner AP nichts routet. Entscheid: abräumen statt ins Template schreiben — sonst erklärt man Werksmüll zur Absicht. Dasselbe Argument hat 2026-08-18 auch die alten WLAN-Objekte auf den APs erledigt (TP28). - 📌
--asserthat dabei zwei Fehlschläge gefangen, die der Job-Status als Erfolg gemeldet hätte. Seitdem ist die Gegenprüfung am Gerät fester Bestandteil vongc-manual-plan.py. - Abh.: TP22 ✅. Direkte Folge: TP5 E3/E4.
TP27 — RouterBOOT-Firmware auf 7.24 nachziehen ▸ ✅ DURCH (2026-08-17/18)
Nachgetragen 2026-08-18. Auch TP27 hatte keinen Abschnitt — die Arbeit steckt in Christophs Commit
b93514aplusrouteros/tp27-routerboot-firmware-724.rscunddocs/routerboot-firmware-klickanleitung.md.
- Kontext: Christoph hat alle vier MikroTik selbst auf RouterOS 7.24 stable gehoben (core/branch 7.19.5 → 7.24, ap1/ap2 7.23.2 → 7.24). Offen blieb die zweite Hälfte jedes MikroTik-Upgrades: die RouterBOOT-Firmware hängt danach zurück.
- 🔑 Die Falle, wegen der es ein eigener TP ist:
/system routerboard upgradeschreibt die Firmware nur — wirksam wird sie erst beim nächsten Reboot, undcurrent-firmwarezeigt bis dahin weiter den alten Wert. Wer direkt nach dem Befehl prüft, hält den Schritt fälschlich für gescheitert. Reihenfolge also: schreiben → gezielt rebooten →current-firmwaregegenprüfen. - ⚠️
/system routerboard upgrade*steht auf der MikroMCP-Deny-Liste (zu Recht — es schreibt den Bootloader). Der Weg führt über Golden Config; der Reboot dann übersshpass/MikroMCP. - ✅ Abnahme 2026-08-18: auf allen vier Geräten
current-firmware = upgrade-firmware = 7.24. - Abh.: keine. Berührt TP28 insofern, als CAPsMAN erst ab 7.2x das neue
/interface/wifimitbringt.
TP28 — WLAN über CAPsMAN auf crs326-core ▸ ✅ KOMPLETT (2026-08-18) — mit Nachtrag: slaves-datapath fehlte, IOT+MEDIA lagen ~14 h
-
🔴🔴 POST-MORTEM 2026-08-18 (gemeldet von Christoph: „die -iot-geräte sind offline … connect möglich, aber kein dhcp"): Seit dem Cutover hingen alle Slave-VAPs in gar keiner Bridge.
/interface wifi cap slaves-datapathwar auf beiden APs leer — und genau dieses Feld ist das Einzige, was die vom Manager erzeugten Slave-VAPs lokal in die Bridge haengt. Der Manager schicktdatapath.bridge=bridgezwar mit, der CAP uebernimmt davon nur dievlan-id. Betroffen:dirtyvader-iot,-media,-untrusted,-guest. Nicht betroffen:dirtyvader-main— dessen Master-Radioswifi1/wifi2sind statische Bridge-Ports und liefen deshalb weiter. Genau das machte den Ausfall unsichtbar.- Fix (live 2026-08-18 auf ap1 + ap2, seither Soll im Template):
/interface wifi datapath add name=dp-caps-slaves bridge=bridge+/interface wifi cap set slaves-datapath=dp-caps-slaves. Das Objekt traegt bewusst keinevlan-id— die liefert der Manager pro VAP. Danach erscheinen die VAPs als dynamische Bridge-Ports mitpvid=30/40/50/90, und DHCP laeuft sofort wieder. - 🔴 Die Diagnose-Lehre: „Client assoziiert" beweist gar nichts. Am Manager standen 25 IOT-
Registrations — das WLAN sah perfekt aus. Erst zwei Reads trennten die Faelle:
torchaufvlan30am Core (leer) und der TP5-Drop-Log (kein einziger DHCP-Eintrag). Beides leer heisst: es wird nichts verworfen, es kommt nichts. Damit war die Firewall — der naheliegende Verdaechtige nach der Haertung derselben Nacht — in zwei Minuten entlastet. - ⚠️ Die Abnahme „✅ Ohne jeden Aussetzer" weiter unten war falsch. Sie zaehlte Registrations
(30 Clients, beide CAPs
Ok, 7 VAPs je AP) — also genau die Metrik, die hier luegt. Keiner dieser Werte beruehrt die Bridge. Ein Abnahmekriterium fuer WLAN-Umbauten ist ab jetzt eine frische DHCP-Lease pro SSID, nicht die Registration-Table. routeros/tp28-ap-wifi-reste-abraeumen.rschat den Ausfall nicht ausgeloest, aber zementiert: mit den geloeschten datapath-Objekten gab es lokal nichts mehr, woraufslaves-datapathhaette zeigen koennen. Der Ein-Zeilen-Fix war damit weg. Nachtrag steht im Skript.- ✅ Reboot-Abnahme an ap2 (2026-08-18), drei Fragen auf einmal beantwortet:
slaves-datapathueberlebt den Neustart (statisches Objekt, steht im/export), der CAP findet seinen Manager durch die gehaertete input-Kette wieder (current-caps-man-identity=crs326-core— MNDP/CAPWAP sind also korrekt offen, das war seit TP5 Etappe 4 nie durchgespielt), und die sieben Slave-VAPs kommen von selbst als dynamische Bridge-Ports mit pvid 30/40/50/90 zurueck. AP nach 40 s wieder erreichbar. Abnahme nach neuer Regel = frische Lease: IOT-Client10.40.30.8last-seen=30s, MAIN-Client10.40.10.180last-seen=1m54s. - ⚠️ Reboot per MikroMCP geht auf 7.24 nicht: das
reboot-Tool sendetdelay, die REST-API antwortetunknown parameter delay;run_commandist fuer/system reboot*per Deny-Policy gesperrt. Weg bis das gefixt ist:sshpass+ssh admin@<ap> "/system reboot". - ✅ Soll nachgezogen, Compliance wieder sauber: 92/92, 0 Drifts (2026-08-18). Weg: Template in
nautobot/mikrotik_routeros.j2→routeros/push-gc-template.py(Secret-Guard) → GitRepository-Sync → Backup/Intended/Compliance. Ohne den Push meldet der Refresh die zwei neuen Zeilen alsextraauf beiden APs — das Jinja lebt im separaten Gitea-Repobf-golden-config, ein Commit hier allein erreicht Nautobot nicht. - ⚠️ Beim ersten Sync-Versuch:
redis.exceptions.ConnectionError: broken pipeauf dem Nautobot-Stack. Ein simpler Retry ging durch; NAS-Load war unauffaellig (0,9). Der Job meldet das alsFAILURE— nicht mit einem inhaltlichen Fehler verwechseln.
- Fix (live 2026-08-18 auf ap1 + ap2, seither Soll im Template):
-
✅ Der offene GC-Rest ist erledigt (2026-08-18). Die fuenf
wifi-*-ComplianceFeatures haengen jetzt am Core, der AP-Zweig des Templates ist auf eine einzige Zeile eingedampft (/interface wifi cap set discovery-interfaces=vlanXX enabled=yes).- 🔴 Dabei aufgefallen: die APs trugen noch die KOMPLETTE Standalone-WLAN-Config aus TP3 —
je 2 channel, 6 datapath, 6 security, 7 configuration, 1 steering. Der Cutover vom 08-17 hatte
sie nie abgeraeumt. Wirkungslos (der Manager liefert alles dynamisch), aber sie im Template als
Soll zu rendern hiesse, totes Zeug zur Absicht zu erklaeren — dasselbe Argument wie bei den
defconf-Firewallregeln in TP26. Abgeraeumt mit
routeros/tp28-ap-wifi-reste-abraeumen.rsc. - ✅ Ohne jeden Aussetzer: vorher/nachher 30 Clients, beide CAPs
Ok, 7 dynamische VAPs je AP. Die Sorge vor einem Radio-Re-Apply (TP25/TP3.3: „wirft jeden Client kurz raus") hat sich nicht bestaetigt — die dynamischen VAPs tragen ihre Werte inline (datapath.vlan-id=…) und referenzieren kein lokales Objekt; nurwifi1/wifi2hielten noch einen totenconfiguration=-Verweis, der beim Loeschen folgenlos blieb. - 🔴
[find !dynamic]ist auf diesen Sektionen ein SYNTAXFEHLER, nicht bloss wirkungslos:/interface wifi configuration& Co. haben gar keinedynamic-Eigenschaft (die gibt es nur auf/interface wifiselbst). Der erste Anlauf lief komplett in dieon-error-Zweige, aenderte nichts und meldete trotzdem „Plan Completed". Wieder: nur die Gegenpruefung am Geraet zaehlt.
- 🔴 Dabei aufgefallen: die APs trugen noch die KOMPLETTE Standalone-WLAN-Config aus TP3 —
je 2 channel, 6 datapath, 6 security, 7 configuration, 1 steering. Der Cutover vom 08-17 hatte
sie nie abgeraeumt. Wirkungslos (der Manager liefert alles dynamisch), aber sie im Template als
Soll zu rendern hiesse, totes Zeug zur Absicht zu erklaeren — dasselbe Argument wie bei den
defconf-Firewallregeln in TP26. Abgeraeumt mit
-
✅ Drei neue ComplianceRules schliessen die letzten WLAN-Luecken:
wifi-capsman(der Manager-Schalter),wifi-provisioning(die vier Regeln jeradio-mac— sie entscheiden, welcher AP welche Kanaele und Slave-VAPs bekommt) undwifi-cap(die CAP-Seite; faelltdiscovery-interfacesweg, findet der AP seinen Manager nach dem naechsten Reboot nicht mehr). Ergebnis: 92/92 compliant, 0 Drifts. -
⚠️
wifi-securityist gruen, aber NICHT deploybar. Die Passphrasen stehen als<<REDACTED>>im Template (User-Entscheid 2026-08-18: alle fuenf Features umhaengen, Platzhalter in Kauf nehmen). Der gruene Haken beweist nur, dass Soll und Ist dieselbe Maske tragen — nicht, dass die Passphrasen stimmen, und schon gar nicht, dass die Sektion ausgerollt werden koennte. Das steht als Warnung im Template. Wer sie aendert, liest den Ist-Stand per REST zurueck (GET http://10.40.99.1/rest/interface/wifi/security) — nicht auswlan-psks.envoder den drei Bring-up-Dateien, die voneinander abgeschrieben sind. -
⚠️ Die frueher hier notierte „bisher fehlende Rule auf
/interface wifi" ist gegenstandslos — wie vorhergesagt: ein CAP hat keine Inline-Overrides mehr, die driften koennten.
Methodenwechsel auf Christophs Anstoß: „ich möchte die methode in frage stellen … eine sot ist zwar nett, aber wenn sie uns das leben zur hölle macht, verzichte ich auf diese governance." Der Entscheid vom 2026-07-22, CAPsMAN abzuschaffen, ist damit revidiert.
- ✅ Warum es diesmal trägt: 2026-07-22 war ap1 Manager UND AP — und ein Manager kann seine eigenen
Radios nicht per CAPsMAN provisionieren (MikroTik-bestätigt). Genau diese Asymmetrie war die Ursache von
TP3.1. Mit dem Core als Manager sind beide APs symmetrisch. Der Core braucht dafür kein
wifi-qcom: dascapsman-Menü steckt im Basis-routeros, die 3,35 MB freier Flash sind irrelevant. Die zweite Begründung von damals („WLAN instabil") war ohnehin widerlegt — standalone blieb es instabil, die Ursachen waren die Funkparameter aus TP25. - ✅ Ist-Stand: Manager auf
vlan99, 4 Kanäle · 6 Datapaths · 6 Security · 2 Steering · 9 Configurations · 4 Provisioning-Regeln jeradio-mac. Beideremote-capOk, je 7 dynamische VAPs. Kanäle exakt wie in TP25 gemessen (ap15180/ax/Ce/I+2412/ax, ap25220/ax/Ce/I+2462/ax). 34 Clients (main 3, iot 27, media 4), Roaming im Manager-Log belegt.ft-over-ds=yesist jetzt aktiv (unter CAPsMAN erstmals verfügbar),-guesthat eigenesst-guestmitneighbor-group=bf-guest— nichtbf-mainmitbenutzen, sonst meldet 802.11k Gast-Clients BSSIDs einer SSID, auf die sie nicht assoziieren können. - 📌 Local-Forwarding ist keine Einstellung mehr: im neuen
/interface/wifigibt es kein zentrales Forwarding („There is no CAPsMAN-forwarding in WiFi (RouterOS 7.0+)"). Diedatapath-Property existiert deshalb nicht —monitorbestätigttraffic processing on CAP. - 🔴 DIE MESSFALLE DIESES TPs — unter CAPsMAN führt der MANAGER die Tabellen, nicht der CAP.
/interface/wifi/registration-tableund diewireless-Logs sind auf ap1/ap2 leer, obwohl das WLAN einwandfrei läuft. Ich habe daraus zweimal „WLAN ist unten" geschlossen, während Christophs Geräte mit vollem Ausschlag verbunden waren und ein Speedtest gut lief. Immer am Manager zählen. - 🔴 DIE ZWEITE FALLE — drei übereinstimmende Dateien sind nicht drei Belege.
wlan-psks.envwich für iot/untrusted/infra vonap1-prov-base.rsc,ap2-prov-base.rscundap1-standalone.rscab. Ich habe die drei als Bestätigung gelesen und die env-Datei „korrigiert" — ~20 Shellys waren 20 Minuten aus dem Netz. Die drei Dateien stammen alle aus dem Bring-up vom 2026-08-08, sind also eine Quelle in drei Kopien. ✅ Auflösung: die Passphrasen sind am Gerät per REST lesbar (GET http://10.40.99.1/rest/interface/wifi/security) — dort ausgelesen ergab sich exakt der env-Wert.wlan-psks.envist neu aus dem Live-Stand befüllt und trägt jetzt eine Kopf-Warnung; die drei Baselines sind seit dem Cutover ohnehin nicht mehr deploybar und wurden entschärft (Passphrasen raus, HISTORISCH). - ✅
OFFEN — das GC-Modell beschreibt weiter Standalone-APs— ERLEDIGT am 2026-08-18. Diewifi-*-Features haengen jetzt am Core, das AP-Template ist auf diecap-Zeile eingedampft, und die toten Standalone-Objekte sind von beiden APs abgeraeumt. Details im ersten Block dieses TPs. Die hier genannte Zahl76/76ist damit doppelt ueberholt (aktuell 92/92 bei 23 Rules). (Der Absatz stand bis 2026-08-19 unveraendert als „OFFEN" hier, obwohl der Kopf des TPs schon „KOMPLETT" sagte — ein Selbstwiderspruch im selben Abschnitt, ueber den prompt die naechste Session gestolpert ist. Merkregel fuer kuenftige Statuswechsel: nicht nur den Header umschreiben, sondern die Punkte darunter mitziehen.) - 📌 Nebenbefund: HAs
mikrotik-Integration pollt alle 10 s und schreibt zwei Log-Zeilen pro Poll auf jedes Gerät. Die AP-Logs sind dadurch für Diagnose praktisch unbrauchbar (get_logohnetopics-Filter liefert nuradmin logged in/out via api). - Abh.: TP25 ✅ (die Funkparameter sind übernommen), TP15/TP21.1 ✅ (Core als L3-Router = Manager-Standort). Verwandt: TP3 (dessen CAPsMAN-Ära hier revidiert wird), TP22 (GC-Scope).
TP-R — Router-Capabilities-Sweep ▸ FERTIG (docs/research/routeros-capabilities.md)
- Leitsatz: nativ vor Container, NAS vor Router (128MB-Flash-Limit).
- Sofort nativ (~0 RAM): RoMON · Netwatch · Scheduler + Auto-Backup/Mail · SNMP→externes Monitoring · mDNS-Repeater · spectral-scan · 802.11r/k/v (Fast-Roaming statt Mesh) (die Sweep-Fassung nannte hier CAPsMAN — das ist seit 2026-08-08 abgeschafft; 11r/k/v läuft standalone weiter, s. TP3/TP3.3) · Back-to-Home/WireGuard.
- Auf NAS: FreeRADIUS(+LDAP) · NPM · icinga/Grafana · CF-Tunnel.
- Weglassen: LoRa (keine HW) · OpenFlow · CALEA · ZeroTier (CPU-Fresser bis ~60 % → WireGuard) · lokales
dude. - ✏️ Korrektur Reverse-Proxy: RouterOS 7.22+ HAT einen nativen (
/ip/reverse-proxy, ACME/SNI) — aber ersetzt NPM NICHT (kein WebSocket/gRPC/Sticky, nur IPv4-Backends, TLS frisst Router-CPU) → NPM bleibt auf NAS. - Speist TP8/9/11/12.
Reihenfolge / Abhängigkeiten
🎯 Kritischer Pfad (Stand 2026-08-19)
TP5 E1 ✅ ─► E2 ✅ ─► E2-Nachtrag ✅ ─► E3 Drop ✅ ─► E4 input+MGMT ✅ ─► E5 MAIN→IOT ✅ ─► TP6 (CAKE) ◄ Ziel
▲
ab hier ist alles frei
TP5 ist am 2026-08-18 abgeschlossen. Damit steht rechnerisch nur noch TP6 auf dem kritischen Pfad —
🟠 aber dessen Prämisse ist offen: eine Messung von 2026-06-16 (docs/call-quality-diagnosis.md)
bescheinigt dem Netz bereits A/A+ und hält CAKE für „marginal". Der nächste Schritt ist deshalb ein
Bufferbloat-Test gegen den heutigen Edge, nicht der Bau einer Queue. Fällt er gut aus, ist der
kritische Pfad leer und das Projekt in seinem Kern fertig — dann entscheidet Christoph, was das neue
Ziel ist. Alles andere läuft nebenher und blockiert nichts.
- ✅ TP5 Etappe 1–4 — komplett durch (2026-08-16 bis 2026-08-18). Details im TP5-Abschnitt oben.
Die Wartezeit-Position, die hier bis 2026-08-17 als eigener Schritt stand, ist eingeloest: statt
eines mehrtaegigen Fensters wurde der Nachtrag aus einem dreieinhalbstuendigen Fenster
abgeleitet und der Drop mit Auto-Revert plus weiterlaufender Log-Regel abgesichert.
Die Vorbedingung D2 (iPhone
.30.201) ist gegenstandslos: das Geraet hing dort bewusst zum Anlernen eines IoT-Geraets (User 2026-08-17). Wer im IOT-SSID sitzt, ist im selben VLAN wie das Geraet und beruehrt dieforward-Kette gar nicht; fuer Ad-hoc-Zugriffe aus MAIN gibt es jetzt die selbstverfallende Gruppejit-admin. - 🟠 TP6 — QoS/CAKE + Call-Quality-A/B-Test.
Das eigentliche Projektziel; keine offenen Blocker mehr.Korrigiert 2026-08-19: kein Blocker, aber eine offene Prämisse — der Satz oben und dieser Punkt widersprachen sich seit dem 18. Richtig ist: der nächste Schritt ist eine Messung, kein Bau. Runbook liegt bereit:docs/tp6-praemisse-messrunbook.md. Fällt sie A/A+ aus, wird TP6 geschlossen statt gebaut — dann ist der kritische Pfad leer und das Projekt in seinem Kern fertig.
Eine harte Reihenfolge-Regel dazwischen: TP5 darf die DNS-Bypass-Sperre erst schließen, wenn TP23s
Ausnahme-Oberfläche steht — der bisherige Workaround „Client von Hand auf 1.1.1.1" ist genau dieser
Bypass. Alles andere aus TP5 ist davon unabhängig und kann vorher laufen.
⚠️ Und eine zweite, aus TP16.1/TP16.3: der Drop braucht cf-mesh explizit — steht seit Etappe 2 als
TP5-E2: mesh->LAN / LAN->mesh drin. Ohne diese zwei Zeilen sperrt Etappe 3 den Fernzugang aus, also genau
den Weg, über den man den Fehler zurücknehmen wollte.
Follow-ups nebenher (blockieren nichts)
- TP25 — WLAN-Stabilisierung (NEU 2026-08-17): Audit durch, 6 Funde (2,4 GHz fährt 40 MHz statt der
profilierten 20; ap2 sendet auf 5 GHz mit 9 statt 18 dBm, weil ch149 unter ETSI leistungsbegrenzt ist;
80 MHz kostet Randabdeckung; unzulässiger Channel-Override auf
w2-iot; keineaccess-list; 5-Minuten-Takt bei IoT-Trennungen offen). Umsetzung in 6 Schritten, alles via GC. Übernimmt den offenen Rest von TP3.3. - TP16.3 — cloudflared-Reduktion (NEU 2026-08-17): Recherche durch. Der Mesh ist schon der private
Datenpfad (im TP5-Log mit 137 Zeilen belegt); Container braucht nur noch der öffentliche Ingress.
Vorschlag:
nautobotals Probe aus dem CF-Ingress nehmen. DoH-Cloudflare auf✅ erledigt 2026-08-18 (TP23 Stufe 1 = TP21.1 TODO 1).crs326-core- TP24 — DC-USV (seit 2026-08-16 eigener TP, aus TP15 herausgelöst).
TP19 — VLAN1-Client-Retirement / cudy-Teardown✅ geschlossen 2026-08-18 (VLAN1-ARP = 0). Die zwei Reste sind dorthin verschoben, wo sie hingehören: tote CF-Tunnel → TP16, HA-Portainersetup_retry→ TP11.TP3.3 — WLAN-Coverage-Kur→ in TP25 aufgegangen (2026-08-17). 802.11k/v ist repariert (08-13); Re-Walk + Dead-Spot-Kartierung laufen als Schritt 5 von TP25 — und zwar erst nach den Funkparameter-Fixes, weil vorher gemessene Werte wertlos sind.- TP10 — DDNS-Auto-Updater für
bf4.emsenhuber.net(auf dem Core möglich,device-modeerlaubt scheduler). - TP14.4 — CF-Access-Service-Token rotieren.
- Doku-Aufräumen (
docs/doku-cleanup-session.md) — Punkte A–D am 2026-08-16 abgearbeitet, E teilweise. 📌 Läuft in einer eigenen Session — Übergabe:docs/handoff-doku-session-20260818.md. ⚠️ Solange die läuft,teilprojekte.mdnicht parallel bearbeiten (in der Nacht auf den 18. viermal committet, das kollidiert sonst).
Nachgelagert / research-getrieben
TP8 (Identity/802.1X) · TP11 (Monitoring) · TP12 (IPv6) · TP13 (Botschafts-WLANs) · TP16.2 (Härtung bypass-Dienste) · TP18 (Garage-Objektspeicher) · TP20.1 (Vaultwarden → Platform-PG) · TP23 (DNS-Policy, s. Regel oben). (TP16.1 stand hier bis 2026-08-17 fälschlich als offen — es ist seit demselben Tag ✅ abgeschlossen und steht unten unter „Durch". Nachfolger ist TP16.3, das oben unter Follow-ups läuft.)
✅ Durch (Fundament — nicht mehr planen, nur nachschlagen)
TP1 · TP2 · TP2.1 · TP3 (Rebuild 2026-08-08) · TP3.1 · TP4 (Rolle seit 08-08 auf dem Core) · TP7 · TP7.2 · TP10 (Kern) · TP14 (+14.1/14.2/14.2a/14.3/14.5) · TP15 · TP16 (Kern) · TP17 · TP19.1 · TP20 · TP21 · TP21.1 · TP22 · TP-R · TP3.2 (08-17) · TP5 (08-18) · TP7.1 (08-18) · TP19 (08-18) · TP23 Stufe 1 (08-18) · TP26 (08-17) · TP27 (08-17/18) · TP28 (08-17, GC-Modell 08-18). Verworfen: TP9 (Gateway-HA, User-Entscheid 2026-08-08). Obsolet: Omada-PVID-Fix (User-Entscheid 2026-07-22 — „nie wieder aufgreifen").
📜 Historische Fassung dieses Abschnitts (bis 2026-08-14 fortgeschrieben, hier bewusst erhalten)
🎯 AKTUELLER KRITISCHER PFAD (Stand 2026-07-16, überschreibt die Reihenfolge unten): TP20 (Platform-Postgres) → TP21 (Nautobot) — Ziel: fertig vor CRS326-Produktivsetzung, spätestens Montag 2026-07-20. TP18 (Garage-S3) und die Komodo-Abhängigkeit wurden am selben Tag als Blocker entfernt/entkoppelt (s. TP20), um diese Deadline zu halten — beide werden später nachgezogen, nicht mehr vorher abgewartet. ➡️ Stand-Update 2026-08-08: TP20/TP21-Plattform steht, Core-Cutover (TP21.1) + WLAN-Rebuild (TP3) + VLAN20-Migration (TP14) sind durch. Neuer Rest-Pfad: TP22 (Device-Adoption + Compliance-Push) → TP5 (Deny-by-default) → TP6 (CAKE, das Ziel). Kleine Follow-ups davor: DoH-Cloudflare auf core, USV (TP24). ➡️ Stand-Update 2026-08-13 (Abschluss): TP22 ist DURCH (alle 5 Schritte; Fleet adoptiert, Deploy-Pipeline scharf, Datenmodell as-built, Secret-Handling entschieden) → kritischer Pfad jetzt: TP5 (Deny-by-default) → TP6 (CAKE). Kleine Follow-ups davor: DoH-Cloudflare auf core, DC-USV (TP24), Doku-Aufräumen (
docs/doku-cleanup-session.md, vorbereitet 2026-08-14 — dieses Dokument beschreibt an mehreren Stellen noch die Topologie vor dem Core-Cutover). ➡️ Neu 2026-08-14: TP23 (DNS-Policy & Self-Service) hängt an TP5 — und zwar in beide Richtungen: TP23 braucht TP5s Firewall, TP5 darf aber die DNS-Bypass-Sperre erst schließen, wenn TP23s Ausnahme-Oberfläche steht (der bisherige Workaround „Client auf 1.1.1.1" ist dieser Bypass). Ebenfalls in TP5 gezogen: TP7.1 (SSDP-Reflector für die macOS-Sonos-App).Kabelentfällt (2026-08-14): gelöst wurde am Port, nicht am Kabel (User-Vorgabe „Patchfeld-Nummerierung wird nicht wegen einer Config geändert") —core ether4→ether2(Sideboard/TV)ether4steht seit 08-13 auf untagged VLAN40, End-to-End-Beweis am 08-14 erbracht, s. TP21.1 Punkt 4. Historisch: TP22 war das nächste Arbeitspaket — TP17 (Shelly-Migration) ist parallel dazu vollständig abgeschlossen (alle Shellys auf VLAN30, User-bestätigt). Grund für den Nautobot-First-Ansatz: Governance-Entscheid „Config exklusiv über Nautobot" (s. oben) macht Nautobot zur Voraussetzung für praktisch jede weitere Router-/Switch-Änderung. Die Punkte 3-4 unten (Omada-PVID-Fix etc.) sind obsolet (User-Entscheid 2026-07-22 — Omada spielt seit TP15-Korrektur keine Rolle mehr, nie wieder aufgreifen) — ganze Liste braucht mal eine Aufräum-Session, hier nur der aktuelle Fokus vorangestellt. ✅ TP16 (CF-Tunnel Round-Robin/macvlan-Host-Isolation → reziprokes 3-Tunnel-HA) KERN UMGESETZT 2026-07-10 (#1033 strukturell weg). Offen nur Access-Strang (WARP/vw) = user-gated. As-Builtdocs/cf-tunnel-mapping.md §10.
TP1 (GE8) → TP2 (Omada Controller).✅ erledigt 2026-06-15.TP4 (Router-Cutover L3-Infra + WAN-Edge).✅ erledigt 2026-06-15 (L3) + 2026-07-01 (Edge-Cutover, FB physisch weg).- Jetzt: Omada-PVID-Fix — Omada Access-Profile korrigieren (PVID 10/20, untagNetworkIds bereinigen, sicher P3/P5/P6 zuerst), dann IP-Migration NAS/macmini/pve auf VLAN-Subnetze + DNS-Einträge updaten. IP-Migration NAS/pve = TP14 (NAS ✅ 2026-07-10, pve 🔜 Session B).
- Dann: TP5 (Deny-by-default fertigziehen — Sonos-/HA-/mDNS-Holes + WAN-Input-Seal stehen bereits; TP5.1 = DNS-Redirect + Live-Torch für Low-Trust-Geräte/Airfryer hängt dran) → TP6 (QoS/CAKE).
TP7 (mDNS)✅ 2026-07-02 (inkl. HA/vlan20),TP3 (WLAN/CAPsMAN)✅ 2026-06-18,TP3.1 (ap2-VLAN-Trunk)✅ 2026-07-01,TP3.2 (P750W/Discovery)✅ 2026-07-02,Sonos-Migration✅ 2026-07-02 (alle 10 auf VLAN 40). ⏳ TP3.3 (WLAN-Coverage-Kur) offen — Fortsetzung neue Session (docs/wifi-p750w-coverage-and-map.md). TP10 (VPN)✅ Kern durch (2026-06-27) + Edge-Cutover (2026-07-01) → DURCH. Offen nur: DDNS-Auto-Updater.- Nachgelagert/Research-getrieben: TP8 (Access), TP9 (HA), TP11 (Monitoring + CF-Tunnel-Track-B/C), TP12 (IPv6), TP13 (Spaß).
- Foundation (2026-07-14): TP15 (MikroTik-Switching / Omada-WLAN, 2× CRS326 bestellt) ∥ TP20 (Platform-Postgres, single-site replication-ready) → TP21 (Nautobot Golden Config) ∥ TP20.1 (Vaultwarden→PG + 2-Site-HA). TP20 hängt an TP18 ① (Garage-Bucket für pgBackRest).