Files
bf-infra/docs/handoff-20260831-tp16.3-vorort-session.md
Christoph Emsenhuber d5b3ce37ff TP37 angelegt: Out-of-Band-Management, ein untagged-VLAN99-Port je Switch
Auslöser (User 2026-08-31): beim Core-Neustart war crs326-branch nicht mehr
erreichbar, weil sein Management ausschliesslich ueber den Core laeuft.

Live nachgemessen: auf dem Branch ist vlan99 tagged=ether1,ether24,bridge mit
untagged="" - es gibt also keinen Weg zu 10.40.99.2, der nicht durch den Core
fuehrt. Wer den Core zerkonfiguriert, verliert den Branch gleich mit und damit
die Moeglichkeit, es vom Branch aus zu reparieren.

Zweiter, unangenehmerer Befund: crs326-branch hat GAR KEINE input-Regeln (Kette
leer). Sein gesamter Schutz besteht heute darin, dass VLAN99 nur ueber den Core
erreichbar ist und dessen forward-Kette deny-by-default faehrt - die
Erreichbarkeitsbeschraenkung IST die Zugangskontrolle. Damit ist ein untagged
MGMT-Port ein physischer Generalschluessel, und das TP traegt eine explizite
Auflage: Port disabled im Normalbetrieb ODER input-Regeln auf beiden Switches
ODER physische Sicherung. Empfehlung im Abschnitt: die input-Regeln, weil sie
eine Luecke schliessen, die unabhaengig von diesem TP besteht.

Kandidat ether23 - auf core und branch beide running=false, also frei, und auf
beiden Geraeten dieselbe Nummer.

Abnahme im Abschnitt so formuliert, dass sie den Zweck prueft: Laptop an
branch ether23, Core-Trunk gezogen, 10.40.99.2 muss antworten. Alles andere
misst nur den Normalfall.

Quick-Index (nach TP36 einsortiert), TP-Abschnitt und Ist-Stand mitgezogen;
Handover 20260831 auf den angelegten TP umgestellt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 15:05:31 +02:00

127 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Handover — TP16.3 §2/§3: Container-Bootstrap auf ap1 / ap2 / ap3
> **Erstellt 2026-08-31.** Zielsession: **§2 + §3** des Runbooks
> [`tp16.3-bf-public-ap-connector-runbook.md`](tp16.3-bf-public-ap-connector-runbook.md) — also
> `container.npk`, `device-mode`, Container. **Vor Ort**, weil jeder AP eine physische Bestätigung braucht.
> **Nicht** Teil dieser Session: der CNAME-Flip (§5) und der Abbau (§6).
---
## 1. Was vor dir schon erledigt ist — nicht nochmal machen
| Punkt | Stand | Nachweis |
|---|---|---|
| **§1 Blocker A** — Redirect-Schleife | ✅ 08-31 | `bf-public`-Ingress → `https://10.40.20.40:443`, `originServerName` je Regel, zurückgelesen |
| **§1 Blocker B** — Firewall `vlan99→vlan20:443` | ✅ 08-31 | via **Nautobot GC** (Plan `Completed`), Position vor `TP5: log-only` geprüft, funktional gegen Caddy nachgewiesen |
| **§1 Blocker C** — `ROUTER_AP3_PASS` | ✅ 08-31 | in `~/.secrets/credentials.env`, REST-Auth ap3 = **200** |
| Rollback-Snapshots | ✅ 08-30 | `docs/cf-backup/*-20260830-vor-tp16.3-schnitt.json` |
| ROS-Upgrade auf **7.24.1** | ✅ 08-31 (User) | alle fünf Geräte, RouterBOOT mitgezogen |
**⇒ Die Session startet bei §2.** Wer §1 nochmal anfasst, arbeitet doppelt.
---
## 2. Die eine Änderung gegenüber dem Runbook-Stand vom 08-30
🎉 **Aus zwei `container.npk` ist eine geworden.** Christoph hat am 08-31 alle fünf MikroTik auf
**7.24.1** gehoben. Damit gilt:
```
container-7.24.1-arm64.npk → ap1, ap2 UND ap3
```
Die frühere Zwei-Dateien-Regel war **rein versionsbedingt**, nicht modellbedingt — `cAP ax` und
`hAP ax²` teilen sich die `arm64`-Pakete. Das Runbook ist entsprechend umgeschrieben (§0, §2.1, §3.1,
Falle 1).
⚠️ **Die Regel dahinter bleibt:** `container.npk` muss **exakt** zur ROS-Version passen. Vor dem Upload
`/system resource print` lesen. Falsche Datei ⇒ Paket ist nach dem Reboot **inaktiv, ohne Fehlermeldung**.
---
## 3. Ablauf in einem Satz
Je AP, **einzeln und vollständig, Reihenfolge ap3 → ap2 → ap1**:
`.npk` hoch → Reboot (SSH, **nicht** MikroMCP) → `/system package print` prüfen →
`device-mode update container=yes` → **physisch bestätigen** → `veth` + `masquerade` →
`.tar` hoch → `/container add file=` → starten → `.tar` löschen → Log prüfen.
**Details, Befehle und Abnahmekriterien: Runbook §2 und §3.** Hier nur die Punkte, die man
erfahrungsgemäß falsch macht:
- 🔴 **Reboot geht NICHT über MikroMCP** (ROS kennt den `delay`-Parameter nicht, `run_command` ist für
`/system reboot*` gesperrt) → `SSHPASS="$PW" sshpass -e ssh admin@<ip> "/system reboot"`.
**Niemals `sshpass -p`** — das schreibt das Passwort in `ps`.
- 🔴 **`~/.secrets/credentials.env` in zsh sourcen schlägt still fehl** (rohe WireGuard-Zeilen ab ~Z. 69).
Variablen bleiben **leer**, und der Fehler sieht aus wie ein ungültiger Token. **Immer `bash -c`.**
- 🔴 **Kein PoE an den CRS326** (beide haben gar kein PoE-Menü) ⇒ kein Remote-Power-Cycle. Die
Bestätigung ist wirklich physisch: **Stecker ziehen/stecken** (Weg A, eindeutig) oder Reset-Knopf am
*laufenden* Gerät kurz drücken (Weg B). Weg B **nie während des Bootens** — das wäre ein Werksreset.
- 🔴 **Ein Container pro AP.** Nach dem Import bleiben ~39 MB. Kein Caddy, kein AGH dazu.
- ⚠️ **Jeder AP rebootet zweimal** → WLAN dieses APs ist je ~1–2 min weg. Die CAPs holen ihre Config
per L2-Discovery vom Core. **Nicht ungeduldig nachprovisionieren.**
- ⚠️ **WLAN-Abnahme ist eine frische DHCP-Lease je SSID, nicht die Registration-Table.**
**Erwartetes Ergebnis am Ende:** `bf-public` meldet `healthy` mit Connectoren (Richtung 12 = 3 APs × 4
CF-Edge). 🔴 **`healthy` heißt nur „Connector redet mit Cloudflare", nicht „Origin antwortet"** — der
Beweis für die Strecke bis Caddy ist §5.1, und der gehört in die **Folge**session.
---
## 4. Was du unterwegs sehen wirst und **nicht** als Fehler behandeln darfst
**`/tool fetch` von einem AP auf `https://10.40.20.40` schlägt mit einem TLS-Alert fehl.**
Das ist **korrekt und erwartet**: Caddy weist Handshakes ohne passenden SNI ab (gemessen: ohne SNI
`000`, mit korrektem SNI `200`). Der Alert **beweist sogar**, dass das Paket ankommt — ein TLS-Alert
kann nur vom Server kommen, die Firewall-Freigabe trägt also. cloudflared schickt den richtigen SNI
über `originServerName`. **Nicht „reparieren".**
---
## 5. Offene Punkte, die NICHT in diese Session gehören
1. 🔴 **Compliance-Drift `crs326-core` / `wifi-security` (134/135).** `sec-main` hat am Gerät
`ft-over-ds=no`, Soll `yes` (`ft=yes` ist korrekt). **Kam mit dem 7.24.1-Upgrade.** Braucht eine
Entscheidung — Gerät korrigieren *oder* neuen Wert zum Soll erklären — plus Re-Provisionierung der
CAPs. ⚠️ **Kein Re-Baseline ohne Entscheid**, das macht die Drift-Erkennung wertlos.
2. 🆕 **[TP37](teilprojekte.md#tp37) — OOB-Management, angelegt 2026-08-31.** Je ein untagged-VLAN99-Port
auf beiden Switches (Kandidat `ether23`, auf core **und** branch frei). Auslöser: beim Core-Neustart
war `crs326-branch` nicht erreichbar, weil sein Mgmt **ausschließlich** über den Core läuft.
🔴 Nebenbefund mit eigenem Gewicht: **der Branch hat gar keine `input`-Firewallregeln** — sein Schutz
ist heute allein die Erreichbarkeit über den gehärteten Core.
💡 **Berührt diese Session, ist aber keine Voraussetzung:** hier rebooten dreimal Geräte, deren Mgmt
am Core hängt. Wer vor Ort ist, kann `ether23` schon mal beschriften — gebaut wird TP37 separat.
3. 🟡 **`mcp/mikromcp/config/routers.yaml` hält `rosVersion: "7.24"`** für alle fünf — jetzt `7.24.1`.
⚠️ **Die Datei liegt auf `main`, nicht auf diesem Branch** (der Worktree hat eine ältere Kopie
**ohne** ap3). Der Fix gehört auf `main`, nicht hierher — sonst gibt es einen Konflikt.
4. **CNAME-Flip (§5) und Abbau (§6)** — eigene Session, §6 frühestens 7 Tage nach dem Flip.
---
## 6. Zugänge und Werkzeuge
| Was | Wie |
|---|---|
| APs | MikroMCP `ap1`/`ap2`/`ap3` (Reads), SSH `admin@10.40.99.11/.12/.13`, Creds `ROUTER_AP{1,2,3}_PASS` in `~/.secrets` |
| Reboot | `bash -c 'set -a; . ~/.secrets/credentials.env; set +a; SSHPASS="$ROUTER_AP3_PASS" sshpass -e ssh admin@10.40.99.13 "/system reboot"'` |
| Config-Änderungen an MikroTik | **ausschließlich Nautobot GC** (`nautobot/gc-manual-plan.py`), Token aus `docs/nas-vlan20/stacks/210-nautobot.yml` (gitignored, **nur im Haupt-Checkout**) |
| Cloudflare | `CF_API_TOKEN` / `CF_ACCOUNT_ID` in `~/.secrets`, Zone `1b5bc02fdf61b6b989afde543f3f4134` |
| Caddy | `caddy-bf1`, LXC 130 auf pve, `10.40.20.40`; Logs `ssh root@10.40.20.100 'pct exec 130 -- journalctl -u caddy -n 50'` |
⚠️ **`device-mode`- und Container-Schritte sind KEINE Golden-Config-Sache** — sie sind Bootstrapping am
Gerät (wie die genehmigte Ausnahme #2 beim CRS326-Bring-up). Die GC-Pflicht gilt für
`/ip firewall`, `/interface` & Co. **Wenn die Session eine Firewall- oder Interface-Zeile braucht:
über `gc-manual-plan.py`, nicht per Direkt-Write.**
---
## 7. Abnahme dieser Session
- [ ] `/system package print` zeigt auf **allen drei** APs `container` in **7.24.1**, nicht disabled
- [ ] `/system device-mode print` zeigt `container: yes` auf allen dreien
- [ ] `/container print` zeigt je AP **einen** Container `running`
- [ ] `.tar` je AP gelöscht (Flash zurück)
- [ ] `bf-public` meldet `healthy` mit Connectoren > 0
- [ ] WLAN je AP zurück — **frische DHCP-Lease pro SSID**, nicht Registration-Table
- [ ] Compliance nicht schlechter als **134/135** (die `wifi-security`-Drift aus Punkt 5.1 bleibt bestehen)