# Cloudflare-Tunnel — Mapping & #1033-Diagnose (Single Source of Truth) > 🆕 **SSoT-Wechsel im Aufbau (TP44, seit 2026-09-02):** Die CF-Estate (Tunnel, WARP-Connector, > VPC-Services, Hyperdrive, Workers, Access-Apps) wird als **native `nautobot.cloud`-Objekte** in > Nautobot (`10.40.20.30`) geführt — Etappe 1 (manuelle Erstbefüllung) ✅. Seeder: > `nautobot/tp44-cf-estate-seed.py`, Detail: `docs/handoff-20260902-cf-estate-nautobot-ssot.md`. > **CF bleibt operativer Master, Nautobot = Dokumentations-SSoT.** Dieses File bleibt gültige Historie > und As-Built-Log; die *strukturierte* Estate liest man ab jetzt in Nautobot. Etappe 2 (CF-API→Nautobot-Sync) > ist offen. > **Aktueller Stand: → §0 (unten).** §1–16 sind Historie/As-Built-Log früherer Sessions und beschreiben > Topologien, die **nicht mehr live** sind (v.a. das 3-Tunnel-HA `bf-mm`/`bf-nas`/`bf-pve`). §9 = Analyse, > §10–15 = As-Built des inzwischen abgelösten 3-Tunnel-Designs. Track A aus `docs/handoff-cf-tunnel-1033.md`. ## §0 — Live-Ist-Stand (2026-09-08, maßgeblich) > Der einzige aktuelle Topologie-Stand. **§1–16 nicht als aktuelle Konfiguration lesen** — insbesondere das > 3-Tunnel-HA `bf-mm`/`bf-nas`/`bf-pve` (§10–15) existiert seit dem TP16.3-Cutover (bf-public/Caddy, > 2026-08-27) **nicht mehr**. Strukturierte Estate = Nautobot (TP44, deckt sich mit diesem Stand); > operativer Master = Cloudflare. Read-only gemessen gegen die CF-API (`cfd_tunnel`, `warp_connector`, > `teamnet/routes`) am 2026-09-08. **cloudflared-Tunnel (live) — es gibt genau drei:** | Tunnel | ID | Conns | Zweck | |---|---|---|---| | **bf-public** | `48d3b0b6-7233-4781-a76a-1de4a5e957ce` | 2, healthy | **einziger öffentlicher BF-Tunnel** (TP31/TP16.3), erstellt 2026-08-27 | | **fm.emsenhuber.net** | `b697d124-53bf-4a33-8fcf-384cced4db1a` | 1, healthy | Standort FM (`ds-fm`, `gateway-fm`), separat | | **terpene-db** | `f2d2fc8a-54ae-41df-b09a-97312cdb9fe2` | 1, healthy | DB-Pfad (Hyperdrive→VPC-Service), Rebuild 2026-09-01 — s. §17 | **bf-public-Ingress** → alle vier auf **Caddy `10.40.20.40:443`** (Caddy macht das Fan-out), catch-all 404: `vw` · `hass` · `n8n` · `gitea` (`.emsenhuber.net`). **WARP / Private Access — nativer Mesh, KEIN cloudflared:** - warp_connector **bf-core-mesh** `d1da7c8a-2736-4cbb-8af1-32db5393fb9c`, healthy — nativer WireGuard-Mesh-Node auf dem Core (TP16.1). **Live und produktiv** (nicht mehr „gated/Konzept" wie in §14). - Routen: `10.40.0.0/16` → **bf-core-mesh** · `10.101.0.0/24` → **fm**. Ein vnet `vnetemsenhuber` (default). ## 1. Alle Tunnel im Account (`393c…66c36`) | Tunnel | ID | Status | Conns | Verwendung | |---|---|---|---|---| | **bf.emsenhuber.net** | `70d6a4cf-…-91fab4fa7270` | **healthy** | **12 (=3 Connectors)** | **BF-Dienste — relevant** | | fm.emsenhuber.net | `b697d124-…-384cced4db1a` | healthy | 4 (1 Connector) | FM-Standort (nas-fm), separat | | TeilzeitCharlie | `6c784c98-…` | down | 0 | tot | | coolify | `4f54ad8a-…` | down | 0 | tot | | johnny2 | `acc73eb5-…` | down | 0 | tot | | openclaw | `7a8f7b53-…` | down | 0 | tot (odroid-m1, offline) | ## 2. bf-Tunnel — die 3 Connectors (Round-Robin!) Fingerprint via Colo-Locations (CF-API ↔ lokale cloudflared-Logs) + Arch. **Wichtig:** DS923+ = AMD Ryzen = amd64; macmini = Apple Silicon = arm64. | CF-Connector | arch | Host (Portainer) | LAN-IP | Docker-Netz | Vantage | |---|---|---|---|---|---| | `1856dfc3-…` | arm64 | **macmini** (ep20) | 10.40.20.167 | **bridge** `cloudflared_default` | **VLAN20** | | `db713b30-…` | amd64 | **pve-LXC** (ep2) | 10.40.20.126 | host | **VLAN20** (TP14.2 2026-07-10 → #1033-Zielbild) | | `d7454e68-…` | amd64 | **nas-bf DS923** (ep14) | 10.40.41.10 | host | VLAN1/.41 | Alle 3 fahren **denselben Tunnel-Token** (`tunnel run`, token-managed Ingress im Dashboard). CF round-robined Requests über alle 3 → **jeder Origin muss von allen 3 Vantages erreichbar sein**, sonst sporadisch 1033. Leichen auf dem NAS (exited, harmlos, aufräumen): `oc-tzcharlie-cloudflared`, `oc-johnny2-cloudflared`. ## 3. Ingress (token-managed, v104) — Reachability je Connector Quelle: macmini aktiv geprobt; pve/NAS aus echten cloudflared-Fehler-Logs (tail 2000). `OK` = erreichbar, `FAIL` = no route / down, `?` = nicht beobachtet (vermutl. OK). | Hostname | Origin | pve | NAS | macmini | Befund | |---|---|---|---|---|---| | pve | https://10.40.41.100:8006 | OK | ? | OK | ok | | hass | http://10.40.41.105:8123 | OK | **FAIL** | OK | NAS no-route (sporadisch) | | ha-mcp | http://10.40.41.105:9583 | OK | **FAIL?** | OK | wie hass | | pbs | https://10.40.41.135:8007 | ? | ? | **FAIL** | macmini no-route | | n8n | http://10.40.41.167:5678 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** (Host weg) | | mcp-ms365 | http://10.40.41.167:3005 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** | | hermes | http://10.40.41.167:9119 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** | | gitea-mcp | http://10.40.41.167:3000 | **FAIL** | **FAIL** | **FAIL** | **STALE → läuft auf 10.40.20.167:3000** | | n8n-mcp | http://10.40.41.167:3001 | **FAIL** | **FAIL** | **FAIL** | **STALE → läuft auf 10.40.20.167:3001** | | 82unkpb5 (ssh) | ssh://10.40.41.167:22 | **FAIL** | **FAIL** | **FAIL** | **STALE → macmini 10.40.20.167:22** | | vw | http://10.40.41.127:80 | OK | **FAIL (1736×)** | **FAIL** | **pve-lokaler Container** — nur pve erreicht | | ccu | http://10.40.41.232:80 | OK | ? | OK | wahrsch. pve-lokal | | iobroker | http://10.40.41.19:8080 | ? | **FAIL** | **FAIL** | nur pve? prüfen | | gateway-dw | http://192.168.178.1 | ? | ? | **FAIL** | **DW-Netz, nur über WG — kein BF-Connector hat die Route** | | gitea | http://10.40.41.157:3000 | OK | ? | OK | ok (macmini transient) | | nginx-bf | http://10.40.41.123:81 | OK | ? | OK | ok | | ds-bf | http://10.40.41.10:8080 | OK | OK | OK | ok | | portainer | https://10.40.20.126:9443 | OK | OK | OK | TP14.2: Origin .41→.20.126; Tunnel-Smoke 200 | | grafana | http://10.40.41.109:3000 | ? | ? | OK | ok | | pve-mcp | http://10.40.41.173:3000 | ? | ? | OK | ok | | gateway-bf | http://10.40.41.254 | OK | ? | OK | ok (FB) | | j44d6tua (ssh) | ssh://10.40.41.100:22 | OK | ? | OK | ok | | 3k23uow7 (ssh) | ssh://10.40.41.10:22 | OK | OK | OK | ok | | (catch-all) | http_status:404 | — | — | — | — | ## 4. DNS-Probleme (Zone emsenhuber.net, `1b5bc02f…`) **Orphan-CNAME → bf-Tunnel, aber KEINE Ingress-Regel → 404:** - `mcp-qdrant.emsenhuber.net`, `ssh-nasbfnew.emsenhuber.net` **CNAME → tote/gelöschte Tunnel → konstante 1033:** - `oc`, `dashboard`, `drawio` → openclaw (down) - `jc` → johnny2 (down) · `charlie` → TeilzeitCharlie (down) · `coolify` → coolify (down) - `oc2` → `d8df70a7…`, `oc3` → `3702dc6e…`, `win11test` → `de818071…` — **Tunnel existiert nicht mehr** (FM-Tunnel-CNAMEs `ds-fm`/`gateway-fm` → `b697d124…` healthy = ok, separat.) ## 5. Root-Cause #1033 (zusammengefasst) 1. **3 Connectors mit asymmetrischer Reachability** + Round-Robin = sporadisch 1033 (Kernursache, log-bewiesen). 2. **pve-lokale Container** (`vw .127`, `ccu .232`) nur vom pve-Connector erreichbar (macvlan, kein LAN-Route von NAS/macmini). 3. **Stale Origin `.41.167`**: macmini nach VLAN20 (`10.40.20.167`) gewandert → 5 Dienste zeigen ins Leere. 4. **gateway-dw** braucht WG-Route — kein BF-Connector hat sie. 5. **DNS-Müll**: 9 CNAMEs auf tote Tunnel (konstante 1033) + 2 Orphans (404). ## 6. Fix-Plan (gestaffelt — Freigabe nötig) **Stufe 1 — Sofort-Entschärfung — ✅ ANGEWENDET 2026-06-30:** - bf-Tunnel auf **nur pve-Connector** reduziert (NAS ep14 + macmini ep20 cloudflared gestoppt, reversibel via `start`). - Verifiziert: Tunnel `healthy`, 1 Connector (`db713b30`/pve). Smoketest `vw` 4×200 (vorher 1736 Fehlversuche), `hass`/`portainer` 302. **Kein 1033 mehr.** **Stufe 2 — Stale-Origins fixen (Dashboard-Ingress) — OFFEN, braucht Entscheidungen:** Die .167-Dienste laufen real auf dem **macmini (ep20, VLAN20 10.40.20.167)** — aber uneinheitlich: - `gitea-mcp` → `10.40.20.167:3000` ✓ · `n8n-mcp` → `10.40.20.167:3001` ✓ · `82unkpb5 ssh` → `10.40.20.167:22` ✓ (saubere Host-Ports) - `n8n` (`n8nio/n8n`): **kein Host-Port** (`pub=[]`) → nur im Docker-Netz, von pve NICHT routbar. Entscheidung: Port publishen ODER macmini-lokalen Connector ODER stilllegen. - `hermes`: **2 Instanzen** — `hermes-christoph` `10.40.20.167:8642`, `hermes-geli` `10.40.20.167:8643`. Ingress-Port `9119` obsolet → klären, welche `hermes.emsenhuber.net` bedienen soll. - `mcp-ms365`: **auf keinem Host gefunden** → Ingress + DNS entfernen? - ⚠️ **Vor Repoint zu verifizieren:** erreicht der pve-Connector (.41.126, FB-Default-GW!) überhaupt VLAN20 (.20.167)? → beim Apply per Smoketest prüfen, sonst Rollback. **Stufe 3 — DNS-Hygiene:** - Tote CNAMEs löschen: `oc`,`oc2`,`oc3`,`win11test`,`jc`,`charlie`,`coolify`,`dashboard`,`drawio`. - Orphans `mcp-qdrant`,`ssh-nasbfnew`: Ingress-Regel ergänzen **oder** CNAME löschen. - NAS-Leichen `oc-tzcharlie`/`oc-johnny2` entfernen. --- ## 7. CHANGE-SET — ✅ KOMPLETT 2026-06-30 > Zugang über **scoped API-Token** in `mcp/cloudflare/.env` (OAuth-MCP blieb read-only). > **A1 + A2 + A3 alle angewendet.** Endzustand: Tunnel healthy/1 Connector (pve), Ingress v106, > 23 Ingress-Hostnames ↔ 23 DNS-CNAMEs, keine Waisen, keine CNAMEs auf tote Tunnel. ### ✅ Erledigt - **A1:** n8n-Compose-Port `10.40.41.167→10.40.20.167` (Stack 174 redeploy, Volume/Encryption-Key erhalten, `/healthz` 200). NAS-Leichen `oc-tzcharlie`/`oc-johnny2` entfernt. - **A2 (Ingress v106):** gitea-mcp/n8n-mcp/82unkpb5/n8n/hermes → `.20.167`; `hermes-geli` (:8643) neu; `mcp-ms365` entfernt. Keine `.41.167`-Origins mehr. pve→VLAN20 verifiziert (n8n-mcp 200 via bf4). - **App-Level-Notizen (kein 1033):** `gitea-mcp` 404 auf `/` (Sub-Pfad?), `hermes` 502 (Origin .20.167:8642 erreicht, App liefert 502) — separat prüfen. ### ✅ A3 (DNS) erledigt - `hermes-geli` CNAME → `70d6a4cf….cfargotunnel.com` (proxied) angelegt → jetzt erreichbar (302). - Gelöscht: `oc`,`oc2`,`oc3`,`win11test`,`jc`,`charlie`,`coolify`,`dashboard`,`drawio`,`mcp-ms365`, `mcp-qdrant`,`ssh-nasbfnew`. - Konsistenz verifiziert: 23↔23, keine Orphans, keine toten Tunnel-Verweise. ### Ursprünglicher Plan (Referenz) ### A. Portainer (Write vorhanden — kann sofort, careful): - **macmini n8n-Container** mit `-p 5678:5678` neu erstellen (Volumes/ENV erhalten!) → Origin `10.40.20.167:5678`. - NAS-Leichen entfernen: `oc-tzcharlie-cloudflared`, `oc-johnny2-cloudflared` (exited). ### B. Tunnel-Ingress `70d6a4cf…` (PUT /configurations) — Ziel-Origins: | Hostname | NEU | alt | |---|---|---| | gitea-mcp | `http://10.40.20.167:3000` | .41.167:3000 | | n8n-mcp | `http://10.40.20.167:3001` | .41.167:3001 | | 82unkpb5 (ssh) | `ssh://10.40.20.167:22` | .41.167:22 | | n8n | `http://10.40.20.167:5678` | .41.167:5678 (nach A) | | hermes | `http://10.40.20.167:8642` | .41.167:9119 | | **hermes-geli** (NEU) | `http://10.40.20.167:8643` | — | | mcp-ms365 | **Regel löschen** | .41.167:3005 | ⚠️ **Vor B: pve→VLAN20-Reachability per Smoketest verifizieren** (1 Repoint, extern testen, sonst Rollback — pve hat FB-Default-GW). ### C. DNS (Zone `1b5bc02f…`) — CNAMEs löschen: `oc`, `oc2`, `oc3`, `win11test`, `jc`, `charlie`, `coolify`, `dashboard`, `drawio`, `mcp-ms365`. **Neu anlegen:** `hermes-geli.emsenhuber.net` CNAME → `70d6a4cf-aa1d-4a91-b918-91fab4fa7270.cfargotunnel.com` (proxied). **Orphans** `mcp-qdrant`, `ssh-nasbfnew`: ohne Ingress → löschen (oder Ingress ergänzen, falls Dienst gewünscht — offen). **Stufe 4 — Zielbild (überlappt Track C / IP-Migration):** - Origins auf konkret routbare IPs in VLAN20 konsolidieren, dann **HA-Connector-Paar** (z.B. pve + NAS) **beide in VLAN20**, sodass jeder Connector jede Origin erreicht. `gateway-dw` über WG-fähigen Connector lösen. - TP5-Firewall ZULETZT (erst wenn alle Origins/Connectors in VLAN20). --- ## 8. Update 2026-07-09 — NAS→VLAN20-Cutover + Ingress v116 Nach NAS-DSM-Cutover auf `10.40.20.10` und Docker-Migration auf ein Macvlan `vlan20` (alle NAS-Container jetzt `10.40.20.x`, s. `docs/nas-vlan20/`): **Ingress v115→v116 (via scoped Token, `cf_repoint`):** 6 Origins `.41→.20` repointet — `ha-mcp` .105:9583, `3k23uow7`(NAS-ssh) .10:22, `gitea` .157, `vw` .127, `grafana` .109, `pve-mcp` .173. Keine `.41`-Stale unter den migrierten Hosts mehr. Bleibt `.41`: pve .100, j44d6tua .100, portainer .126, nginx-bf .123, gateway-bf .254. **Connector-Reachability — geklärt (kein Routing-Problem):** Der pve-Connector `.41.126` **erreicht VLAN20** — `vw.emsenhuber.net` → **200** über den Tunnel (Vaultwarden `.20.127` läuft). ap1 macht das Inter-VLAN-Routing VLAN1↔VLAN20, das steht. Ein `502` direkt **nach** dem Ingress-PUT war **transient** (Connector-Origin-Cache/ARP noch nicht warm), verschwindet nach kurzer Zeit. `grafana` `502` = Container `exited` (starten → geht). **Kein pve-Static-Route nötig.** **Bleibt offen (Stufe 4, Connector-Vantage — nicht dringend):** Round-Robin-Asymmetrie #1033, falls mehrere Connectors aktiv: macmini (`.20.167`, VLAN20) erreicht NAS-Macvlan, scheitert aber an pve-lokalen Origins/pbs/gateway-dw; NAS-eigener host-net-Connector taugt nicht (Host↔eigene-Macvlan- Isolation). Zielbild = **ein** Connector, der alles erreicht — löst sich weitgehend von selbst, sobald pve (+ Connector) mit dem PVID1-Cutoff in VLAN20 wandert (dann sind Origins+Connector im selben L2). --- ## 9. Ist-Inventory & Endanalyse 2026-07-10 (TP16) — SSoT-Stand > ⚠️ Die „3 Connectors sind gut/Zielbild"-Framings der Abschnitte 2/6/8 oben sind **überholt** — maßgeblich > ist dieser Abschnitt. **Analyse turnkey; Umsetzung = eigene Session** (User-Entscheidung). ### 9.1 Invariante (die Regel, an der alles hängt) - **Ein cloudflared-Connector ist blind NUR für macvlan/ipvlan-Container auf seinem EIGENEN Host** (Linux-Kernel: Host ↔ eigene macvlan/ipvlan-Children isoliert). Fremdhost-L2 + co-lokierte *Bridge*-Container erreicht er sehr wohl. - **Mehrere Connectoren auf EINEM Tunnel = geteilter Ingress + CF-Round-Robin.** Jede Origin, die auf dem Host *eines* Connectors als macvlan/ipvlan liegt, fällt bei ~**1/N** der Requests aus (#1033, „jeden 3. Schuss eine Niete"). **Strukturell** — nicht durch „Origins fixen" heilbar, solange ein Connector Origins seines eigenen Hosts bedient. - **Kein Route→Connector-Pinning INNERHALB eines Tunnels.** „Ausgewählte Routen für ausgewählte Connectoren" gibt es nur über **getrennte Tunnel** (CNAME → jeweiliger Tunnel; pro Tunnel eigene Connectoren). ### 9.2 Live-Inventory (gemessen 2026-07-10, Ingress **v119**, 24 Hostnames + catch-all, 2 live Connectoren `b797ee1b`/`f480dc69`) CF-Access: **`vw` = `bypass` (ÖFFENTLICH!)** ⚠️ · `hass` & Rest geschützt via Wildcard `*.emsenhuber.net` (`allow:christoph` / `non_identity:bf4` / `allow:claude-mcp`). | Hostname | Origin | Live | Host/Netz (zu verifizieren) | |---|---|---|---| | pve / j44d6tua(ssh) | `.41.100:8006` / `:22` | UP | Proxmox-Host (VLAN1) | | hass / ha-mcp | `.20.105:8123` / `:9583` | UP | HA-Host .105 | | pbs | `.20.135:8007` | **DOWN** | Proxmox Backup Server | | n8n / hermes / hermes-geli / gitea-mcp / n8n-mcp / 82unkpb5(ssh) | `.20.167:*` | n8n/mcp UP · **hermes+hermes-geli DOWN** | macmini | | portainer | `.20.126:9443` | UP | pve-LXC (host-net) | | nginx-bf | `.41.123:81` | **DOWN** | **noch VLAN1!** | | ds-bf / 3k23uow7(ssh) | `.20.10:8080` / `:22` | UP | NAS-Host | | gitea / grafana / pve-mcp | `.20.157` / `.20.109` / `.20.173` | UP | **NAS-macvlan** (NAS-Connector-blind) | | omada | `.20.175:8043` | UP | **NAS-macvlan** (NAS-Connector-blind) | | ccu / vw / iobroker / z2m25 | `.20.232` / `.20.127` / `.20.107:8081` / `.20.106:8080` | UP | **Host/Netz unklar → messen** | | gateway-dw | `192.168.178.1` | — | **nur via WG** (kein BF-Connector hat Route) | ### 9.3 Ziel-Design: reziproke Per-Host-Tunnel (HA) Jeder Host-Dienst wird von den Connectoren der **anderen** Hosts bedient (nie vom eigenen), gegenseitig: | Tunnel (= Dienste eines Hosts) | Connectoren auf | HA | |---|---|---| | pve-Dienste | NAS + macmini | 1 abdrehbar | | NAS-Dienste (omada/pve-mcp/gitea/grafana/…) | pve + macmini | 1 abdrehbar | | macmini-Dienste (`.20.167`) | pve + NAS | 1 abdrehbar | 3 Tunnel, jeder Host fährt **2 cloudflared** (für die 2 anderen Tunnel) → Host-Ausfall ⇒ jeder Tunnel ≥1 Connector = **voll HA**. Der macmini ist vollwertiger dritter Knoten (nicht „vergessen"). ### 9.4 Umsetzungs-Reihenfolge (eigene Session) 1. **Reachability-Matrix je Host** (pve/NAS/macmini → jede der 24 Origins, read-only) — klärt v.a. `vw`/`ccu`/`iobroker`/`z2m25` (Bridge nur-eigener-Host? macvlan? ipvlan-auf-pve → dann pve-blind!). Ergebnis bestimmt die Tunnel-Gruppierung. 2. **Interim-Sofortfix:** bf-Tunnel auf **pve-only** (pve erreicht alles außer gateway-dw) → 0×1033. Reversibel. 3. **Reziprokes 3-Tunnel-HA bauen:** 3 Tunnel anlegen, ~24 CNAMEs re-pointen, 6 Connectoren (2/Host, je eigenes Token), Alt-Token aus NAS/macmini-cloudflared entfernen. `vw`/`ccu` ggf. auf VLAN20-macvlan heben (dann L2-erreichbar). 4. **Tote Origins bereinigen:** `pbs`, `nginx-bf` (noch .41!), `hermes`, `hermes-geli`. 5. **Access-Strang (Track B):** `hass`-400 ohne Passthrough → iPhone in **WARP** enrollen; **`vw` von bypass → geschützt**. 6. **Loop-Gegentest** aller FQDNs (0×1033), `gateway-dw` als WG-Sonderfall klären/entfernen. ---
🗄️ ARCHIV (§10–16) — überholtes 3-Tunnel-HA bf-mm/bf-nas/bf-pve. Seit dem TP16.3-Cutover (2026-08-27) nicht mehr live — siehe §0. Aufklappen nur für die Historie. ## 10. AS-BUILT 2026-07-10 (TP16 umgesetzt) — reziprokes 3-Tunnel-HA ✅ > Gebaut & verifiziert in eigener Session. Round-Robin-#1033 **strukturell weg** (Loop-Gegentest 0×530 über alle 19 Live-FQDNs, HA per Host-Ausfall-Sim bewiesen). Schritte 1–4+HA durch; **Schritt 5 (Access/WARP + `vw`) offen** (user-gated). ### 10.1 Reachability-Matrix (die Basis, read-only gemessen) Einzige Blindheit im System: **NAS-Connector (host-net) ↔ NAS-Docker-macvlan** (Kernel-Isolation). Alles andere cross-host-L2 / inter-VLAN-geroutet erreichbar. - **NAS-`vlan20` = macvlan** (parent `ovs_eth0`): gitea `.157`, grafana `.109`, pve-mcp `.173`, omada `.175`, vw `.127`, drawio `.139`, prometheus `.151`, iob_slave `.33` → **NAS-Connector blind**. - **pve-LXC-400-`vlan20` = ipvlan** (parent `veth20`): adguard `.16/.17`, omada-mcp `.176` → pve-Connector blind, aber **keine davon ist Tunnel-Origin** → irrelevant. - **macmini** = alles Docker-**bridge + Port-Publish** auf `.20.167` → keine Blindheit. - `ccu .232`=RaspberryMatic(qemu/330), `iobroker .107`=iob-exposed(lxc/150), `z2m25 .106`=lxc/112, `hass/ha-mcp .105`=haos(qemu/100) = **pve-Gäste auf vmbr/VLAN20** → von allen erreichbar (keine Docker-macvlan-Kinder). - **Ergebnis:** pve **und** macmini erreichen je 100 % der Live-Origins; NUR NAS ist für seine 5 eigenen macvlan-Dienste blind. Darum: NAS darf nie bf-nas fahren. ### 10.2 Die 3 Tunnel (config_src=cloudflare, token-managed Ingress) | Tunnel | ID | Dienste | Connectoren (2/Tunnel) | |---|---|---|---| | **bf-nas** ⚠️ *ID überholt, s. §11* | ~~`70d6a4cf`~~ → **`220c9958-401b-4111-9451-f3db09bba2d5`** (2026-07-12 frisch) | gitea, grafana, pve-mcp, omada, vw, ds-bf, 3k23uow7 (+gateway-dw→404) | **pve + macmini** | | **bf-pve** (neu) | `f7fdf3a6-…-b0f273794d09` | pve, j44d6tua, ccu, iobroker, z2m25, portainer, hass, ha-mcp | **NAS + macmini** | | **bf-mm** (neu) | `7a322261-…-8ebce99f5ed1` | n8n, n8n-mcp, gitea-mcp, 82unkpb5 | **pve + NAS** | Prinzip: **jeder Host-Dienst wird von den Connectoren der ANDEREN Hosts bedient** → Host-Ausfall lässt jeden Tunnel ≥1 Connector = voll HA. Innerhalb eines Tunnels kein Route-Pinning (CF round-robined) — aber beide Connectoren erreichen 100 % → Round-Robin schadet nicht. ### 10.3 Connector-Roster (6 = 2/Host, Docker `cloudflare/cloudflared:latest`, `restart=unless-stopped`) | Host (Portainer ep) | Container | Tunnel | Netz | |---|---|---|---| | pve-LXC (ep2) | `cloudflared-bfnas` (c80a7db) · `cloudflared-bfmm` (faa0960) | bf-nas · bf-mm | host | | NAS (ep14) | `cloudflared-bfpve` (97312b5) · `cloudflared-bfmm` (963217983) | bf-pve · bf-mm | host | | macmini (ep20) | `cloudflared-bfnas` (5c5b3ba) · `cloudflared-bfpve` (3339f86) | bf-nas · bf-pve | bridge | Tokens: nur im Container-Env + jederzeit via `GET /accounts/…/cfd_tunnel//token` (Bearer `CF_API_TOKEN`). Tunnel-IDs in `mcp/cloudflare/.env` (`CF_BF/PVE/MM_TUNNEL_ID`). **Nicht** als Compose-Stacks angelegt (raw Portainer-API-Container) → bei Neuaufbau: Container mit `TUNNEL_TOKEN=` + `tunnel --no-autoupdate run`. ### 10.4 As-built Verifikation - Loop-Smoke 19 FQDNs ×5: **0×530**. gitea/omada/vw/ds-bf/pve/portainer/ccu/iobroker/z2m25/n8n/n8n-mcp/82unkpb5 = 200; grafana 302 (Access); pve-mcp 400 (MCP-Handshake); hass 400 / ha-mcp 403 (Access davor, s. Schritt 5); gitea-mcp 404 (App-Pfad). - HA-Sim: macmini-Host down → bf-nas via pve (4 conns), bf-pve via NAS (4 conns), bf-mm unberührt (8) — alle Dienste weiter 200. Restore → alle 3 Tunnel 8 conns. ### 10.5 Cleanup gemacht - Tote CNAMEs gelöscht: `pbs`, `nginx-bf`, `hermes`, `hermes-geli`. NAS-cloudflared-Leichen `oc-tzcharlie`/`oc-johnny2` entfernt. - `gateway-dw` (192.168.178.1, nur via WG) bleibt CNAME→bf-nas = **404** (kein BF-Connector hat die WG-Route). **Offen: klären/entfernen.** ### 10.6 Schritt 5 Access-Strang — TEILWEISE ✅ (2026-07-10) **✅ `vw`-Leck geschlossen:** vw-App (`1dbc45ca`) hatte 1 Policy = **bypass/everyone (öffentlich)**. Ersetzt durch 2 eigene (engere als die Wildcard!) Policies: `non_identity bf4-home-ip` (`90.146.35.38/32` = Heim ohne Login) + `allow christoph` (email `christoph@emsenhuber.com`, **kein** `login_method:*`). Bypass war eine **reusable** Policy `a8129e37` → nicht via App/Policies-DELETE löschbar, sondern per **App-PUT detacht** (nur die 2 neuen im `policies`-Array). Verifiziert: Heim = 200, kein `everyone` mehr; Account-weiter Sweep = **keine** App mehr öffentlich. Heim-IP `90.146.35.38` = aktuell (== bf4-DNS). **🔴 NEUER FUND (wichtiger als vw!) — Wildcard `*.emsenhuber.net` (`16aaec78`) zu offen:** Policy `christoph` hat `include: email:christoph OR login_method:github OR login_method:google`. **`login_method:` als include matcht JEDEN, der sich via GitHub/Google einloggt** — nicht nur christoph. D.h. **jeder GitHub-/Google-User erreicht nach Login alle internen Dienste** (hass, grafana, portainer, pve, gitea, …). Fix = die zwei `login_method`-Includes raus (nur `email:christoph` + ggf. weitere erlaubte Mails + `non_identity bf4` + `claude-mcp`). **NICHT einseitig geändert** (ändert Login-Verhalten überall) → User-Entscheidung. War im Memory schon als „Policy christoph verschlanken" geflaggt. **⏸️ `hass` 400 / `ha-mcp` — zwei getrennte Layer:** - **Access-Layer (remote):** HA-Companion-App kann kein interaktives Access-Login → Fix = iPhone in **WARP** enrollen (`Warp Login App` `6c32fe23` `allow:christoph` existiert → christoph darf enrollen). Client-seitig, braucht User am Gerät. Vom Heim-Netz (bf4-IP) ohnehin ohne Login erreichbar. - **Origin-Layer:** `hass.emsenhuber.net` gibt **vom Heim-Netz** (Access passt via bf4-IP) trotzdem **400** (CF `server:cloudflare`, aber Origin-verursacht) = **HA lehnt den Request ab** — HA-`http:`-Config (`use_x_forwarded_for` + `trusted_proxies` inkl. cloudflared-Range, ggf. Host-Allowlist). **Separates HA-Thema, NICHT Tunnel/Access** — offen. **gateway-dw** (192.168.178.1, nur via WG) = CNAME→bf-nas = 404 (kein BF-Connector hat WG-Route). Offen: Route bauen oder CNAME entfernen. --- ## 11. Nachtrag 2026-07-12 — bf-nas als EIGENER Tunnel nachgezogen ✅ §10 hatte bf-nas noch als **wiederverwendeten Legacy-Monolith** `70d6a4cf` (Name „bf.emsenhuber.net") gefahren. Jetzt sauber getrennt: - **Neuer Tunnel `bf-nas` = `220c9958-401b-4111-9451-f3db09bba2d5`** (config_src=cloudflare, Ingress 1:1 kopiert). 2 Connectoren neu: pve `cloudflared-bfnas` (host-net), macmini `cloudflared-bfnas` (`cloudflared_default` bridge). - **8 CNAMEs** (gitea/grafana/pve-mcp/omada/vw/ds-bf/3k23uow7/gateway-dw) auf den neuen Tunnel umgebogen. - **WARP-Route `10.40.0.0/16`** (vnet `1480b545-…`) via `PATCH /accounts/…/teamnet/routes/{id}` `{tunnel_id}` umgezogen — **sonst Block:** DELETE-Tunnel scheitert mit `1023 „private network routes"`. - **Legacy-Tunnel `70d6a4cf`/`bf.emsenhuber.net` GELÖSCHT.** `mcp/cloudflare/.env CF_BF_TUNNEL_ID` = neue ID. - Zero-downtime: neue Connectoren parallel hoch → CNAMEs → alte Container/Tunnel weg. Verifiziert: gitea/omada/vw/ds-bf 200, grafana 302, pve-mcp 400 (MCP-Bare-GET), bf-nas 2 Connectoren healthy. - **Writes gehen NUR über `CF_API_TOKEN` (curl/Bearer)** — der `cloudflare`-MCP (OAuth) ist read-only (Create-Tunnel → `10000 Authentication error`). > ⚠️ **CF-Zugang für frische Sessions — die häufigste Stolperfalle (2× reproduziert 2026-07-17):** Es gibt **zwei getrennte** CF-Zugänge, und `~/.claude.json` verweist NUR auf den read-only-MCP (`https://mcp.cloudflare.com/mcp`), **nicht** auf den Write-Token → ein frischer Agent weiß nichts vom Token und meldet fälschlich „fehlende Permissions". > - **`cloudflare`-MCP** (`mcp__cloudflare__docs/search/execute`, OAuth): **strikt read-only**. Reads/Spec-Suche/Batch super; **jeder** Write → `10000: Authentication error` (erwartet, KEIN echtes Rechteproblem). > - **`CF_API_TOKEN` in `mcp/cloudflare/.env`** (scoped, `valid & active`): **der Write-Pfad.** Damit wurde das komplette 3-Tunnel-HA gebaut. Verifiziert 2026-07-17 mit identischem no-op-vnet-PATCH: MCP → `10000`, curl+Token → `success:True`. > - **Muster:** `cd ~/dev/bf-network-r6/mcp/cloudflare && set -a; . ./.env; set +a` → dann `curl -H "Authorization: Bearer $CF_API_TOKEN" …/accounts/$CF_ACCOUNT_ID/`. Keys im .env: `CF_API_TOKEN/CF_ACCOUNT_ID/CF_ZONE_ID/CF_{BF,PVE,MM}_TUNNEL_ID`. > - Alle Calls über `api.cloudflare.com` → **WARP-unabhängig** (Rollback klappt auch bei totem Privatpfad). > - **Klarstellung „Claude hat doch zig Tunnel erstellt/geändert":** ja — aber immer über curl+Token, **nie** über den MCP. Der MCP war nie der Write-Pfad. **hass-400 (2026-07-12 präzisiert):** `hass`/`vw`/`gitea` sind aktuell wieder auf **`bypass`** (App „hass, vw, gitea") → der 400 ist **rein** der Origin-Layer, **nicht Access**. HA-Log: „Received X-Forwarded-For header from an untrusted proxy **10.40.20.10**". Die reziproken bf-pve-Connectoren (macmini `.20.167`, NAS `.20.10`) fehlen in HAs `http.trusted_proxies`. **Fix** = beide IPs + `use_x_forwarded_for: true` + Core-Restart. **Kein SSH-Key auf HA `.20.105` → user-gated** (oder Zugang geben). Access-Härtung (bypass→WARP) bleibt der zweite, device-gated Schritt. --- ## 12. Nachtrag 2026-07-13 — pve-Host-Mgmt VLAN1→VLAN20 (letzter TP14-Host-Umzug) ✅ Letzte in §9.2/§8 als „bleibt `.41`" geführte Origin-Klasse (`pve .41.100`, `j44d6tua`-SSH `.41.100`) nachgezogen — der pve-Host selbst (nicht nur seine Gäste/Container) ist jetzt auf VLAN20: - pve-Host: `vmbr0.20` (bereits als Stub vorhanden, aber mit ungültiger `address 10.40.20.0/24` — Netzadresse statt Host-IP) korrigiert auf **`10.40.20.100/24`**, live via `ifreload -a` (ifupdown2, kein Reboot). `vmbr0`/`.41.100` bleibt drauf, aber **ohne** `gateway`-Zeile (kein Doppel-Default-Route) — interim wie sw1/sw2/ap2-Mgmt bis VLAN99. - Default-Route auf pve geflippt: `default via 10.40.20.1 dev vmbr0.20`. Outbound (`1.1.1.1`) + SSH-Key-Login extern beide grün. - **Ingress `bf-pve` (`f7fdf3a6-…`) gepatcht** (via `CF_API_TOKEN`/curl, `cloudflare`-MCP weiterhin read-only): `pve.emsenhuber.net` `.41.100:8006`→`.20.100:8006`, `j44d6tua.emsenhuber.net`(ssh) `.41.100:22`→`.20.100:22`. Smoke: beide 200 über den Tunnel. - ap1-DNS: `pve.bf.lan`→`.20.100`. **Kollateral-Fund:** `pve-mcp.bf.lan` zeigte noch auf `.41.173` (nie nachgezogen seit TP14.1) → korrigiert auf `.20.173`. - Geprüft nur der Tunnel `bf-pve` (8 Hostnames + catch-all) — sonst keine `.41`-Origins mehr darin (`ccu`/`iobroker`/`z2m25`/`portainer`/`hass`/`ha-mcp` waren schon `.20.x`). `nginx-bf .41.123`/`gateway-bf .41.254` aus §8/§9.2 gehören zu anderen Tunneln/Sub-TPs, **nicht** geprüft in dieser Session. --- ## 13. Incident 2026-07-16 — macmini-Connectoren QUIC-Flap (unterwegs, WARP „spinnt") ✅ gefixt **Symptom (User, unterwegs/BF-fern):** über WARP keine BF-IPs mehr erreichbar; FM-Tunnel (`fm.emsenhuber.net`) ging; FQDNs (`*.emsenhuber.net` über CF Access) gingen noch. User hatte selbst „in Cloudflare herumgedreht". **Befund 1 — Connector-Flap auf macmini (Hauptbefund):** `cloudflared-bfnas` + `cloudflared-bfpve` auf dem **macmini** liefen zwar (`docker ps` = Up 3 Tage), aber die QUIC-Verbindungen zum CF-Edge brachen alle 1–10 Min ab (`timeout: no recent network activity` / `accept stream listener encountered a failure`), live reproduzierbar in den Container-Logs. Dadurch hatten **`bf-nas` und `bf-pve` nur noch je 1 von 2 Connectoren aktiv** (4 statt 8 Conns) — TP16-HA faktisch außer Kraft (nicht down, aber kein Host-Ausfall mehr abgefangen). `bf-mm` (nur pve+NAS, kein macmini) war die ganze Zeit sauber bei 8 Conns — das hat die Diagnose auf macmini eingegrenzt. - **Root Cause:** macminis cloudflared-Connectoren laufen unter **Docker-Desktop-Bridge-Networking** (`cloudflared_default`/`bridge`, userspace-NAT/vpnkit), im Gegensatz zu pve/NAS die **Host-Networking** fahren. Docker Desktop for Mac hat ein bekanntes Problem mit langlebigen UDP/QUIC-Flows über die interne NAT → periodische Idle-Drops. `ping`/UDP-Punktcheck von macmini aus liefen sauber (0 % Loss), nur die **dauerhaften** QUIC-Streams von cloudflared waren betroffen. - **Fix (angewendet, rollend, 0 Downtime da jeweils der andere Connector des Tunnels durchgehend lief):** beide Container auf macmini neu erstellt mit `-e TUNNEL_TRANSPORT_PROTOCOL=http2` (erzwingt TCP/HTTP2 statt QUIC/UDP) — Token/Netz/`restart unless-stopped` unverändert übernommen. cloudflareds eigener Precheck bestätigte das sogar (`suggested_protocol=http2`). Beide sofort stabil, 4/4 Conns, keine Reconnects mehr seit Fix. Verifiziert über `GET /cfd_tunnel/{id}/connections`: `bf-nas` und `bf-pve` wieder je 2 Connectoren / 8 Conns. - **Konvention für die Zukunft:** jeder künftige cloudflared-Connector **auf dem macmini** (egal welcher Tunnel) sollte von vornherein `TUNNEL_TRANSPORT_PROTOCOL=http2` bekommen — pve/NAS (Host-Networking) brauchen das nicht. **Befund 2 — WARP-Private-Network-Route umgebogen (User selbst, Audit-Log bestätigt):** Route `10.40.0.0/16` (vnet `1480b545…`) zeigte bis eben laut §11 auf `bf-nas`. Audit-Log zeigt: User hat um **11:36:11 UTC die alte Route gelöscht und um 11:36:24 UTC eine neue angelegt** — die neue zeigt auf **`bf-pve`** (`f7fdf3a6…`), neue Route-ID `5546dcb6…`. Funktional unproblematisch (bf-pve ist nach Befund-1-Fix wieder voll HA, NAS+macmini erreichen wie pve/macmini bei bf-nas 100 % der Origins/VLANs, s. §10.1). Keine weiteren Anomalien im Audit-Log (10.09–10.36 UTC nur erwartete Änderungen: `nautobot`-DNS+Ingress auf `bf-nas` angelegt, mehrere `tunnel.management_session` = Dashboard-Logins). - Gateway-Regeln, Split-Tunnel-Exclude/Include, Virtual-Networks (nur 1, `vnetemsenhuber`) — alle unauffällig, kein Blocker gefunden. - ⚠️ **Zwischenentscheidung (2026-07-16, später am Tag REVIDIERT — s. Befund 3 + §14):** kurzzeitig als „`bf-pve` bleibt WARP-Route-Baseline wegen USV" festgehalten (Commit `1c1a676`). **Diese Begründung war invertiert** und ist hinfällig: `bf-pve`s Connectoren laufen auf **NAS + macmini** (NICHT auf pve). Bei Stromausfall (nur pve an USV) wären damit **beide** `bf-pve`-Connectoren tot → Route weg. Für die WARP-Route zählt der **Connector**-Standort, nicht der Origin-Host. Der USV-Gedanke führt daher NICHT zu bf-pve. Route bleibt interim auf `bf-pve` als Fallback, bis der native Mesh-Node (§14) steht. **Befund 3 — ICMP strukturell kaputt (User-Ping-Test, nach dem Commit):** TCP über die WARP-Route ging überall (SSH/Web-UIs/MCP), **ICMP nicht.** Dreiländer-Befund: **fm 36 % Loss** (45–655 ms Jitter — ICMP-Proxy über QUIC-Connector, funktioniert aber mies), **bf 100 %** (macmini-Connector jetzt http2 = QUIC-los → ICMP-unfähig; cloudflared-Container ohne Ping-Sockets), **dw 100 %** (192.168.0.0/16 in der WARP-Split-Tunnel-Exclude → Pings betreten den Tunnel gar nicht). **Kernursache:** cloudflared ist ein L7/L4-QUIC-Proxy, kein WireGuard — ICMP darüber ist Zusatz-Gefrickel und war nie sauber eingerichtet. Das ist **kein Bug im heutigen Fix**, sondern eine strukturelle Grenze des cloudflared-Pfads für Private Access. **Einordnung „WARP spinnt" beim User selbst:** die macmini-Connector-Flaps waren ein echter, messbarer Backend-Defekt (Befund 1) und plausibel (mit-)ursächlich für die Unzuverlässigkeit; der ICMP-Totalausfall (Befund 3) ist davon getrennt und strukturell. **Nächster Schritt = Richtungswechsel, s. §14:** Private Access verlässt den cloudflared-Pfad und wandert auf einen **nativen Cloudflare-Mesh-Node (WireGuard) auf dem CRS326 Core-Switch** (Retarget von ap1 auf CRS326, User-Entscheid 2026-07-22). Der cloudflared-Public-FQDN-Teil (3-Tunnel-HA) bleibt unberührt. (Ghost-Connector-Eintrag bei `bf-pve`, arm64, 1 Conn, `run_at` 2026-07-12, seither inaktiv — harmlos, Cleanup bei Gelegenheit.) --- ## 14. Richtungsentscheid 2026-07-16 — Private Access via native Cloudflare Mesh (WARP Connector) auf dem CRS326 Core-Switch (TP16.1) > ✅ **Nachtrag 2026-09-08 (live):** umgesetzt. warp_connector **bf-core-mesh** (`d1da7c8a-…`) ist healthy > und trägt die Route `10.40.0.0/16` — der „Scharfschalten = eigene Session, gated"-Status unten ist > überholt. Siehe §0. > ✅ **Update 2026-07-22 (User-Entscheid):** Ziel-Device retargeted von **ap1** auf den **CRS326 Core-Switch** — konsistent mit TP15-Endstand (kein RB5009, Router bleibt ap1/ap2) und TP21s Kabel-Fabric-Modell. Reine Ziel-Doku-Änderung, Scharfschalten bleibt gated bis TP21 den CRS326 abdeckt. Der Rest dieser Sektion ist entsprechend auf den neuen Zielhost umgeschrieben; CRS326 ist aktuell noch Werkszustand, Management-IP/Interface TBD. **Trennung der Concerns (wichtig):** - **Public FQDNs** (`*.emsenhuber.net`, MCP-Endpoints, HA-Companion, Access-Policies): bleiben auf dem **cloudflared 3-Tunnel-HA** (bf-nas/bf-pve/bf-mm). Unverändert. macmini-Connectoren = `http2` (Befund 1). - **Private Access** (unterwegs → `10.40.0.0/16` per IP, inkl. ICMP): wechselt vom cloudflared-QUIC-Proxy auf einen **nativen WireGuard-Mesh-Node auf dem CRS326 Core-Switch**. **Warum CRS326-nativ statt cloudflared/LXC/Container:** Cloudflare Mesh spricht WireGuard, RouterOS kann natives WireGuard (der TP10-Hub auf ap1 *ist* einer, Muster überträgt sich) → Mesh-Node = WG-Peer zu einem CF-PoP, **kein Container, kein `/dev/net/tun`, kein LXC, keine neue HW**. Der CRS326 ist der zentrale Kabel-Fabric-Knoten und sieht ohnehin alle VLANs; ap1 bleibt Public-Edge/WLAN-Anker, übernimmt aber nicht mehr die Mesh-Node-Rolle. RouterOS-Container-Weg bleibt tot (kein TUN-Passthrough auf JEDER Router/Switch-HW) — daher weiterhin natives WireGuard. **Status: Konzept + Runbook fertig, Scharfschalten = eigene Session, jetzt zusätzlich gated durch CRS326-Bring-up** (User-Entscheid: heute nur Konzept, da der TCP-Pfad funktioniert und nur ICMP-Komfort fehlt; die CF-Prerequisites sind account-weit und träfen die Live-WARP-Geräte). **Vollständiges Runbook + gemessener Account-Ist-Stand: `docs/tp16.1-warp-mesh-native-crs326.md`.** **Kernpunkte fürs Scharfschalten (Details im TP16.1-Doc):** - Plan-Probe zuerst: `POST /accounts/…/warp_connector` (via `CF_API_TOKEN`) — zeigt, ob Mesh im Free-ZT-Plan erlaubt ist; sonst Fallback LXC-auf-pve. - Account-weit (1× kurzer WARP-Reconnect): Unique-Device-IP AN (`use_zt_virtual_ip`), „allow CF-One-Traffic → devices", Device-Profile „Cloudflare Mesh" (WireGuard), Split-Tunnel-Exclude `100.64.0.0/10` → `/11`+`100.112.0.0/12`. - WG-Config via `ghcr.io/animmouse/wgcf-connector ` (ephemer) → 4 native WG-Zeilen auf dem **CRS326** (IF + CF-PoP-Peer `bmXOC+…`/`162.159.193.x:2408` + `100.96.x/32` + Route `100.96.0.0/12`) — konkrete Interface-/IP-Zuordnung erst nach CRS326-Bring-up (TP15) final. - vnet-Route `5546dcb6…` von `bf-pve` auf den Mesh-Tunnel umhängen (Rollback = PATCH zurück; bf-pve bleibt Fallback). - Team-Domain gemessen: `emsenhuber.cloudflareaccess.com` → Node-Identität `warp_connector@emsenhuber.cloudflareaccess.com`. Noch kein `warp_connector`-Tunnel im Account. - Governance „Config nur via Nautobot" (TP21): CRS326-WG-Zeilen regulär via Golden Config, sobald das Device dort adoptiert ist — die alte ap1-Ausnahme gilt hierfür **nicht**. ## 15. Incident 2026-07-21 → ✅ GEFIXT 2026-08-24 — macmini-Connectoren gestoppt, HA fünf Wochen degradiert **Symptom (erhoben 2026-08-16, gefixt 2026-08-24):** `bf-nas` und `bf-pve` liefen auf **je einem** Connector statt zwei. Kein `530`, kein Round-Robin — reiner **Redundanzverlust**: die Dienste hinter diesen Tunneln hingen an einem einzigen cloudflared-Prozess. **Ursache — nicht das erwartete QUIC-Flap.** Die beiden macmini-Container standen auf `Exited (0)`, `finishedAt` **beide auf `2026-07-21T13:00:53`** (gleiche Sekunde, Exit 0, `restart=unless-stopped`, `TUNNEL_TRANSPORT_PROTOCOL=http2` korrekt gesetzt). Ein Absturz sieht anders aus: gleiche Sekunde + Exit 0 + kein Neustart trotz `unless-stopped` = **ein `docker stop` bzw. `compose down` auf genau diese zwei**. Die übrigen macmini-Container liefen die ganze Zeit, der Daemon ist seither auch neu gestartet — Docker hat die zwei also als „vom Benutzer gestoppt" geführt. ⇒ **Die Datierung in TP16 war falsch: degradiert seit 2026-07-21, nicht seit dem 08-16.** Der 08-16 war nur der Tag, an dem es *aufgefallen* ist. Zwischen Eintritt und Entdeckung lagen **vier Wochen**. **Fix:** `docker start cloudflared-bfnas cloudflared-bfpve` auf dem macmini. Sonst nichts — Tokens, Transport und Restart-Policy waren korrekt. **Abnahme (2026-08-24):** - CF-API: `bf-mm` / `bf-nas` / `bf-pve` je **2 Connectoren / 8 conns**, alle `healthy`. - Connector-Log: `Registered tunnel connection … protocol=http2` (Konvention aus §13 gehalten). - **Smoke-Test gegen das Round-Robin-Muster: 6 FQDNs über beide betroffenen Tunnel (`gitea`/`nautobot`/`grafana` = bf-nas, `portainer`/`hass`/`vw` = bf-pve), je 6 Läufe = 36 Anfragen, `530er = 0`.** Das reziproke Design hält: macmini hostet weder NAS- noch pve-Origins, die macvlan-Host-Isolation aus §9 kann dort also nicht zuschlagen. 🔴 **Die eigentliche Lehre ist nicht der Fix, sondern die Nachweislücke.** Ein Tunnel mit einem von zwei Connectoren meldet `healthy` — die Degradation ist über den Tunnel-Status **nicht sichtbar**, nur über die **Connector-Anzahl**. Genau deshalb blieb sie vier Wochen unbemerkt und wurde beim Doku-Aufräumen zufällig gefunden. **Ein HA-Design ohne Zähler auf die Redundanz ist kein HA-Design.** ⇒ Gehört als Check nach **TP11** (Monitoring): `connectoren < 2` je bf-Tunnel = Alarm. ### Korrektur: die vier toten Alt-Tunnel sind harmloser als notiert Stand 2026-08-24, live erhoben: `openclaw`, `coolify`, `johnny2`, `TeilzeitCharlie` sind `down`, 0 Connectoren. Ihre **Ingress-Configs beanspruchen weiterhin Hostnames** — `openclaw` unter anderem `n8n.emsenhuber.net` → `10.40.41.147:5678` (toter VLAN1-Origin), dazu `oc`, `dashboard`, `drawio`; `coolify` → `10.40.41.133`; `johnny2` → `jc`; `TeilzeitCharlie` → `charlie`. 🔵 **Aber: kein einziger CNAME zeigt auf einen dieser vier Tunnel.** Alle 23 Tunnel-CNAMEs der Zone zeigen auf `bf-mm`/`bf-nas`/`bf-pve`/`fm`/`terpene-db`; **`n8n.emsenhuber.net` zeigt korrekt auf `bf-mm`**. ⇒ Die in TP16 notierte Sorge, ein wiederbelebter `openclaw` würde „exakt das alte Round-Robin-Muster auf diesem Hostname" erzeugen, ist **so nicht richtig**: **welcher Tunnel einen Hostname bedient, entscheidet das DNS**, nicht die Ingress-Config. Ein hochkommender `openclaw` wäre inert, solange niemand `cloudflared tunnel route dns` dafür ausführt (was den CNAME umschreiben *würde* — das ist der reale, aber aktive Angriffspfad). Das Round-Robin aus §9 war ein Problem **mehrerer Connectoren auf EINEM Tunnel**, nicht mehrerer Tunnel auf einem Namen. ⇒ **Löschen bleibt richtig — als Hygiene und um die `route dns`-Falle zu entfernen, nicht als Störungsbehebung.** Weiterhin user-gated (Löschen ist nicht umkehrbar). 📌 **Doku-Drift mitkorrigiert:** §10 führt `bf-nas` als `70d6a4cf`; live ist die Tunnel-ID **`220c9958`** (Tunnel am 2026-07-12 neu angelegt, s. §11). §10 gilt sonst unverändert. ℹ️ **Nicht Teil des BF-HA-Designs** (und daher kein Defekt, obwohl sie 1 Connector haben): `fm.emsenhuber.net` (Standort FM) und `terpene-db` (eigenes Projekt). ### ✅ Nachtrag 2026-08-24 — die vier toten Tunnel sind gelöscht User-Entscheid „alle vier löschen". Über die CF-API entfernt, je `success: true`: `openclaw` (`7a8f7b53`), `coolify` (`4f54ad8a`), `johnny2` (`acc73eb5`), `TeilzeitCharlie` (`6c784c98`). **Gegenprobe direkt danach — 5 Tunnel verbleiben:** | Tunnel | Status | Connectoren | |---|---|---| | `bf-mm` | healthy | **2** | | `bf-nas` | healthy | **2** | | `bf-pve` | healthy | **2** | | `fm.emsenhuber.net` | healthy | 1 *(Standort FM, kein BF-HA-Ziel)* | | `terpene-db` | healthy | 1 *(eigenes Projekt)* | Nebenwirkung, die zu **TP19** gehört: mit `openclaw` und `coolify` sind die letzten **VLAN1-Origins** (`10.40.41.147`, `.148`, `.139`, `.133`) aus der Cloudflare-Konfiguration verschwunden. `.41.133` war eines der „unidentifizierten VLAN1-Geräte" aus TP19 B1.2 und ist damit endgültig abgeräumt. ## 16. Korrektur 2026-08-25 — die macvlan-Blindheit war behebbar, der Workaround war größer als der Fix §9 hält die Host-Isolation als **„strukturell, nicht durch Origins-Fixen heilbar"** fest, und daraus ist das reziproke 3-Tunnel-Design mit **sechs** Connectoren entstanden. **Das war zu pessimistisch.** Christoph erinnerte sich (2026-08-24) an einen früheren Fall — *„dass ich vom container meinen host nicht sehen konnte … ich glaube, das haben wir damals die routing table gepatcht"*. Das trifft zu und ist der dokumentierte Standardfix: ein **Shim** — ein zweites macvlan-Interface auf dem Host am selben Parent, mit eigener IP im Subnetz, plus eine Route für die Container-IPs darüber. Danach erreicht der Host seine eigenen macvlan-Container. Für ipvlan gilt dasselbe Muster. ⇒ **Sechs Connectoren und drei Tunnel standen gegen ein Interface und eine Route pro Docker-Host.** Gratis ist der Shim nicht (er muss Reboots überleben — systemd-Unit, LXC-Hook, auf Synology ein Boot-Task), aber der Aufwand liegt um Größenordnungen darunter. 🔑 **Merkregel, die bleibt: bei einer als „strukturell" notierten Einschränkung erst prüfen, ob sie ein Default ist oder ein Gesetz.** Hier stand die pessimistische Lesart über ein Jahr unwidersprochen in der SSoT und hat eine ganze Architektur getragen. 📌 **Für TP31 wird der Shim nicht gebraucht:** Caddy bekommt einen **eigenen LXC** (eigener Netzwerk-Namespace, sieht ohnehin alles), und die cloudflared-Connectoren laufen auf **ap1/ap2** — eigene Maschinen, auf denen die Blindheit prinzipiell nicht auftreten kann. Der Shim bleibt als Option für den Fall, dass später doch ein Dienst neben macvlan-Nachbarn einziehen soll.
## 17. Terpenfinder-DB-Pfad neu aufgebaut 2026-09-02 (Fremdprojekt-Handout blaueblüten) **Auslöser:** Handout `blaueblueten-n8n/docs/handout-bf-infra-db-pfad-20260902.md` — der Cloudflare-Worker `terpene` (`420.teilzeitladen.xyz`) lieferte `503 CONNECTION_CLOSED …hyperdrive.local:5432` auf allen `/api/*`-Reads. **Root-Cause:** TP16.3 §6 hat beim Alttunnel-Abbau den Container **`terpene-cloudflared` (LXC 400)** mit abgeräumt, obwohl das Runbook ihn ausdrücklich als „nicht anfassen" markierte. Damit war der Tunnel `terpene-db` (`b83b68f0`) `deleted_at 2026-08-31`. Der **VPC-Service** `terpene-db` (`019fa3d5`) zeigte weiter auf diese tote ID. Der Public-Weg (PWA→`bf-public`/Caddy) und der **DB-Weg** (Hyperdrive→VPC-Service→cloudflared→Postgres) wurden verwechselt — der DB-Weg ist unabhängig und blieb ungesichert. **Verworfene Optionen (live geprüft):** - **Mesh (`bf-core-mesh`, warp_connector):** CF lehnt ab — `5101: Tunnel is not a cloudflared tunnel`. Ein VPC-Service akzeptiert im `host.network.tunnel_id` **nur einen cloudflared-Tunnel**, keinen warp_connector. (Mesh geht nur über *VPC Networks*, die Hyperdrive nicht nutzt.) - **`bf-public` (AP-Endpoints) wiederverwenden:** bräuchte eine neue Firewallregel `vlan99→10.40.20.20:5432` (Loch mgmt→INFRA, heute nur `.20.40:443` offen, Regel `*42`) **plus** `warp-routing` auf dem geteilten Public-Tunnel (steht auf `false`) — Projekt-Vermischung. Verworfen. **Umgesetzt (Option B):** eigener neuer cloudflared-Tunnel neben der DB. | Objekt | Wert | |---|---| | cfd_tunnel `terpene-db` (neu) | **`f2d2fc8a-54ae-41df-b09a-97312cdb9fe2`**, remotely-managed, healthy/4 Conns | | Connector | Container `terpene-cloudflared` auf **LXC 400** (VLAN20, `.20.126`), `restart=unless-stopped`, Token per `--env-file` | | VPC-Service `terpene-db` | `019fa3d5-…` `host.network.tunnel_id` → `f2d2fc8a` (PUT 200, 2026-09-01T23:57Z) | | Firewall | **0 Änderungen** — Connector und DB im selben VLAN20, kein Cross-VLAN | | Tombstone | Alttunnel `b83b68f0` bleibt soft-deleted, kein Aufräumbedarf | 🔑 **Gotcha 1:** VPC-Service = `/accounts/{id}/connectivity/directory/services/{id}`, Update ist **PUT** (voller Body), **nicht** unter `/vpc/…`. 🔑 **Gotcha 2:** der Repo-`CF_API_TOKEN` (`mcp/cloudflare/.env`) darf `cfd_tunnel` (Create lief per curl), aber **nicht** die Workers-VPC-Resource — dort `10000 Auth error`; der PUT lief über den `cloudflare`-MCP-Credential. 🔑 **Merkregel:** vor einem AP-basierten Weg immer die Egress-VLAN-Seite der Connectoren prüfen — `bf-public` sitzt auf **vlan99**, nicht vlan20.