193 lines
13 KiB
Markdown
193 lines
13 KiB
Markdown
# Übergabe — nächste Session: AdGuard als Resolver + Split-Horizon (TP23 Stufe 2 ∥ TP31 Schritt 4)
|
||
|
||
> **Einstieg:** diese Datei, dann [`teilprojekte.md`](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**, `nautobot` 302, 0,02–0,11 s.
|
||
Config im Repo **`caddy/Caddyfile`**, Ausrollen mit **`caddy/deploy.sh`**.
|
||
- ℹ️ `pve-mcp` 400 / `ha-mcp` 403 / `gitea-mcp` 404 sind **keine Proxy-Fehler** — dieselben Codes
|
||
kommen direkt vom Origin. Nicht als Baustelle behandeln.
|
||
- 🧹 Der Zertifikatsspeicher hält **17** Zertifikate bei 16 Sites: `grafana` ist verwaist (harmlos).
|
||
- ✅ **`hass` liefert 200** (gelöst 2026-08-26). Ursache war **nicht** der fehlende YAML-Eintrag:
|
||
HA hat die http-Config nach **`.storage/http`** migriert, der `http:`-Block in `configuration.yaml`
|
||
ist seither **wirkungslos**. `10.40.20.40` ist über den WS-Zweischritt `http/config/configure` →
|
||
`http/config/promote` in die Trusted-Liste gekommen und als `stable` bestätigt. Details in TP31.
|
||
⇒ **Damit ist die CNAME-Umstellung von `hass` nicht mehr blockiert.**
|
||
- ✅ **Aufgeräumt** (TP31 Schritt 1): LXC `120/121/128/129/130(alt)/131` **und `104`** zerstört,
|
||
72/72 PBS-Snapshots weg — **`ct/104` ebenfalls auf 0**, und am selben Abend die vier gestoppten
|
||
Gäste **`103 minarca`, `109 node-red`, `115 hms-mqtt-publisher`, `201 openproject`** samt ihren
|
||
**28 Snapshots** (User-Entscheid 2026-08-25).
|
||
🎯 **Ergebnis: auf pve läuft jetzt jeder existierende Gast** — 11 LXC + 2 VMs, kein einziger
|
||
`stopped`. Der PBS-Datastore enthält nur noch aktuelle Gäste.
|
||
⚠️ **Reihenfolge dabei ist kein Detail:** die Snapshot-Liste **vor** dem `pct destroy` einsammeln.
|
||
`pvesm list --vmid <id>` liefert danach 0, obwohl die Backups noch liegen — der Filter braucht die
|
||
Gast-Config. Gegenprobe deshalb **direkt am Datastore** (`/nodes/pve/storage/pbs/content`).
|
||
- ✅ **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`, `mfc` gibt es weiter, sie sind nur umgezogen
|
||
> (NAS `10.40.20.10`, macmini `10.40.20.167`, Brother MFC `10.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.net` ist unsere Domain, nicht `bf.lan`.**
|
||
> `bf.lan` ist 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 auf `bf.emsenhuber.net` heben (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".
|
||
|
||
1. **LXC 110 `agh-bf1` + 111 `agh-bf2` bauen**, Muster exakt wie LXC 130 (Debian 13, `tag=20`,
|
||
`onboot=1`, `startup order=10`, in den Backup-Job `backup-6dcf5c10-610f`).
|
||
**Als Paar** — ein einzelner AGH wäre ein DNS-SPOF auf pve.
|
||
**Adressen `10.40.20.36` / `.37`** — TP32 will DNS auf `.3x`, `.30/.31/.32` sind Nautobot;
|
||
`.36/.37` sind **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–.199` App-Services". Bestand bleibt; nur beim *Vergeben* aufpassen.
|
||
2. **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.
|
||
3. **Die 16 Rewrites setzen**: jeder Site-Name aus `caddy/Caddyfile` → **`10.40.20.40`**.
|
||
4. **Firewall zuerst** (Fund 3): `TP5-E2`-Regeln auf `.36/.37` erweitern, per GC deployen,
|
||
`--refresh-compliance` fahren.
|
||
5. **Testen, bevor irgendein DHCP angefasst wird:** `dig @10.40.20.36 vw.emsenhuber.net`
|
||
(erwartet `10.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.
|
||
6. **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-time` im 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 ein `ping`.
|
||
|
||
### 🔙 Rollback (vorher lesen, nicht danach)
|
||
1. `dns-server` im betroffenen `/ip dhcp-server network` zurü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.
|
||
2. Clients erneuern lassen (s. `lease-time` oben) oder gezielt bouncen.
|
||
3. 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.net` lieferte
|
||
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 free` scheitert 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-compliance` fahren, 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.
|