Files
bf-infra/docs/tp16.3-nautobot-mesh-only-runbook.md
Christoph Emsenhuber 914ff980b5 TP16.3 und TP14.4 als ausfuehrbare Runbooks
Beide TPs waren "Recherche durch / Umsetzung offen" bzw. "TODO" -- also
jeweils eine Zeile, aus der eine frische Session nicht losarbeiten kann.

TP16.3: der Schnitt (nautobot aus dem bf-nas-Ingress) ausformuliert, mit
Vorbedingungen, PUT-Ablauf und Rollback. Zwei Dinge stehen jetzt explizit
drin, die den TP sonst kippen: Mesh-Hostname-Routes sind Egress und
veroeffentlichen nichts -- wer das verwechselt, baut den Public-Strang ab;
und Nautobot ist nicht nur eine Web-UI, sondern die Deploy-Pipeline, also
gehoert ein Job-Lauf zur Abnahme und nicht nur ein Browser-Aufruf.

TP14.4: Ist-Stand nachgesehen -- in mcp/cloudflare/.env stehen weder
CF_ACCESS_CLIENT_ID noch _SECRET, es ist also nichts halb erledigt. Das
Secret gibt es nur im Moment der Rotation, das steht jetzt als Warnung
davor. Abnahme braucht beide Faelle: mit Headern antwortet, ohne 403 --
sonst haette ein bypass-Hostname wie vw als Erfolg durchgehen koennen.

Kein CF-Write, kein Token rotiert. Beides bleibt Papier.

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

122 lines
5.9 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.
# TP16.3 — Probe: `nautobot` aus dem CF-Ingress nehmen (mesh-only)
> **Stand 2026-08-19 · vorbereitet, nicht ausgeführt.** Die Recherche zu TP16.3 ist seit 2026-08-17
> durch; offen war nur die Umsetzung. Dieses Runbook macht daraus einen ausführbaren, in einer Minute
> zurücknehmbaren Schnitt.
---
## 1. Worum es geht (in drei Sätzen)
Der private Datenpfad läuft seit TP16.1 über **natives WireGuard auf dem Core** (`cf-mesh`), nicht über
Container — belegt, nicht vermutet: im TP5-Log-Lauf standen **137 Zeilen `in:cf-mesh`**. Für Dienste,
die **niemand ohne WARP im Browser** aufrufen muss, ist `cloudflared` damit überflüssiger Aufwand:
eine Ingress-Zeile, ein Connector-Paar, eine HA-Frage. Diese Probe nimmt **einen** solchen Dienst
heraus und schaut eine Woche zu.
### Warum ausgerechnet `nautobot`
| Kriterium | `nautobot` |
|---|---|
| Wer nutzt es | nur Christoph — kein Fremdgerät, kein Gast |
| Braucht es einen Client ohne Access-Login? | **nein** (das ist das TP16.2-Kriterium, an dem `vw` hängt) |
| Wie oft schon per Mesh angefasst | **62×** im TP5-Log — der Spitzenreiter |
| Was kostet ein Fehlschlag | nichts Produktives; im Zweifel greift man per IP zu |
---
## 2. 🔴 Die Verwechslungsfalle, die den ganzen TP kippen kann
**Mesh-Hostname-Routes sind Egress, nicht Publishing.** Cloudflare kennt seit 2026-07-02 auch
Hostname-Routes auf dem Mesh — die klingen so, als könnten sie den Ingress ersetzen. Sie können es
nicht: sie leiten *ausgehenden* Verkehr zu diesem Hostname über den Node und egressen mit dessen
öffentlicher IP. **Sie veröffentlichen nichts.**
Wer das verwechselt, baut den öffentlichen Strang ab und wundert sich, warum von außen nichts mehr geht.
→ **Diese Probe ersetzt nichts. Sie entfernt einen Dienst, der öffentlich gar nicht gebraucht wird.**
---
## 3. Vorbedingung — VOR dem Schnitt prüfen (read-only)
Alle drei Punkte müssen erfüllt sein, sonst wird nicht geschnitten:
1. **Die Mesh-Route steht.** Auf dem Core: die vnet-Route `10.40.0.0/16` zeigt auf `bf-core-mesh`
(TP16.1 §4.4, „Weg A"). Ohne sie ist Mesh-Zugriff auf `10.40.20.30` gar nicht möglich.
2. **Der Dienst antwortet über die private IP, mit aktivem WARP** — von einem Client, der *nicht* im
BF-LAN steht (das ist der einzige Test, der etwas beweist; im LAN geht es ohnehin):
```
http://10.40.20.30:8080
```
3. ⚠️ **ICMP nicht als Beweis nehmen, aber auch nicht als Gegenbeweis.** Der Mesh kann ICMP (das war
der Gewinn von TP16.1). Wenn Ping scheitert, TCP aber geht, ist zuerst zu prüfen, ob lokal noch ein
WARP-Client läuft — s. Memory `ref_warp_local_icmp_trap`. Umgekehrt ist ein erfolgreicher Ping kein
Beleg, dass der HTTP-Dienst erreichbar ist.
---
## 4. Der Schnitt
**Was:** die `nautobot`-Zeile aus der Ingress-Config des Tunnels **`bf-nas`** entfernen.
Die DNS-CNAME-Zeile bleibt zunächst stehen (Rollback bleibt so eine reine Ingress-Operation).
**Womit:** die Cloudflare-API mit `CF_API_TOKEN`.
> 🔴 **Nicht über den Cloudflare-MCP.** Der ist **strikt read-only** — Writes gehen ausschließlich über
> die API mit dem Token (Memory `ref_cf_mcp_readonly_token_writes`). Das Token ist **account-owned**,
> nutzt also einen anderen verify-Endpoint als ein User-Token, und **läuft am 2027-01-09 ab**.
**Wo die Werte stehen:** `mcp/cloudflare/.env` (chmod 600, gitignored) —
`CF_API_TOKEN`, `CF_ACCOUNT_ID`, `CF_BF_TUNNEL_ID`.
**Ablauf:**
1. **Ist-Config sichern** (das ist der Rollback):
`GET /accounts/{account_id}/cfd_tunnel/{tunnel_id}/configurations` → JSON wegschreiben, mit Datum.
2. Aus dem `ingress`-Array die `nautobot`-Zeile entfernen. ⚠️ Die abschließende Catch-all-Regel
(`service: http_status:404` ohne `hostname`) **muss die letzte bleiben** — sonst greift der Ingress
für alle übrigen Hostnames nicht mehr.
3. **Zurückschreiben:** `PUT` derselben Route mit dem gekürzten Array.
4. **Gegenprobe am Gerät, nicht am Statuscode:** ein `GET` der Config liest zurück, was wirklich steht.
*(Dieselbe Regel wie in TP22/TP23: ein „success" der API ist kein Wirksamkeitsnachweis.)*
---
## 5. Abnahme
| Prüfung | Erwartung |
|---|---|
| Öffentlicher FQDN `nautobot.…` ohne WARP | **nicht mehr erreichbar** (das ist der Zweck) |
| `http://10.40.20.30:8080` mit WARP, von außerhalb des LAN | erreichbar |
| Die übrigen Hostnames auf `bf-nas` (gitea, grafana, pve-mcp, vw, ds-bf) | **unverändert erreichbar** |
| Golden-Config-Deploys (Netmiko aus Nautobot) | laufen weiter |
🔴 **Der letzte Punkt ist der, den man übersieht:** Nautobot ist nicht nur eine Web-UI, sondern die
Deploy-Pipeline. Der Netmiko-Deploy kommt von **`10.40.20.31`** (`nautobot-worker`), nicht von `.20.30`
— das war einer der vier TP5-Funde. Der Schnitt betrifft nur den *eingehenden* öffentlichen Weg, aber
nach dem Schnitt gehört ein Job-Lauf zur Abnahme, nicht nur ein Browser-Aufruf.
---
## 6. Betriebsfenster und Rollback
- **Eine Woche fahren**, dann entscheiden: bleibt es so, oder kommt es zurück.
- **Rollback = die gesicherte Ingress-Config aus Schritt 1 zurückschreiben.** Eine Zeile, eine Minute.
- Danach ist zu entscheiden, ob weitere Dienste der rechten Spalte folgen (`pve`, `portainer`,
`grafana`, `pve-mcp`, `ha-mcp`, `gitea-mcp`, `ds-bf`, `ccu`, `iobroker`, `z2m25`).
### Was in dieser Probe ausdrücklich NICHT entschieden wird
- **`vw`, `hass`, `n8n` bleiben öffentlich** — harte Kriterien: Bitwarden-Clients (TP16.2-Constraint),
die HA-Companion-App (das 400-Muster), eingehende Webhooks von Dritten.
- **`gitea` ist offen** und wird hier nicht mitentschieden: Git-Clients/CI von außen können keinen
interaktiven Access-Login. Braucht eine eigene Prüfung, ob es solche Zugriffe real gibt.
---
## 7. Nebeneffekt, der den Fall stärkt
Die **TP16-HA-Degradierung** (`bf-nas` und `bf-pve` haben je nur **einen** Connector, Befund 2026-08-16)
verliert an Gewicht, je weniger Dienste an cloudflared hängen. Das ersetzt die Reparatur nicht —
aber es verkleinert, was der SPOF trifft.