From d8c8c3b8288df6da30250a62fb570826b8e064c4 Mon Sep 17 00:00:00 2001 From: Christoph Emsenhuber Date: Thu, 23 Jul 2026 18:02:10 +0200 Subject: [PATCH] TP15: WG-Endpoint (bf4) geklaert + Session-Handover - bf4.emsenhuber.net = CF-A-Record (proxied=false, TTL120, 90.146.35.38), KEIN Updater auf ap1 -> nichts zu migrieren. Bei WAN-IP-Wechsel via CF_API_TOKEN nachziehen (bf4-Record + Access-Policy bf4-home-ip). Core ist nicht device-mode=home -> DDNS-Auto-Updater dort baubar (TP10-Follow-up). - docs/tp15-core-swap-session-handover.md: Einstieg fuer die Cutover-Session (locked decisions, Pre-Window-Checkliste, Kurz-Runbook, Gotchas). - staged .rsc + teilprojekte.md entsprechend fortgeschrieben. Co-Authored-By: Claude Opus 4.8 --- docs/teilprojekte.md | 4 +- docs/tp15-core-swap-session-handover.md | 70 +++++++++++++++++++++++++ routeros/tp15-core-l3-staged.rsc | 12 +++-- 3 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 docs/tp15-core-swap-session-handover.md diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index aee5b50..96fc49b 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -354,7 +354,9 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung". - 🐞 **Gotchas festgehalten:** (1) **Kabel ether3↔ether5 waren beim Umstecken vertauscht** → ein AZ-Sonos landete als Access-VLAN10 in `10.40.10.190` **und** blutete via SonosNet nach VLAN40 (= Dual-Homing-Muster, `project_dual_homing_slowness_incident`) → Kabeltausch gefixt, beide AZ-Sonos jetzt sauber VLAN40 (`.191`/`.192` bound). (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 mehrzeiligem `source` ist kein sauberes JSON → ID separat via `?.proplist=.id` holen. (5) Claude-Code-Auto-Mode-Classifier blockt Device-Config-*Writes* per Bash (Reads ok) → `autoMode.allow`-Regel in `.claude/settings.local.json` nötig (kann Claude sich nicht selbst setzen). - **🔜 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 `.99.13`→`.99.12`, core bleibt `.99.11`. - ✅ **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 Betriebsumlenkende `disabled=yes`, im Cutover in einem Rutsch `enable`; ~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**. - - 🐞 **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 gegen `http://10.40.41.211/rest`. (b) Mgmt-`.99.11` tot (sw1 #12 trägt kein 99T), nur VLAN1-Temp `.41.211` erreichbar. (c) **WG-Hub-Fallen:** Privkey von ap1 mitnehmen (sonst FM/DW-Reconfig nötig) + Hub-Endpoint der Spokes klären, da core am WAN evtl. neue Liwest-IP zieht (nicht MAC-gelockt). (d) core-vlan99 wird GW `.1`; Bring-up-`.11` dadurch redundant (Fenster-Reconcile). (e) VLAN1 raus: Hybrid-VLAN1-Drops sw1 GE3/7/10 beim Umstecken einem echten VLAN zuordnen oder stilllegen. + - 🐞 **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 gegen `http://10.40.41.211/rest`. (b) Mgmt-`.99.11` tot (sw1 #12 trägt kein 99T), nur VLAN1-Temp `.41.211` erreichbar. (c) **WG-Hub:** Privkey von ap1 mitnehmen (sonst FM/DW-Reconfig nötig). (d) core-vlan99 wird GW `.1`; Bring-up-`.11` dadurch 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, aktuell `90.146.35.38`). **Kein Updater auf ap1** → nichts zu migrieren; `bf4` folgt der IP manuell (offener TP10-Follow-up). Zieht core am WAN eine neue IP (Lease sticky, eher nicht), via `CF_API_TOKEN` nachziehen: `bf4`-Record + Access-Policy `bf4-home-ip` (`90.146.35.38/32`). **Chance:** core ist nicht `device-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 bleibt `docs/tp15-core-swap-session-handoff-prompt.md`). - 📦 **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 (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. diff --git a/docs/tp15-core-swap-session-handover.md b/docs/tp15-core-swap-session-handover.md new file mode 100644 index 0000000..34f2b7c --- /dev/null +++ b/docs/tp15-core-swap-session-handover.md @@ -0,0 +1,70 @@ +# TP15 Core-Swap — Session-Handover (Prep → Cutover) + +> **Von:** Prep-Session 2026-07-23 (kein Netz-Eingriff). **An:** die Cutover-Session (eigenes Wartungsfenster). +> **Erster Prompt der neuen Session:** „Lies `docs/tp15-core-swap-session-handover.md` und führe den Core-Swap +> im Wartungsfenster durch." Der ausführliche Auftrag/Runbook liegt zusätzlich in +> `docs/tp15-core-swap-session-handoff-prompt.md`; dieses Doc ist der aktuellere Einstieg. + +--- + +## Was ist passiert (Prep-Session) +ap1s komplette Live-L3-Config wurde gelesen und **fertig als staged Config materialisiert**: +`routeros/tp15-core-l3-staged.rsc` — alles Betriebsumlenkende `disabled=yes`, im Cutover in EINEM Rutsch `enable`. +Runbook/Rollback/Verifikation stehen im Plan; die drei Fenster-Entscheide sind gefällt. **Kein Gerät angefasst.** + +## Locked decisions (gelten, nicht neu diskutieren) +1. **WG-Hub (TP10 FM/DW-VPN) migriert MIT** in dasselbe Fenster. (Hing im Handoff-Prompt nicht drin — er sitzt auf + ap1s Public-Edge und kann dort nicht bleiben.) +2. **Governance = frische Direkt-Ausnahme #3** (REST/MikroMCP), danach Ist-Stand als *intended* → Nautobot. + ⚠️ **User muss die Ausnahme #3 zu Fensterbeginn formal erteilen.** +3. **Rettungspfad = iPhone-Hotspot** am Notebook (nicht über sw1/ap1). + +## Endpoint-Frage (war der letzte offene Rechercheposten) — ✅ GEKLÄRT +- Spokes adressieren den Hub über **`bf4.emsenhuber.net:51821`** = **Cloudflare-A-Record** (proxied=false, TTL 120, + aktuell `90.146.35.38` = ap1s Public-IP). **Kein DDNS-Updater auf ap1** (nur WANTEST/mac-clone-Scripts) → nichts + zu migrieren. `/ip/cloud` = MikroTik-DDNS `update-interval=none`, irrelevant (andere Domain). +- **Cutover-Konsequenz:** Liwests Lease ist sticky → core zieht am WAN sehr wahrscheinlich **dieselbe** IP → `bf4` + passt weiter → FM/DW kommen von selbst hoch. **Falls doch neue IP:** per `CF_API_TOKEN` nachziehen — + (a) `bf4`-A-Record **und** (b) CF-Access-Policy `bf4-home-ip` (`90.146.35.38/32`). (CF-MCP ist read-only!) +- **Chance:** core ist **nicht** `device-mode=home` → **scheduler+fetch gehen** → den `bf4`-DDNS-Auto-Updater bauen, + den ap1 nie konnte → schließt den offenen TP10-Follow-up (`docs/teilprojekte.md:289`). + +## Bekannte Prep-Gotchas (im Fenster einplanen) +- **MikroMCP kann core noch NICHT schreiben:** `ROUTER_CRS326_CORE_USER/PASS` sind im MCP-Prozess nicht geladen + → **vor dem Fenster MikroMCP neu starten** (ENV `CRS326_CORE_*` aus `~/.secrets/credentials.env`) **oder** + REST-curl gegen `http://10.40.41.211/rest` (wie beim Bring-up). +- **core-Mgmt `.99.11` ist tot** (sw1 #12 trägt kein 99T) — erreichbar nur VLAN1-Temp **`10.40.41.211`**. +- **WG-Privkey:** ap1s `wg-hub`-Private-Key im Fenster von ap1 holen und auf core setzen (Platzhalter im `.rsc`), + damit core denselben Public Key hält → FM/DW brauchen keine Reconfig. **Secret → nicht committen.** +- **vlan99:** core-GW wird `.1`; Bring-up-`.11` dadurch redundant → im Fenster reconcilen (Secondary behalten oder droppen). +- **VLAN1 raus:** Hybrid-VLAN1-Drops sw1 GE3/GE7/GE10 (+ GE1) beim Umstecken echtem VLAN zuordnen oder stilllegen. + +## Pre-Window-Checkliste (was Christoph parat haben muss) +- [ ] Wartungsfenster gewählt (Vollausfall Haus), iPhone-Hotspot am Notebook aktiv. +- [ ] Governance-Ausnahme #3 formal erteilt. +- [ ] MikroMCP neu gestartet (core schreibbar) **oder** REST-curl bereit. +- [ ] Port-Umzugsplan sw1→core final (Anker: **#4=ap1, #8=branch, #16=WAN**; Rest gegen Verkabelung prüfen). +- [ ] ap1-Voll-Backup (`/export`, `create_backup`) frisch gezogen. + +## Cutover-Schritte (Kurzform — Detail im Plan/Handoff-Prompt) +1. Staged core-Config bauen (`.rsc`, alles disabled) + Reservierungen maschinell von ap1 heben + (`/ip/dhcp-server/lease/export`, nur `dynamic=no`) + WG-Privkey einsetzen. +2. ap1 als Router stilllegen (DHCP/DNS/NAT/GW-IPs/WAN-DHCP-Client/`wg-hub` down; Config bleibt restorbar). +3. Kabel sw1→core umstecken (ap1 `ether2`→`ether1`/PoE, `poe-out=off`), sw1 stromlos. +4. core-L3 in einem Rutsch `enable` (GW-IPs, DHCP-Server, WAN-DHCP-Client, WG, DNS/NAT/Firewall). +5. **Abnahme:** je VLAN Lease/GW-Ping/Internet · DNS `*.bf.lan` · branch über core #8 · **WG fm+dw Handshake <2m** + + Ping in `10.101.0.0/24`/`10.95.10.0/24` · CF/WARP · Public-IP==bf4 (sonst CF nachziehen) · VLAN1 endgeräte-frei. +6. **Rollback jederzeit:** Kabel zurück auf sw1 + ap1 wieder `enable` → Netz wie zuvor. + +## Nach erfolgreichem Cutover +- Mgmt-Renumber (branch `.99.13`→`.99.12`, core `.99.11`-Reconcile), VLAN1-Temp-IPs (`.41.211`/`.41.213`) entfernen. +- Ist-Stand als *intended* → **Nautobot** (core `Planned`→`Active`, finale Ports, GraphQL-verifiziert). +- Doku: `teilprojekte.md` TP15/TP4, `CLAUDE.md`, `docs/ip-plan.md` (core produktiv, ap1 = AP). Commit + Push. +- **Danach TP3** — WLAN-Neuprovisionierung ohne CAPsMAN (ap1/ap2 reine APs, aus Nautobot generiert). Eigene Session. +- Optional gleich mitnehmen: `bf4`-DDNS-Auto-Updater auf core (TP10-Follow-up). + +## Artefakte +- `routeros/tp15-core-l3-staged.rsc` — die staged L3-Config (Vorlage = ap1-Live 2026-07-23). +- `docs/tp15-core-swap-session-handoff-prompt.md` — ausführlicher Original-Auftrag/Runbook. +- `nautobot/ingest-crs326-ports.py` — sw1-Belegung (`:190`) + core-Ziel-Layout (`:167`). +- `~/.secrets/credentials.env` — `CRS326_CORE_*` (REST/MCP), `CF_API_TOKEN` (CF-Writes). diff --git a/routeros/tp15-core-l3-staged.rsc b/routeros/tp15-core-l3-staged.rsc index 97916be..8c74b0c 100644 --- a/routeros/tp15-core-l3-staged.rsc +++ b/routeros/tp15-core-l3-staged.rsc @@ -155,9 +155,15 @@ public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw=" /ip/route add dst-address=10.101.0.0/24 gateway=wg-hub comment="TP10: FM spoke -> wg-hub" /ip/route add dst-address=10.95.10.0/24 gateway=wg-hub comment="TP10: DW spoke -> wg-hub" -# ⚠️ VOR dem Fenster klären: wie adressieren FM/DW den HUB (feste Public-IP vs. DDNS) und -# wer aktualisiert den Record, wenn core am WAN eine neue Liwest-IP zieht? Sonst bleibt -# die Standortkopplung nach dem Cutover tot, bis der Hub-Endpoint nachgezogen ist. +# ✅ GEKLÄRT (2026-07-23): FM+DW adressieren den Hub über `bf4.emsenhuber.net:51821` = +# Cloudflare-A-Record (proxied=false, TTL 120, aktuell 90.146.35.38). KEIN Updater auf +# ap1 (nur WANTEST/mac-clone-Scripts) -> nichts zu migrieren. bf4 folgt der Public-IP +# MANUELL (TP10-Follow-up, nie automatisiert). +# -> Cutover-Konsequenz: zieht core am WAN eine ANDERE Liwest-IP (Lease ist sticky, +# eher nicht), dann via CF_API_TOKEN nachziehen: (a) bf4-A-Record, (b) CF-Access- +# Policy `bf4-home-ip` (90.146.35.38/32). Solange die IP gleich bleibt = No-op. +# -> Chance: core ist NICHT device-mode=home -> scheduler+fetch gehen -> hier den +# bf4-DDNS-Auto-Updater bauen, den ap1 nie konnte (schliesst TP10-Follow-up). # ============================ [CUTOVER-ENABLE] (im Fenster, EIN Rutsch) ============ # NACH Kabel-Umstecken sw1->core und NACHDEM ap1 als Router still ist: