diff --git a/CLAUDE.md b/CLAUDE.md index 3320409..043aac4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -81,7 +81,20 @@ GW je VLAN = `.1` (crs326-core L3) · Mgmt VLAN99: core `.99.1`, branch `.99.2`, ## Kritische Gotchas - 📜 **~~ALLNET-Gotchas (1 Telnet-VTY, `save` nicht vergessen)~~ — gegenstandslos seit 2026-08-08** (Gerät ausgebaut). Nur noch historisch relevant, s. `switch/README.md`. -- **hAP ax² hat 128 MB Flash, kein USB** → Container NICHT auf dem Router; Container laufen auf NAS/pve. +- 🔵 **Container auf MikroTik — korrigiert 2026-08-25, die alte Pauschalregel war nie nachgemessen.** + Es hiess hier „hAP ax² hat 128 MB Flash, kein USB → Container NICHT auf dem Router". Live gelesen: + **ap1/ap2 sind `arm64` mit 95 MB FREIEM Flash und 690 MB freiem RAM** — das reicht für **einen** + kleinen Container (USB ist laut MikroTik-Doku nur für schnellere Extraktion, nicht Pflicht). + Faustregel: **~70 MB nutzbar je AP**, weil RouterOS Reserve für sein eigenes `.npk` braucht. + 🔴 **`crs326-core` dagegen NIE:** `arm` **32-bit**, **2,9 MB frei von 16 MB**. Der Core ist der + Netz-SPOF, aber **kein Anwendungs-Host** — das ist eine Hardware-Tatsache, keine Politik. + 🔑 **Und die TP16.1-Aussage „Connector als RouterOS-Container ❌ nicht möglich" gilt nur für den + WARP-Connector**, weil der ein **TUN-Device** braucht (RouterOS reicht keines durch). + **`cloudflared` braucht kein TUN** — Userspace-Proxy. Die Schlussfolgerung überträgt sich nicht. + Merkregel: **bei einer „strukturellen" Einschränkung erst prüfen, ob sie ein Default ist oder ein + Gesetz** — und ob sie dem konkreten Dienst überhaupt gilt. +- **Schwere Container laufen weiterhin auf NAS/pve**, nicht am Router (Caddy, AdGuard: die eine Config + ändert sich staendig, die andere schreibt dauernd Logs auf NAND). - **VLAN20-Docker-Hosts: Host-DNS nach dem Umzug prüfen (2026-07-10, TP14.2a):** NAS + pve-LXC zeigten `/etc/resolv.conf` noch auf totes `.41.254` → `docker pull` ghcr scheitert (`EAI_AGAIN`, aber Egress ok!). Fix = `.20.1`: LXC `pct set 400 --nameserver 10.40.20.1`; **Synology-Falle: DSM-„Allgemein"-DNS ≠ was `dockerd` liest** — Interface zieht DNS per DHCP → Fix an der *Netzwerkschnittstelle* „DNS manuell". Laufende Container frieren den `127.0.0.11`-Upstream zum Erstellzeitpunkt ein (Recreate nötig). Merkregel: `docker-pull-hängt` + `dns.lookup EAI_AGAIN` aber `TCP zu ghcr-IP:443 ok` = toter Resolver, nicht Egress. - 📜 **~~ALLNET VLAN-DB (TP1)~~ — historisch.** Die VLAN-Semantik gilt weiter (**40=MEDIA, 50=UNTRUSTED**), die Portangaben (GE1/GE2/GE8) beziehen sich auf ein ausgebautes Gerät. - **ap2 hängt an `crs326-branch ether24`** (Trunk, native VLAN1 + tagged 10-99); **branch-Uplink `ether1` → `crs326-core ether8`** (korrigiert 2026-08-16 — die frühere Angabe „→ sw1 GE8" stammt aus der Zeit vor dem Core-Tausch; MAC-hart belegt in TP22 Schritt 5). diff --git a/docs/cf-tunnel-mapping.md b/docs/cf-tunnel-mapping.md index b466c2f..ec4a104 100644 --- a/docs/cf-tunnel-mapping.md +++ b/docs/cf-tunnel-mapping.md @@ -419,3 +419,27 @@ User-Entscheid „alle vier löschen". Über die CF-API entfernt, je `success: t 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. diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 7e07522..1273d5b 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -75,7 +75,13 @@ ab jetzt bei jeder Änderung mitgezogen, nicht nur die TP-Abschnitte.)* -**Nächster Schritt (Stand 2026-08-23): Christoph entscheidet — der kritische Pfad ist LEER.** +**Nächster Schritt (Stand 2026-08-25): [TP31](#tp31) — Caddy als Reverse Proxy für innen und außen.** +> 🆕 **Neu am 2026-08-24/25:** [TP31](#tp31) löst **TP16** und **TP16.2** ab und dampft cloudflared +> von **sechs Containern auf einen** ein; [TP32](#tp32) gibt die Nummern- und Adress-Systematik vor +> (und hat nebenbei die **falsche Startreihenfolge auf pve repariert** — HA startete vor seiner +> Datenbank). **TP16 ✅, TP25 ✅ und TP16.3 (Pilot) ✅** sind am 24./25. durchgezogen worden. + +**Vorherige Fassung (Stand 2026-08-23): Christoph entscheidet — der kritische Pfad ist LEER.** > 🎯 **Das Projekt ist in seinem Kern fertig.** deny-by-default steht (TP5), Golden Config steht und > meldet **104/104 compliant bei 0 Drifts** (live geprüft 2026-08-23), WLAN steht über CAPsMAN auf dem > Core (TP28), VLAN1 ist leer (TP19) — und **TP6 ist beantwortet statt offengelassen**: CAKE gebaut, @@ -1324,6 +1330,183 @@ unabhängig vom gebündelten Durchgang.** **Blockiert nichts.** Die frühere Kopplung „erst TP17.1, dann rotieren" ist **gegenstandslos** — TP17.1 ist am 2026-08-23 verworfen, die Geräte bleiben WLAN-Clients. + + +### TP31 — Reverse Proxy für innen und außen; cloudflared von sechs Knoten auf einen ▸ 🔜 **GEPLANT 2026-08-25** +> **Auslöser (User 2026-08-24):** „ich weigere mich, für public applications 2 cloudflare container zu +> installieren. … ich habe [den Core] unter der prämisse gekauft, dass über diesen dann auch die public +> apps laufen können. wir wollten doch den core als single point of failure platzieren." + +#### Der Vorwurf, fair geprüft +Eine schriftliche Zusage, dass die Public-Apps auf den Core wandern, existiert **nicht** — +[TP16.1](teilprojekte-archiv.md#tp16-1) ist durchgehend auf den *privaten* Zugang zugeschnitten und hält +mehrfach fest, dass „der cloudflared-Public-Teil unberührt blieb". **Aber der Vorwurf trifft trotzdem +etwas Richtiges:** dasselbe Dokument begründet die gesamte Auswahl mit **Christophs** Prinzip — +*„Router = einziger SPOF, keine Abhängigkeit zu anderen Rechnern"* — und **niemand hat je geprüft, ob der +öffentliche Strang ohne sechs Container auskommt.** Keine Täuschung, aber eine **ungeprüfte Annahme**. + +#### Die Lösung ist nicht „raus aus Cloudflare", sondern „ein Knoten statt sechs" +**Caddy** als Reverse Proxy für **innen und außen**, `emsenhuber.net` in beiden Richtungen, plus **ein** +cloudflared als Tunnel-Endpunkt. + +- ⚖️ **Erst geprüft, dann verworfen: der Weg über `dst-nat`.** Der Core hält `90.146.33.177` direkt ohne + CGNAT, Liwest lässt eingehend alles durch (User: „hatte früher schon nginx hier laufen"), und + Origin Rules (Ziel-Port, **Free = 10 Regeln**), die CF-HTTPS-Ports (`443, 2053, 2083, 2087, 2096, 8443`) + sowie Authenticated Origin Pulls sind alle im Free-Tarif enthalten. Es **ginge** also ohne jeden Container. +- 🎯 **Christophs Einwand ist der bessere Weg:** *„caddy muss so oder so. nachdem dieser vorhanden ist, + fahren wir natürlich über zero trust apps. noch etwas sicherer, aber kein zusätzlicher knotenpunkt, + der ausfallen kann."* Der Tunnel spart drei Risiken auf einmal: **keine angreifbare Origin-IP, keine + CF-IP-Allowlist, kein DDNS als Voraussetzung** (der TP10-Updater bliebe sonst zwingend). + +#### Zielbild +``` +Internet ─► Cloudflare (Access, WAF) ─► Tunnel »bf-public« ─► cloudflared auf ap1/ap2 +WARP ─► cf-mesh (nativ am Core, kein Container) ─┐ +LAN ─► Split-Horizon-DNS ───────────────────────┴─► Caddy (LXC 130, 10.40.20.40) + └─► alle Dienste per Host-Header +``` +**Öffentlich bleiben vier:** `vw` (Bitwarden-Clients), `hass` (Companion-App), `n8n` (Webhooks Dritter), +`gitea` (Access **nur für die Web-UI**, Git-/API-Pfade daran vorbei ⇒ **Push ohne WARP bleibt**). +Alles andere ist intern; **19 Ingress-Zeilen über drei Tunnel werden EINE Catch-all-Regel auf Caddy.** + +#### Wo cloudflared läuft — und warum die APs (live gemessen 2026-08-24/25) + +| Gerät | Arch | Flash frei | RAM frei | Container? | +|---|---|---|---|---| +| **ap1 / ap2** (hAP ax²) | **arm64** | **95 MB / 128 MB** | **690 MB / 1 GB** | ✅ ja | +| **crs326-core** | arm **32-bit** | **2,9 MB / 16 MB** | 512 MB | ❌ **nie** | + +- ✅ **Christophs Argument, das den Ausschlag gibt:** *„cf auf den aps hat den vorteil, dass wir gegenüber + unseren hosts/container nicht blind sind."* — Der AP ist eine **eigene Maschine**, kein Docker-Host; + die macvlan/ipvlan-Blindheit kann dort **prinzipiell** nicht auftreten. Kein anderer Ort hat das. + 💡 Daraus folgt eine Reserve: fällt Caddy aus, kann derselbe Connector über eine zweite Ingress-Regel + **direkt** auf ein, zwei kritische Backends zeigen. +- 🔴 **Ehrliche Einschränkung:** cloudflareds einziges Origin ist Caddy. Solange Caddy auf pve liegt, + kauft ein Connector auf dem AP **Hardware-Diversität, aber keine Verfügbarkeit** — fällt pve aus, ist + alles weg. Der echte Gewinn kommt erst mit `caddy-bf2` (LXC 131). +- **Caddy oder AGH zusätzlich auf die APs? Nein.** 95 MB minus RouterOS-Reserve fürs eigene `.npk` + (~20 MB) = **ein Container pro AP**. Kriterium, das auch künftig trägt: **auf die Infrastruktur darf, + was sich selten ändert und wenig schreibt** — cloudflared ja (Config liegt in Cloudflare, schreibt + nichts); **Caddy nein** (Caddyfile ändert sich bei jedem neuen Dienst); **AGH nein** (Query-Log + schreibt dauernd → NAND-Verschleiß). +- ⚠️ **Preis:** `container` verlangt eine **`device-mode`-Änderung mit physischer Bestätigung** am Gerät + (ap1 Technik UG, ap2 Technik OG). Und der AP bekommt eine zweite Rolle neben dem WLAN. + +#### Umsetzung +1. **Leichen löschen:** `120 adguard-bf1`, `121 adguard-bf2`, `128 nginx-proxy-manager`, `129 caddy`, + `130 pihole1`, `131 pihole2` — alle `stopped`, alle auf **totem VLAN1** (`10.40.41.116/.117`, + GW `.41.254`), `onboot: 0`. ⚠️ `130`/`131` **müssen** weg, bevor die neuen Nummern vergeben werden. + **Alte Backups radieren** (Job `backup-6dcf5c10-610f`, So 01:00, Storage `pbs`, führt heute `120` + und `128`), **`130` neu aufnehmen — derselbe Job.** +2. **LXC 130 `caddy-bf1`** neu anlegen: VLAN20 `tag=20`, `10.40.20.40/24`, GW/DNS `10.40.20.1`, + **`onboot: 1`**, ~4 GB / 512 MB. *(Neu bauen statt umkonfigurieren — die Altlasten sind + Helper-Script-AdGuard-Container und würden auf Jahre eine falsche Identität führen.)* +3. **Caddy mit Cloudflare-DNS-Modul** → **DNS-01**, damit auch rein interne Namen echte Zertifikate + bekommen. 🔑 **Eigenes, eng geschnittenes Token** (`Zone:DNS:Edit` nur auf `emsenhuber.net`), **nicht** + das account-weite `CF_API_TOKEN` ⇒ neuer Posten für **TP30**. +4. **Split-Horizon**: Service-FQDNs → Caddy. 🔗 **Vorher entscheiden: Core (`/ip dns static`) oder + AdGuard?** Sobald AGH nach **TP23 Stufe 2** scharf ist, gehören die Einträge dorthin — sonst zweimal gebaut. +5. **Tunnel `bf-public`** + Connectoren auf ap1/ap2, CNAMEs umhängen (`n8n` → `gitea` → `hass` → `vw`). +6. **Abbau:** `bf-nas`/`bf-pve`/`bf-mm` löschen, sechs Container weg, SSH-Browser-Rendering entfällt, + **MCP-Clients auf FQDN umstellen** (`~/.claude.json` spricht heute `10.40.20.105:9583` und + `10.40.20.173:3000` roh; `n8n-mcp`/`gitea-mcp` kommen dabei wieder in Betrieb). + +🎯 **Kernabnahme: WAN trennen, dann alle Dienste per FQDN.** Das ist die Autarkie, um die es geht. +⚠️ **Preis, offen benannt:** mit Split-Horizon greift **Access innerhalb des Netzes nicht mehr**; dort +tragen TP5-Segmentierung und die App-eigene Auth. + +#### HA-Ausblick (nicht Teil der Umsetzung) +**Es bleibt bei Caddy** — zustandslos bis auf den Zertifikatsspeicher, identisches Caddyfile je Instanz, +versionierbar; NPM hätte eine Datenbank, die man mitreplizieren müsste. +🔴 **Prinzip für `vw`: der Eingang darf nicht klüger sein als die Datenbank.** [TP20.1](#tp20-1) sieht +**manuelles Promote** vor. Zwei Connectoren auf **verschiedene** Caddys an verschiedenen Standorten +würden die Hälfte der **Schreib**zugriffe auf einen read-only Standby schicken — das #1033-Muster, +diesmal mit Datenverlust statt 530ern. **Automatisches Ingress-Failover erst, wenn der DB-Teil es trägt** +(User: vertagt bis TP20.1 Phase 1+2 laufen). + +- **Abh.:** [TP32](#tp32) (Nummern/IPs — vergibt `130`/`.40`), TP16.1 ✅ (Mesh), **TP23 Stufe 2** + (Split-Horizon-Ort). **Löst ab:** TP16 (reziprokes HA) und **TP16.2** (der `vw`-bypass-Strang bekommt + mit Caddy + CF davor einen anderen Schutz). **TP16.3 ist der Pilot dieses TP.** +- 📋 **Vollständiger Plan mit allen Abwägungen:** `~/.claude/plans/expressive-pondering-clarke.md` + + +### TP32 — Nummern- und Adress-Systematik ▸ 🟢 **KONZEPT STEHT (2026-08-25), Startreihenfolge bereits repariert** +> **User-Auftrag 2026-08-24:** „du/ich sollst in der lage sein, selbstständig nach einem vorgegebenen +> system freie ips vergeben zu können … und diese systematik findet sich in anderen netzen künftig auch +> wieder" · „ich meine 100 sollte künftig für die core services stehen." +> +> **Eigener TP, weil es eine Konvention ist, kein Bauteil** — TP31 ist ihr erster Kunde. +> **Regel: Bestand bleibt, wo er ist; jeder NEUE Gast folgt der Systematik.** + +🔑 **Ein gemeinsamer VMID-Raum für VMs *und* LXCs.** `100 haos` und `330 RaspberryMatic` sind **VMs** — +die Klasse bestimmt die Nummer, nicht die Virtualisierungsart. + +| Kreis | Klasse | heute dort (VM *kursiv*) | +|---|---|---| +| **100–199** | **Core / Infrastruktur** | `108 mcast-relay` | +| **200–299** | **Daten / DBs** (Precious-Tier) | *(`105`, `106`, `107`, `302` → später hierher)* | +| **300–399** | **Security / Identity** | — | +| **400–499** | **Platform / Runtime** | ✅ `400 docker` passt bereits | +| **500–599** | **App-Services / Smart Home** | `101`, `102`, `112`, `150`, *`100`*, *`330`* → später hierher | +| **600–699** | **Business / ERP** | `201 openproject` | +| **700–799** | **KI / ML** | — | +| **800–899** | **Dev / R&D / Test** | — | +| **900–999** | **Ephemeral / Scratch** | wird ungefragt gelöscht | + +**Zehnerschritte innerhalb eines Kreises** („Respektabstand", User), damit Instanzen und Nachbarn Platz +haben: `100–109` netznah · **`110–119` DNS** · **`130–139` Reverse Proxy** · `150–159` Monitoring · +`170–179` PKI/Zeit. ⇒ **AGH `110`, Caddy `130`.** + +**Letztes Oktett je /24 — gilt in jedem VLAN, an jedem Standort:** + +| Oktett | Rolle | Anker heute | +|---|---|---| +| `.1–.9` | Gateways / L3 | `.1` je VLAN ✅ · `99.1` core, `99.2` branch ✅ | +| `.10–.29` | physische Hosts (Storage, Hypervisor, APs) | NAS `20.10` ✅ · APs `99.11/.12` ✅ | +| `.30–.99` | virtuelle Core-Services, Zehnergruppen wie oben | DNS `.3x` · Ingress `.4x` · DBs `.5x` · Security `.6x` · Monitoring `.7x` | +| `.100–.199` | App-Services | | +| `.200–.249` | DHCP-Pool | | +| `.250–.254` | VIPs / Relays | | + +🔑 **Der Merk-Trick: die Zehnergruppe im Oktett spiegelt die der VMID.** `110 agh` → `.3x`, +`130 caddy` → `.4x`. Wer eine Zahl kennt, kennt die Klasse der anderen. + +#### Warum der Bestand anders aussieht — er war nicht falsch, nur auf einer anderen Achse +**User 2026-08-25:** „zuerst war haos, welches mit 100 den nummernkreis für iot eröffnet hat. und die +anderen … gehörten zu ha, daher 1xx. erst später habe ich erfahren, dass die nummer die +startreihenfolge definiert." +⇒ Der Bestand gruppiert nach **Zugehörigkeit**, die neue Systematik nach **Klasse**. Beide Achsen sind +legitim; die zweite ist die, die das System auswertet. Der alte `1xx`-Block ist der **Smart-Home-Block** +und wandert später als Gruppe nach `5xx`. + +#### ✅ ERLEDIGT 2026-08-25: die Startreihenfolge war nachweislich falsch +🔴 **Und der Hebel ist NICHT die VMID.** Drei Gäste hatten ein explizites `startup: order=` +(`101 iob-master` 110, `102 mqtt5` 120, `100 haos` 125), alle übrigen keines. **Proxmox startet erst +alle Gäste mit `order=`, dann den Rest nach VMID** — real lief also `iob-master → mqtt5 → haos` und +**erst danach** `platform-pg`, `mariadb`, `z2m25`, `docker`. +⇒ **Home Assistant startete vor seiner eigenen Datenbank.** + +**Repariert (wirkt beim nächsten pve-Neustart):** + +| `order=` | Stufe | Gäste | +|---|---|---| +| 10 | Core | `108 mcast-relay` | +| 20 | Daten | `105 platform-pg` (`up=15`), `302 mariadb` (`up=15`), `106 influxdb2`, `107 redis` | +| 30 | Platform | `400 docker` (`up=20`) | +| 40 | Broker / Funk | `102 mqtt5` (`up=10`), `112 z2m25`, `330 RaspberryMatic` | +| 50 / 51 | Anwendungen | `101 iob-master`, **`100 haos`**, `150 iob-exposed` | + +🎯 **Die wichtigste Erkenntnis des TP: VMID = Klassifikation, `startup: order=` = Abhängigkeitsreihenfolge.** +Die Umnummerierung muss die Startreihenfolge gar nicht reparieren — das ist bereits erledigt, ohne eine +einzige ID zu ändern. **Die Nummernkreise sind damit reine Ordnung und Lesbarkeit**, und der Bestand +kann in Ruhe nachziehen. + +- **Offen:** Migration des Bestands (Tabelle oben) — *am Ende der Reise, nicht jetzt*. Und die + Kollision **AGH will `.30`, dort sitzt Nautobot** (`.31` = nautobot-worker) ⇒ Vorschlag `.36` als + Interim, `.30` erst nach dem Nautobot-Umzug in den App-Bereich. **Fällt vor dem AGH-Neubau an.** +- **Abh.:** keine. **Blockiert nichts**, aber TP31 vergibt bereits danach. + + --- ## Abgeschlossene Teilprojekte ▸ [`teilprojekte-archiv.md`](teilprojekte-archiv.md) diff --git a/docs/tp16.1-warp-mesh-native-crs326.md b/docs/tp16.1-warp-mesh-native-crs326.md index d76cece..c3b2b6b 100644 --- a/docs/tp16.1-warp-mesh-native-crs326.md +++ b/docs/tp16.1-warp-mesh-native-crs326.md @@ -530,3 +530,22 @@ compliance: **68/68, keine Drifts.** - Plan-Gate: wenn `warp_connector`-Create scheitert → LXC-auf-pve-WARP-Connector als Fallback (TUN-Passthrough `c 10:200 rwm`, `warp-cli connector new`, ap1-Static-Route `100.96.0.0/12`→LXC). - ax³/ZeroTier/Tailscale = separate Eval-Fußnoten, nicht Teil dieses Fixes. + +--- + +## Nachtrag 2026-08-25 — „Connector als RouterOS-Container ❌" galt dem TUN-Bedarf, nicht jedem Container + +§2 schließt „Connector als RouterOS-Container" aus, weil **RouterOS-7-Container kein `/dev/net/tun` +durchreichen** und der WARP-Connector-Daemon ein TUN-Device braucht. **Das stimmt weiterhin — für den +WARP-Connector.** + +🔴 **Es wurde damals aber nicht getrennt, und die Verallgemeinerung hat sich festgesetzt:** +**`cloudflared` braucht kein TUN.** Es ist ein Userspace-HTTP/QUIC-Proxy und läuft in einem +RouterOS-Container problemlos — auf arm64 oder x86, `container`-Paket und `device-mode` vorausgesetzt. + +**Live gemessen 2026-08-25:** ap1/ap2 sind **arm64** mit **95 MB freiem Flash** und **690 MB freiem RAM** +— genug für einen Connector. `crs326-core` ist **arm 32-bit mit 2,9 MB frei von 16 MB** und kommt für +Container **nie** in Frage. + +⇒ Die Zeile „verletzt *Router = einziger SPOF, keine Abhängigkeit zu anderen Rechnern*" trug für den +privaten Strang — für den **öffentlichen** hat sie nie jemand geprüft. Genau das holt **TP31** nach.