@@ -344,12 +344,14 @@ dann Tunnel** (umgekehrt gäbe es 530er).
- 📌 **Und die Erwartung wird damit ehrlicher: ** Nautobot war nie ohne Access-Login öffentlich
erreichbar. Der Schnitt schließt **keine offene Tür ** , er entfernt eine **überflüssige zweite ** .
- ⚠️ **Vorprüfung, die vor jedem weiteren Schnitt zu wiederholen ist: ** hängt Werkzeug am
öffentlichen Namen? Hier nein — `gc-configplan.py` spricht `http://10.40.20.30 :8080/api` , und
öffentlichen Namen? Hier nein — `gc-configplan.py` spricht `http://10.40.20.154 :8080/api`
(TP45 Schicht A 2026-09-21; zum Messzeitpunkt war es `.20.30` ), und
kein Repo-Skript nutzt den FQDN.
- ✅ **Betriebsfenster ausgewertet 2026-08-30 (Tag 6/7): `nautobot` bleibt mesh-only. ** Kein Rückweg
gebraucht, kein Ausfall. `nautobot.emsenhuber.net` hat inzwischen auch **keinen DNS-Record ** mehr
(mit den CF-Leichen am 08-29 gelöscht, Commit `39ba5da` ) — der Dienst ist vollständig aus dem
öffentlichen Strang heraus und ausschließlich über `10.40.20.30 :8080` bzw. intern über Caddy erreichbar.
öffentlichen Strang heraus und ausschließlich über `10.40.20.154 :8080` (TP45 Schicht A 2026-09-21)
bzw. intern über Caddy erreichbar.
##### ✅ §2/§3 durchgezogen — Vor-Ort-Session 2026-08-31
@@ -632,12 +634,13 @@ und Letzteres verlangt die **physische Bestätigung am Gerät** — ap1 Technik
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 über `10.40.20.30 :8080` **mit WARP von außerhalb ** ),
ausformuliert: Vorbedingungen (Mesh-Route, Zugriff über `10.40.20.154 :8080` **mit WARP von außerhalb ** ),
Ingress-`PUT` über `CF_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.3 1` (`nautobot-worker` ), nicht von `.20.30` .
— der Netmiko-Deploy kommt von `10.40.20.155 ` (`nautobot-worker` ), nicht von `.154` (Werte nach
TP45 Schicht A 2026-09-21; zum Messzeitpunkt `.31` / `.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.
- **Abh.:** TP16.1 ✅ (Mesh live), TP16 (Public-Strang + dessen HA-Degradierung), **TP16.2 ** (der `vw` -Constraint
@@ -2732,17 +2735,67 @@ unter `*1A TP5-WOULD-DROP` / `*2D TP5: deny-by-default` (621 Pakete).
#### Schichten (Reihenfolge = Abhängigkeit)
| Schicht | Inhalt | Stand |
|---|---|---|
| **A** | VLAN20 virtuelle Gäste ins Schema — **Nautobot zuerst** (` .30– .34` → ` .154– .156`/` .158`), dann AGH | offen |
| **A** | VLAN20 virtuelle Gäste ins Schema — **Nautobot zuerst** (` .30– .34` → ` .154– .156`/` .158`), dann AGH | 🔄 **Nautobot ✅ 2026-09-21** (s. u.) · AGH + übrige Gäste offen |
| **B** | VLAN30 — **nur die Pool-Grenze**, Geräte bleiben (Christoph 2026-09-21) | offen |
| **C** | DNS/FQDN: ` ds-bf` über Caddy, ` coolify.bf` neu, ` .bf` vollständig auf den Core, AGH nur Filtering, TP34 | offen |
| **D** | Tunnel-Inventar + GC + generische Namen, TP30 #10, Leak-Ursachen | offen |
| **E** | nas/pve/macmini mit Doppeladresse — **eigene Session**, pve2 nur reservieren | offen |
| **F** | CF-/Tunnel-SSoT + Recovery → **TP46** | offen |
🔴 **Warum Nautobot zuerst.** AGH will ` .30`/` .31` — dort sitzt heute Nautobot (` .30`/` .31`/` .32`/` .34`).
**27 Skript-/Config-Dateien** referenzieren ` 10.40.20.30` (alle ` gc-*.py`, 14× ` ingest-*.py`,
` tp44-*`, ` routeros/fetch-core-cutover-config.py`). Und: **der GC-Pfad läuft über Nautobot** — AGH
zuerst zu ziehen hieße, die Werkzeugkette gegen sich selbst laufen zu lassen.
🔴 **Warum Nautobot zuerst.** AGH will ` .30`/` .31` — dort saß Nautobot (` .30`/` .31`/` .32`/` .34`).
**28 Skript-/Config-Dateien** referenziert en ` 10.40.20.30` (alle ` gc-*.py`, 14× ` ingest-*.py`,
` tp44-*`, ` routeros/fetch-core-cutover-config.py`) — alle am 2026-09-21 mitgezogen. Und: **der
GC-Pfad läuft über Nautobot** — AGH zuerst zu ziehen hieße, die Werkzeugkette gegen sich selbst
laufen zu lassen.
##### ✅ Nautobot-Umzug durch (2026-09-21) — ` .30/.31/.32/.34` → ` .154/.155/.156/.158`
` .157` ist gitea, deshalb nimmt redis ` .158`. Reihenfolge und Belege:
1. **Core-Adressliste ` nautobot` additiv erweitert** (` .154/.155/.156` **dazu**, Alt-Einträge bleiben).
Das ist die wirksame Ebene: der Mgmt-Zugang des Cores läuft über ` src-address-list=nautobot`
(Regel ` *28`, 113 Pakete), **nicht** über den Literal ` *24`.
2. **Nautobot-Datenmigration** über das neue [` nautobot/tp45-ip-move.py`](../nautobot/tp45-ip-move.py).
Nautobot **verbietet** das Ändern einer IP nach dem Anlegen (` Host address cannot be changed once
created`) → Umzug ist Dreischritt *anlegen → ` primary_ip4` umhängen → Altobjekt löschen*.
3. **Stack-YML + Redeploy** (` PUT /api/stacks/203?endpointId=14`), Container auf den neuen IPs,
` http://10.40.20.154:8080/health/` = **200**, alle vier Alt-IPs **000** (keine Doppeladresse —
so entschieden).
4. **Caddy** ` nautobot.bf` → ` .154`, deployt und **verifiziert**.
5. **Core-Literal ` *24` auf ` .154`** über GC (` gc-manual-plan.py --deploy`, Plan ` 51a90e25`,
Completed) mit Wirksamkeitsprüfung am Gerät.
6. **` python3 nautobot/gc-configplan.py --refresh-compliance` → 140/140, 0 Drifts.**
##### 🔴 Zwei Werkzeug-Fehler, die genau dabei Zeit gekostet haben (beide neu)
**(a) ` pct push` meldet Exit 0, auch wenn es die Quelle nicht lesen kann.**
Gemessen: ` pct push 130 <nicht-vorhandene-datei> /etc/caddy/Caddyfile` →
` failed to open … for reading`, **` rc=0`**.
Folge in ` caddy/deploy.sh`: die Push-Zeile war als ` push || push`-Fallback gebaut (wegen einer
` $$`-Escaping-Verwechslung); der Fallback griff **nie**, weil der kaputte Push „Erfolg" meldete. Die
anschließende ` caddy validate` prüfte damit die **alte** Datei und war grün — **grüne Abnahme bei
unverändertem Zustand**. Symptom war ` nautobot.bf` **502** bei gleichzeitig gesundem Backend.
**Fix:** ` push_verified()` in ` caddy/deploy.sh` — Push **und** md5-Vergleich in *einem* Remote-Aufruf,
harter Abbruch bei Abweichung. Merkregel: **ein Push-Werkzeug, dessen Exit-Code nicht stimmt, wird
geprüft, nicht geglaubt** — dieselbe Klasse wie ` nc -z` (09-01) und das ` sed`-Muster (08-31).
**(b) 🔴 Die Firewall-Adressliste ` nautobot` wird von Golden Config NIRGENDS gerendert.**
Der Core-Zugang für Nautobot hängt an ` src-address-list=nautobot` — die Liste stammt aber aus dem
**von Hand gelaufenen** ` routeros/tp5-etappe2-whitelists.rsc` und existiert im Template nicht
(` grep` auf ` address-list` findet nur Kommentare). **Ein Golden-Config-Recovery von null erzeugt
damit einen Core, in den Nautobot nicht mehr per SSH kommt** — die Deploy-Pipeline wäre tot und
würde sich selbst nicht reparieren können. Gleiche Klasse wie die fehlenden DHCP-Reservierungen.
Der Renderer gehört in dieselbe Baustelle wie Punkt „DHCP-Reservierungen" oben.
**(c) Nebenfund — Regel ` *24`/` *28` sind Dubletten.** Dieselbe Erlaubnis existiert zweimal:
` src-address=10.40.20.30` (Literal, **0 Pakete** = tot) und ` src-address-list=nautobot`. Nur die
Liste ist wartbar. Der Literal wurde auf ` .154` gezogen (Soll-Konsistenz), die **Zusammenlegung**
bleibt als Aufräumposten offen.
**(d) Nebenfund — ` gc-manual-plan.py` Diagnosepfad ist tot.** Die Log-Abfrage
` /api/extras/job-log-entries/?job_result=…` liefert **HTTP 404** (Nautobot 3.x hat den Endpunkt
verschoben). Bei einem **erfolgreichen** Deploy ist das kosmetisch, bei einem **gescheiterten**
nimmt es die Fehlermeldung weg — genau dann, wenn man sie braucht.
#### Soll-Oktette (Nachschlagetabelle, s. TP32 für die Herleitung)
| Oktett | Rolle | Soll |