Christophs zweiter GitHub-Account kam durch — der Ursprungsfund war echt. Die
vormittägliche Schliessung als "Phantom" war ein Fehlschluss (Google-Test
ungeprueft auf GitHub uebertragen) und ist hiermit zurueckgenommen.
Fix: login_method:github aus include raus, in require -> email AND github.
Gesetzt via PUT /accounts/{id}/access/policies/{policy_id} (der App-Pfad gibt
12130 fuer reusable Policies), zurueckgelesen ueber beide Endpunkte.
Sweep ueber alle Apps: login_method nur noch in Terpenfinder v3 — christoph
(github+onetimepin) und geli (nur onetimepin, harmlos). Scope geprueft: die
reusable Policy haengt nur an dieser einen App, kein Kollateral.
Drei neue Gotchas: 12130 (reusable nur unter /access/policies/{id}, der alte
Merkatz meinte das Detach, nicht das Aendern), MCP read-only (1010), 32-Hex-IDs.
Grenze dokumentiert: die Absicht war Kopplung an den GitHub-Username — den
Selector gibt es nicht. Identity-provider-group braucht SCIM (hier disabled,
scim/groups -> 500/12158). email AND github ist das vollstaendige Moegliche.
Aktenhistorie des Umwegs bleibt in allen drei Dateien stehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
47 KiB
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.154, TP45 Schicht A 2026-09-21; vorher.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 ausdocs/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 vnetvnetemsenhuber(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)
- 3 Connectors mit asymmetrischer Reachability + Round-Robin = sporadisch 1033 (Kernursache, log-bewiesen).
- pve-lokale Container (
vw .127,ccu .232) nur vom pve-Connector erreichbar (macvlan, kein LAN-Route von NAS/macmini). - Stale Origin
.41.167: macmini nach VLAN20 (10.40.20.167) gewandert → 5 Dienste zeigen ins Leere. - gateway-dw braucht WG-Route — kein BF-Connector hat sie.
- 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). Smoketestvw4×200 (vorher 1736 Fehlversuche),hass/portainer302. 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-christoph10.40.20.167:8642,hermes-geli10.40.20.167:8643. Ingress-Port9119obsolet → klären, welchehermes.emsenhuber.netbedienen 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-johnny2entfernen.
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,/healthz200). NAS-Leichenoc-tzcharlie/oc-johnny2entfernt. - A2 (Ingress v106): gitea-mcp/n8n-mcp/82unkpb5/n8n/hermes →
.20.167;hermes-geli(:8643) neu;mcp-ms365entfernt. Keine.41.167-Origins mehr. pve→VLAN20 verifiziert (n8n-mcp 200 via bf4). - App-Level-Notizen (kein 1033):
gitea-mcp404 auf/(Sub-Pfad?),hermes502 (Origin .20.167:8642 erreicht, App liefert 502) — separat prüfen.
✅ A3 (DNS) erledigt
hermes-geliCNAME →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:5678neu erstellen (Volumes/ENV erhalten!) → Origin10.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)
- 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. - Interim-Sofortfix: bf-Tunnel auf pve-only (pve erreicht alles außer gateway-dw) → 0×1033. Reversibel.
- 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/ccuggf. auf VLAN20-macvlan heben (dann L2-erreichbar). - Tote Origins bereinigen:
pbs,nginx-bf(noch .41!),hermes,hermes-geli. - Access-Strang (Track B):
hass-400 ohne Passthrough → iPhone in WARP enrollen;vwvon bypass → geschützt. - Loop-Gegentest aller FQDNs (0×1033),
gateway-dwals 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 (parentovs_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 (parentveth20): 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 | 70d6a4cf220c9958-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-Leichenoc-tzcharlie/oc-johnny2entfernt. 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.
✅ BESTÄTIGT und BEHOBEN am 2026-10-06 — der Fund oben war RICHTIG. Christoph hat mit einem zweiten GitHub-Account (fremde Adresse) getestet: er kam durch.
login_method:githubimincludeist ein OR — die danebenstehendeFix (ausgeführt):
login_method:githubvonincludenachrequireverschoben ⇒email AND github. Zurückgelesen über beide Endpunkte, Fix bestätigt. ⚠️ Nebenwirkung: der E-Mail-Einmalcode allein reicht auf GitHub-Seite nicht mehr.🔴 Zwischenzeitliche Fehlspur (dokumentiert, weil lehrreich): eine frühere Fassung dieser Notiz erklärte den Fund am selben Tag für widerlegt — auf Basis eines Google-Tests (
testus@emsenhuber.com→ abgelehnt) plus eines Schlusses auf GitHub. Der Schluss war falsch: der Google-Test zeigt nur Googles Verhalten. Die IdP-Configs sind konfigurationsgleich (beide nurclient_id+redirect_url) — das unterscheidende Feld steht nicht in der Config. Lehre: pro IdP einzeln messen, nicht den ersten Test auf den zweiten übertragen.Bleibt gültig: TP41 hat den internen Wildcard auf Access-Groups (
zt-humans/zt-home/zt-automation) umgestellt — dort steht heute keinlogin_methodmehr. Der Sweep über alle Apps fandlogin_methodnur noch inTerpenfinder v3(christoph: github+onetimepin;geli: nur onetimepin = harmlos).Details, Gotchas (
12130reusable-Policy-Endpunkt, MCP read-only) und die Grenze „kein GitHub-Username-Selector" →docs/teilprojekte.md→### TP49.
⏸️ 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 App6c32fe23allow:christophexistiert → christoph darf enrollen). Client-seitig, braucht User am Gerät. Vom Heim-Netz (bf4-IP) ohnehin ohne Login erreichbar. - Origin-Layer:
hass.emsenhuber.netgibt vom Heim-Netz (Access passt via bf4-IP) trotzdem 400 (CFserver:cloudflare, aber Origin-verursacht) = HA lehnt den Request ab — HA-http:-Config (use_x_forwarded_for+trusted_proxiesinkl. 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: pvecloudflared-bfnas(host-net), macminicloudflared-bfnas(cloudflared_defaultbridge). - 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(vnet1480b545-…) viaPATCH /accounts/…/teamnet/routes/{id}{tunnel_id}umgezogen — sonst Block: DELETE-Tunnel scheitert mit1023 „private network routes". - Legacy-Tunnel
70d6a4cf/bf.emsenhuber.netGELÖ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) — dercloudflare-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.jsonverweist 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_TOKENinmcp/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→ danncurl -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ültigeraddress 10.40.20.0/24— Netzadresse statt Host-IP) korrigiert auf10.40.20.100/24, live viaifreload -a(ifupdown2, kein Reboot).vmbr0/.41.100bleibt drauf, aber ohnegateway-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 (viaCF_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.lanzeigte 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-mcpwaren schon.20.x).nginx-bf .41.123/gateway-bf .41.254aus §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-stoppedunverändert übernommen. cloudflareds eigener Precheck bestätigte das sogar (suggested_protocol=http2). Beide sofort stabil, 4/4 Conns, keine Reconnects mehr seit Fix. Verifiziert überGET /cfd_tunnel/{id}/connections:bf-nasundbf-pvewieder 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=http2bekommen — 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-pvebleibt WARP-Route-Baseline wegen USV" festgehalten (Commit1c1a676). 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 beidebf-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 aufbf-pveals 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 Route10.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/16per 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(viaCF_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-Exclude100.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-PeerbmXOC+…/162.159.193.x:2408+100.96.x/32+ Route100.96.0.0/12) — konkrete Interface-/IP-Zuordnung erst nach CRS326-Bring-up (TP15) final. - vnet-Route
5546dcb6…vonbf-pveauf den Mesh-Tunnel umhängen (Rollback = PATCH zurück; bf-pve bleibt Fallback). - Team-Domain gemessen:
emsenhuber.cloudflareaccess.com→ Node-Identitätwarp_connector@emsenhuber.cloudflareaccess.com. Noch keinwarp_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-pveje 2 Connectoren / 8 conns, allehealthy. - 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 imhost.network.tunnel_idnur 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 Firewallregelvlan99→10.40.20.20:5432(Loch mgmt→INFRA, heute nur.20.40:443offen, Regel*42) pluswarp-routingauf dem geteilten Public-Tunnel (steht auffalse) — 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.