Files
bf-infra/docs/cf-tunnel-mapping.md
Christoph Emsenhuber 1b413b41f3 TP44 Etappe 1: CF-Estate als SSoT in Nautobot (manuelle Erstbefüllung)
Native nautobot.cloud-Modelle befüllt: 1 CloudAccount, 6 ResourceTypes,
4 CloudNetworks (bf-public/fm/terpene-db/bf-core-mesh), 14 CloudServices
(VPC/Hyperdrive/Worker/Access-Apps), 3 Service-Network-Assignments.
Idempotenter Seeder nautobot/tp36-cf-estate-seed.py (get-or-create).
CF bleibt operativer Master, Nautobot = Doku-SSoT; Sync = Etappe 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 02:26:32 +02:00

44 KiB
Raw Blame History

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/tp36-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: → §10 (2026-07-10, TP16 UMGESETZT ✅). §9 = Analyse/Zielbild, §10 = As-Built. Abschnitte 1–8 sind Historie (Track A, 2026-06-30); die „3 Connectors gut/Zielbild"-Aussagen dort sind durch §9/§10 überholt (Round-Robin = macvlan-Host-Isolation → 1/N-Ausfälle). Track A aus docs/handoff-cf-tunnel-1033.md.

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.

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/<id>/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=<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:<idp> 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/<pfad>. 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-pves 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)

✅ 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 <token> (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.