SoT: CF und Caddy werden NICHT synchron gehalten - die Doppelpflege faellt mit Schritt 5/6 weg. Heute stehen 19 Ingress-Regeln und 16 Caddy-Sites nebeneinander und stimmen fachlich ueberein; im Zielbild haelt CF nur noch eine Catch-all auf 10.40.20.40. Danach: Caddyfile = Name->Origin, CF = welcher Name ist oeffentlich (4), AGH = Name->IP intern. Nebeneffekt: die 12 internen Namen brauchen keinen oeffentlichen DNS mehr. caddy/cf-sync.py (read-only, Exit 1 bei Drift) findet im ersten Lauf sieben Abweichungen, alle auf CF-Seite: grafana noch im Ingress, nautobot und gateway-dw als CNAME ohne Ingress (Quelle der 302), drei *.bf-CNAMEs auf den zerstoerten NPM, dazu die Wildcard-Access-App, die alles maskiert. Uebergabe korrigiert nach User-Einwand und Gegenmessung: - Rewrites sind veraltet, nicht wertlos - Hosts leben auf VLAN20 weiter, also Ziele umbiegen statt Namen loeschen. - Die Redundanz existiert doch, reziprok ueber die Standorte: FM antwortet auf 10.101.0.16/.17 (DS415+) - und beide liefern fuer nas.bf die tote VLAN1-Adresse. Ein Rewrite-Satz nur im neuen BF-Paar erzeugt standortabhaengig verschiedene Antworten. - Vorratsregel auf .16 wird gestrichen statt erweitert (User-Entscheid). - Cave: emsenhuber.net ist die Domain, bf.lan nur der DHCP-Suffix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
13 KiB
Übergabe — nächste Session: AdGuard als Resolver + Split-Horizon (TP23 Stufe 2 ∥ TP31 Schritt 4)
Einstieg: diese Datei, dann
teilprojekte.md→ TP31 und TP32. Zustand am Netz: stabil. Caddy läuft produktiv und ist abgenommen, keine Config-Transaktion offen.🔄 Zweite Fassung (2026-08-25, spät). Die erste entstand vor der Caddy-Abnahme und enthielt drei Annahmen, die live nicht halten — sie stehen unten unter „Was den Plan ändert". Wer die alte Fassung im Kopf hat: Punkt 2 des Auftrags („Konfiguration übernehmen") ist so falsch.
Warum eine eigene Session
Der Schritt verschiebt die DNS-Auflösung des ganzen Standorts vom Core in einen Container. Heute
liefert der DHCP in allen sieben VLANs dns-server = <VLAN>.1 (live geprüft) — AdGuard bekommt
niemand. Ein Fehler trifft sofort jedes Gerät und ist schlecht zu diagnostizieren, wenn die
Auflösung selbst das Kaputte ist. Nicht ans Ende einer langen Sitzung legen (Lehre aus TP28).
Ausgangslage (Stand 2026-08-25 23:30, live geprüft)
- ✅ Caddy produktiv und abgenommen: LXC 130
caddy-bf1,10.40.20.40,onboot=1,startup order=10, im Backup-Job. Caddy v2.11.4, 16 Sites. Abnahme über den Host-Header von einem zweiten Host: 11× 200,nautobot302, 0,02–0,11 s. Config im Repocaddy/Caddyfile, Ausrollen mitcaddy/deploy.sh.- ℹ️
pve-mcp400 /ha-mcp403 /gitea-mcp404 sind keine Proxy-Fehler — dieselben Codes kommen direkt vom Origin. Nicht als Baustelle behandeln. - 🧹 Der Zertifikatsspeicher hält 17 Zertifikate bei 16 Sites:
grafanaist verwaist (harmlos).
- ℹ️
- 🟡
hassliefert weiter 400 — ungelöst, gehört VOR die CNAME-Umstellung (nicht vor diesen Schritt).http:-Block steht in/homeassistant/configuration.yaml(use_x_forwarded_for: true,trusted_proxies: 10.40.20.0/24+.10+.167), Sicherungconfiguration.yaml.bak-20260825-tp31. Die Änderung ist seit 23:18 drin, HA läuft aber noch mit dem Stand von 22:40 — der Neustart fehlt. ⚠️ Sowohl der Schreibzugriff als auch der Restart wurden zuletzt vom Auto-Mode-Klassifikator blockiert; entweder freigeben oder selbst ausführen:ha core restartbzw.homeassistant.restart, danachcurl -o /dev/null -w "%{http_code}\n" --resolve hass.emsenhuber.net:443:10.40.20.40 https://hass.emsenhuber.net/- 🔎 Der Logtext ist der Befund, nicht der Statuscode:
Received X-Forwarded-For header from an untrusted proxy 10.40.20.40≠ „not set-up for reverse proxies" ⇒ die Option greift, die Liste nicht.
- 🔎 Der Logtext ist der Befund, nicht der Statuscode:
- ✅ Aufgeräumt (TP31 Schritt 1): LXC
120/121/128/129/130(alt)/131und104zerstört, 72/72 PBS-Snapshots weg. Die 14 Snapshots vonct/104stehen bewusst (einzige Grafana-Kopie). - ✅ Startreihenfolge auf pve repariert (TP32): HA startet nach MariaDB, Docker, MQTT, z2m25.
🔴 Was den Plan ändert — drei Funde vom 2026-08-25 (spät), alle live erhoben
1. Die Rewrites sind veraltet, nicht wertlos — Ziele umbiegen statt löschen
🔴 Korrektur (User, 2026-08-26): „manche hosts leben auf vlan 20 weiter" — die erste Fassung hat die
10.40.41.x-Einträge pauschal als tot bezeichnet. Falsch ist das Ziel, nicht der Name:nas,macmini,appletv,tv,mfcgibt es weiter, sie sind nur umgezogen (NAS10.40.20.10, macmini10.40.20.167, Brother MFC10.40.10.6— der steht auf VLAN10). ⇒ Jeder Name einzeln bewerten: umbiegen, wenn der Host lebt; streichen, wenn nicht.adguard_bf1(10.40.20.16, Docker in LXC 400) läuft seit 7 Tagen und hält 24 Rewrites — davon ist der überwiegende Teil tot:
| Klasse | Anzahl | Beispiel | Was damit zu tun ist |
|---|---|---|---|
| Ziel im toten VLAN1, Host lebt | 8 | nas.bf…→10.40.41.10, mfc.bf…→10.40.41.4, macmini.bf…→10.40.41.167 |
umbiegen auf die VLAN20/VLAN10-Adresse |
Ziel nginx-bf.emsenhuber.net |
9 | portainer, z2m25, nodered, grafana, vw, speedtest, … |
Ziel ersetzen durch 10.40.20.40 — Caddy tritt an die Stelle des NPM (LXC 128 ist zerstört) |
| FritzBox-Reste | 2 | *.myfritz.net → 100.72.62.31 / 10.40.41.254 |
streichen (FB6660 seit 2026-07-01 ausgebaut) |
| FM-Standort | 3 | nas.fm…→10.101.0.10 |
dort gepflegt, s. Fund 2 |
⇒ Übernehmen: upstream_dns, bootstrap_dns, Filterlisten.
Die 16 Service-Rewrites entstehen neu aus caddy/Caddyfile (jeder Site-Name → 10.40.20.40).
Die Host-Rewrites oben werden einzeln entschieden — nicht blind mitschleppen, aber auch nicht
pauschal wegwerfen.
Was dort richtig steht und mitmuss:
upstream_dns:
- https://px35ynlol3.cloudflare-gateway.com/dns-query
- '[/bf.lan/]10.40.20.1'
- '[/40.10.in-addr.arpa/]10.40.20.1'
⚠️ Cave (User, 2026-08-26):
emsenhuber.netist unsere Domain, nichtbf.lan.bf.lanist nur der DHCP-interne Suffix, den der Core heute vergibt (domain=bf.lan+add-dns-entries-suffix=lan) — er hat keine Namensautorität. Offene Entscheidung für diese Session: so lassen oder aufbf.emsenhuber.netheben (dann zieht der conditional upstream mit und die Lease-Namen liegen unter der echten Domain). Nicht nebenbei umstellen — es betrifft jeden Lease-Namen.
🔑 Der conditional upstream ist nicht optional: der Core vergibt domain=bf.lan und legt aus jeder Lease
einen *.lan-Eintrag an (add-dns-entries-suffix=lan). Ohne diesen conditional upstream sterben
alle Lease-Namen. Ebenso bleibt mDNS Sache des Core (mdns-repeat-ifaces = vlan10/20/30/40/90).
2. Die Redundanz gibt es — wechselseitig standortübergreifend (und sie ist überall stale)
🔴 Korrektur (User, 2026-08-26): „die redundanz gab es schon! und zwar wechselseitig standortübergreifend. bei fm klarerweise auf ds415+ gehostet."
Live gegengeprüft (2026-08-26, nslookup über den WG-Tunnel):
| Instanz | wo | antwortet auf 53 | nas.bf.emsenhuber.net → |
|---|---|---|---|
adguard_bf1 |
BF, Docker in LXC 400 (10.40.20.16) |
✅ | BF-Rewrite, VLAN1-Ziel |
adguard_fm2 |
BF (10.40.20.17), für FM |
✅ | — |
| FM-Resolver 1 | FM, DS415+ (10.101.0.16) |
✅ | 10.40.41.10 |
| FM-Resolver 2 | FM, DS415+ (10.101.0.17) |
✅ | 10.40.41.10 |
⇒ Das Muster ist reziprok: jeder Standort hostet auch eine Instanz des anderen, spiegelbildlich
auf .16/.17. (10.101.0.10 — die FM-NAS selbst — antwortet nicht auf 53.)
🔑 Die Konsequenz ist größer als „ein Paar bauen": die BF-Namen liegen in vier Resolvern an zwei Standorten, und beide FM-Instanzen antworten heute mit der toten VLAN1-Adresse. Ein Rewrite-Satz, den nur das neue BF-Paar kennt, erzeugt standortabhängig verschiedene Antworten für denselben Namen. Zum Auftrag gehört deshalb eine Festlegung:
- entweder den Rewrite-Satz als eine Quelle definieren und auf alle Instanzen ausrollen,
- oder — wartungsärmer und konsistent mit der SoT-Antwort für CF/Caddy (s. TP31) — festlegen, dass FM die BF-Namen nicht mehr selbst beantwortet, sondern per conditional upstream nach BF fragt.
- ⚠️ Nicht in dieser Session mitfixen, aber notieren: FM zeigt auf tote Ziele. Das braucht ein eigenes Fenster und den DS415+-Zugang.
3. Die Firewall-Vorratsregeln zeigen auf die falsche IP
TP5 Etappe 2 hat vorgesorgt, aber hart auf den heutigen Container:
TP5-E2: LAN->AGH dns accept udp dst-address=10.40.20.16 dst-port=53
TP5-E2: LAN->AGH dns-tcp accept tcp dst-address=10.40.20.16 dst-port=53
🔴 Das ist der Punkt, an dem dieser Cutover sonst scheitert: heute fragt jeder Client seinen
eigenen Gateway (input-Kette, keine Regel nötig). Nach dem DHCP-Flip wird DNS zu einem
forward-Fluss über VLAN-Grenzen — und die Firewall ist seit 2026-08-18 deny-by-default.
Ohne passende Regeln verlieren IOT, MEDIA, UNTRUSTED, GUEST und MGMT schlagartig die Auflösung,
während VLAN20 (wo der Resolver steht) unauffällig weiterläuft.
✅ Entscheid (User, 2026-08-26): die Vorratsregel auf 10.40.20.16 wird GESTRICHEN — „.16 war
historisch, passt aber nicht mehr ins System." Also nicht erweitern, sondern ersetzen: die zwei
alten Zeilen raus, zwei neue auf das Paar 10.40.20.36/.37 rein — über Nautobot Golden Config,
nicht ad hoc (Core-Config ist GC-only), und bevor irgendein DHCP angefasst wird.
Der Auftrag
User-Entscheid 2026-08-25: Split-Horizon nicht auf dem Core, sondern in AdGuard, zusammen mit TP23 Stufe 2 — „nichts zweimal bauen".
- LXC 110
agh-bf1+ 111agh-bf2bauen, Muster exakt wie LXC 130 (Debian 13,tag=20,onboot=1,startup order=10, in den Backup-Jobbackup-6dcf5c10-610f). Als Paar — ein einzelner AGH wäre ein DNS-SPOF auf pve. Adressen10.40.20.36/.37— TP32 will DNS auf.3x,.30/.31/.32sind Nautobot;.36/.37sind frei geprüft (kein ARP, keine Lease, DHCP-Pool beginnt erst bei.100). ⚠️ Nebenbefund: TP32 nennt als Pool.200–.249, live läuft.100–.200— Konflikt mit „.100–.199App-Services". Bestand bleibt; nur beim Vergeben aufpassen. - Basis-Config übernehmen (Upstreams/Bootstrap/Filter) aus
adguard_bf1,/opt/docker/adguard_bf1/conf/AdGuardHome.yaml(Backup daneben:…bak-tp23-20260817). Rewrites NEU bauen — s. Fund 1. - Die 16 Rewrites setzen: jeder Site-Name aus
caddy/Caddyfile→10.40.20.40. - Firewall zuerst (Fund 3):
TP5-E2-Regeln auf.36/.37erweitern, per GC deployen,--refresh-compliancefahren. - Testen, bevor irgendein DHCP angefasst wird:
dig @10.40.20.36 vw.emsenhuber.net(erwartet10.40.20.40),dig @10.40.20.36 <irgendein-lease>.lan(erwartet die Lease-IP), und dasselbe gegen.37. Zusätzlich aus einem anderen VLAN — sonst prüft man nur VLAN20 und übersieht genau den Firewall-Fall. - VLAN für VLAN umstellen, nicht alle sieben: VLAN20 → VLAN10 → Rest, VLAN30 (IoT, 26 Geräte) zuletzt; dort ist ein Reconnect am teuersten.
⏱️ Die Falle, die den Zeitplan bestimmt: lease-time=1d
Alle sieben Server stehen auf 1 Tag (GUEST 12 h). Ein geändertes dns-server erreicht die Clients
erst zur Erneuerung (T1 ≈ halbe Laufzeit) — der Cutover wirkt also verzögert und ungleichzeitig,
und ein Rollback wirkt genauso langsam. Zwei Konsequenzen:
- Vor dem Flip die
lease-timeim betroffenen VLAN auf ~10 min senken (GC-Deploy), umstellen, verifizieren, danach zurücksetzen. Sonst zieht sich die Umstellung über Stunden. - „Es geht noch" beweist nach dem Flip gar nichts — das Gerät hat schlicht die alte Lease.
Abnahme ist eine frische Lease +
scutil --dns/resolvectl status, nicht einping.
🔙 Rollback (vorher lesen, nicht danach)
dns-serverim betroffenen/ip dhcp-server networkzurück auf<VLAN>.1— der Core ist unverändert ein vollwertiger Resolver (DoH zum CF-Gateway,verify-doh-cert=yes,allow-remote-requests=yes); er wird in diesem TP nicht abgeschaltet.- Clients erneuern lassen (s.
lease-timeoben) oder gezielt bouncen. - Firewall-Regeln dürfen stehen bleiben — sie schaden nicht. ⇒ Der Core bleibt bis zum Ende der Session unangetastet als Rückfallebene. Erst wenn alle sieben VLANs sauber über AGH laufen, wird über sein Abschalten überhaupt geredet (eigener Entscheid).
Fallen, die schon bezahlt sind
- 🔴 Ein Statuscode vom öffentlichen FQDN beweist nichts.
grafana.emsenhuber.netlieferte monatelang 302 — das war der Access-Login, während der Dienst gar nicht existierte. Immer gegen das Origin messen. Umgekehrt gilt dasselbe: die 400/403/404 der MCP-Endpunkte sind echte Serverantworten, kein Proxy-Fehler. - 🔴
pvesm freescheitert an geschützten PBS-Snapshots stillschweigend. Entschützen:pvesh set /nodes/pve/storage/pbs/content/<volid> --protected 0. - 🔴 Startreihenfolge auf pve hängt NICHT an der VMID, solange ein Gast
startup: order=trägt. - ⚠️ Core-Config läuft über Nautobot Golden Config — DHCP- und Firewall-Änderung brauchen
Template und ComplianceRule, sonst Drift. Letzter geprüfter Stand: 104/104, 0 Drifts (08-23);
vor dem Cutover einmal
--refresh-compliancefahren, damit die Ausgangslage sauber ist. - ⚠️ Caddy in LXC 130 hat einen eigenen Netz-Namespace und ist deshalb nicht von der macvlan/ipvlan-Blindheit betroffen — ein AGH im Docker-LXC 400 wäre es. Ein weiterer Grund für eigene LXCs statt „Container dazu".
- ⚠️ Mit Split-Horizon greift CF Access innerhalb des Netzes nicht mehr. Bewusster Preis (User 2026-08-25); innen tragen TP5-Segmentierung und die App-eigene Auth.
Danach offen (TP31 Rest)
Tunnel bf-public + cloudflared auf ap1/ap2 (arm64, 95 MB Flash frei — ⚠️ je ein physischer
device-mode-Wechsel am Gerät nötig), CNAMEs umhängen (n8n → gitea → hass → vw; hass erst
nach dem 400er-Fix), dann bf-nas/bf-pve/bf-mm löschen und die alten Container entfernen.
Danach: adguard_bf1 im Docker-LXC 400 abbauen — sonst stehen zwei AdGuards mit
widersprüchlichen Rewrites im selben Netz.