Die Datei war bereits im Working Tree, aber ohne klaren Zweck -- jetzt
umbenannt auf .snapshot.yaml und mit Marker-Kommentar versehen, der sagt:
- das ist KEINE Transaktions-Akte (kein .json)
- das ist auch KEIN Vor-Zustand zum heutigen nas.emsenhuber.net-Edit
- das ist die AGH-Komplett-Config mit bereits angewandtem Standortsuffix
(*.bf.emsenhuber.net), die beim Bau des AGH-Paars (110/111) in der
naechsten Session als Soll-Zustand gilt.
upstream_dns ist auf /bf.emsenhuber.net/ bedingt (Suffix-Form), 26 von
30 Rewrites haben .bf.-Suffix, 4 Public (vw/hass/n8n/gitea) bleiben ohne
Suffix.
Baut auf handoff-20260825 auf (AdGuard-Paar + Split-Horizon) und ergaenzt
den Auftrag um den heute eingefuehrten Standortsuffix-Sweep: alle BF-Hosts
in AGH heissen kuenftig <host>.bf.emsenhuber.net statt ohne Suffix.
nas.emsenhuber.net ist seit 1d569fa weg (Commit direkt vorher).
`nas.emsenhuber.net` war nur als AGH-Rewrite auf 10.40.20.10 vorhanden,
zeigte aber nirgends hin: kein CF-CNAME, kein Caddyfile-Eintrag (der
hatte von Anfang an ds-bf.emsenhuber.net fuer Synology DSM).
Mit dem TP23-Stufe-2-Cutover wandert die DNS-Aufloesung in ein
AdGuard-Paar und der Rewrite-Satz wird neu aufgebaut. Die Regel
ist ab jetzt: Hosts, die es an mehreren Standorten gibt, heissen
immer `<host>.<site>.emsenhuber.net` — kein gemeinsamer Name
ohne Suffix.
Andere namensgleiche Hosts (macmini/mfc/tv/docker/platform-pg/
core/ap1/ap2/branch) bleiben vorerst ohne Suffix in AGH und werden
einzeln in der TP23-Stufe-2-Session bewertet.
- adguard/AdGuardHome.yaml: AGH-Wizard-Setup (27 Rewrites ohne .bf, DoH zum CF-Gateway, conditional emsenhuber.net).
- nautobot/mikrotik_routeros.j2: DHCP dns-server=10.40.20.36,.37, domain=emsenhuber.net.
- docs/transaktionen/TP23-agh-firewall.commands.rsc: TP5-E2 LAN->AGH dns auf .16/.17 ersetzt durch .36/.37.
- docs/transaktionen/TP23-agh-dhcp-cutover.commands.rsc: DHCP-Cutover (dns-server + domain in einem Deploy).
Compliance 104/104, 0 Drifts. Core bleibt als Rückfallebene unangetastet.
[KEIN go fuer den Rest: Persistenz (CLAUDE.md/memory), Host.Naming (.host.emsenhuber.net),
add-dns-entries-Suffix, conditional-Upstream, lease-time-Transaktion, TP31-defer — alles im Plan,
Wartet auf separates go des Users.]
User-Entscheid. minarca, node-red, hms-mqtt-publisher und openproject
zerstoert, 28 PBS-Snapshots geloescht, 0 Fehler. Gegenprobe direkt am
Datastore: keine Spur von ct/103|109|115|201 mehr.
Ergebnis: auf pve laeuft jetzt jeder existierende Gast -- 11 LXC + 2 VMs,
kein einziger stopped. Der Datastore enthaelt nur noch aktuelle Gaeste.
Merkregel mitgeschrieben: die Snapshot-Liste VOR dem pct destroy
einsammeln. pvesm list --vmid liefert danach 0, obwohl die Backups noch
liegen -- der Filter braucht die Gast-Config. Genau deshalb lief der
104er-Loeschversuch vorhin ins Leere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Entscheid: auch die Grafana-Backups loeschen. Gegenprobe direkt am
Datastore (ct/104 = 0), nicht ueber 'pvesm list --vmid' -- dessen Filter
ist nach dem destroy nicht mehr aussagekraeftig.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christoph hat 10.40.41.10/32 (alte VLAN1-NAS) entfernt und den Stand als
stable bestaetigt - kein pending offen. Vertraut wird jetzt nur noch, was
tatsaechlich proxyt: 10.40.20.40 (Caddy) plus die drei cloudflared-Origins,
die mit Schritt 6 wegfallen. Abnahme: hass/vw/gitea/n8n je 200 ueber Caddy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ursache war nicht der fehlende Eintrag, sondern der falsche Ort: HA hat die
http-Konfiguration nach .storage/http migriert ("yaml_migration_done": true,
created_at 2026-08-05). Der YAML-Block wird seither kommentarlos ignoriert -
auch ein absichtlich ungueltiger Schluessel darin erzeugt keinen Fehler.
Die Logzeile fuehrt aktiv in die Irre: "untrusted proxy 10.40.20.40" faellt
laut Quelltext nur bei aktivem use_x_forwarded_for - beide Werte kamen aber
aus .storage, wo .20.10/.126/.167 (die cloudflared-Origins) standen und
Caddy fehlte.
Fix ueber den vorgesehenen Weg: http/config/configure (setzt pending, startet
HA neu) und binnen 5 Minuten http/config/promote. stable enthaelt jetzt
10.40.20.40/32, pending ist leer, hass/vw/gitea/n8n liefern 200 ueber Caddy.
Der wirkungslose Block in configuration.yaml ist durch einen Hinweis ersetzt.
Offen und bewusst vertagt: 10.40.41.10/32 (tote VLAN1-NAS) steht weiter in
der Trusted-Liste.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SoT: CF und Caddy werden NICHT synchron gehalten - die Doppelpflege faellt
mit Schritt 5/6 weg. Heute stehen 19 Ingress-Regeln und 16 Caddy-Sites
nebeneinander und stimmen fachlich ueberein; im Zielbild haelt CF nur noch
eine Catch-all auf 10.40.20.40. Danach: Caddyfile = Name->Origin,
CF = welcher Name ist oeffentlich (4), AGH = Name->IP intern.
Nebeneffekt: die 12 internen Namen brauchen keinen oeffentlichen DNS mehr.
caddy/cf-sync.py (read-only, Exit 1 bei Drift) findet im ersten Lauf sieben
Abweichungen, alle auf CF-Seite: grafana noch im Ingress, nautobot und
gateway-dw als CNAME ohne Ingress (Quelle der 302), drei *.bf-CNAMEs auf den
zerstoerten NPM, dazu die Wildcard-Access-App, die alles maskiert.
Uebergabe korrigiert nach User-Einwand und Gegenmessung:
- Rewrites sind veraltet, nicht wertlos - Hosts leben auf VLAN20 weiter,
also Ziele umbiegen statt Namen loeschen.
- Die Redundanz existiert doch, reziprok ueber die Standorte: FM antwortet
auf 10.101.0.16/.17 (DS415+) - und beide liefern fuer nas.bf die tote
VLAN1-Adresse. Ein Rewrite-Satz nur im neuen BF-Paar erzeugt
standortabhaengig verschiedene Antworten.
- Vorratsregel auf .16 wird gestrichen statt erweitert (User-Entscheid).
- Cave: emsenhuber.net ist die Domain, bf.lan nur der DHCP-Suffix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die erste Fassung entstand vor der Caddy-Abnahme. Live erhoben, dagegen:
- adguard_bf1 (.20.16) ist ein Archiv, keine Vorlage: 24 Rewrites, davon 8
ins tote VLAN1, 9 auf den heute zerstoerten nginx-proxy-manager (LXC 128)
und 2 FritzBox-Reste. Uebernommen werden Upstreams/Filter, die Rewrites
entstehen neu aus caddy/Caddyfile.
- .20.17 ist nicht "bf2", sondern adguard_fm2 (FM-Standort) und antwortet
fuer gitea mit 10.40.41.123. BF hat heute EINEN AGH.
- Die TP5-Vorratsregeln erlauben LAN->DNS hart auf .20.16. Nach dem
DHCP-Flip wird DNS ein forward-Fluss ueber VLAN-Grenzen; ohne erweiterte
Regeln verlieren IOT/MEDIA/UNTRUSTED/GUEST/MGMT die Aufloesung, waehrend
VLAN20 weiterlaeuft und den Fehler tarnt.
Dazu neu: lease-time=1d macht Flip und Rollback traege (erst zur
Erneuerung wirksam), expliziter Rollback-Abschnitt, .36/.37 als frei
geprueft, und der Core bleibt bewusst Rueckfallebene.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Schritt 3 ist durch: Token liegt, deploy.sh gelaufen, Dienst active+enabled.
Abnahme ueber den Host-Header von einem zweiten Host (pve): 11x 200,
nautobot 302, Antwortzeiten 0,02-0,11 s.
Zwei Funde, die man sonst falsch ablegt:
- pve-mcp 400 / ha-mcp 403 / gitea-mcp 404 sind KEINE Proxy-Fehler - die
Gegenprobe direkt am Origin liefert dieselben Codes. Es sind die Antworten
der MCP-Server auf ein nacktes GET /.
- hass bleibt 400, aber die Logzeile sagt "untrusted proxy 10.40.20.40" und
nicht "not set-up for reverse proxies": use_x_forwarded_for greift also,
nur die Liste zieht nicht. Zwei volle Neustarts, Config-Check valid.
Naechster Schritt notiert; die atime taugt unter relatime nicht als Beweis.
Ist-Stand-Block mitgezogen (Projektregel).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Split-Horizon-Entscheid (AdGuard statt Core) macht aus 'ein paar
Eintraegen' eine Verschiebung der DNS-Aufloesung des ganzen Standorts in
einen Container -- heute liefert der DHCP in allen sieben VLANs den Core.
Das gehoert nicht ans Ende einer langen Sitzung (Lehre aus TP28).
Handoff enthaelt: Ausgangslage (Caddy produktiv, 16 Sites/17 Zertifikate),
den Auftrag in fuenf Schritten inkl. der IP-Kollision .30 (Nautobot) und
der Vorgabe, AGH als Paar 110/111 zu bauen statt als DNS-SPOF, sowie die
Staffelung VLAN fuer VLAN mit VLAN30 zuletzt.
Vier Fallen mitgegeben, alle in dieser Session bezahlt: Statuscode vom
oeffentlichen FQDN beweist nichts (grafana), pvesm free scheitert an
geschuetzten Snapshots stillschweigend, Startreihenfolge haengt nicht an
der VMID, und Core-Config braucht Golden Config.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Caddy in LXC 130 ist produktiv: 17 von 17 Zertifikaten per DNS-01 von
Let's Encrypt, Dienst active+enabled, Proxy gegen Host-Header verifiziert
(nautobot 302, gitea 200, pve 200, portainer 200). deploy.sh laeuft
End-to-End; Token per Fingerprint gegengeprueft -- eigenes Zone:DNS:Edit,
nicht das account-weite.
🔴 Fund beim Durchtesten: grafana war seit Langem tot und Cloudflare
Access hat es maskiert. LXC 104 stopped, konfigurativ noch auf VLAN1
(10.40.41.109), waehrend die Ingress-Zeile auf 10.40.20.109 zeigte -- eine
Adresse die es fuer Grafana nie gab. Der FQDN lieferte trotzdem 302, weil
das der Access-Login war. Exakt die Falle aus TP16.3 Paragraph 8, diesmal
in freier Wildbahn: ein toter Dienst sieht hinter Access monatelang
gesund aus.
=> Caddy-Zeile raus (16 Sites), LXC 104 zerstoert, aus dem Backup-Job.
Die 14 PBS-Snapshots bleiben bewusst stehen -- einzige Kopie etwaiger
Dashboards.
hass liefert 400: bekannter trusted_proxies-Punkt aus TP16, gehoert vor
die CNAME-Umstellung.
Split-Horizon entschieden (User): in AdGuard zusammen mit TP23 Stufe 2.
Dokumentiert, was das bedeutet -- heute liefert der DHCP in allen sieben
VLANs den Core als DNS; AGH bekommt niemand. Der Schritt verschiebt die
Aufloesung des ganzen Hauses in einen Container, deshalb als Paar
110/111 bauen. Die geloeschten Altlasten hiessen nicht zufaellig
adguard-bf1/-bf2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nach der Relay-Reparatur lag weiter nichts an. tcpdump auf der VLAN40-Leitung:
jedes SSDP-Paket des MacBooks kam von Chrome (ST dial-multiscreen,
USER-AGENT Chromium), kein einziges von Sonos. Ursache war das
macOS-Local-Network-Gate - es stand auf "an" und griff nicht. Schalter
aus/ein + App-Neustart hat es gerichtet (User-bestaetigt).
Damit faellt auch die tragende Zahl des Vormittags-Handoffs: die "291 Suchen
der App in 12 Minuten" waren Chrome plus eigene Proben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die macOS-Sonos-App fand ihre Player nicht. Ursache war nicht die Firewall
(MEDIA->MAIN ist offen) und nicht der vermutete Race um den globalen
"last SSDP search source"-Slot, sondern die Flagge --ssdpUnicastAddr selbst:
multicast-relay.py Z. 630 schreibt die Quelle JEDES SSDP-Pakets an
239.255.255.250:1900 auf <addr>:1901 um (auch NOTIFY), Z. 691 verwirft
das Paket dann beim Senden auf eth1, weil 10.40.10.21 nicht im VLAN40-Netz
liegt. Der Hinweg lief damit nie.
Messung vorher: 0 Pakete via eth1 gegen 308 via eth0 in 20 min, 0x
"Received SSDP Unicast" im gesamten Journal seit 2026-08-18. Nachher:
M-SEARCH quellerhaltend in VLAN40, HTTP/1.1 200 OK von 10.40.40.193/.195
an beiden MacBook-Beinen, Drop-Log in:vlan40 out:vlan10 = 0.
- mcast-relay/multicast-relay.service: reparierte Unit jetzt im Repo
(ausgerollt auf LXC 108, Backup /root/multicast-relay.service.bak-20260825)
- CLAUDE.md: Gotcha korrigiert, Richtungsbilanz als Erstmessung, Hinweis auf
die SO_REUSEPORT-Falle auf Port 1900 und das dual-homed MacBook (.183/.82)
- docs/teilprojekte.md: Ist-Stand nachgezogen, TP33 (Fernzugriff) als Stub
- docs/teilprojekte-archiv.md: TP7.1-Aussage "--ssdpUnicastAddr ist noetig"
widerrufen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die sieben verbliebenen Snapshots waren in PBS als protected markiert.
Auf User-Freigabe entschuetzt (pvesh set .../content/<volid> --protected 0)
und geloescht. Gegenprobe: 0 Snapshots zu allen sechs geloeschten IDs,
72 von 72 weg. VMID 130 gehoert damit ausschliesslich caddy-bf1.
Merkregel mit aufgenommen: pvesm free scheitert an geschuetzten
Snapshots mit 'cannot remove protected snapshot' -- und zwar
stillschweigend, wenn man den Fehler nicht ausliest. Wer nur die
Erfolgszaehler liest, haelt ein halb erledigtes Aufraeumen fuer fertig.
Genau so waeren hier sieben Snapshots stehen geblieben.
TP31-Abschnitt auf den Ist-Stand gezogen: Schritte 1 und 2 erledigt,
Schritt 3 wartet nur noch auf das Zone:DNS:Edit-Token.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Aufgeraeumt (User-Freigabe): LXC 120/121/128/129/130/131 zerstoert --
alle stopped, onboot=0, alle konfigurativ noch auf totem VLAN1
(10.40.41.116/.117, GW .41.254). pct destroy --purge hat 120 und 128
zugleich aus dem Backup-Job entfernt. 65 von 72 PBS-Snapshots geloescht;
sieben sind PROTECTED und stehen noch -- bewusst nicht ueberschrieben.
Neu nach TP32-Systematik:
- LXC 130 caddy-bf1, VLAN20 tag=20, 10.40.20.40/24, GW/DNS .20.1,
onboot=1, startup order=10 (Core), Debian 13, 4 GB / 512 MB
- Caddy v2.11.4 mit dns.providers.cloudflare (Custom-Build)
- caddy/Caddyfile im Repo, 17 Sites: 4 oeffentlich (vw/hass/n8n/gitea),
13 intern inkl. der vier MCP-Endpunkte und drei HTTPS-Backends
- caddy/deploy.sh liest CF_DNS_API_TOKEN aus ~/.secrets und schreibt es
in die Container-Env -- nie auf stdout, nie in einer Kommandozeile
- 130 in denselben Backup-Job aufgenommen
Caddy laeuft noch NICHT: das eng geschnittene Zone:DNS:Edit-Token fehlt.
Ein Token anzulegen und im Klartext zu handhaben ist nichts, was ich
selbst tue -- der Weg ist ~/.secrets plus deploy.sh.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP31 -- Caddy als Reverse Proxy fuer innen UND aussen, cloudflared von
sechs Containern auf einen. Anlass war Christophs Einwand, er habe den
Core unter der Praemisse gekauft, dass auch die Public-Apps darueber
laufen. Aktenlage geprueft: eine Zusage gibt es nicht, aber TP16.1
begruendet die Auswahl mit seinem Prinzip 'Router = einziger SPOF' --
und niemand hat je geprueft, ob der oeffentliche Strang ohne sechs
Container auskommt. Keine Taeuschung, eine ungepruefte Annahme.
- dst-nat-Variante geprueft und verworfen (ginge, Free-Tarif reicht),
weil Christophs Tunnel-Variante drei Risiken spart: keine angreifbare
Origin-IP, keine CF-IP-Allowlist, kein DDNS als Voraussetzung
- cloudflared auf ap1/ap2: live gemessen arm64, 95 MB Flash frei,
690 MB RAM frei. Der Core kann es nie (arm 32-bit, 2,9 MB frei)
- Kriterium fuer Infrastruktur-Container: was sich selten aendert und
wenig schreibt. Caddy nein (Config aendert staendig), AGH nein
(Query-Log frisst NAND)
TP32 -- VMID-Systematik (Hunderter = Klasse, gemeinsamer Raum fuer VMs
und LXCs) + letztes Oktett je /24, uebertragbar auf andere Standorte.
🔴 Dabei gefunden und SOFORT REPARIERT: die Startreihenfolge war falsch.
Proxmox startet erst Gaeste mit explizitem startup order=, dann den Rest
nach VMID -- drei Gaeste hatten einen, die DBs nicht. Home Assistant
startete damit vor MariaDB, MQTT und z2m25. Jetzt fuenf Stufen
(Core/Daten/Platform/Broker/Apps). Erkenntnis: VMID = Klassifikation,
startup order = Abhaengigkeit -- die Umnummerierung muss den Startlauf
gar nicht reparieren.
Doku-Korrekturen aus den Messungen:
- CLAUDE.md: 'Container NICHT auf dem Router' war nie nachgemessen
- tp16.1: 'Connector als Container ❌' galt dem TUN-Bedarf des
WARP-Connectors; cloudflared braucht kein TUN
- cf-tunnel-mapping Paragraph 16: die macvlan-Blindheit war mit einem
Shim behebbar -- der Workaround war groesser als der Fix
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Runbook ausgefuehrt. Vorbedingungen alle erfuellt, Testclient hing im
Hotspot-Netz 172.20.10.13 mit aktivem WARP -- also nicht im BF-LAN, der
einzige Aufbau der fuer Vorbedingung 2 etwas beweist.
Schnitt: nautobot.emsenhuber.net aus bf-nas (8 -> 7 Regeln), Catch-all
bleibt letzte. Rollback-Sicherung in docs/cf-backup/. Gegenprobe durch
Zuruecklesen der Config, nicht am Statuscode.
Abnahme vollstaendig, inkl. des uebersehenen Punktes: Golden Config lief
durch (Backup -> Intended -> Compliance, 104/104, 0 Drifts). Die uebrigen
fuenf bf-nas-Hostnames unveraendert.
Befund, der die Abnahmetabelle des Runbooks korrigiert: der oeffentliche
FQDN taugt nicht als Test. Er liefert vor UND nach dem Schnitt 302, weil
der von Cloudflare Access kommt, nicht vom Origin -- Access greift vor
dem Tunnel (JWT: auth_status NONE bei is_warp true). Damit auch eine
ehrlichere Erwartung: nautobot war nie ohne Access-Login oeffentlich
erreichbar, der Schnitt entfernt die zweite Tuer, nicht die erste.
Paragraph 7 des Runbooks ist ueberholt -- die HA-Degradierung ist am
selben Tag repariert, der Fall steht auf dem verbliebenen Argument.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Steht bisher nur in TP30/TP25, also nur beim Oeffnen von
teilprojekte.md sichtbar. Gehoert neben die sshpass-p-Warnung im
Tooling-Abschnitt, weil es dieselbe Klasse ist (Credential geraet
ueber ein Nebenprodukt in ein Transkript) und CLAUDE.md jede Session
gelesen wird.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Kollektor am Manager (15-s-Takt, 29 Samples, 28 Clients). Von den drei
Kandidaten fallen zwei, und beide ohne Wartezeit:
- (b) DHCP-lease-time: tot. dhcp-v30 faehrt lease-time=1d, Renew bei
12h -- kann 5:05 nicht erzeugen. Eine Abfrage, keine Messung.
- (a) periodischer VAP-Re-Apply: tot. Auf genau dem VAP, der angeblich
alle 5:05 abwirft, standen drei Clients bei 16h51m Uptime, 25 von 28
ueber 6h. Dafuer braucht es die vier Zyklen nicht -- ein einziges
Sample mit 16h51m widerlegt einen 5-Minuten-Takt.
- (c) Geraet selbst: bleibt, ist aber nicht pruefbar.
Denn die zwei Fund-F-MACs sind schlicht weg: ARP status=failed, keine
Lease, nicht in der Registration-Table, HA kennt sie nicht. Merkregel
wie beim P750W -- erst pruefen ob das Geraet ueberhaupt da ist, bevor
ein periodisches Trennen als Funk-/Configfehler untersucht wird.
Nebenbefund: einziger Client mit Uptime-Ruecksetzer war der DTU
(54:F2:9F:12:51:F0) auf ap1, 43min Sitzung, bei -52 dBm. Nicht Fund F,
aber echt -- derselbe ESP-Ein-Radio-Mechanismus wie in der Transaktion
TP17.1-dtu-pin-ap2. Gehoert zur Neubewertung des Pins.
Rohdaten: docs/messdaten/tp25-fundf-20260824.log
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Vier Alt-Tunnel (openclaw/coolify/johnny2/TeilzeitCharlie) per CF-API
geloescht, User-Entscheid. Gegenprobe: 5 Tunnel, bf-* je 2 Connectoren.
Letzte VLAN1-Origins damit auch aus der CF-Config weg (Rest von TP19)
- TP25: Kanalplan fuer den dritten AP gerechnet, DFS genehmigt.
ETSI-Budget als Tabelle (Band A/B/C, 40-MHz-Bloecke duerfen keine
Bandgrenze queren). Empfehlung: neuer cAP ax auf 5180/Ce non-DFS,
ap1/ap2 nach Band B (5260/5300), 5220/Ce als Ausweichspur frei.
Band B statt C wegen CAC 60s statt 600s und gleichem 23-dBm-Deckel
- Zwei Fallen benannt: hart gepinnte Frequenz macht DFS zum SPOF
(Channel-Objekt braucht eine Liste), und die erreichte tx-power in
Band B messen BEVOR umgezogen wird -- das ist Fund B nochmal
- Platzierung: Messung widerspricht dem Aufstellen an bisheriger Stelle
(17/21 Abschnitte haben 0% Verlust). Vorschlag: cAP ax an den guten
Platz, verdraengter hAP in den Drei-Zimmer-Schatten
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP16 -- Ursache war NICHT das erwartete QUIC-Flap: die beiden
macmini-Connectoren standen auf Exited(0), beide finishedAt auf
derselben Sekunde 2026-07-21T13:00:53, bei korrektem
restart=unless-stopped und http2. Also ein docker stop / compose down.
Fix = docker start. Abnahme: alle drei bf-Tunnel je 2 Connectoren /
8 conns, 36 Anfragen ueber 6 FQDNs beider Tunnel mit 530er=0.
- Datierung korrigiert: degradiert seit 07-21, nicht seit 08-16
(der 08-16 war der Tag der Entdeckung) -- vier Wochen unbemerkt
- Nachweisluecke festgehalten: 1 von 2 Connectoren meldet healthy,
nur die Connector-ANZAHL zeigt die Degradation -> Check nach TP11
- openclaw-Warnung korrigiert: welcher Tunnel einen Hostname bedient,
entscheidet das DNS; kein CNAME zeigt auf die vier toten Tunnel,
n8n zeigt korrekt auf bf-mm. Loeschen bleibt richtig als Hygiene
- Doku-Drift: bf-nas ist live 220c9958, nicht 70d6a4cf
- cf-tunnel-mapping.md Paragraph 15 als As-Built
TP25 -- 5-GHz-Umfeldscan am Manager: je EIN Fremdnetz pro AP, -86 bzw
-89 dBm. Band leer, Bloecke ueberlappungsfrei => beide ueblichen Gruende
fuer 20 MHz treffen nicht zu. Empfehlung: 20/40 behalten; der echte
Ausloeser ist die AP-Zahl (Band A = genau 2x40 MHz, mit zwei APs voll),
dann lautet die Wahl 20 MHz flottenweit gegen DFS akzeptieren.
TP30 -- neues Leak-Ereignis dokumentiert: list_wifi_interfaces gibt alle
Passphrasen im Klartext aus, damit sind fuenf WLAN-PSKs exponiert.
Als Falle aufgenommen. TP17.2-Stub entfernt (Verweise erklaeren den
Merge, ein Wegweiser ist nicht mehr noetig).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Entscheid: TP30 sammelt jedes Credential, das neu gesetzt werden
muss -- nicht nur Rotationen. Das Shelly-Geraetepasswort (TP17.2) ist
eine Erstvergabe und gehoert damit dorthin; ausserdem teilt es sich mit
der PSK-Rotation den Geraete-Durchgang (ein Reboot statt zwei).
- TP17.2-Volltext nach TP30 verschoben (Posten #3), Stub bleibt als
Wegweiser, damit die Nummer nicht ins Leere zeigt
- TP30-Titel/Scope geweitet: "neu setzen & rotieren", mit expliziter
Trennung Erstvergabe vs. Rotation (Prioritaet unterschiedlich,
Arbeitsaufwand identisch)
- Detailabschnitte symmetrisch als "Posten #1" / "Posten #3" benannt
- Querverweise nachgezogen: Naechster-Schritt-Block, Split-Regel,
TP17.3-Abgrenzung, Archiv-Kopfzeile TP17
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vier Rotationsposten (MikroTik-admin, IoT-PSK, Shelly-Geraetepasswort,
CF-Access-Token) lagen als verstreute Follow-up-Zeilen herum. Der teure
Teil jeder Rotation sind die Konsumenten (HA-Re-Auth x4, Nautobot-Stack-
Redeploy), nicht das Setzen -- einzeln gemacht zahlt man den mehrfach.
Deshalb ein Sammel-TP mit Ausloesekriterium statt Termin.
- 100 Zeilen Radius-/Etappe-1-Detail aus den Follow-ups nach TP30 verschoben
(nicht dupliziert), Follow-ups tragen jetzt einen Zeiger
- Etappe 1 (Service-Accounts ha/nautobot) ist durch; admin ist NICHT rotiert
- Stale: "nach TP17.1 sind es weniger Geraete" -- TP17.1 ist verworfen,
die Geraete bleiben WLAN-Clients, die Rechnung gilt unveraendert
- Handoff 08-24 + Naechster-Schritt-Block als ueberholt markiert
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Einstieg ist die Passwort-Rotation Etappe 2: Nautobot und die vier
HA-mikrotik-Integrationen auf die gestern angelegten Service-Accounts
umhaengen, dann erst admin rotieren. Die Vorarbeit steht komplett, und
das admin-Passwort ist zweimal in ein Transkript geraten -- derselbe
Wert, da alle vier Geraete ihn teilen.
Festgehalten sind ausserdem die beiden Messungen, die vorherige Annahmen
widerlegen (eco_mode hebt die Sendeleistung nicht an; restart_required
auf 14 Geraeten war ein Fehlalarm), der Grund fuer das Verwerfen von
TP17.1, und die Fallen, die man sonst neu erhebt -- darunter die
abweichende s-Nummerierung zwischen HA und Repo, der stale VLAN1-Sweep
in migrate.py und die Regel, nach jedem Shelly-Firmwarewechsel den AP zu
pruefen.
teilprojekte.md zeigt im Ist-Stand jetzt auf diese Uebergabe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vor dem Rotieren den Radius erhoben -- und der ist groesser als geplant:
das Admin-Konto teilen sich fuenf Konsumenten. Neben ~/.secrets und der
MikroMCP-Registry haengen der Nautobot-Stack (Portainer-Redeploy noetig)
und VIER HA-mikrotik-Integrationen mit 40 device_tracker daran. Die HA-
Eintraege melden supports_reconfigure=false, sind also nicht skriptbar.
Christophs Entscheid daraufhin: Konten trennen statt ein Passwort teilen.
Nicht das Rotieren ist das Problem, sondern dass ein einziges admin von
fuenf Stellen benutzt wird -- sonst kostet jede Rotation wieder vier
Re-Auths und einen Stack-Redeploy.
Etappe 1 ist durch, rein additiv, kein laufender Dienst beruehrt. Vorher
existierte auf allen vier Geraeten nur admin in der Gruppe full. Jetzt:
grp-ha read,api,rest-api,test -> user ha
grp-nautobot ssh,read,write,test,sensitive -> user nautobot
Passwoerter als MIKROTIK_HA_PASS / MIKROTIK_NAUTOBOT_PASS in ~/.secrets.
Angelegt ueber ein Skript, das die Werte aus der Datei liest -- bewusst
nicht ueber manage_user, dessen password-Parameter im Transkript landet.
Abnahme auf allen vier Geraeten: ha liest (am Core 59 DHCP-Leases) und
wird beim Schreiben abgewiesen; nautobot kommt per SSH rein und
exportiert. Der Export von nautobot ist byte-identisch zu dem von admin
(391/56/87/87 Zeilen) -- die GC-Compliance driftet beim Umstellen also
nicht, was das Hauptrisiko dieser Etappe war. /user wird von keiner
ComplianceRule abgedeckt, die Konten erzeugen selbst keinen Drift.
Offen: Konsumenten umhaengen (Nautobot-Stack, 4x HA), dann erst admin
rotieren -- danach beruehrt eine Rotation nur noch zwei Dateien.
Eigener Fehler protokolliert: eine Enumeration hat das ap1-Passwort im
Klartext ins Transkript geschrieben. Selber Wert wie der am 22.08.
verbrannte, also keine neue Expositionsklasse -- aber Merkregel ergaenzt,
dass Secrets-Enumeration nur Schluesselnamen ausgibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs strukturelle Frage hat TP17.1 gekippt: "zigbee sollte die
antwort auf die vielen radios auf -iot geben. nutzt aber wenig wenn man
das wifi nicht abdrehen kann bzw. es nicht mehr aktivieren kann ohne
reset."
Der Pilot hat den Weg technisch vollstaendig bewiesen -- und gezeigt, dass
das Ziel so nicht erreichbar ist. Das Geraet bleibt WLAN-Client; der
gemessene Funkgewinn ist klein (12 von 26 IoT-Clients, je 150-200 KB rx /
0,6-3 MB tx in sechs Stunden); und WLAN abzuschalten waere unumkehrbar,
weil die Zigbee-Firmware keinen AP hat, Shelly kein Zigbee-OTA macht und
InstallAlt eine IP braucht. Der Weg ist nicht gescheitert, das Ziel war
mit ihm nicht erreichbar. Das Runbook bleibt als Wissensspeicher.
Rueckbau: ZHA-Knoten entfernt -- Leave VOR dem Flash, damit kein
Geisterrouter im 52-Geraete-Mesh bleibt. s9 zurueck auf PowerStrip, Config
aus dem Backup. Alle vier roten EZSP-Zaehler blieben 0, Retry-Quote fiel
im Delta auf 8,9 %.
Neue Merkregel: der Rueckflash zog einen OFFENEN AP hoch (ap.enable=true,
is_open=true). Abgeschaltet und mit dem IoT-PSK abgesichert. Nach jedem
Shelly-Firmwarewechsel den AP pruefen.
eco_mode flottenweit aus (User: "der rotz macht nur probleme"): 13 Geraete
umgestellt, null Fehler, 9 standen schon so. Jetzt eco=false auf allen 22
erreichbaren Shellys ausser s24, das es nicht unterstuetzt. Dafuer
migrate.py um ein eco-Kommando ergaenzt -- mit Retry je Geraet, weil ein
Timeout an einem schwachen Link den Sweep sonst abreisst.
Die Gegenmessung widerlegt meine eigene Warnung: eco aus hebt die
Sendeleistung NICHT messbar an. 13 geaenderte Geraete im Mittel -0,9 dB,
Kontrollgruppe von 13 unveraenderten +0,0 dB bei gleicher Streuung. Die
TP17-Aussage, eco senke Takt UND Sendeleistung, stimmt nur zur Haelfte.
Vorbedingung der Passwort-Rotation geprueft: alle vier Skripte laufen
laengst auf sshpass -e, die gegenteilige Notiz war veraltet. Uebrig war
CLAUDE.md, das sshpass -p weiterhin aktiv als Reboot-Weg empfahl -- genau
das Muster, das den Leak verursacht hat. Auf sshpass -e korrigiert.
TP17.2 aus "zurueckgestellt" aktiviert und an die PSK-Rotation gekoppelt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ZHA-Backup zuerst (is_complete true, Kanal 20, PAN 5B5A) -- das ist der
Punkt, der 2024 gefehlt hat. Dann permit_join + StartNetworkSteering:
network_state joined nach 10 Sekunden.
Abnahme nach Runbook-Kriterium erfuellt. ZHA hat vier switch-Entities
angelegt. Gegenprobe quer ueber beide Wege: turn_on ueber ZHA gesendet,
Ergebnis ueber die WLAN-RPC des Shelly gelesen -- switch:0 output=True,
2.1 W. Der Zigbee-Befehl hat das physische Relais geschaltet. Danach
wieder aus, Ausgangszustand hergestellt.
Zaehlervergleich vor/nach dem Join: alle vier roten Zaehler unveraendert
0. NEIGHBOR_ADDED +1 (genau der neue Router), NEIGHBOR_REMOVED weiterhin
0. Broadcast:Unicast im Delta 1,8:1 gegen eine Normallage von 6,7:1 --
unicast-lastiger Interview-Traffic, das Gegenteil einer Sturmsignatur.
Erhoeht und vor dem zweiten Geraet erneut zu lesen: Retry-Quote im Delta
44 % (Normallage ~15 %) und PHY_CCA_FAIL_COUNT 7 -> 19.
Der Pilot ist damit noch nicht fertig -- Schritt 2 (HA-Seite) steht:
alte Shelly-Entities entfernen, bevor umbenannt wird, sonst haengt HA
ein _2 an; vier Ziel-entity_ids notiert; zwei Gruppen-Helper (sonos
wohnzimmer, tv) referenzieren s9 und brechen sonst; Ausgangsnamen und
initial_state aus dem Backup zurueckschreiben; Energie-Statistiken
brauchen einen Fix-Lauf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christoph hat Weg (A) gewaehlt (Zigbee, Hersteller-Firmware) und als Pilot
s9 wohnzimmer_sideboard bestimmt -- nach dem Kriterium physische
Zugaenglichkeit. Das ist das bessere Kriterium: von den 12 Gen4 sind nur s9
und s13 Steckerleisten, die anderen zehn Unterputz. s13 scheidet aus (NAS
und Drucker haengen dort).
Ergebnis: s9 laeuft auf slot=0, app=PowerStripZB, ver 2.0.0.
Korrekturen am Runbook, alle live am Geraet erhoben:
- Deckung ist 12 von 12 Gen4, nicht 10. Die frueher als "von keinem Weg
abgedeckt" gefuehrten S4PL-00416EU (s9, s13) bekommen PowerStripZB
angeboten, mit stable-Build.
- s4 kueche_mikrowelle ist ein S3PL-00112EU = Gen3. Der im Runbook erhoffte
beste Pilot existiert nicht; das Geraet bleibt bei -93 dBm im WLAN.
- Der Wechsel ist KEIN Modus-Umschalter, wie die Shelly-Support-Seite
beschreibt, sondern ein Firmware-Wechsel im Zwei-Slot-Modell. Auf der
WiFi-Firmware existiert kein Zigbee.*-Namespace. Drei undokumentierte
RPCs aus dem UI-JS extrahiert: Shelly.InstallAlt, Shelly.SetAlternative,
Shelly.ListAlternatives -- nur die erste ist hier nutzbar.
- Blocker (a) Rueckrollbarkeit ist geschlossen: die Zigbee-Firmware bietet
PowerStrip ("with Matter", stable) ihrerseits als alt an, ueber das Netz.
WLAN und statische IP ueberleben den Wechsel, das Geraet bleibt unter
10.40.30.216 erreichbar. Eine frueher in derselben Session geaeusserte
Einschaetzung, der Rueckweg sei physisch und die Unterputz-Module damit
Einbahnstrassen, war falsch.
Verloren gehen: Matter komplett, der AP, alle Ausgangsnamen und
initial_state. Vollbackup vor dem Flash liegt vor.
Beobachtung fuer die Serie: der erste InstallAlt brach bei 2 % ab; nach
eco_mode=false lief derselbe Aufruf glatt durch. n=1, keine bewiesene
Kausalitaet -- aber eco_mode=false vor dem Flash kostet nichts.
Offen: s9 ist noch keinem Zigbee-Netz beigetreten (network_state failed),
die vier Ausgaenge sind derzeit nicht aus HA steuerbar. Vor dem Join in ZHA
fehlt das ZHA-Backup.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beide von Christoph gemeldeten Geraete sind repariert:
s23 dieleug-wohnzimmer_licht (.203, ProDimmer 2PM)
eco_mode=false, Geraete-AP abgeschaltet
-> beide Lampenausgaenge flackerfrei, Workaround entfaellt
s26 bad_luefter (.233, Gen4 2PM)
eco_mode=false + Reboot
-> Doppeldruck weg
Der diskriminierende Test lief in der im TP vorgesehenen Reihenfolge: erst
eco_mode aus bei weiter aktivem AP (nicht aussagekraeftig, beide Hypothesen
sagen dort dasselbe voraus), dann AP aus -- und genau die Konstellation, die
vorher geflackert hat, blieb stabil.
Weitere Ergebnisse aus dem Sweep ueber alle 22 erreichbaren Shellys:
- Die RSSI-basierte eco-Politik aus TP17 ist damit nicht nur stale, sondern
widerlegt. Der Flotten-Entscheid "eco flottenweit aus" haengt jetzt an
TP17.1, weil er die Sendeleistung von ~20 IoT-Geraeten anhebt und damit
ins Funkbild von TP25 greift.
- restart_required stand auf 14 von 22 Geraeten, nicht auf 2. Entwarnung:
Reboot von s26 mit Config-Vergleich davor/danach -- identisch. Kein Geraet
sitzt auf versteckten Aenderungen.
- Was das Bit gesetzt hat, ist am Geraet nicht rekonstruierbar (169 RPC-
Methoden, Config-Diff, Geraetelog -- alle drei Wege negativ). Nicht erneut
untersuchen.
- eco_mode braucht keinen Reboot; das Geraet antwortet selbst mit
restart_required=false. Eine anderslautende Warnung von mir war falsch.
- AP-Anker-Sweep erledigt: nur s23 hatte einen AP an, kein Rest im Bestand.
- Nebenbefund: alle Shellys ziehen NTP von time.cloudflare.com statt vom
Core -- statische IPs sehen DHCP-Option 42 nie. Betrifft jedes statisch
adressierte Geraet im Netz.
- inventory/bf.csv fuehrt s12 noch auf der alten .41.219.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Uebergabe docs/handoff-20260823-session.md: was die Session war (Doku-Split Punkt F
fertig, dann Shelly-/Funkmigration), womit die naechste anfangen sollte (TP17.3 --
einziger offener Punkt mit spuerbarem Alltagsschaden, von uns verursacht, blockiert
TP17.1), und die Zahlen, die niemand neu erheben muss.
Neu: docs/wifi-access-list-erklaert.md auf Christophs Wunsch ("keine ahnung von tuten
und blasen"). Von Null: was die Liste ist, wo sie unter CAPsMAN lebt, wann sie greift,
was eine Regel matchen kann -- und der eine Satz, der alle Ueberraschungen erklaert:
eine Regel kann nur nein sagen, sie kann kein Geraet irgendwo hinschicken. Dazu die
drei Anwendungsfaelle im Projekt (Signal-Boden, Messen, PSK-Wechsel ohne Flag-Day),
die Governance seit der ComplianceRule und fuenf Merkregeln aus echten Fehlgriffen.
Ausserdem: ein Duplikat von TP17.3 entfernt, das ich beim Anlegen uebersehen hatte --
der Abschnitt existierte bereits und war deutlich gruendlicher (Phasenanschnitt-
Hypothese, Gegenprobe s12, stale eco-Politik, restart_required-Fund). Die
ausfuehrliche Fassung bleibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
get-config read-only ueber Port 10081 abgefragt (hoymiles-wifi 0.5.6, isoliertes venv,
nur lesende Kommandos, Passwortfelder in der Ausgabe redigiert).
channel_select = 0. Damit ist Christophs These "Kanalwahl fix eingebrannt" widerlegt,
und zwar an der Quelle statt durch Indizien. Seine Beobachtung war trotzdem richtig,
nur die Ursache eine andere.
Die tragfaehige Erklaerung: das Geraet sucht nicht. Es haelt an dem AP fest, mit dem es
provisioniert wurde, und gibt auf, wenn der es abweist, statt sich einen anderen zu
suchen -- genau das beobachtete Verhalten. Nicht der Kanal ist starr, sondern die
AP-Bindung. Typisch fuer einfache ESP-Firmware ohne Roaming-Logik.
Folge, die eine Option wiederbelebt: ap1s eigenen Kanal umzulegen wirkt. Ohne
channel_select folgt der DTU dem AP, an dem er haengt -- der Stoerer wandert mit, ohne
dass das Geraet je abgewiesen wird oder neu provisioniert werden muss. Das ist der
einzige risikoarme Weg, ihn von ch1 wegzubekommen, und er faellt beim Kanalplan fuer
die zwei neuen APs ohnehin an.
Die access-list bleibt gesperrt -- nicht wegen des Kanals, sondern wegen der
Aufgeben-Eigenschaft.
Nebenbefund mit Vorsicht notiert: dtu_ap_pass und lock_password liefern nur 1 Zeichen
zurueck, mit hoher Wahrscheinlichkeit ein maskierter Platzhalter. Daraus wird
ausdruecklich KEINE Passwortschwaeche abgeleitet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nachtrag zum fehlgeschlagenen Pin. Auch nach dem Rollback, mit freiem ap1 auf ch1,
blieb der DTU weg. Zurueck kam er erst, als Christoph ihm ueber die S-Miles-App die
WLAN-Zugangsdaten erneut uebergab -- danach binnen Sekunden wieder auf ap1,
dirtyvader-iot, -51 dBm, verifiziert in der Registration-Table.
Damit verschaerft sich die Lehre: ein einmal abgewiesener DTU gibt seine gespeicherte
Verbindung dauerhaft auf. Ein reject gegen dieses Geraet ist kein Experiment, sondern
ein Ausfall, dessen einziger Rueckweg Handarbeit vor Ort mit der Hersteller-App ist --
nicht per Fernzugriff behebbar. Die access-list ist fuer dieses Geraet gesperrtes
Gebiet, solange der PV-Datenpfad produktiv ist.
Nebenbefund: dass die Re-Provisionierung auf ap1 (ch1) sofort klappte, waehrend der
Wechsel auf ap2 (ch11) scheiterte, stuetzt die Kanal-These zusaetzlich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Audit-Trail zum fehlgeschlagenen DTU-Pin. state=rolledback, closed 2026-08-23.
access-list ist wieder leer, Snapshot-Vergleich 0 zu 0 Zeilen, keine offenen
Transaktionen mehr auf crs326-core.
Abnahme am Geraet statt am Job-Status: DTU wieder erreichbar, und die Telemetrie
fliesst -- 385,8 W, Tagesertrag 613, Zeitstempel 14:48. Die Unterbrechung hat rund
zehn Minuten gedauert.
Hinweis fuer spaetere Leser: das reason-Feld der Akte nennt noch die Annahme, ueber
ap2 wandere der DTU-AP auf ch11. Genau die ist widerlegt worden -- das Geraet hat
eine feste Kanalwahl und kann auf ch11 nicht assoziieren. Die Akte bleibt bewusst
unveraendert (sie ist ein Protokoll, kein Dokument); die Aufloesung steht im
Runbook unter "Versuch DTU an ap2 binden -- FEHLGESCHLAGEN".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auftrag war, den nicht abschaltbaren DTU-AP von ch1 wegzubekommen, indem man den
Client per access-list an ap2 bindet. Transaktion TP17.1-dtu-pin-ap2 eroeffnet, fuenf
reject-Regeln auf ap1s 2,4-GHz-Interfaces deployt. Der DTU flog um 14:38:48 von ap1
und kam bei ap2 nie an. Nach 2,5 Minuten zurueckgerollt, access-list ist wieder leer.
Ursache ist Christophs Verdacht und protokollseitig belegbar: SetConfig.proto kennt
channel_select (Feld 9). Der eigene AP des Geraets sendet auf ch1, und ein ESP hat ein
Radio -- AP und STA teilen zwingend den Kanal. ap2 laeuft auf ch11, dort kann das
Geraet gar nicht assoziieren. Die Sperre hat es also nicht umgeleitet, sondern
ausgesperrt. Christophs Wiederverbindungsversuch ueber S-Miles scheiterte mit genau
der Meldung, die er von Frequenz-Fehlanpassungen kennt.
Damit ist meine Empfehlung "AP-Kanal verschieben, indem man den Client bindet" fuer
dieses Geraet widerlegt und im Text durchgestrichen. Sie gilt weiter fuer frei
scannende Geraete wie die Shellys.
Zwei Merkregeln festgehalten:
- Ein reject auf AP A ist keine Umleitung auf AP B, sondern ein Rausschmiss. Ob das
Geraet woanders unterkommt, ist seine Entscheidung. Bei fixem Kanal: nirgends.
- Vor einem Pin pruefen, ob der Client den Kanal des Ziel-APs ueberhaupt benutzen
kann. Der Beleg lag vor: DTU-AP auf 2412, ap2 auf 2462. Signalstaerke ist kein
Nachweis fuer Assoziationsfaehigkeit -- meine Abnahme war zu lasch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs Hinweis war richtig, die Antwort steckte im Addon-Umfeld -- allerdings
nicht im Addon selbst (ha-hoymiles-wifi-addon v0.5 alias hms-mqtt-publisher ist rein
lesend und pollt nur Telemetrie), sondern in der Protokolldefinition, die die
Schwester-Bibliothek suaveolent/hoymiles-wifi offenlegt.
SetConfig.proto kennt dtu_ap_ssid (48) und dtu_ap_pass (49), dazu wifi_ssid/-password,
netmode_select, channel_select und dhcp_switch. Es gibt KEIN ap_enable. Damit ist
"AP laesst sich nicht abschalten" aus der Schnittstellendefinition ableitbar statt aus
Forenberichten.
KORREKTUR eines eigenen Fehlbefunds: ich hatte "null offene TCP-Ports" gemeldet.
Falsch, 10081 ist offen. Ursache war ein kaputter Port-Test -- timeout existiert auf
macOS nicht, jeder Aufruf lief auf command not found und wurde als geschlossen
gewertet. Merkregel festgehalten: ein Test, der bei jedem Port dasselbe Ergebnis
liefert, hat sich selbst widerlegt.
Folge: mein Gegenargument gegen die Fallback-Idee ("dann kaeme man gar nicht mehr an
die Konfiguration") ist hinfaellig -- ueber 10081 bleibt die Konfiguration auch ohne
AP erreichbar. Die Idee ist technisch sauber, Hoymiles implementiert sie nur nicht.
Gueltig bleibt: 80/443/8080/8000 sind zu, es gibt LAN-seitig keine Weboberflaeche.
Und der AP ist verschluesselt (wpa2-psk), der bekannte Fall vom offenen DTU-WLAN
trifft hier nicht zu. Einzige sinnvolle Haertung waere dtu_ap_pass, falls dort noch
das Werkspasswort steht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Am Geraet geprueft und recherchiert. Es ist kein separater DTU-Kasten, sondern der
Wechselrichter mit eingebautem DTU -- daher DTUBI, Built-In.
Abschalten: existiert nicht. Hoymiles bietet keine Funktion dafuer an, im
Herstellerumfeld wird sie von Nutzern gefordert. Christophs Recherche hat nichts
gefunden, weil es nichts zu finden gibt.
Entwarnung: der AP ist bereits verschluesselt (wpa2-psk;wpa-psk). Der bekannte Fall
"Hoymiles-DTU funkt ein offenes WLAN" trifft hier nicht zu. Ab FW 3.0.8 gibt es die
AP-Passwort-Einstellung, die offenbar gesetzt ist.
Die Fallback-Idee (AP nur wenn kein Link) ist ein Standardmuster, aber hier mit
Haken: das Geraet hat LAN-seitig null offene TCP-Ports -- geprueft, nur ICMP
antwortet, Daten kommen per MQTT-Push. Die Weboberflaeche existiert ausschliesslich
auf dem AP. Bei funktionierender STA-Verbindung waere sie damit unerreichbar, obwohl
man sie genau dann braucht.
Der Hebel, den es stattdessen gibt: ein ESP hat ein Radio, AP und STA laufen
zwangslaeufig auf demselben Kanal. Der DTU-AP sitzt auf ch1, weil seine STA-Verbindung
dort haengt. Bindet man den Wechselrichter per access-list an ap2, wandert sein AP
mit. Nicht abschaltbar, aber verschiebbar -- und dieselbe Regel erklaert den Shelly
s23: wer den Stoerer verschieben will, verschiebt den Client.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Meldung: der Luefter-Shelly muss doppelt gedrueckt werden, und der Dimmer in
der Diele UG flackert unkontrolliert seit der Migration -- mit eingeschaltetem AP
ist das Symptom weg.
KORREKTUR eines eigenen Fehlbefunds von heute Vormittag: ich hatte den aktivierten
AP auf s23 als vergessenen Anker aus TP17 eingeordnet, der abgeschaltet gehoert.
Er ist Christophs Workaround. Der als "Einzeiler" beschriebene Fix haette eine
funktionierende Reparatur zerstoert. Merkregel dazu festgehalten: ein Zustand, der
nach einem Verfahren uebrig aussieht, kann eine Reparatur sein -- vor dem Aufraeumen
fragen, wozu er da ist, nicht ob er ins Schema passt.
Leithypothese aus dem read-only-Sweep ueber alle 22 Geraete: nicht die WLAN-Config,
sondern eco_mode. Es senkt den CPU-Takt; ein Phasenanschnitt-Dimmer braucht praezises
Nulldurchgangs-Timing, und ein aktiver AP hebt die Energiesparzustaende auf -- das
erklaert genau die Beobachtung "AP an, Symptom weg". s23 ist ein SPDM-002PE01EU
(app ProDimmerx) mit eco_mode=true; s26 hat eco_mode=true bei momentary-Eingang, was
zum verschluckten ersten Tastendruck passt. Gegenprobe: s12 am selben Ort, gleiches
Modell wie s26, eco_mode=false, unauffaellig. Diskriminierender Test in vier Schritten
notiert, reversibel, ein Geraet.
Zwei Nebenfunde aus demselben Sweep:
- Die eco-Politik von 2026-07-13 ist stale und war nie konsistent: drei Geraete haben
eco an, obwohl sie unter -80 dBm liegen; zwei haben es aus, obwohl sie darueber
liegen. Die fuer "nach TP3.3" vorgemerkte zweite Evaluation hat nie stattgefunden.
- restart_required=true auf s26 und s12: dort liegt eine geschriebene, nie aktivierte
Konfigurationsaenderung, seit 21 bzw. 33 Tagen ohne Neustart.
Anker-Sweep gelaufen: s23 ist der einzige Shelly mit aktivem AP, die anderen 21 sind
sauber de-anchored.
5-GHz-Scan nachgeholt: nur drei Fremdnetze, alle <= -83 dBm, das Band ist praktisch
leer. Planungsaussage fuer die zwei neuen APs: im ETSI-Indoor-Band sind bei 40 MHz
genau zwei ueberlappungsfreie Bloecke vorhanden, und beide sind vergeben -- AP drei
und vier muessen ins DFS-Band. Dass DFS hier nutzbar ist, belegt ein Nachbar auf 5500.
DTU: bleibt wie sie ist (User). Sie gehoert zur PV, ihr AP ist deren Konfignetz, die
Messdaten kommen ohnehin ueber -iot. Als bekannter Dauersender auf ch1 dokumentiert,
nicht bekaempft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Scan auf beiden APs durchgefuehrt (User hat die Client-Unterbrechung freigegeben).
Neuer Gotcha, auch in CLAUDE.md: /interface wifi scan geht am CAP NICHT, nur am
Manager gegen cap-wifiN. Der Gegentest schliesst device-mode und Policy aus --
/tool fetch meldet auf demselben Geraet explizit "not allowed by device-mode",
waehrend der Scan nur "not allowed" sagt, und die Gruppe full hat test und sniff.
Ein CAP besitzt sein Radio nicht.
Ergebnis: kein einziges Fremdnetz ueber -81 dBm. Die Nachbarschaft ist fuer eine
Wohnlage bemerkenswert ruhig.
Die zwei lautesten Stoerer im Band sind eigene Geraete, und keines davon ist ein AP:
- Shelly s23 (dieleug-wohnzimmer_licht) sendet einen eigenen Access Point auf ch11
mit -51 dBm. WiFi.GetConfig bestaetigt ap.enable=true. Das ist ein uebrig
gebliebener Anker aus dem TP17-Migrationsverfahren, bei dem das De-Anchoring nicht
angekommen ist -- das Geraet funkt seither doppelt, als Client auf ch1 und als AP
auf ch11. Fix waere ein Einzeiler, nicht ausgefuehrt weil nicht beauftragt. Die
anderen 21 Anker sind nie gegengeprueft worden.
- Hoymiles-DTU sendet ebenfalls einen Konfig-AP, auf ch1 mit -59 dBm.
Fuer die Zigbee-Frage: das Fenster 2426-2448 ist nur schwach belegt, ZB18 bleibt
valide -- aber ohne Handlungsdruck, CCA=4 gilt weiter. ZHA bleibt auf 20.
Neue Randbedingung durch die zwei kommenden APs: 2,4 GHz hat drei ueberlappungsfreie
Kanaele. Funken vier APs dort, ist ch6 belegt und ZB18 faellt aus. Empfehlung, die
beides loest: die neuen APs als 5-GHz-Schwerpunkt fahren -- haelt ch6 frei, vermeidet
Selbststoerung und legt Kapazitaet dorthin, wo sie laut TP25 fehlt.
Homematic/HmIP nachgetragen (User-Hinweis): 37 Geraete an der CCU, classic und HmIP
gemischt, beide auf 868 MHz -- ausserhalb dieser Rechnung. Eigener Ausfallmodus ist
der 1-Prozent-Duty-Cycle, das Gegenstueck zum Broadcast-Sturm. Relevant fuer TP29,
dessen Aktor genau die HmIP-HEATING-Geraete waeren.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei Fragen von Christoph beantwortet, alle mit Messung statt Schaetzung.
1) Woran erkennt man einen Broadcast-/Routing-Sturm: die EZSP-Zaehler des
Koordinators, mit einer echten Baseline von heute. BROADCAST_TABLE_FULL,
ALLOCATE_PACKET_BUFFER_FAILURE, PHY_TO_MAC_QUEUE_LIMIT_REACHED und
TYPE_NWK_RETRY_OVERFLOW stehen alle auf 0 -- jede Abweichung davon ist der Alarm.
Normallage sonst: Retry-Quote ~15 Prozent, Broadcast-zu-Unicast 6,7:1. Dazu ein
vorab festgelegtes Abbruchkriterium fuer den Testjoin, damit im Moment nicht
diskutiert werden muss.
2) Welche Geraete sind fuer fehlerhaftes Routing anfaellig -- beide Netze
durchgesehen. ZHA: 3 Aqara lumi.weather als Kanarienvogel (klassisches
Aqara-an-Hue-Problem, 14 Hue-Router im Netz), 3 GLEDOPTO mit dokumentierter
Router-Schwaeche. Z2M: 6 Busch-Jaeger ZLL-Altgeraete, die die Wandbeleuchtung
tragen, plus 4 Tuya-Geraete, eines davon ohne saubere Definition.
Daraus die Netzwahl fuer den Test: ZHA, nicht Z2M -- Proportion (24 vs 7 Router),
Blast Radius (in Z2M haengt das Licht an den Altgeraeten) und Messbarkeit.
3) ZHA-Kanal: bleibt auf 20. Korrektur meines eigenen Befundes -- ich hatte ch20
als den Konflikt im Haus markiert, weil 2450 auf der Unterkante von WLAN ch11
liegt. PHY_CCA_FAIL_COUNT steht bei 4 ueber die gesamte Zaehlperiode, die Adjazenz
beisst also nicht. Ein Wechsel muessten 52 Geraete mitmachen, und wer nicht folgt,
ist verwaist -- Risiko ohne belegten Nutzen. Falls doch je gewechselt wird: 18,
und erst nach einem Scan der Nachbar-WLANs, weil die Luecke genau WLAN-Kanal 6 ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nachtrag zum vorigen Commit -- diese drei Aenderungen sind dort durch einen
fehlgeschlagenen Textanker nicht mitgeschrieben worden, nur Runbook und CLAUDE.md
waren drin.
- Zwei Drucker: P750W = Etikettendrucker VLAN30 (stimmte), Brother MFC = der
eigentliche Drucker auf VLAN10, live bestaetigt 10.40.10.6 (OUI Brother,
statisch). Beide Angaben waren richtig, sie meinten verschiedene Geraete.
- s1/s2/s3 sind in HA DEAKTIVIERT, nicht fehlend -- meine Formulierung war falsch.
- Das vollstaendige 2,4-GHz-Bild (Thread 15 / ZHA 20 / Z2M 25 gegen WLAN 1+11)
samt dem einen Konflikt: ZHA ch20 auf der Unterkante von WLAN ch11.
- Der Z2M-Vorbehalt aus 2024 als das, was er ist: die schwerste offene Frage des
Zigbee-Wegs, mit Blast-Radius-Trennung als Mitigation ohne Ursachenkenntnis.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alle vier Funknetze live erhoben: WLAN ap1 ch1 / ap2 ch11, Thread (OTBR) ch15,
ZHA ch20, Z2M ch25. Es sind DREI 802.15.4-Netze, nicht eines -- das war in der
bisherigen Planung nicht abgebildet.
Befund: das Band ist gut geplant bis auf ZHA ch20 (2450), das direkt auf der
Unterkante von WLAN ch11 (2451) sitzt -- ausgerechnet 52 ZHA-Geraete gegen den AP
mit 26 Clients. Thread ch15 und Z2M ch25 liegen je 2 MHz ausserhalb einer
WLAN-Bandkante, also sauber. Die Luecke 2423-2451 (ZB 16/17/18) ist unbenutzt,
aber ein Kanalwechsel muessen 52 Geraete mitmachen -- erst Energy-Scan.
Z2M-Vorbehalt aus dem 2024-Vorfall als eigenes Kapitel: die Fehlerklasse ist
benennbar (Broadcast-/Routing-Sturm, trifft ZHA genauso), der Root Cause aber
nicht mehr rekonstruierbar. Mitigation ohne Ursachenkenntnis = Blast Radius
trennen: die zehn neuen Router komplett in EIN Zigbee-Netz, und zwar nicht in
das, das Licht und Fernbedienungen traegt. Dazu einzeln joinen, Backup vorher,
keine Gruppen-Bindings, Abbruchkriterium vorher festlegen.
UART-Prozedur konkret dokumentiert: J6-Pinout (TXD GPIO16, RXD GPIO17, 3V3, GPIO0
als BOOT, GND), GPIO0 beim Einschalten LOW, Versorgung vom Adapter statt Netz,
Geraet muss aus der Wand. Kein Reset-Knopf. Faellt einmal je Geraet an, danach
alles OTA. Recovery = dasselbe rueckwaerts mit dem 8-MB-Image.
Zwei Korrekturen von Christoph uebernommen:
- Es gibt ZWEI Drucker. P750W = Etikettendrucker auf VLAN30 (stimmte), der
eigentliche Brother MFC haengt auf VLAN10 -- live bestaetigt 10.40.10.6, OUI
Brother, statisch. Auch in CLAUDE.md eingetragen, samt der Folge fuer TP5: der
MFC steht im selben VLAN wie die Macs, die forward-Kette greift dort nicht.
- s1/s2/s3 (weihnachten) sind in HA DEAKTIVIERT, nicht fehlend. Meine Formulierung
"existieren gar nicht" war falsch -- deaktivierte Entities haben keinen Zustand.
Entity-Bruch entschaerft: der Umbau behaelt die Entity-Namen (User-Entscheid).
Damit faellt der teuerste Posten der Abwaegung weg, fuer Zigbee wie fuer Thread.
Zwei Fallen dazu notiert (alte entity_id erst nach Entfernen frei; unique_id und
Statistiken sind trotzdem neu).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Entscheid: das Arbeitspaket wird im Netz-Projekt gesteuert, nicht im
HA-Projekt. HA ist Betroffener (Entity-Bruch), nicht Eigentuemer -- die
Entscheidung ist eine Funk- und Netzentscheidung.
Aus der Uebergabe wird docs/tp17.1-shelly-gen4-funkmigration-runbook.md, auf den
heutigen Stand gebracht: die drei Wege (Zigbee offiziell / Thread abwarten /
Thread per Dritt-Firmware) als Vergleichstabelle, die Geraetebefunde, die
Zigbee-Kanalplanung gegen ap1 ch1 und ap2 ch11 als Rechenschritt, und die
Verzahnung mit der parallel laufenden PSK-Rotation inkl. der s1/s2/s3-Falle.
Titel geaendert: "Thread ODER Zigbee". Der reine Thread-Zuschnitt haette den
einzigen heute verfuegbaren Weg ausgeschlossen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Shelly.CheckForUpdate ueber die Flotte (read-only): stable ist ueberall 2.0.0,
fuer KEIN Geraet gibt es ein stabiles Update; beta waere 2.0.1-beta1 (Build
2026-08-19). Entscheidend ist der alt-Block: fuer die Gen4 liefert Shelly
alternative FUNK-Firmware ueber den normalen Update-Kanal -- S2PMG4ZB, S1PMG4ZB,
PowerStripZB, jeweils "with Zigbee". Gen3 hat keinen alt-Eintrag.
Zwei Folgerungen eingetragen:
- Frueindikator statt Pressemeldungen: eine kuenftige Thread-Variante erschiene
mit hoher Wahrscheinlichkeit genau dort als weiterer alt-Eintrag. Pollen statt
warten.
- Zigbee ist eine Option, die vorher nicht auf dem Tisch lag: erfuellt alle drei
Ziele von TP17.1 (raus aus dem WLAN, Mesh, Funkruhe), heute, mit
Hersteller-Firmware, ohne Garantieverlust und ohne UART-Backup -- und
Zigbee2MQTT laeuft bereits als LXC 112. Offene Pruefpunkte notiert, u.a. dass
Zigbee und WLAN sich 2,4 GHz teilen (Kanalplanung gegen ap1 ch1 / ap2 ch11).
Presselage korrigiert: Shellys offizielle Linie ist "wird evaluiert", nicht
"angekuendigt", Engpass ist der Flash-Platz. Die Thread-Firmware, die im Mai 2026
durch die Presse ging, ist die Dritt-Firmware.
Reihenfolge revidiert (User): PSK-Rotation und Funk-Umstellung laufen PARALLEL.
Der Passphrase-Override je MAC macht den Flag-Day ueberfluessig; die Reihenfolge
war nie technisch noetig, nur oekonomisch.
HA-Gegencheck: genau ein Shelly ist offline (s4 kueche_mikrowelle, RSSI -93),
deckungsgleich mit dem Netz-Sweep. s1/s2/s3 (weihnachten) existieren in HA gar
nicht -- sie kommen beim naechsten Einstecken mit dem alten PSK.
Drucker: NICHT stillschweigend auf VLAN10 geaendert. Das Geraet sagt VLAN30
(Reservierung 10.40.30.5 auf dhcp-v30, ARP vlan30, derzeit aus, last-seen 3d15h),
CLAUDE.md sagt seit 08-08 dasselbe. Als offener Klaerungspunkt notiert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ergebnis der read-only-Recherche-Session, hier gegengeprueft und in die kanonische
Doku uebernommen.
Der PSK in docs/teilprojekte-archiv.md (TP17) ist NOCH der live konfigurierte --
verifiziert am Manager per Fingerprint (Laenge + drei Zeichenpaare) statt im
Klartext, damit der Wert nicht ein zweites Mal in einem Transkript landet. Das ist
zugleich die Merkregel: Uebereinstimmung prueft man mit Stichproben, nicht durch
Ausgeben.
User-Entscheid: Historie belassen, im Nachtrag dokumentieren -- kein filter-repo.
Traegt, weil es genau eine getrackte Fundstelle gibt, drei Commits, Remote nur
gitea.emsenhuber.net und einen einzigen lokalen Klon; der Wert hat die eigene
Infrastruktur nie verlassen. Der wirksame Schritt ist die Rotation, und die bleibt
hinter TP17.1.
Blast radius selbst nachgemessen (crs326-core, read-only), Peer-Zahlen bestaetigt:
26 der 27 WLAN-Clients des gesamten Netzes haengen auf dirtyvader-iot (main 1,
media/untrusted/guest je 0), VLAN30 fuehrt 41 Leases/Reservierungen (5 bound).
Neben den ~26 Shellys: P750W, Airfryer, SwitchBot, Twinkly, DTUBI, SONOFF-NSPanelPro,
ein iPhone.
Damit praezisiert sich TP17.1: nach zehn migrierten Gen4 blieben grob 16 Geraete
auf dem IoT-SSID, nicht 12 -- der Funkruhe-Effekt ist real (-38 % Clients), der
PSK-Effekt nur halb. Die Reihenfolge-Entscheidung bleibt richtig, ihre Begruendung
wird ehrlicher.
Zwei Umsetzungshinweise fuers spaetere Rotations-Paket festgehalten: migrate.py hat
kein Rotate-Kommando, und ein Flag-Day ist vermeidbar ueber Passphrase-Overrides je
MAC in /interface wifi access-list -- was dem TP25-Befund "keine access-list"
nebenbei einen Zweck gibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Entscheid 2026-08-23: das IoT-WLAN-Passwort bleibt vorerst wie es ist.
Stattdessen zuerst die Shelly Gen4 auf Matter over Thread umstellen; danach
haengen deutlich weniger Geraete am WLAN und die Rotation wird billig. Damit ist
die Rotation NACHFOLGER von TP17.1, nicht mehr eigenstaendiger Follow-up.
TP17.1 stand seit 2026-07-11 als Projektion im (inzwischen archivierten) TP17.
Es hat jetzt wieder offene Arbeit und steht deshalb nach der eigenen Split-Regel
wieder vorne in teilprojekte.md. Umsetzung liegt im HA-Projekt:
~/dev/ha-xstate/docs/shelly-gen4-thread-migration.md
Bestand live gesweept (mcp/shelly/discover.py, read-only, VLAN30): 22 von 26
erreichbar -- 12 Gen4, 8 Gen3, 2 Gen2, alle fw 2.0.0. Nicht erreichbar: s1/s2/s3
(saisonal) und s4 kueche_mikrowelle (RSSI -93).
Recherchiert und als Praemissen-Korrektur eingetragen: Shelly unterstuetzt Matter
over Thread OFFIZIELL NICHT und plant es nicht -- Gen4 kann offiziell nur Matter
over WiFi, was hier nutzlos waere (Geraet bliebe im WLAN, braeuchte den PSK
weiter). Thread nur ueber Dritt-Firmware; das brauchbare Projekt deckt 10 der 12
Geraete ab (Plug S Gen4 faellt raus), kostet Garantie + Shelly-Cloud und hat als
Rueckweg nur ein UART-Vollbackup je Geraet. Selbst bei vollem Erfolg blieben 12
Geraete im WLAN -- Gen3 hat kein 802.15.4 und kann nie folgen.
Nebeneffekt fuer TP12.1: je mehr Thread-Geraete kommen, desto oefter zahlt man
den -infra-SSID-Umweg beim Commissioning. Das ist das erste Argument fuer TP12.1,
das nicht an einem einzelnen Fuehler haengt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Getrennt nach ZUSTAND, nicht nach TP (der Vorschlag "1 MD pro Teilprojekt"
haette ~35 Dateien ergeben und genau die Querbezuege zerschnitten, die das
Dokument wertvoll machen -- Reihenfolge, Abhaengigkeiten, "TP23 haengt an TP5
in beide Richtungen"):
- docs/teilprojekte.md = Rahmen + kritischer Pfad + 16 OFFENE TPs
- docs/teilprojekte-archiv.md = 34 abgeschlossene TPs, Volltext + Inhaltsverzeichnis
Zuordnungsregel steht in beiden Dateien und in CLAUDE.md: ein TP wandert erst
dann ins Archiv, wenn nichts mehr daran zu tun ist. Wo nur ein Sub-TP offen
war, blieb dieses vorne (TP17.2 <-> TP17, TP20.1 <-> TP20).
TP25 von 393 auf ~100 Zeilen kondensiert: Stand, Offenes (Fund F, die
20-MHz-Entscheidung) und die Merkregeln bleiben vorne, die Langfassung liegt
unveraendert im Archiv (#tp25-lang) -- ein guter Teil ihres Werts steckt in den
widerlegten Erklaerungen, die zeigen, welche Wege schon abgelaufen sind.
Kein Inhalt verloren: maschinell gegengeprueft, von 2218 Originalzeilen tauchen
alle wieder auf bis auf 7 bewusste Korrekturen.
Drift, der beim Aufraeumen aufgefallen ist (dieselbe Klasse wie die 08-18-Lehre,
dass der Ist-Stand-Block zuletzt nachgezogen wird):
- Compliance im Ist-Stand war einen Tag alt: 100/100 bei 25 Rules -> live gegen
die Nautobot-API geprueft 104/104 bei 26 Rules, 0 Drifts
- VLAN-Tabelle trug immer noch "Public-IP an ap1" -> crs326-core (Rest aus
Punkt C, den vier Durchgaenge uebersehen haben, weil er in einer Tabellenzelle
steckt und nicht in einem TP-Absatz)
- die DOCSIS-Erklaerung aus dem TP6-Abschluss stand im kritischen Pfad noch als
Begruendung, obwohl TP6.1 sie am selben Tag widerlegt hat -> datierter Nachtrag
Live gegengeprueft statt abgeschrieben: crs326-branch traegt keine
192.168.88.x-Adresse mehr, damit ist der letzte offene Aufraeum-Punkt aus TP21.1
geschlossen und das TP durfte ins Archiv.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs Anstoss vom 2026-08-23 festgehalten, damit er die separate Doku-Session
erreicht statt im Sitzungskontext zu verfallen.
Empfehlung mit Zahlen: nach ZUSTAND splitten (offen / Archiv), nicht 1 MD pro TP.
1071 der 2205 Zeilen sind abgeschlossene TPs, TP25 allein 393. Ein Schnitt pro TP
waeren ~35 Dateien und wuerde das Versprechen aus CLAUDE.md brechen ("kein anderer
Kontext noetig") -- er zerstoert die teuerste Eigenschaft der Datei, um ihr
billigstes Problem zu loesen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs Einwand beim TP6-Abschluss war berechtigt, und er kippt die Erklaerung,
die ich einen Tag lang vertreten habe.
ABNAHME (gleiche NAS-Last, gleicher Messclient, Kontrolle inklusive):
Priorisierung aus 40,8 ms avg / 53,4 max
Priorisierung an 11,0 ms avg / 14,6 max -73 %
Die Last war echt, nicht behauptet: wan-up-total fuhr 9,0 Mbit (max-limit greift
exakt), wan-up-bulk 8,87 Mbit mit 1581 Drops, vlan100 tx 9,0 Mbps. Die Kontrolle
mit abgeschalteter Markierung war noetig, um auszuschliessen, dass die Verbesserung
bloss daher kommt, dass Bulk und Ping jetzt von verschiedenen Hosts stammen.
KORREKTUR AN TP6: dort steht, die 30 ms entstuenden im DOCSIS-Uplink und seien
unabaenderlich. Das ist widerlegt. Der Fehler lag in der METHODE dieser Messung:
Bulk und Messverkehr kamen vom SELBEN Host, also gab es fuer CAKEs triple-isolate
nichts zu trennen -- alles lag in derselben Klasse, und Shapen allein aendert keine
Reihenfolge. Was CAKE nicht schaffte, schafft explizite Klassentrennung.
TP6 traegt jetzt einen Warnhinweis und ist als Messprotokoll zu lesen, nicht als
Ursachenanalyse. Weiter gueltig bleibt: CAKE als EINE Queue ueber allem brachte
nichts (dreimal gemessen), und Interface-HTB ist auf diesem Geraet tot.
GEBAUT (Template [11a], via GC):
2x mangle postrouting (VOR src-nat -- nur dort ist die LAN-Quelle sichtbar):
NAS 10.40.20.10 -> bulkup, alles andere -> restup
wan-up-total (parent=global, max-limit=9M)
wan-up-rest priority=1 limit-at=6M
wan-up-bulk priority=8 limit-at=1M
Drei Entscheidungen, begruendet im Template:
- Prioritaet statt Cap: ein Limit haette die NAS auch nachts gebremst und
Bandbreite verschenkt (DSM drosselt nicht, User-bestaetigt). limit-at=1M
sorgt dafuer, dass der Sync nie ganz verhungert.
- src-address=10.40.20.10, NICHT VLAN20: dort haengen auch HA, Nautobot, pve.
- parent=global, nicht vlan100: Interface-HTB ist hier wirkungslos.
GOVERNANCE: ComplianceRule ip-firewall-mangle angelegt (ingest-mangle-rule.py),
config_ordered=True -- die NAS-Regel muss vor dem Catch-all stehen, sonst waere die
Priorisierung STILL wirkungslos. 26 Rules x 4 Geraete = 104 Checks, 104/104 gruen.
Formatfalle nebenbei: priority=8 ist Default und wird von /export weggelassen --
explizit im Template erzeugt es Dauer-Drift, bei dem das Geraet recht hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Abschluss wie entschieden. CAKE-Queue vom Geraet entfernt, Template-Abschnitt [11]
bleibt als BEGRUENDET LEER stehen: er traegt jetzt die Messreihe und die zwei
Fallen, damit der naechste QoS-Gedanke nicht bei null anfaengt.
ohne CAKE 42,4 ms | 88 % 43,3 | 73 % 44,0 | 52 % der Linerate 44,6 (idle 12,9)
Die ComplianceRule `queue` BLEIBT und bewacht den Abschnitt weiter -- als leer.
Das ist derselbe Gedanke wie bei wifi-access-list: ein leerer Soll-Zustand ist
eine Aussage, kein fehlender Eintrag. 100/100 compliant, keine Drifts.
NEU: TP6.1 -- Saettigung vermeiden statt Bufferbloat bekaempfen.
Christophs Einwand beim Abschluss ("dann koennten wir zumindest den Sync von der
NAS zurueckhalten") trifft eine echte Luecke im TP6-Urteil: die 30 ms Zusatzlatenz
sind nicht wegzushapen, aber sie treten NUR unter Saettigung auf -- im Leerlauf
misst dieselbe Strecke 12,9 ms. Ein NAS-Sync, der bei laufendem Call zurueckweicht,
haelt die Leitung aus der Saettigung. Das ist eine groessere Verbesserung, als
Bufferbloat-Bekaempfung hier je gebracht haette.
Entwurf steht als TP6.1, bewusst NICHT gebaut:
- Global-HTB (in TP6 als wirksam bewiesen) + zwei Prioritaetsklassen
- Prioritaet statt hartem Cap: nimmt dem Sync die Bandbreite nur, solange
jemand anders sie braucht
- src-address=10.40.20.10, NICHT ganz VLAN20 -- dort haengen auch HA, Nautobot
und pve, die nicht pauschal hinten anstehen sollen
- Vorbedingung: /ip firewall mangle steht unter KEINER ComplianceRule
- Abnahme misst den Call, nicht die Queue
- und zuerst pruefen, ob der Fall ueberhaupt auftritt oder DSM schon drosselt
Kritischer Pfad: LEER. deny-by-default steht, Golden Config steht, WLAN steht,
VLAN1 ist weg, TP6 ist beantwortet statt offengelassen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Korrigiert den Befund von heute Nacht. Der stand so nicht richtig da.
WAS FALSCH WAR: "der CRS326 fuehrt keine Software-Queue". Die These stuetzte sich
auf zwei eigene Testfehler und ist widerlegt. ipv4-fast-path-active=no und
fasttrack-packets=0 belegen sogar, dass die CPU jedes Paket im Slow Path sieht --
die Hardware war nie die Grenze.
WAS RICHTIG IST (MikroTik-Doku, woertlich): "Interface HTB will not work correctly
when the out-interface is hardware offloaded and the bridge Fast Path is not
active." Das war die Ursache der wirkungslosen Queue auf parent=vlan100. Ueber
parent=global + mangle mark-packet funktioniert CAKE einwandfrei:
6.040.563 Bytes gezaehlt
cake-bandwidth=7000000 -> Durchsatz faellt 9,3 auf 7,78 Mbit
Sie zaehlt UND drosselt. Es scheitert nicht am Bau.
Die zweite "Gegenprobe" von heute Nacht war ebenfalls untauglich: Simple Queue auf
10.40.0.0/16 laeuft im Postrouting NACH src-nat, wo die Quelle laengst die WAN-IP
ist. Sie konnte nie matchen und bewies nichts.
DER BEFUND, DER TP6 BEENDET -- A/B, gleicher Client, Minuten auseinander:
ohne CAKE 42,4 ms
CAKE 8,5 Mbit (88 %) 43,3 ms
CAKE 7 Mbit (73 %) 44,0 ms
CAKE 5 Mbit (52 %) 44,6 ms (idle 12,9 ms)
Selbst bei halber Linerate keine Verbesserung -- und dort MUSS die Warteschlange im
Router liegen. Die ~30 ms entstehen stromabwaerts im Arris/DOCSIS-Uplink, wo
Request/Grant-Scheduling auf MAC-Layer sitzt und gar keine Queue ist. Das kann kein
Shaper im Router beheben. Die max-Werte steigen mit haerterer Drosselung
(53 -> 94 -> 148 ms): die eigene Queue waechst, die DOCSIS-Latenz bleibt.
EMPFEHLUNG: TP6 schliessen. Nicht mangels Nutzen, sondern weil das Werkzeug nicht an
die Ursache reicht -- ein staerkeres Ergebnis als das "marginal" von 2026-06-16.
Weder hw-offload opfern noch Chip-QoS ist noetig; der Global-HTB-Weg braucht beides
nicht. Es lohnt nur nicht.
Am Geraet steht weiterhin die wirkungslose Interface-Queue (qos-wan-up), in der SoT
und compliant, aber ohne Funktion -- markiert, gehoert beim Abschluss entfernt.
Alle Testaenderungen liefen als Transaktion, alle zurueckgebaut, 100/100 compliant.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Entscheidung dieser Sitzung war "bauen statt schliessen". Gebaut ist es. Das
Ergebnis stellt TP6 aber neu: die Queue steht, ist compliant, und tut nichts.
DREI BELEGE AM GERAET, unabhaengig voneinander:
/queue tree nach 6 MB echtem Client-Upload -> 0 Bytes
Simple Queue auf 10.40.0.0/16 (Gegenprobe) -> 0 Bytes
Upload gegen cake-bandwidth=8.5Mbps -> 9,48 Mbit
Der dritte ist der harte. Ein Zaehler auf 0 laesst sich als Anzeigeproblem
wegerklaeren, ein Durchsatz UEBER dem gesetzten Limit nicht.
URSACHE (sehr wahrscheinlich, nicht abschliessend bewiesen): CRS326 mit
Marvell-98DX3236. Bridge faehrt hw-offload, alle Ports only-hardware-queue,
Bridge-Interface no-queue. Der Switch-Chip serialisiert, nicht die CPU. Dass
l3-hw-offloading=no ist, widerspricht dem nicht: die CPU routet (Firewall zaehlt
32,9 Mio Pakete), aber sie serialisiert nicht.
WAS BESTAND HAT -- die ComplianceRule `queue`:
- nautobot/ingest-queue-rule.py (idempotent, Dry-Run default)
- match_config = "/queue type\n/queue tree"; /queue interface bewusst NICHT,
das traegt nur die Default-Portzuordnung und hat mit QoS nichts zu tun
- Wirksamkeit bewiesen, nicht behauptet: erst 99/100 mit exakt der fehlenden
Queue als `missing`, nach dem Deploy 100/100, 0 Drifts
- Zaehler jetzt 25 Rules x 4 Geraete = 100 Checks
Damit ist dieselbe blinde Stelle zu, die TP26 fuer /ip firewall filter geschlossen
hat -- und zwar VOR der Queue, wie Runbook 4.1 es verlangt.
ZWEI DESIGN-ENTSCHEIDUNGEN, die im Template begruendet stehen:
- nur die Senderichtung: der Download liegt mit +23..28 ms UNTER der
3-Schwelle und ist nach demselben Kriterium Fall A
- parent=vlan100 statt target=10.40.0.0/16: eine Simple Queue aufs LAN-Supernetz
haette Inter-VLAN (NAS <-> MAIN, geroutet ueber dieselbe CPU) mitgedrosselt
VIER SACKGASSEN, dokumentiert in ref_crs326_keine_software_queue:
1. active-queue=queue-tree heisst nur "verdrahtet", nicht "wirksam"
2. parent=global OHNE packet-mark faengt per Definition nichts
3. target=0.0.0.0/0 wird stillschweigend zu target="" verworfen
4. router-eigener Verkehr durchlaeuft die Queues nicht -- Test-Pings vom Router
beweisen nichts, es braucht einen echten LAN-Client
Zwei davon sahen wie Hardware-Befunde aus und waren eigene Testfehler.
FORMATFALLE: RouterOS exportiert 8.5Mbps statt 8500000 und schiebt eine eigene
Hinweiszeile vor die Tree-Zeile, wodurch der Backup-Normalisierer /queue tree
nicht abflacht. Template baut beides nach -> 100/100.
Alle Testaenderungen liefen als Config-Transaktion und sind zurueckgebaut; keine
Akte offen. Die wirkungslose Queue bleibt vorerst am Geraet und in der SoT --
dokumentiert, nicht als aktives QoS misszuverstehen -- bis ueber die drei Wege
entschieden ist (hw-offload opfern / Chip-QoS ohne CAKE / TP6 schliessen).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
/interface wifi access-list stand unter KEINER ComplianceRule. Eintraege dort
erzeugten keinen Drift und liessen sich nicht als Config-Transaktion fuehren --
gc-transaktion.py verlangt eine ComplianceRule als --scope. Seit dem 22.8. ist
das nicht mehr theoretisch: docs/tp25-pin-s22.sh schreibt bei jedem Messrundgang
Regeln dorthin, und TP25 Fund E (signal-range-Boden) wuerde dauerhaft genau in
diesem blinden Fleck landen.
- nautobot/ingest-wifi-access-list-rule.py (idempotent, Dry-Run default)
- Template-Abschnitt [6c], bewusst NUR Kommentare: der Soll-Zustand ist LEER,
und das ist die Aussage. Die intended config gewinnt keine wirksame Zeile.
Nach bf-golden-config gepusht (51c11f0), Repo-Sync SUCCESS.
ZWEI KORREKTUREN AN DER AUFGABENSTELLUNG:
1. Der Zaehler geht auf 96, nicht auf 94. Die Regeln gelten PLATTFORMWEIT, nicht
geraetespezifisch -- 92 Checks waren exakt 23 Rules x 4 Geraete, jetzt sind es
24 x 4. Die Annahme "2 geraete-relevante Checks" war falsch.
2. Vor Beginn stand bereits ein Drift in der Anzeige (bridge-vlan auf
crs326-core, ether3 als Trunk), obwohl der Sideboard-Rollback am 08-22
gelandet war. Das Geraet war live korrekt -- die Compliance vergleicht gegen
das letzte BACKUP, und das war aelter als der Rollback. Mit dem Refresh weg.
WIRKSAMKEIT BEWIESEN, nicht behauptet (TP22-Regel "Job-Status ist kein
Wirksamkeitsnachweis"):
96/96 compliant, 0 Drifts
-> Test-Eintrag mit nicht existierender MAC (kein echter Client betroffen)
-> 95/96, extra = exakt diese Zeile bei crs326-core | wifi-access-list
-> Eintrag entfernt -> 96/96, 0 Drifts
Zusaetzlich: gc-transaktion.py akzeptiert --scope wifi-access-list.
Ausserdem geprueft: 4 Compliance-Datensaetze (einer je Geraet), und der
[6c]-Block steht wirklich in der intended config von crs326-core.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP25 hat den Pfad seit dem 08-20 blockiert und ist im Kern durch -- die
Terrasse ist repariert, Fund E abgestuft. Der TP25-Header und der Abschnitt
"Kritischer Pfad" sagten beide noch das Gegenteil und sind nachgezogen.
Neu: docs/handoff-20260822-naechste-schritte.md -- fuenf zugeschnittene
Sessions, jede mit frischem Kontext arbeitsfaehig:
1. TP6 bauen ODER begruendet schliessen. Diese Session MISST NICHT, sie
entscheidet: formal Fall B (+28..47 ms), aber durch sechs Lastphasen mit
laufendem Videocall kein einziger Problem-Klick. Wenn gebaut wird, erst
/queue ins GC-Template plus ComplianceRule, dann die Queue, dann A/B.
2. Admin-Passwort der vier MikroTik rotieren. Vorbedingung ist erledigt --
kein sshpass -p mehr im Repo.
3. TP25 abschliessen: Fund F messen (am MANAGER, die AP-Tabellen sind unter
CAPsMAN leer) + Entscheidung 5 GHz auf 20 MHz.
4. ComplianceRule fuer /interface wifi access-list -- seit tp25-pin-s22.sh
nicht mehr theoretisch.
5. Der Rest ohne Rangfolge (TP12.1 mit zwingender Reihenfolge v6-Firewall
VOR Adressen, TP16.3, TP24, TP20.1, ...).
Dazu eine Werkzeugtabelle, damit niemand neu baut, was schon existiert, und
die drei Fallen dieser Sitzung, die wiederkommen werden: dynamische
cap-wifiN-Nummern, abgewiesene Verbindungsversuche die wie Funkloecher aussehen,
und dreimal Anzeige-statt-Wirkung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Erster Lauf mit beiden Ping-Strecken (23:30-23:41, per Stopp-Knopf beendet).
TERRASSE, die Frage des Aufbaus:
2026-08-21, ap2 tief: 43 % Verlust, laengste Luecke 20,4 s, -72 dBm
2026-08-22, ap2 auf 2,5 m: 9 % Verlust, laengste Luecke 1,0 s, -69,0 dBm
Gleiches Geraet, gleiche Rolle. 1,0 s liegt unter der Hoerbarkeitsschwelle im
Videocall. Der Dead Spot, der TP25 seit dem 08-20 getragen hat, ist weg.
STRUKTURBEFUND: die Referenz hat in 17 von 21 Raumabschnitten 0 % Verlust --
die Alltagsabdeckung ist ueberall in Ordnung. Der Gegen-AP traegt dagegen fast
nirgends: Schlafzimmer -84,6/38 %, Bad -82,3/24 %, Kueche -82,0/23 %, Terrasse
-78,7/19 %. Faellt ein AP aus, ist die halbe Wohnung "verbunden, aber tot".
Ein dritter AP kaufte damit REDUNDANZ, keine Abdeckung -- nach Christophs
eigener Randbedingung derzeit nicht begruendet.
KORREKTUR zum 22:43-Lauf: "die Kueche ist ein Loch fuer beide APs" gilt nur
fuer die aeusserste Ecke. Hier hat die Referenz in der Kueche 1 % Verlust bei
-71 dBm. Der Unterschied ist der Weg -- der Vorlauf ging ausdruecklich allen
Waenden entlang in die totesten Winkel. Beide Aussagen gelten, sie messen
verschiedene Orte.
Fund E weiter abgestuft: der Sticky-Client vom 08-20 reproduzierte sich nicht
(Treppe: sauberer Wechsel ap2/5G -> ap1/5G, 0 % ueber 57 s). Nicht umsetzen,
bevor ein Sticky-Fall erneut gemessen ist. Ein Lauf widerlegt Fund B nicht,
er zeigt nur, dass es nicht der Normalfall ist.
WERKZEUG: die Auswertung wies die groesste Sonden-Luecke auf der Treppe als
"⚠️ eher Ruhezustand" aus (4,6 s). Das war unser eigener Eingriff -- um
23:35:10 wechselte der Pin, das S22 war 23:35:12-16 abgemeldet. Ein Artefakt
als "Geraet war erreichbar, wollte nur nicht" zu beschriften ist doppelt
falsch. Pin-Wechsel werden jetzt erkannt und als solche benannt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Auswertung liest jetzt beide Geraete und stellt sie je Raum untereinander:
REFERENZ (iPhone, frei) was du an dieser Stelle wirklich hast
SONDE (S22, Gegen-AP) was die Rueckfallebene noch leisten koennte
Damit faellt der Terrassen-Vergleich beim naechsten Lauf von selbst raus, und
die Lesart wird eindeutig: gute Referenz + schlechte Sonde = alles haengt an
EINEM AP; beide schlecht = echtes Loch ohne Rueckfallebene (der Kuechenfall).
Rueckwaertskompatibel: Laeufe ohne walk-ping-iphone.csv/beide-telefone.csv
laufen einspaltig weiter und liefern fuer den Lauf vom 22.8. Ziffer fuer Ziffer
dieselben Zahlen wie vorher. Das Geraet heisst dort "Geraet" -- welches es war,
steht in den Dateien nicht, also wird es auch nicht behauptet.
Drei Fehler, die der Abnahmetest zutage foerderte und die alle den naechsten
Rundgang gekostet haetten:
1. Die Gegen-AP-Automatik war nach dem Start AUS. Wer den Klick vergisst, geht
die ganze Runde mit beiden Telefonen auf DEMSELBEN AP -- im Test genau so
passiert. tp25-runde.sh schaltet sie jetzt scharf; /auto nimmt dafuer ?an=1
(ein Toggle waere falsch: bei schon laufender Konsole haette der Start sie
ausgeschaltet).
2. "Funk da, aber keine einzige Ping-Antwort" erschien als "—", also wie eine
Datenluecke. Beim Test lag das iPhone gesperrt auf dem Tisch: angemeldet mit
-47 dBm und trotzdem stumm. Wer das als Luecke liest, sucht danach ein
Funkloch, das es nicht gibt. Jetzt: "keine Antwort" + "⚠️ Display gesperrt?".
3. Der Aufraeumer meldete "AP-Pin geloest", und danach standen die Regeln
trotzdem am Core. Wettlauf: er loeste den Pin, waehrend die Konsole noch
lief, und deren Automatik setzte ihn binnen zwei Sekunden wieder. Das
Telefon waere nach JEDER Runde gepinnt geblieben. Jetzt erst Konsole toeten,
dann Pin loesen.
Zuletzt: tp25-pin-s22.sh laeuft auf sshpass -e. Damit steht das Router-Passwort
in keiner Kommandozeile mehr -- `grep -rn "sshpass -p" docs/ nautobot/` findet
nur noch die Erwaehnung in teilprojekte.md. Die Rotation kann jetzt kommen.
Abnahme (mehrere echte Laeufe): Automatik meldet EIN, beide Telefone stehen auf
verschiedenen APs, beide werden gepingt, ein Klick auf Stopp beendet alles,
Pin danach "off", kein Prozess uebrig.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Maengel aus dem Rundgang vom 22.8. behoben.
1. STOPP-KNOPF. Die Konsole nannte "⏹ Aufzeichnung stoppen", es gab ihn nicht.
Christoph drueckte "Call beendet" und den Not-Aus -- beide schreiben nur
Marken -- und die Messung lief weiter, waehrend der Core sein Telefon mit
5 Pings/s bearbeitete. Jetzt legt der Knopf stop.flag ab, und die
Warteschleife des Messskripts bricht darauf ab.
2. ZWEITES TELEFON. Der Beobachter las immer schon beide Geraete, hielt die
Zahlen aber nur im Speicher fuer die Anzeige. Da das S22 per Automatik
immer auf dem GEGEN-AP sitzt, fehlte damit ausgerechnet die Strecke, die
die Alltagsabdeckung zeigt -- der Terrassen-Vergleich war nicht zu fuehren.
Jetzt: zweiter Ping (walk-ping-iphone.csv) und beide-telefone.csv im
2-s-Takt mit iface + Signal je Geraet.
Beim Testen kamen zwei Fehler ans Licht, die den naechsten Lauf gekostet
haetten:
- `PINGER=$(ping_lauf ...)` blockiert. Die Kommandosubstitution wartet, bis die
stdout-Pipe schliesst, und der Hintergrundjob darin haelt sie offen. Das
Skript stand in dieser Zeile, der zweite Ping wurde nie gestartet -- und es
sah von aussen aus wie ein normal laufender Lauf. Die Funktion laeuft in der
aktuellen Shell, also liefert $! danach die richtige PID.
- `kill $SAMPLER` traf nur den Wrapper. Dessen Subshell samt SSH-Sitzung wurde
dabei verwaist und lief weiter: nach dem Stopp hielt der Core stumm eine
Sampler-Sitzung offen. Wer den Vater zuerst killt, verliert den Zugriff auf
die Kinder -- jetzt killbaum(), Kinder zuerst.
Mitgenommen von der Rotationsliste: tp6-monitor-core.sh und der Ping in
tp25-walk-messung.sh laufen jetzt ueber `sshpass -e` statt `-p`. Damit steht
das Router-Passwort in keiner Kommandozeile mehr. `pgrep -fl "sshpass -p"`
ist leer. Offen bleibt tp25-pin-s22.sh.
Abnahme: Lauf gestartet, beide Ziele gepingt (10.40.10.178 + .196), ein Klick
auf den Stopp-Knopf, danach kein Prozess und keine SSH-Sitzung mehr uebrig,
Pin geloest.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Erster Lauf mit der Gegen-AP-Automatik: iPhone frei roamend, S22 automatisch
auf den jeweils anderen AP gezwungen. Gemessen wird damit nicht die
Alltagsabdeckung, sondern die RUECKFALLEBENE. Christoph ist bewusst allen
Waenden entlang in die totesten Winkel gegangen -- Worst Case je Raum.
Messguete: 22 von 784 Funkproben nicht angemeldet (2,8 %). Die befuerchteten
Abweisungs-Artefakte des Pins sind praktisch ausgeblieben, die Verluste sind
echte Funkschwaeche.
HAUPTBEFUND: In der Kueche fallen BEIDE APs gleichzeitig aus, unabhaengig
voneinander belegt.
S22 auf ap2: 57 % Verlust ueber 2 min, laengste Totzeit 24 s, dabei
durchgehend ANGEMELDET bei -79..-87 dBm und staendig
zwischen 5 und 2,4 GHz springend -- "verbunden, aber tot".
iPhone auf ap1: 22:51:37 "disconnected, connection lost" bei -76 dBm,
89 Sekunden komplett weg, wieder da erst beim Verlassen
des Raums.
Es gibt dort also keine Rueckfallebene. Das ist schlimmer als alles vom 08-21.
Terrasse: Anzeichen einer Verbesserung nach dem Anheben von ap2 (kein
Verbindungsabbruch statt 43 % Verlust am 08-21), aber NICHT bewiesen -- der
Ping lief nur auf das S22, und das war dort auf ap1 gezwungen. Belegt ist
dagegen Fund C: vier Bandwechsel in 49 s auf ap2, nach der Hoehenaenderung,
mit aktivem 802.11k/v und FT.
Folge fuer Fund E: ein signal-range-Boden steuert auf den besseren AP -- den
gibt es in den Problemraeumen nicht (ap2 liefert im UG -80..-86). Fund E hilft
auf der Treppe, nicht gegen den Dead Spot. Bleibt richtig, ist aber nicht mehr
die Antwort.
Zwei Werkzeugmaengel, die der Lauf aufdeckte und die noch offen sind:
kein Stopp-Knopf (die Aufzeichnung lief nach dem Ende weiter, der Core pingte
mit 5/s), und die iPhone-Zeitreihe wird nicht mitgeschrieben -- nachtraeglich
liess sich nur das Roaming-Log am Manager sichern.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs/tp25-runde.sh startet Konsole und Messung zusammen, friert die AP-Karte
ein, sagt die vom Interface GELESENE Adresse fuers Telefon an und loest beim
Beenden den Pin. Grund: beide Einzelteile hatten als Standard-Laufverzeichnis
einen Pfad in ein Sitzungs-Scratchpad -- wer sie ohne die passende
Umgebungsvariable startete, mass in ein totes Verzeichnis und merkte es erst
bei der Auswertung.
Der Probelauf hat dabei sofort einen Fehler in der eigenen Anzeige aufgedeckt:
die Seite meldete "✅ beide angemeldet, auf verschiedenen APs", waehrend beide
Telefone auf ap2 hingen. Das Kriterium prueft "beide angemeldet" -- nicht, ob
sie auf VERSCHIEDENEN APs sitzen. Das ist ein gruenes Licht fuer einen
Messpunkt, den es nicht gibt: Piep, weitergehen, kein Gegen-AP gemessen.
Wieder dieselbe Klasse wie der 14-h-Ausfall -- Anzeige geprueft statt Wirkung.
Jetzt vier Zustaende, gegen sechs Faelle geprueft (inkl. "gleicher AP, anderes
Band" -> zaehlt NICHT):
bereit verschiedene APs -> Piep, weitergehen
wird nachgezogen gleicher AP, Automatik -> warten
kein Gegen-AP gleicher AP, ohne Auto -> Warnung statt gruen
S22 sucht S22 nicht angemeldet -> stehenbleiben
teilprojekte.md: Passwort-Rotation als offener Follow-up eingetragen (User:
"machen wir, aber erst spaeter") -- inkl. der noch offenen sshpass -p in
tp6-monitor-core.sh und tp25-pin-s22.sh, die vorher nachgezogen gehoeren.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim Bauen der Gegen-AP-Automatik fiel auf, dass die feste AP-Tabelle in
server.py und tp25-gehweg-auswertung.py nicht zum Live-Zustand passt: heute
sind cap-wifi1/2 = ap2 und cap-wifi3/4 = ap1. Der Manager vergibt die Nummern
dynamisch beim Anmelden der CAPs; ap1 hat sich beim Rueckbau auf ether15 neu
angemeldet.
Der erste Schluss daraus war voreilig ("die alten Auswertungen sind
falsch beschriftet"). Die Gegenprobe widerlegt ihn: mit der HEUTIGEN Karte
haette Technik OG am 08-21 von ap1 mit -43 dBm versorgt worden sein -- in dem
Raum, in dem ap2 steht. Die alte Tabelle war zu ihrer Zeit also richtig und
ist erst durch das Umstecken falsch geworden.
Konsequenz, und das ist der eigentliche Fix: eine live nachgeschlagene Karte
auf alte Daten anzuwenden ist nicht die Loesung, sondern derselbe Fehler mit
umgekehrtem Vorzeichen. Die Zuordnung gehoert zum Messzeitpunkt.
- tp25-walk-messung.sh friert sie als ap-map.txt im Laufverzeichnis ein.
- tp25-gehweg-auswertung.py nimmt ausschliesslich diese Datei. Fehlt sie
(alle Laeufe vor heute), bleiben die rohen cap-wifiN stehen, mit lauter
Warnung -- unbeschriftet ist ehrlicher als falsch beschriftet.
teilprojekte.md: TP25 um den Werkzeug-Fund, den neuen Messaufbau (eine Runde
statt zwei) und den Pausenstand ergaenzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mit dem Gating der Call-Buttons wurde der Hinweis "Erst den Treiber starten
lassen" zur Sackgasse: ohne Treiber gibt es keinen Start-Button mehr. Er sagt
jetzt, was ohne Treiber SEHR WOHL geht (Raeume, AP-Pin) und wie man die
Ping-Aufzeichnung dazuholt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Christophs Einwand, und er hat recht: wer in ap2-Zone losgeht und das S22
auf ap2 pinnt, misst dort dasselbe, was das frei roamende iPhone ohnehin
liefert. Der Erkenntnisgewinn liegt beim ANDEREN AP.
Die Konsole liest deshalb beide Telefone mit und zwingt das S22 automatisch
auf den Gegen-AP des iPhones. Pro Standort gibt es damit zwei Messpunkte
statt einem, ohne den Weg zweimal zu gehen. Ein kurzer Doppelton meldet
"beide angemeldet, verschiedene APs" -- das ist das Signal zum Weitergehen.
Drei Zustaende statt zwei, weil zwei hier luegen wuerden:
bereit beide haengen -> Piep, weiter
sucht S22 versucht den Gegen-AP -> stehenbleiben
unerreichbar nach 45 s: der Gegen-AP traegt hier NICHT. Das ist das
Messergebnis, kein Defekt -- Marker UNERREICHBAR=apX, kein
Dauer-Alarm, weitergehen.
Ausserdem:
- Raumkacheln sind zurueck. Sie hingen am TP6-Treiber-Zustand und waren ohne
laufenden Call-Treiber unsichtbar -- ausgerechnet beim Kartieren.
- Die Call-Buttons (Start / Not-Aus fuer die Saettigungs-Flows) erscheinen nur
noch MIT Treiber. Ohne einen haette der Start-Klick nichts gemessen; der
Not-Aus haette nichts zu stoppen gehabt. 🚶/📍 brauchen keinen Treiber und
bleiben immer da.
Zwei Fehler beim Bauen, beide mit Merkwert:
1. `(:while (true) do={...})` -- die Klammern beenden die RouterOS-Sitzung
wortlos. Mit stderr auf DEVNULL sah man nur, dass alle 3 s ein neuer ssh
startet, und sonst nichts. stderr geht jetzt in beobachter.log.
2. `for zeile in proc.stdout` liest blockweise vor: bei einer Zeile alle 2 s
waeren die ersten Daten nach etwa einer Stunde gekommen. iter(readline, "").
Und eine Sicherheitskorrektur: `sshpass -p` schreibt das Router-Passwort in
die Kommandozeile -- sichtbar in ps und in jedem argv-Trace. Beim Debuggen ist
es am 2026-08-22 genau so im Klartext gelandet. Der Beobachter nutzt jetzt
`sshpass -e` (Passwort nur in der Umgebung des Kindprozesses). tp6-monitor-core.sh
und tp25-pin-s22.sh haben dieselbe Schwaeche und sind noch NICHT umgestellt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP25: das S22 laesst sich jetzt per access-list am Manager auf EINEN AP
festnageln (docs/tp25-pin-s22.sh, Umschalter in der Klick-Konsole). Damit
werden Einzel-AP-Abdeckungskarten messbar, statt dass der Client mitten im
Weg wechselt. Gepinnt wird der Standort, nicht das Band -- Band-Ping-Pong
(Fund C) bleibt damit ein echter Befund und wird nicht wegkonfiguriert.
Beim Bauen fielen drei Fehler auf, die alle dieselbe Form haben: eine
Konstante, die einmal richtig war.
1. Die AP-Zuordnung war VERTAUSCHT. server.py und tp25-gehweg-auswertung.py
fuehren cap-wifi1/2 als ap1 -- live ist es ap2 (belegt ueber cap=,
configuration= und Kanal). Baender stimmten, Identitaet nicht. Die
cap-wifiN-Nummern vergibt der Manager dynamisch in der Anmeldereihenfolge
der CAPs, jede feste Tabelle dazu wartet auf den naechsten AP-Reboot.
server.py liest sie jetzt vom Geraet; die Auswertung ist NOCH NICHT
angefasst -- offen ist, ob die Funde vom 08-21 mit vertauschten AP-Namen
notiert sind.
2. Das Laufverzeichnis war beim Serverstart eingefroren. Die Konsole laeuft
als Dauer-Preview, der Messlauf legt spaeter ein neues Verzeichnis an --
Marker waeren in den Lauf von gestern gewandert, waehrend der Sampler ins
neue schreibt. tp25-walk-messung.sh hinterlaesst jetzt einen Zeiger.
3. Das Startbanner nannte eine hartkodierte IP (10.40.10.183 = MacBook Air).
Auf dem Mac mini ist es 10.40.10.82, und genau die falsche Adresse ging
ans Telefon: "geht nicht" bei einem Server, der sauber auf 0.0.0.0 lauschte.
Es werden jetzt die real gefundenen Interface-Adressen gedruckt.
Ausserdem, aus dem Test heraus:
- Ein vom Pin ABGEWIESENER Verbindungsversuch ist in den Ping-Daten nicht von
einem Funkloch zu unterscheiden, und der Manager protokolliert ihn auf
info-Ebene nicht. Android quittiert ihn mit "Verbindung fehlgeschlagen" und
waehlt das Netz ab -- danach misst der Rest des Rundgangs Stille. Die Konsole
schlaegt deshalb mit Vollbanner, Ton und Vibration Alarm, sobald das gepinnte
Geraet nirgends haengt.
- Die Konsole laeuft diesmal auf dem S22 selbst, also auf genau dem Geraet, das
der Pin gleich vom WLAN wirft. Die Anweisung zum Wiederverbinden erscheint
deshalb clientseitig VOR dem Abbruch.
- ThreadingHTTPServer: der Pin braucht ~8 s ueber SSH und haette sonst die
ganze Seite blockiert, Not-Aus inklusive.
Governance: /interface wifi access-list steht unter KEINER ComplianceRule --
der Change erzeugt keinen Drift und laesst sich nicht als Transaktion fuehren.
Fuer eine Messung vertretbar; relevant wird es, wenn Fund E (signal-range)
dauerhaft dort landet.
teilprojekte.md: die beiden Hinweise auf die offene Transaktion
TEST-ether3-trunk-ap1-sideboard nachgezogen -- sie ist seit 08-22
zurueckgerollt, crs326-core ist transaktionsfrei.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Entscheid 2026-08-22: es wird kein ESP32 als ESPHome-BT-Proxy
angeschafft. ble_proxy bleibt an, ist aber wirkungslos -- HA hat keine
connectable BLE-Quelle (Shellys: slots=0 auf allen dreien, gemessen) und
bekommt keine. Konsequenz, die beim naechsten Thread-Geraet zaehlt: der Weg
ist wieder die temporaere -infra-SSID. Runbook entsprechend von "Plan B" auf
Standardweg umgeschrieben, Blocker-Abschnitt als erledigt markiert (aber mit
dem Hinweis, dass Regel 3 jederzeit wieder greifen kann).
Neuer Nebenbefund unter TP12.1, bewusst als thread-, nicht ipv6-Thema
markiert: die Knoten @1:a (Diele OG/Treppenauge), @1:f und @1:10 flappen seit
Stunden (Resolving address is unreachable -> offline grace period expired),
waehrend die uebrigen ~20 stabil sind -- also kein Fabric-Problem. Vor jeder
Diagnose die Sonderlage von heute abziehen: OTBR-Neustart um 17:33 und ap1
zwischenzeitlich vom Netz. Erst pruefen, ob es danach noch besteht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Workaround aus TP12.1 ist durchgespielt: dirtyvader-infra temporaer auf
ap2, iPhone auf VLAN20, TIMMERFLOTTE per Companion-App angelernt (25,44 C /
53,1 % rF / Batterie 100 %, Technik UG). SSID danach wieder vom Funk;
cfg-infra/dp-infra/sec-infra bleiben auf User-Wunsch inaktiv am Manager
stehen, damit das naechste Thread-Geraet ein Zweizeiler ist. Beide Akten
geschlossen, crs326-core transaktionsfrei.
TP12.1 bleibt offen: der Workaround umgeht das fehlende IPv6-Routing, er
behebt es nicht.
Neuer Gotcha in CLAUDE.md, an dem ich mich heute selbst verrannt habe:
slave-configurations zu setzen bewirkt am Funk nichts ohne
remote-cap provision -- und zwar in BEIDE Richtungen, auch beim Entfernen.
Schlimmer: beim Rueckbau wird der Interface-Kommentar geleert, waehrend der
VAP weitersendet. Ich habe auf comment~"dirtyvader-infra" geprueft, nichts
gefunden und "weg" gemeldet -- tatsaechlich liefen wifi13/wifi18 mit vlan=20
weiter. Richtige Abnahme ist datapath.vlan-id am CAP. Also wieder: Wirkung
messen, nicht Anzeige.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TEST-infra-ssid-matter-pairing (Scope wifi-provisioning, Frist 2026-08-29):
cfg-infra als Slave-VAP in beide ap2-Provisioning-Zeilen. Nicht ap1, weil der
gerade auf ether11 (VLAN10-Access) haengt und kein CAP ist.
Zweck ist TP12.1: das iPhone fuer EIN Matter-Commissioning auf denselben
L2-Link wie der OTBR bringen, damit dessen RA (On-Link-Prefix + Route in den
Thread-OMR-Prefix) beim Telefon ankommt. Danach zurueckbauen -- ein WLAN nach
INFRA soll nicht stehen bleiben.
Zwei Dinge fuer die Ablage:
- Provisioning-Zeilen aendern reicht nicht, der CAP muss re-provisioniert
werden (/interface wifi capsman remote-cap provision). Das ist eine Aktion,
keine Config, also kein Nautobot-Weg noetig.
- Danach zeigt der MANAGER running=false fuer alle cap-*-Interfaces, waehrend
am CAP wifi13/wifi18 sauber DBR laufen. Beim Interface-Zustand ist der CAP
die Wahrheit, nicht der Manager -- Gegenstueck zur bekannten Regel, dass die
Registration-Table am Manager zu lesen ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TEST-ether3-trunk-ap1-sideboard ist zurueckgerollt und geschlossen: ether3
faellt aus allen tagged-Listen und ist in VLAN40 wieder untagged (Sideboard-
Access-Port). Am Geraet gegengeprueft, Snapshot-Diff leer. crs326-core ist
damit transaktionsfrei.
TP25 Fund (G): ap1 am Sideboard richtet das Wohnzimmer nicht und kostet das
Schlafzimmer (-61 -> -83 dBm). Die Idee "ap1 ersetzt den Sideboard-Switch" ist
damit entschieden -- nein, Platzierung vor eingespartem Geraet. ap2 haengt
jetzt auf 2,5 m, Terrasse subjektiv besser, Nachmessung steht aus.
Korrektur im selben Zug: die erste Fassung von (G) behauptete, der Steering-
Fall entfalle mit dem Rollback. Falsch -- es entfaellt nur die konkrete
Auspraegung. Fund B und C wurden am 08-20 mit ap1 auf ether15 gemessen, also
in genau der Stellung, in die wir zurueckgebaut haben; der Defekt ist
platzierungsunabhaengig und verlagert sich nur. Fund E bleibt die Massnahme
und ist jetzt oberster offener Punkt.
TP12.1 neu (unter TP12, kein Duplikat daneben): Matter/Thread-Commissioning
scheitert an fehlendem IPv6-Routing zwischen VLAN10 und VLAN20 -- nicht an der
Firewall. Der Kostenpunkt des TP ist aber nicht die Adressvergabe, sondern
dass /ipv6 firewall filter leer ist: heute harmlos, ab der ersten Adresse ein
Loch an TP5 vorbei. Reihenfolge deshalb zwingend v6-Firewall vor Adressen.
Runbook + Kommandodateien fuer die temporaere dirtyvader-infra-SSID
(cfg-infra existiert bereits, haengt nur in keiner provisioning-Zeile).
Vorbereitet, nicht deployt.
Repo-lokalen projektstatus-Skill geloescht: er war seit 11. Juli stale
(harte Themenblöcke, kritischer Pfad von TP14.3) und wurde nicht geladen --
aktiv ist der globale.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Uebergabedokument nach dem Muster des TP6-Handovers, das sich bewaehrt hat. Sein
Wert liegt in zwei Dingen, die eine frische Session nicht selbst herausfinden
kann: die offene Config-Transaktion mit Frist, und die acht Messfallen, die in
dieser Session je einen Fehlbefund produziert haben.
Der Statusstand: TP6 gemessen und nachrangig, TP25 auf dem kritischen Pfad, und
auf crs326-core ist TEST-ether3-trunk-ap1-sideboard offen (Frist 2026-09-04) --
die Compliance ist deshalb absichtlich nicht 92/92.
Inhaltlich neu ist die Umdeutung des Abend-Befunds. Nach dem ap1-Umzug ans
Sideboard verlieren die Schlafraeume rund 20 dB und fallen auf ap2/2,4 GHz
zurueck. Laut Christophs Massangaben liegen sie aber 2 bzw. 4 m Luftlinie von
ap1, waehrend ap2 4-6 m entfernt ist und zwei zusaetzliche Mauern dazwischen hat.
Ein Client, der so am ferneren AP klebt, hat kein Abdeckungs-, sondern ein
Steering-Problem -- und damit ist das die erste Stelle im Haus, an der Fund E
(signal-range-Boden) wirklich das richtige Werkzeug ist. Auf der Terrasse waere
er falsch gewesen, weil es dort keine Alternative gibt. Der Test dafuer steht im
Handover und ist die naechste Messung.
Ebenfalls korrigiert: der Platz, an dem das Telefon auf der Terrasse
normalerweise steht, ist mit -46 bis -66 dBm gut. Der Dead Spot ist der Teil
dahinter.
TP29 haelt Christophs Idee fest, Anwesenheit ueber BLE (Shellys), WLAN und
mmWave-Radar zu erkennen, um ohne Komfortverlust zu heizen. Der Entwurfsgedanke
sind die komplementaeren Schwaechen der drei Quellen -- BLE braucht ein
getragenes Geraet, WLAN erkennt nur Menschen mit Telefon, Radar auch die
stillsitzende Person, kostet aber einen Sensor je Raum. Nicht auf dem kritischen
Pfad.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein iPhone mit gesperrtem Display beantwortet ICMP nicht. In der Verlustspalte
sieht das exakt aus wie ein Funkloch, und heute haette es fast zu einem falschen
Befund gefuehrt: 58 Sekunden Ping-Luecke auf der Terrasse -- bei -53 dBm, 275 Mbps
PHY-Rate und weiterlaufenden 3 kbit/s Hintergrundverkehr. Das Geraet war
erreichbar, es wollte nur nicht antworten.
Die Auswertung markiert solche Luecken jetzt (gutes Durchschnittssignal plus hohe
PHY-Rate) und sagt dazu, dass sie NICHT als Funkloch zu lesen sind. Bewertet wird
der Durchschnitt des Abschnitts, nicht sein Minimum -- ein einzelner schwacher
Sample beim Durchgehen darf den Befund nicht kippen.
Dazu die Rohdaten des Gangs mit ap1 am Sideboard.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Port trug keines der sieben VLANs, deshalb war ap1 nach dem Umpatchen tot.
Sieben set-Zeilen ueber gc-manual-plan.py, und der erste Deploy zeigte gleich zwei
bekannte Fallen von ihrer praktischen Seite:
Der Plan meldete Failed, und der Teilzustand war real -- sechs VLANs hatten ether3
bekommen, VLAN 40 nicht. Der Grund ist sauber: ether3 war dort UNTAGGED-Mitglied,
und ein Port kann in derselben VLAN nicht zugleich tagged und untagged sein.
Nachtrag deployt (untagged=ether2,ether4,ether5), diesmal mit --assert, und der
hat den Effekt am Geraet nachgewiesen statt dem Job zu glauben.
Ergebnis: ap1 antwortet in 447 us und traegt wieder 12 Clients (ap2: 16).
Die Aenderung bleibt bewusst UNCOMMITTED: sie steht am Geraet, nicht in der SoT,
und die Compliance meldet den Drift auf bridge-vlan. Genau so soll es sein,
solange offen ist, ob ap1 am Sideboard bleibt. Faellt die Entscheidung, wird
entweder das Template nachgezogen (commit) oder aus dem Snapshot zurueckgebaut.
Ein Bugfix im neuen Werkzeug faellt dabei gleich mit an: der Feature-Name steht
bei depth=1 nicht ausgeschrieben in rule.feature, dort kommt nur eine URL.
Verwendbar ist rule.display. Ohne das meldete status JEDEN Drift als "ausserhalb
des Scopes" -- also ausgerechnet die Zuordnung falsch, fuer die es gebaut wurde.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine Aenderung, die am Geraet steht, aber nicht in der SoT, ist Drift -- und Drift
sieht bisher immer gleich aus, egal ob er ein Versehen ist oder ein laufender
Versuch. Wer testen wollte, hatte die Wahl zwischen "Compliance kaputt" und "gar
nicht testen".
gc-transaktion.py macht die Absicht sichtbar, ohne die Governance aufzuweichen:
der Change geht weiterhin ausschliesslich ueber Golden Config, die Compliance
meldet den Drift weiterhin -- neu ist, dass `status` ihn zuordnen kann,
"erwartet (offene Transaktion)" statt "unerklaert". Und dass er ein Ablaufdatum
hat.
Drei Regeln erzwingt das Werkzeug: --expires ist Pflicht (eine unbefristete
Ausnahme ist undokumentierter Drift mit besserem Gewissen), der Scope ist eine
ComplianceRule und kein Freibrief (Drift ausserhalb wird ausdruecklich als nicht
abgedeckt gemeldet), und es gibt genau eine offene Transaktion je Geraet -- sonst
ist beim Rollback nicht mehr entscheidbar, wohin zurueck. Der Commit wird
verweigert, solange der Scope noch driftet: dann waere die SoT gar nicht
nachgezogen worden.
Zwei bewusste Grenzen: der Rollback pusht nicht selbst, sondern schreibt einen
Vorschlag zum Pruefen (add-Zeilen aus einem /export legen neu an, statt zu
aendern), und der Snapshot enthaelt nur den Scope-Abschnitt. Der Vollexport
enthielt Firewall, Adressen, Benutzerliste und Skriptquellen -- nichts davon
braucht der Rueckbau, und die Akten liegen im Git.
Erste Akte ist der ether3-Trunk: ap1 haengt testweise am Sideboard auf core
ether3, und dieser Port traegt bisher keines der sieben VLANs. Deploy steht noch
aus -- er wurde in dieser Session vom Berechtigungs-Klassifikator blockiert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei User-Korrekturen (2026-08-21) an der Erklaerung des Terrassen-Dead-Spots:
"Technik OG" ist kein eigener Raum, sondern ein virtueller Bereich im
Arbeitszimmer -- es gibt dort keine bauliche Trennung. Die bisherige Erklaerung
zaehlte drei Waende und war damit falsch.
Zwischen ap2 und Terrasse liegen zwei Mauern der Diele OG und teilweise die
PV-Anlage an der Mauer. Module und Unterkonstruktion sind eine leitende Flaeche,
also ein Schirm und keine daempfende Wand. Das erklaert, warum es auf der
Terrasse nicht knapp, sondern kaputt ist -- und sagt zugleich voraus, dass mehr
Sendeleistung oder ein schmalerer Kanal dort wenig ausrichten werden.
Daraus folgt die neue Reihenfolge: ap2 testweise an den Kandidatenplatz haengen,
an dem spaeter ohnehin ein Decken-AP sitzen wuerde (kein Config-Change noetig, ap2
ist ein CAP und provisioniert sich am neuen Platz selbst). Bleibt die Terrasse
dabei schlecht, ist das OG die falsche Seite: dann ist das Wohnzimmer der
Kandidat, das unterhalb der Terrasse liegt -- ein AP dort strahlt an der PV-Anlage
vorbei statt durch sie hindurch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Statusblock war im Commit davor haengengeblieben (Anker im Skript verfehlt,
Assertion geworfen, Doku committet, Status nicht). Genau der Fehler, vor dem
Spielregel 4 der TP6-Uebergabe warnt: neuer Inhalt geschrieben, alter Status
stehen geblieben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zweiter Gehweg-Durchgang, diesmal methodisch sauber: Ping vom Core statt vom
Laptop, Konsole auf dem iPhone (Wake Lock haelt es wach, sonst misst man
Ruhezustand), Raumwechsel per Klick markiert.
Das Ergebnis ist eindeutig und macht die Roaming-Geschichte klein. Im ganzen Haus
null Paketverlust -- Technik UG und OG, Diele, Kinder-, Schlaf- und
Arbeitszimmer, Treppe, alle 0 %, und die Uebergaben ap1<->ap2 auf der Treppe
kosten 0,2 s. Auf der Terrasse dagegen 43 % Verlust ueber 162 Sekunden, am Stueck
fehlen 20,4 Sekunden, bei -72 dBm. Dort ist ein Call nicht gestoert, sondern weg.
Die Topologie erklaert es vollstaendig: ap2 steht in Technik OG, das nur ueber
das Arbeitszimmer zugaenglich ist -- zur Terrasse liegen Technik OG,
Arbeitszimmer, Diele OG und die Aussenwand dazwischen.
Das dreht die Massnahmen um. Ein signal-range-Boden (Fund E) wuerde die Terrasse
VERSCHLECHTERN, weil es dort keinen besseren AP gibt, auf den er steuern koennte
-- er wuerde nur rauswerfen. Stattdessen: 5 GHz auf 20 MHz (+3 dB, ein Wort im
Template), dann ap2 von Technik OG in die Diele OG umhaengen, die an Terrasse,
Arbeitszimmer und Treppe grenzt. Kein neuer AP noetig, damit ist auch die
User-Randbedingung erfuellt.
Konsole nachgezogen: Marker werden URL-dekodiert und behalten ihre Gross- und
Kleinschreibung (aus "RAUM=Diele OG" wurde "RAUM%3DDIELE%20OG"), Diele OG ist
ergaenzt, und das Raumraster steht jetzt oben -- ohne JavaScript laedt die Seite
nach jedem Klick neu, und dann muss der naechste Raum ohne Scrollen erreichbar
sein.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pingt der messende Laptop das Telefon an, laeuft der Weg ueber zwei
Funkstrecken -- Laptop -> AP -> Core -> AP -> Telefon. Fehlt dann ein Paket, ist
nicht entscheidbar, welches der beiden Geraete weg war, und genau diese
Trennschaerfe ist der ganze Zweck der Messung. Vom Core aus ist die Strecke bis
zum AP durchgehend Kabel.
Ausloeser war unfreiwillig: das MacBook ist mitten in einem Lauf vom Dock ans
WLAN gewechselt und hat dabei die IP gewechselt -- die Konsole war ploetzlich
nicht mehr erreichbar, und der Ping haette ab da zwei Funkstrecken gemessen.
Das Ping-Protokoll ist jetzt eine CSV (ts_local,seq,ms; leeres ms = Verlust), die
Auswertung liest beide Formate, damit die Laeufe von gestern lesbar bleiben.
RouterOS-Dauern kommen als "3ms441us" oder "529us" und werden entsprechend
geparst.
Eine Falle steckt im Skript-Kommentar: tr puffert blockweise, sobald die Ausgabe
in eine Pipe geht -- die ersten ~130 Zeilen haengen im Puffer und die Datei
bleibt scheinbar leer. Das \r kommt deshalb im Shell-Loop weg, nicht per tr.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Gehweg-Messung erzeugte bisher eine Zeitachse, aus der niemand ablesen
konnte, WO es schlecht war -- der teure Abschnitt von gestern liegt bei
"15:07 bis 15:09", und das ist kein Satz, aus dem eine Massnahme folgt.
Die Konsole bekommt deshalb ein Raster mit einem Button je Raum; der aktive Raum
wird hervorgehoben und die Verweildauer mitgezaehlt. Die Liste steht per
TP25_ROOMS in der Umgebung, damit ein fehlender Raum kein Codeeingriff ist.
tp25-gehweg-auswertung.py verbindet die drei Mitschnitte -- Ping aufs Telefon,
Funkwerte vom Manager, Raum-Marken -- zu einer Tabelle mit Signal, Paketverlust
und laengster Luecke je Raum, samt AP, auf dem der Client dort haengt.
Dazu die Lehre aus dem ersten Durchgang, diesmal als Anleitung statt als Fussnote:
die Konsole gehoert waehrend der Messung auf DAS TELEFON. Der Wake Lock haelt das
Display an und das Polling das Geraet wach -- ohne das beantwortet ein iPhone die
Pings verzoegert oder gar nicht, und 44 % Verlust sind Ruhezustand statt Funk.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die "~4 Sekunden je Wechsel" aus der Nachtmessung waren als Obergrenze markiert,
und die Vorsicht war berechtigt: 5 Pings/s auf das Telefon zeigen bei -48 bis
-55 dBm Uebergabekosten von 0 bis 2,6 s, meist unter einer halben Sekunde. Fast
Transition funktioniert. Der Zaehlerstand nach einer Neuanmeldung hatte die
Luecke vorgetaeuscht.
Der wahre Befund ist schlimmer und liegt woanders: bei -69 bis -77 dBm ist das
Telefon 6 bis 45 s nicht erreichbar, zweimal ueber 20 s am Stueck. Die Trennlinie
laeuft sauber entlang der Signalstaerke, nicht entlang der Wechsel -- es ist kein
Roaming-Problem, es ist ein Dead Spot.
Ehrlich dazu: ueber den ganzen Weg gingen 44 % der Pings verloren, und das ist
nicht alles Funk -- ein iPhone mit gesperrtem Display beantwortet ICMP verzoegert
oder gar nicht (RTT-Median 3,7 ms, Maximum 8,2 s). Power-Save haengt aber am
Display, nicht am Ort; dass alle langen Luecken in der schwachen Zone liegen und
alle kurzen in der starken, erklaert es nicht. Fuer eine exakte Zahl braucht es
ein waches Telefon.
tp6-monitor-core.sh bekommt eine Reconnect-Schleife: die SSH-Sitzung ist mitten
in der Messung weggebrochen und die Funkdaten endeten 2,5 Minuten vor dem
Ping-Mitschnitt -- ausgerechnet im interessanten Teil.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Sampler-Daten zeigen bei jedem AP-/Bandwechsel ~4 s ohne Durchsatz, koennen
das aber nicht beweisen: nach einer Neuanmeldung starten die Zaehler der
Registration-Table ohnehin bei null. tp25-walk-messung.sh trennt beides, indem es
mit 5 Pings/s AUF das Telefon zielt -- Paketverlust ist echte Funkstille, kein
Verlust heisst, die 4 Sekunden waren Buchhaltung.
Laeuft ohne Call und ohne Last: Core-Sampler im 1-s-Takt plus der Ping, dazu eine
Anleitung auf der Klick-Konsole (Gehen/Stehen als Marker). Ein vorheriger Lauf
wird beiseitegelegt statt ueberschrieben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die TP6-Praemisse ist ausgefuehrt: drei Messreihen von einem kabelgebundenen
Client in VLAN10, zwei davon mit laufendem Telegram-Videocall an zwei Orten.
Ergebnis (Runbook §5): unter Dauer-Upload steigt die Latenz von 13 auf 40--60 ms,
im Download auf 36--41 ms. Das sind +28 bis +47 ms und damit ueber der Schwelle
von 30 ms, die §3 VOR der Messung festgelegt hat -- formal Fall B, CAKE ist
begruendet. Die Einschraenkung gehoert zur Zahl: durch alle sechs Lastphasen lief
ein Videocall, und es wurde kein einziger Problem-Button gedrueckt. Messbar ja,
wahrnehmbar nein. waveform sagt zeitgleich Grade A -- kein Widerspruch, sondern
ein kuerzerer Test, dessen Upload-Verteilung zweigipflig ist (25. Perzentil
14,5 ms, 75. Perzentil 47,5 ms).
Erstmals dokumentiert: die tatsaechliche Linerate. Upload 9,6 Mbit, Download
54,6 Mbit. Die im Repo kolportierten "~10 Mbit" galten immer nur dem Upload.
Der lautere Befund ist ein Nebenprodukt: der Core-Sampler hat 2,5 Stunden lang
das iPhone mitgeschrieben. Sticky Client (ein Weg durchs ganze Haus, dreimal
direkt an ap1 vorbei, eine einzige Uebergabe -- und die erst oben bei -73 dBm)
und Band-Ping-Pong (zwoelf Wechsel in neun Minuten am selben Ort). Je Wechsel bis
zu 4 s ohne Durchsatz -- als Obergrenze notiert, denn die Zaehler starten nach
einer Neuanmeldung bei null; der saubere Test per ping auf das Telefon steht aus.
Das passiert TROTZ aktivem 802.11k/v und FT, live geprueft: damit ist die
Merkregel ref_ft_is_not_roaming historisch. Der Bandabstand von 8--10 dB ist
dabei normale Physik; das Problem ist, dass 5 GHz an den Telefonier-Orten bei
-75 bis -80 dBm landet.
Zwei Messfehler bleiben dokumentiert, weil sie die Methode betreffen und beide
denselben Typ haben -- die Anzeige war gruen, die Wirkung fehlte:
speed.cloudflare.com/__down antwortet ohne User-Agent mit 403 und einem Byte
(saubere Ping-Reihe ueber tote Flows), und ein Call lief 5,5 Minuten ohne
Treiber (Marker geschrieben, nichts gemessen).
Status nachgezogen -- Header inklusive: TP6 von "Praemisse pruefen" auf
"gemessen, Fall B, nachrangig", TP25 auf kritischen Pfad. Rohdaten liegen unter
docs/messdaten/tp6-20260820/, damit die Zahlen nachpruefbar bleiben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Durchlauf 1 ist gemessen (Ergebnis folgt separat im Runbook). Fuer den Durchlauf
mit laufendem Videocall brauchte es Werkzeug, das es noch nicht gab:
- tp6-monitor-core.sh haengt EINE persistente SSH-Sitzung an den Core und laesst
dort eine Console-Schleife laufen, die im 2-s-Takt CPU, WAN-Rate und die
Registration-Table-Werte eines WLAN-Clients als CSV ausgibt. Nur Lesezugriffe.
Unter CAPsMAN fuehrt der Manager die Tabelle, deshalb wird der Core abgefragt
und nicht ap1/ap2. Zwei RouterOS-Fallen sind im Code kommentiert: die Console
parst eine per SSH uebergebene Mehrzeilen-Eingabe zeilenweise, und in der
Einzeiler-Form braucht jeder do={}-Block ein abschliessendes Semikolon.
- tp6-marker/server.py ist die Konsole fuer die Person am Telefon: Phasenkarte
mit Klartext-Anweisung, Countdown, Fortschritt, Marker-Buttons und Not-Aus,
bedienbar vom iPad. Die Buttons sind server-seitig gerenderte Formulare und
die Anleitung aktualisiert sich notfalls per meta-refresh -- auf dem iPad ist
das JavaScript ausgefallen, uebrig blieb nur der eine statische Button.
- tp6-call-run.sh fuehrt Durchlauf 2 mit denselben Messparametern wie Durchlauf 1
(3 Flows x 430 KB/s, 24 Pings, 30 s Settle) und ergaenzt Ruhephasen davor und
danach, Phasenmarken, eine PID-Datei fuer den Not-Aus und einen Heartbeat.
Der Heartbeat ist kein Detail: ohne ihn geht der Start-Klick still ins Leere,
der Call laeuft ohne Last, und "keine Probleme" liest sich wie ein Ergebnis,
obwohl es eine Nicht-Messung ist -- genau so passiert, 5,5 Minuten lang.
- tp6-auswertung.py schneidet die Sampler-CSV an den Phasenmarken auf und meldet
neben min/avg/max auch die Ereignisse, die im Mittelwert untergehen: Roaming,
Re-Assoc und Verschwinden des Clients.
- tp6-bufferbloat-messung.sh schickt jetzt User-Agent und Referer mit. Ohne die
beantwortet speed.cloudflare.com /__down mit 403 und einem Byte: die Flows
sind sofort tot, die Ping-Reihe sieht sauber aus, und die Download-Seite gilt
faelschlich als bufferbloat-frei. Aufgefallen ist es nur, weil der Sampler am
Core 164 kbit statt 50 Mbit zeigte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Messrunbook beschreibt die Methode, war aber nichts, das man jemandem in
die Hand druecken kann. Dazu jetzt zwei Artefakte:
- tp6-bufferbloat-messung.sh reproduziert die Methode von 2026-06-16
(3 Flows Saettigung, 24 Pings idle/Last) und misst zusaetzlich die
Download-Richtung, die damals nie gemessen wurde. Es prueft vorab die zwei
Vorbedingungen, an denen die Messung sonst still scheitert: Default-Route
ueber utun* = WARP-Verdacht, und mehr als eine 10.40er-Adresse = dual-homed.
Beides nur als Warnung -- die definitive WARP-Kontrolle ist das
Menueleisten-Icon, das kein Skript sehen kann.
Es misst ausschliesslich und aendert nichts am Netz.
- tp6-messung-tutorial.md ist die Anleitung fuer die Person am Kabel (Geli),
getrennt in den einfachen Browser-Weg und den exakten Skript-Weg. Das Warum
bleibt im Runbook, hier steht nur das Machen.
Beide verweisen fuer die Auswertung auf tp6-praemisse-messrunbook.md §3/§5,
damit das Abbruchkriterium an genau einer Stelle steht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Messrunbook verlangte einen kabelgebundenen VLAN10-Client, warnte aber
nicht vor WARP. Ein aktiver WARP-Client tunnelt alles durch Cloudflares
QUIC-Proxy -- gemessen waere der Tunnel statt der Leitung, und ICMP kaeme gar
nicht erst durch. Genau das ist hier schon zweimal passiert. Dazu die
Dual-Homing-Falle: das MacBook haelt zeitweise Leases in VLAN10 und VLAN20.
Beides steht jetzt als Vorbedingung vor Schritt 1, nicht als Fussnote.
Die Uebergabe traegt den live verifizierten Ist-Stand (92/92, 0 forward-Drops
heute), die fuer die Messung relevanten Randbedingungen -- Fasttrack ist
entschieden, /queue fehlt im Template, der Core ist ein 800-MHz-ARM -- und
was mit beiden moeglichen Ergebnissen zu tun ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alle drei haben am 19. ein ausfuehrbares Runbook bekommen, trugen im Header
aber weiter "VORBEREITET (08-08)", "TODO" bzw. "Recherche durch, Umsetzung
offen". Dasselbe Muster, das heute schon TP3, TP3.3 und TP28 betroffen hat:
der neue Inhalt wird geschrieben, der Header bleibt stehen.
Die jeweils wichtigste Erkenntnis steht jetzt im Header-Vorspann, damit sie
nicht erst im Runbook gefunden werden muss -- bei TP13 vor allem der
Denkfehler "SSID ohne Security".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine frische Session hat nach Core und CAPsMAN gefragt, weil die Datei sich
selbst widersprach. Ursache war nicht fehlende Information, sondern dass bei
Statuswechseln jeweils nur der neue Abschnitt geschrieben und der alte Header
stehengelassen wurde:
- TP3 trug im Header "beide hAP ax2 sind reine Standalone-APs, CAPsMAN
abgeschafft", und sein Lesehinweis verwies als "Ist-Stand" auf den
08-08-Eintrag. Wer die WLAN-Frage hatte, landete zuerst dort -- und bekam
die falsche Antwort. TP3 ist jetzt als vollstaendig historisch markiert und
verweist auf TP28.
- TP3.3 stand als "TODO (neue Session)", obwohl es seit 08-17 in TP25
aufgegangen ist.
- TP28 selbst trug unter dem Header "KOMPLETT" noch einen Punkt "OFFEN -- das
GC-Modell beschreibt weiter Standalone-APs" mit der stale Zahl 76/76. Das
war mein Rest vom 18.: Header umgeschrieben, Punkte darunter nicht.
- Die Abnahme in doku-cleanup-session.md verlangte woertlich "kein CAPsMAN" --
ein Kriterium, das den falschen Zielzustand beschreibt, bestaetigt genau die
Session, die den ueberholten Stand wiedergibt.
- Dazu HW-Refresh-Zeile und die ft-over-ds-Notiz in TP25 nachgezogen.
Merkregel, die jetzt an drei Stellen im Dokument steht: bei einem Statuswechsel
nicht nur den Header umschreiben, sondern die Punkte darunter mitziehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
E5 war in teilprojekte.md beschrieben, aber an drei Stellen nicht
mitgezogen. Die Etappen-Kette im kritischen Pfad endete bei E4, der
TP5-Header trug "DURCH (2026-08-18)" -- E5 kam einen Tag spaeter -- und
CLAUDE.md nannte "IoT anlernen" weiter als Fall fuer jit-admin, obwohl
MAIN->IOT seit E5 dauerhaft offen steht.
Beim TP5-Header steht jetzt explizit, dass "DURCH" nicht "abgeschlossen"
heisst: unter deny-by-default braucht jeder neue Dienst ueber eine
VLAN-Grenze seine Regel, weitere Etappen sind Betrieb und kein
Rueckschritt. Sonst liest die naechste Session ein ✅ und wundert sich
ueber E6.
In CLAUDE.md steht jetzt, welche Paare dauerhaft offen sind (MAIN nach
INFRA/MEDIA/MGMT/IOT) und dass IOT->MAIN bewusst zu bleibt, plus die
SNMP-Merkregel: der Drucker faellt mit udp/161 auf, nicht mit 631 -- eine
Whitelist auf dem erwarteten Port haette nichts repariert.
Gegengeprueft: Compliance live 92/92, 0 Drifts; E5-Regel am Geraet aktiv
mit 100 Paketen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ip-plan.md war als Statusdokument stale: ap1 stand als "Router/GW, ist GW,
kein Umzug" und sw1 als lebendes Geraet mit offenem Migrationsschritt.
Beides seit dem Core-Cutover falsch. Kopfblock mit der heutigen
Rollenverteilung davorgesetzt, die sechs betroffenen Zeilen nachgezogen --
die Planung von damals bleibt darunter lesbar, geloescht wurde nichts.
doku-cleanup-session.md: Punkt E geschlossen. Der Nachlauf haelt fest, dass
zwischen 16. und 19. zwei Runden Drift dazugekommen sind, und warum die
erste lehrreicher ist: nachgezogen wurden die TP-Abschnitte und CLAUDE.md,
stehen blieb ausgerechnet der Block, den eine frische Session zuerst liest.
Memories: project_tp3_ap_rebuild bekommt einen Superseded-Kopf (der Satz
"reine Standalone-APs, kein Manager/CAP" war bis 08-17 richtig), das
wifi-rebuild-Memory einen Hinweis, dass die CAPsMAN-Abschaffung inzwischen
selbst revidiert ist. In ref_nautobot_api_gotchas stand "kein CAPsMAN" als
Begruendung fuer den logischen Controller -- die Begruendung ist weg, der
Stand bleibt, und die Modellfrage ist jetzt als offen markiert statt still
falsch.
Neu: feedback_abnahme_wirkung_nicht_anzeige. Drei Fehlbefunde in einer
Nacht -- Registration-Table, Job-Status, 70-Sekunden-Zaehler -- hatten
dieselbe Ursache: gemessen wurde die Anzeige daneben, nicht die Wirkung am
Ziel. Der WLAN-Fall kostete 14 Stunden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Deny-by-default arbeitete korrekt — es gab nie eine vlan10->vlan30-Zeile.
Offen waren nur MAIN->MEDIA, MAIN->INFRA, MAIN->MGMT; IOT fehlte als einziges
Paar. Neue Regel voll einbahnig ohne Portfilter (User-Entscheid): MAIN steht zu
INFRA/MEDIA/MGMT ohnehin ungefiltert offen, und dort liegen NAS/Proxmox/Nautobot.
IOT->MAIN bleibt bewusst zu — dort sitzt der Wert der Segmentierung.
Merkregel aus dem Drop-Log: der Drucker faellt mit udp/161 auf, nicht mit 631.
macOS fragt zuerst den SNMP-Status ab und bricht ab, bevor es zu IPP kommt —
eine Whitelist auf 631 haette nichts repariert.
Abnahme von 10.40.10.82 (der Quelle aus dem Log): .30.5 ICMP 0% Loss,
snmpget sysName.0 -> P750W, tcp/631+9100+80 offen; Shellys .30.202/.203/.221
HTTP 200. Compliance 92/92, 0 Drifts. Seit dem Deploy keine neue
vlan10->vlan30-Zeile im Kollektor.
Nebenbei: gc-manual-plan.py --assert URL-encodet die Query jetzt. Ein Kommentar
mit Leerzeichen warf InvalidURL erst NACH dem erfolgreichen Deploy — man steht
mit einem Traceback da und weiss nicht, ob der Change gewirkt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Sachen standen in TP13, die so nicht stimmen.
Erstens beschrieb der Technikteil noch Standalone-APs und wollte die
Beacon-SSIDs in ap{1,2}-prov-base.rsc ergaenzen. Seit dem CAPsMAN-Cutover
entstehen SSIDs am Manager auf dem Core -- was fuer TP13 sogar einfacher
ist, ein Deploy statt zwei.
Zweitens der eigentliche Fund: der Entwurf wollte "nur ssid=, kein
Security" und begruendete das damit, dass Namens-SSIDs ohne offenen Zugang
rechtlich unkritisch seien. Eine SSID ohne Security IST aber ein offenes
WLAN, also genau der Fall, den der Rechtsvorbehalt ausschliessen will.
Richtig ist ein PSK, den niemand kennt: beacont den Namen, niemand kommt
rein. Kostet nichts.
Dazu die Datapath-Falle: ein Slave-VAP ohne explizite vlan-id am Manager
landet ungetaggt in der Bridge, weil der CAP vom Manager-Datapath nur die
vlan-id uebernimmt. Gleiche Mechanik wie der 14-h-Ausfall. Die
Botschafts-SSID braucht deshalb beides -- PSK und toten Datapath.
VAP-Budget am Geraet nachgesehen statt geschaetzt: max-interfaces=16 je
Radio, belegt sind 4 bzw. 5. Die Zahl ist also nicht die Grenze, Airtime
ist es -- jeder VAP beacont eigenstaendig. Empfehlung steht im Runbook.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beide TPs waren "Recherche durch / Umsetzung offen" bzw. "TODO" -- also
jeweils eine Zeile, aus der eine frische Session nicht losarbeiten kann.
TP16.3: der Schnitt (nautobot aus dem bf-nas-Ingress) ausformuliert, mit
Vorbedingungen, PUT-Ablauf und Rollback. Zwei Dinge stehen jetzt explizit
drin, die den TP sonst kippen: Mesh-Hostname-Routes sind Egress und
veroeffentlichen nichts -- wer das verwechselt, baut den Public-Strang ab;
und Nautobot ist nicht nur eine Web-UI, sondern die Deploy-Pipeline, also
gehoert ein Job-Lauf zur Abnahme und nicht nur ein Browser-Aufruf.
TP14.4: Ist-Stand nachgesehen -- in mcp/cloudflare/.env stehen weder
CF_ACCESS_CLIENT_ID noch _SECRET, es ist also nichts halb erledigt. Das
Secret gibt es nur im Moment der Rotation, das steht jetzt als Warnung
davor. Abnahme braucht beide Faelle: mit Headern antwortet, ohne 403 --
sonst haette ein bypass-Hostname wie vw als Erfolg durchgehen koennen.
Kein CF-Write, kein Token rotiert. Beides bleibt Papier.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der kritische Pfad widersprach sich selbst: der Einleitungsabsatz sagte seit
dem 18. "Praemisse offen, erst messen", Punkt 2 der Liste darunter sagte
weiter "keine offenen Blocker mehr". Punkt 2 nachgezogen.
Neu: docs/tp6-praemisse-messrunbook.md. Reproduziert die Methode von
2026-06-16 (3 Flows Saettigung + 24 Pings idle/Last), damit die Zahlen
vergleichbar sind, und misst erstmals die Download-Richtung -- die wurde
damals nie gemessen und ist beim asymmetrischen Kabelanschluss die
wahrscheinlichere Problemseite. Das Abbruchkriterium steht VOR der Messung:
A/A+ heisst TP6 wird geschlossen statt gebaut.
Fasttrack (die Entscheidung, die der Handoff Christoph vorbehalten hat):
bleibt wie er ist, gilt ab jetzt aber als Absicht statt als Unfall. Bei
~10 Mbit WAN kostet der Verzicht nichts, fuer CAKE ist er sogar die
bequemere Ausgangslage. Gegenbedingung notiert: wer Inter-VLAN je auf
Gigabit will, muss vorher messen, was die Core-CPU ohne Fasttrack traegt.
Damit sind zwei offene Stellen zu -- das "Entscheidung noetig" in TP6 und
die TP21-Warnung, dass das Re-Baseline den Zustand zum Soll erklaert hat.
Die Merkregel dort bleibt: dass es diesmal gut ausging, war Glueck.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ich hatte "30 Clients vorher, 30 nachher, kein Aussetzer" attestiert. Genau
diese Zahl hat einen laufenden Ausfall verdeckt: seit dem CAPsMAN-Cutover vom
17. war slaves-datapath auf beiden APs leer, IOT/MEDIA/UNTRUSTED/GUEST hingen
in keiner Bridge, Clients assoziierten und bekamen nie DHCP -- 14 Stunden.
Die Registration-Table zeigte derweil zufriedene Clients.
Abnahme fuer WLAN-Umbauten ist eine frische DHCP-Lease pro SSID, nicht die
Registration-Table. In der Uebergabe nachgetragen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine parallele Session hat drei Befunde gemeldet, alle drei richtig. Sie sind
hier abgearbeitet.
1) Der "Ist-Stand (Kurz)"-Block war an vier Stellen ueberholt: Standalone-APs
statt CAPsMAN, RouterOS 7.19.5/7.23 statt 7.24, "plain 1.1.1.1" statt DoH,
68/68 statt 92/92. In der Nacht wurden die TP-Abschnitte und CLAUDE.md
nachgezogen, aber ausgerechnet der Block, den eine frische Session zuerst
liest, blieb stehen.
2) TP26 und TP27 existierten nur als Commits und .rsc-Dateien, ohne Abschnitt.
Beide nachgetragen. TP27 (RouterBOOT 7.24) ist auf allen vier Geraeten
abgeschlossen -- current-firmware = upgrade-firmware = 7.24, geprueft.
3) Fasttrack ist auf dem Core tot: 32,9 Mio Pakete auf der accept-Regel davor,
0 auf Fasttrack, 0 von 445 Verbindungen fasttracked. Herkunft ist der
Core-Cutover (ap1 hatte die Reihenfolge richtig). Und das Re-Baseline vom
18. hat den Fehler als Absicht in die SoT geschrieben -- die Kehrseite von
ingest-core-firewall.py, jetzt als Warnung in TP21.
Dazu: die TP6-Praemisse wackelt. call-quality-diagnosis.md misst A/A+ und
haelt CAKE fuer marginal; TP6 wird trotzdem als "DAS Ziel" gefuehrt. Naechster
Schritt ist deshalb eine Messung gegen den heutigen Edge, nicht eine Queue.
Uebergabe fuer die Doku-Session: docs/handoff-doku-session-20260818.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ap2 durchgestartet, nach 40 s wieder da. slaves-datapath=dp-caps-slaves
steht noch, der CAP findet crs326-core durch die gehaertete input-Kette
wieder (MNDP/CAPWAP korrekt offen — seit TP5 Etappe 4 nie getestet), die
sieben Slave-VAPs kommen als dynamische Bridge-Ports mit pvid 30/40/50/90
von selbst zurueck. Abnahme per frischer Lease: IOT 10.40.30.8 nach 30 s.
Nebenbefund: /system reboot ist ueber MikroMCP auf 7.24 nicht machbar
(Tool sendet unbekanntes delay, run_command per Deny-Policy gesperrt).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Template ueber push-gc-template.py nach bf-golden-config gepusht,
GitRepository-Sync, dann Backup -> Intended -> Compliance. Der erste
Sync-Versuch starb an einem redis broken pipe im Nautobot-Stack; Retry
ging durch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seit dem CAPsMAN-Cutover (2026-08-17) war `/interface wifi cap
slaves-datapath` auf ap1 und ap2 leer. Das ist das einzige Feld, das die
vom Manager erzeugten Slave-VAPs lokal in die Bridge haengt: der Core
schickt `datapath.bridge=bridge` zwar mit, der CAP uebernimmt davon aber
nur die vlan-id. Ergebnis: -iot, -media, -untrusted und -guest hingen in
gar keiner Bridge — Clients assoziierten sauber und bekamen nie DHCP.
`dirtyvader-main` lief weiter, weil wifi1/wifi2 statische Bridge-Ports
sind; genau das hat den Ausfall getarnt.
Fix live auf beiden APs: dp-caps-slaves (bridge=bridge, bewusst ohne
vlan-id) + slaves-datapath darauf. Die VAPs stehen seither als dynamische
Bridge-Ports mit pvid 30/40/50/90 in der Bridge.
Nicht die TP5-Haertung: torch auf vlan30 am Core leer UND kein einziger
DHCP-Eintrag im Drop-Log — es wurde nichts verworfen, es kam nichts an.
tp28-ap-wifi-reste-abraeumen.rsc hat den Ausfall nicht ausgeloest, aber
zementiert: mit den geloeschten datapath-Objekten gab es lokal nichts
mehr, worauf slaves-datapath haette zeigen koennen.
Die TP28-Abnahme "ohne jeden Aussetzer" ist korrigiert — sie zaehlte
Registrations, also genau die Metrik, die hier luegt. Abnahmekriterium
fuer WLAN-Umbauten ist ab jetzt eine frische DHCP-Lease pro SSID.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92/92 compliant, 0 Drifts (vorher 71/76 bei 19 Rules -- jetzt 23 Rules).
NTP: die Wurzel war doppelt. Der Core hatte keinen eigenen Client, UND sein
Server hielt Stratum 16 fest, weil er eingeschaltet wurde, bevor der Client
synchron war. Der Test, der es aufgeklaert hat: branch einmal auf
at.pool.ntp.org zeigen lassen -- 20 Sekunden bis synchronized, also war der
Client heil und der Server schwieg. Jetzt im Template, per DHCP-Option 42 an
alle Clients ausgeliefert und mit der Rule system-ntp ueberwacht.
TP7.1: SSDP-Relay laeuft als LXC 108 auf pve, zweibeinig in VLAN10+40.
User-bestaetigt: "sonos ist da!". core ether13 traegt dafuer jetzt beide VLANs.
TP28: die APs trugen noch die komplette Standalone-WLAN-Config aus TP3 --
wirkungslos, aber sie haette als Soll totes Zeug zur Absicht erklaert.
Abgeraeumt, ohne einen einzigen Client zu verlieren (30 vorher, 30 nachher).
Die fuenf wifi-*-Features haengen jetzt am Core, dazu drei neue Rules
(wifi-capsman, wifi-provisioning, wifi-cap).
Gelernt: [find !dynamic] ist auf /interface wifi configuration ein
SYNTAXFEHLER, kein Filter -- der erste Anlauf aenderte nichts und meldete
trotzdem "Plan Completed".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Core hatte keinen eigenen NTP-Client bei use-local-clock=no. Ein Server
ohne Synchronisation liefert Stratum 16, das jeder Client verwirft -- die
Anfragen kamen an und wurden trotzdem nicht brauchbar beantwortet. Der
Standort hatte an keiner Stelle eine funktionierende Zeitsynchronisation.
Notiert ist auch, dass /system ntp gar keine Compliance-Rule hat -- derselbe
blinde Fleck, den TP26 fuer /ip firewall filter geschlossen hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP5 ist durch: deny-by-default steht in forward UND input. Der kritische Pfad
besteht damit nur noch aus TP6 (CAKE).
Drei Funde, die den Drop sonst zum Ausfall gemacht haetten und die im
70-Sekunden-Fenster von Etappe 2 unsichtbar waren:
- der Netmiko-Deploy kommt von nautobot-worker (.20.31), nicht vom
Web-Container (.20.30) -- der Drop haette den GC-Pfad selbst gekappt
- Matter laeuft ueber udp/5540, die IOT->INFRA-Regel war TCP-only
- die CAPs finden ihren Manager per Layer-2-Discovery (MAC, keine IP);
der input-Drop verwarf MNDP, kaputt gewesen waere es erst beim naechsten
AP-Reboot
TP19 geschlossen: VLAN1-ARP = 0, Prometheus ohne .41.x-Ziele, ap2-Kruecke weg.
Die zwei Reste sind dorthin verschoben, wo sie hingehoeren (tote CF-Tunnel
-> TP16, HA-Portainer setup_retry -> TP11), statt den TP offen zu halten.
Nebenbefund und behoben: der Standort hatte keine funktionierende Zeitquelle
(alle zeigten auf 10.40.99.1, wo kein NTP-Server lief; ap2 war 17 h versetzt).
TP21: der Nautobot-Stack hat sich zweimal selbst umgebracht -- Ursache war der
Image-Healthcheck (voller Django-Start alle 10 s, Aufrufe stapeln sich), nicht
Celery. Dazu zwei echte Template-Fehler: /ip service heisst seit 7.23
available-from, und hw-offload gehoert in die SKIP-Liste. 71/76 compliant.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs/routerboot-firmware-klickanleitung.md: Schritt-fuer-Schritt fuer WinBox.
RouterOS ist auf allen vier bereits 7.24, nur der Bootloader haengt zurueck
(core/branch 7.19.5, ap1/ap2 7.23.2 -- live erhoben). Der Weg geht per Hand,
weil `/system routerboard upgrade` interaktiv nachfragt: MikroMCP blockt ihn per
Deny-Policy, und Netmiko bekommt den Prompt statt einer Antwort und quittiert mit
E3001 bei LEERER Fehlermeldung. Auf core/branch waere ein Scheduler-Umweg
moeglich, auf den APs nicht (device-mode=home sperrt ihn).
Reihenfolge ap1 -> ap2 -> core -> branch mit Ausfall je Geraet; branch zuletzt,
weil der Arbeitsplatz per Kabel daran haengt. Dazu Gegenprobe-Einzeiler fuer alle
vier und die Falle, dass ohne Schritt 7 (Reboot) `Current Firmware` alt bleibt.
Aus der Parallelsession dazugekommen:
- TP5 Etappe 3 UND 4 sind abgenommen, beide Auto-Reverts abbestellt. Die
Abnahmen stehen in den Skriptkoepfen: forward-Drop hat in der Testphase 11
Pakete gefressen, ausschliesslich die eigene pve->branch:22-Sonde; beim
input-Drop war es reines Broadcast-Rauschen (NetBIOS, SSDP). Der GC-Deploy-Pfad
wurde als Pfadbeweis mitgetestet (nautobot-worker -> ap2:22 = SUCCESS).
- E4-Nachtrag: MNDP und CAPWAP muessen in den input. Die CAPs finden ihren
Manager per Layer-2-Discovery (`current-caps-man-address` ist eine MAC, keine
IP) -- bestehende Sitzungen laufen ueber seal-est weiter, der Bruch schluege
also erst beim naechsten AP- oder Manager-Neustart zu.
- TP19 NTP: alle drei Nicht-Core-Geraete fragten einen Zeitserver, den es nicht
gab (`status=waiting`, branch hatte gar keinen). ap2 war 17 Stunden nach und
hat einen Logeintrag von 04:57 als 12:19 gestempelt -- geraeteuebergreifende
Korrelation war damit wertlos. Core wird Zeitquelle, die drei werden Clients.
- Template: `/ip service` exportiert `available-from=`, nicht `address=`. Das
Soll war falsch und das Geraet hatte recht -- vier Dauer-Drifts. Und
`hw-offload` fliegt aus dem Firewall-Renderer, weil REST es meldet und
/export es weglaesst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorbereitet, NICHT ausgerollt: 0 TP5-E4-Regeln am Geraet, seal-lan weiter
aktiv, kein input-Drop.
Der riskantere Teil, riskanter als der forward-Drop: der Core ist DNS- und
DHCP-Server fuer alle sieben VLANs, und beides ist input-Verkehr, der heute
allein von TP10-seal-lan durchgewunken wird. seal-lan naiv auf vlan10 zu
verengen nimmt in derselben Sekunde jedem anderen VLAN DHCP und DNS. Das
Skript geht deshalb strikt: Ersatzregeln (dns udp+tcp, dhcp, MAIN, HA:8728,
Nautobot-ssh, cf-mesh) zuerst, dann seal-lan disabled, dann Log, dann Drop.
Auto-Revert steht als Schritt 0 und setzt BEIDE Schnitte zurueck.
Zwei am Geraet gepruefte Voraussetzungen sind darin festgehalten: /system ntp
server ist disabled, es braucht also keine udp/123-Regel; und HA pollt den
Core selbst auf 8728 als INPUT -- die forward-Regel aus Etappe 2 deckt das
nicht ab. Dazu die JIT-Admin-Gruppe aus D3: Dauerregel mit leerer Liste, die
nichts oeffnet, bis sich jemand mit timeout eintraegt.
Nachtrag zum vorigen Commit da452ce: der dort als "vorbereitet" beschriebene
Etappe-3-Drop ist inzwischen ausgerollt und greift (5 Pakete). Der
tp5autorevert-Scheduler laeuft und wuerde ihn um 05:02:29 wieder abschalten --
wer ihn behalten will, muss den Scheduler vorher entfernen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drei Skripte aus der Folgesession. Stand am Geraet zum Commit-Zeitpunkt
(per REST gegengeprueft, nicht aus den Dateikoepfen abgeschrieben):
- tp23-stufe1-doh-core.rsc -> LIVE. use-doh-server auf den
Cloudflare-Gateway-Resolver, verify-doh-cert=true. Nur der GTS Root R4
importiert statt eines Bundles: der Core hat ~2,8 MB freien Flash, und die
Kette endet nachweislich dort. Der Root wurde per SFTP hochgeladen, nicht
per fetch geholt -- fetch haette check-certificate=no gebraucht und damit
genau die Pruefung ausgehebelt, die hier aufgebaut wird.
Schliesst zugleich TP21.1 TODO 1.
- tp5-etappe2-nachtrag.rsc -> LIVE. 17 TP5-E2-Whitelists (11 + 6).
Vier Luecken, die der Kollektor ueber dreieinhalb Stunden gezeigt hat:
Matter (udp/5540, 92 der 119 Zeilen -- die E2-Regel war protocol=tcp und
liess Matter komplett durchfallen), der Nautobot-Deploy-Pfad (kommt von
.20.31 = worker, nicht von .20.30 = web; jetzt als address-list, weil der
scheduler dieselben Jobs faehrt), und zwei Rueckwege aus abgelaufenen
Conntrack-Eintraegen. Dazu eine Vorratsregel fuer AdGuard, damit das
spaetere DNS-Umstellen ein reiner DHCP-Change bleibt.
Korrigiert meine Aussage vom Vortag: "die Log-Regel ist verstummt" beruhte
auf einem 70-Sekunden-Fenster und war so nicht haltbar. Genau deshalb
verlangt das Runbook ein mehrtaegiges Fenster.
- tp5-etappe3-drop.rsc -> VORBEREITET, NICHT AUSGEROLLT. Kein Drop und kein
Scheduler auf dem Geraet. Der Auto-Revert steht im Skript bewusst VOR dem
Drop, sonst gibt es ein Fenster ohne Sicherung; der Drop kommt HINTER die
Log-Regel, damit der Kollektor weiter sieht, was gefressen wird.
Gate fuer Etappe 3: die Log-Regel steht aktuell auf 0 Paketen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Cutover ist durch (34 Clients, iot=27, beide CAPs Ok, Roaming belegt).
Festgehalten sind vor allem die zwei Fallen, die mich Zeit und Christoph das
halbe IoT-Netz gekostet haben:
1. Unter CAPsMAN fuehrt der MANAGER die registration-table und die
wireless-Logs, nicht der CAP. Auf ap1/ap2 sind beide leer, obwohl das WLAN
laeuft — ich habe daraus zweimal faelschlich 'WLAN ist unten' geschlossen.
2. Drei uebereinstimmende .rsc-Dateien sind nicht drei Belege, wenn sie aus
demselben Bring-up stammen. Genau daran habe ich wlan-psks.env fuer
veraltet gehalten und ueberschrieben. Die Passphrasen sind am Geraet per
REST lesbar — das ist der Weg, nicht der Dateivergleich.
Offen: das GC-Modell beschreibt weiter Standalone-APs; die 76/76 ist stale
(13:55 gemessen, Cutover 18:05). wifi-*-Features muessen auf den Core.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Methodenwechsel ist vollzogen. Beide hAP ax2 sind CAPs, die gesamte
WLAN-Konfiguration liegt auf dem Core: 4 Kanaele, 6 Datapaths, 6 Security,
2 Steering, 9 Configurations, 4 Provisioning-Regeln je radio-mac.
Warum es diesmal traegt, obwohl CAPsMAN 2026-07-22 abgeschafft wurde: damals
war ap1 Manager UND AP, und ein Manager kann seine eigenen Radios nicht per
CAPsMAN provisionieren — genau diese Asymmetrie war die Ursache von TP3.1.
Mit dem Core als Manager sind beide APs symmetrisch. Der Core braucht dafuer
kein wifi-qcom: das capsman-Menue steckt im Basis-routeros, die 3,35 MB
freier Flash sind irrelevant.
Verifiziert am Geraet: beide remote-caps "Ok", alle 7 dynamischen VAPs je AP
mit korrekter SSID und VLAN, Kanaele exakt wie in TP25 gemessen (ap1
5180/ax/Ce/I + 2412/ax, ap2 5220/ax/Ce/I + 2462/ax), Bridge-Ports mit
richtigen PVIDs. "traffic processing on CAP" bestaetigt Local-Forwarding —
im neuen /interface/wifi gibt es ohnehin kein zentrales Forwarding mehr,
die datapath-Property existiert deshalb nicht.
ft-over-ds=yes ist jetzt aktiv (unter CAPsMAN erstmals verfuegbar), und
dirtyvader-guest hat eigenes Steering mit neighbor-group=bf-guest — nicht
bf-main mitbenutzt, sonst meldet 802.11k Gast-Clients BSSIDs einer SSID,
auf die sie nicht assoziieren koennen.
🔴 routeros/.secrets/wlan-psks.env war fuer infra/iot/untrusted VERALTET.
Die laufenden PSKs standen in ap1-prov-base.rsc. Mit den Datei-Werten
konnten die Shellys sich nicht mehr anmelden. Datei auf den laufenden Stand
korrigiert, PSKs auf dem Manager nachgezogen. Wer die Datei blind als
Wahrheit nimmt, sperrt das halbe IoT-Netz aus.
🔴 Eigener Messfehler, festhalten: /interface/wifi/registration-table auf dem
CAP zeigt unter CAPsMAN NICHTS. Die Registrierungen fuehrt der MANAGER.
Ich habe daraus faelschlich "WLAN ist unten" geschlossen, waehrend Christophs
Geraete mit vollem Ausschlag verbunden waren. Ab jetzt nur noch am Manager
zaehlen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bis heute gab es nur ip-firewall-nat. "72/72 compliant" sagte ueber die
Firewall gar nichts — und TP5 Etappe 3 wollte dort einen Deny-by-default
setzen, der dann als einzige Regel im Netz unbeobachtet gewesen waere.
Umsetzung datengetrieben statt als Templatezeilen: die 36 Regeln liegen in
local_config_context_data.firewall_filter, das Template rendert sie nur.
36 Regeln fest ins Jinja zu schreiben hiesse, dass jede TP5-Etappe einen
Template-Edit braucht — genau die Reibung, wegen der die Governance in
Verruf geraten ist. Neue Regel = ein Listeneintrag.
ingest-core-firewall.py ist ein RE-BASELINE-Werkzeug, kein Sync: es erklaert
den Ist-Stand zum Soll und macht blind ausgefuehrt die Drift-Erkennung
wertlos. Darum nur nach einer bewusst verifizierten Aenderung laufen lassen.
Drei Formatfallen beim Nachbau des /export-Formats, alle durch Vergleich mit
dem echten Geraete-Export bzw. durch die neue Rule selbst gefunden:
- REST liefert Booleans als STRINGS. `if rule.get("dynamic")` ist fuer
"false" wahr und filterte erst alle 36 Regeln weg (0 statt 36).
- REST sagt hw-offload=true, /export schreibt yes. Und "!" bzw. Kommas
werden NICHT gequotet (connection-nat-state=!dstnat, dst-port=8123,1883).
Quoting nur bei Leerzeichen.
- /export laesst Default-Werte weg: `disabled=no` steht nie drin,
`disabled=yes` dagegen schon. Das schlug beim ersten Lauf der neuen Rule
als 75/76 auf — die Rule hat ihren Zweck damit sofort erfuellt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 statische Werksregeln je AP entfernt (input-seal, fasttrack, ipsec, sogar
"accept to local loopback (for CAPsMAN)"). Ein reiner AP routet nicht; die
Regeln waren inert. Mgmt haengt an /ip service (TP16.1), nicht an der
input-Kette — kein Lockout-Risiko. ap2 danach: 2 Radios running, 7 Clients.
Der eigentliche Wert dieser Session steckt in den zwei Fehlschlaegen davor,
die --assert bei seinem ERSTEN echten Einsatz gefangen hat. Beide meldeten
"Plan-Status: Completed":
1. `remove [find]` erfasst die DYNAMISCHE Fasttrack-Dummy-Regel mit. RouterOS
verweigert deren Entfernung, das ganze Kommando wirft, es wird NICHTS
entfernt. Log: "tp26: remove warf".
2. Der naheliegende Fix `[find !dynamic]` ist ein SYNTAXFEHLER — korrekt ist
`[find where !dynamic]`. Und Syntaxfehler schlagen beim Parsen zu:
`:do {} on-error={}` faengt sie NICHT, der Handler laeuft nie. Symptom
deshalb besonders tueckisch — kein Fehler im Log, keine Wirkung,
Plan "Completed". Merkregel: on-error schuetzt vor Laufzeitfehlern,
nicht vor Tippfehlern.
Ohne --assert waeren beide unbemerkt geblieben. Genau der Fehlermodus, den
Christoph mit "einstellungen werden nicht uebernommen, dir faellt das nicht
mal auf" benannt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Plan-Status: Completed" sagt nur, dass die Zeilen abgesetzt wurden. Am
2026-08-17 blieb ein `/interface/wifi/set ... !channel` wirkungslos ohne zu
werfen, und das Selbstprotokoll meldete trotzdem Erfolg — weil es das Profil
las, waehrend der Interface-Inline-Override gewann. Die Abnahme haengt seither
daran, dass jemand daran denkt nachzusehen. Das ist kein Mechanismus.
--assert prueft nach dem Deploy per RouterOS-REST am Geraet und bricht laut ab:
--assert '/ip/firewall/filter|count=0'
--assert '/interface/wifi?name=wifi1|channel.width=20/40mhz'
--assert 'cmd:/interface/wifi/monitor?numbers=wifi1&once=|channel=5180/ax/Ce/I'
Format [cmd:]<pfad>[?query]|<feld-oder-count>=<erwartet>, mehrfach angebbar.
GET fuers Lesen, cmd: fuer POST-Kommandos wie monitor. Trenner ist |, nicht :,
weil MAC-Adressen in Werten Doppelpunkte haben.
Dokumentierte Regel dazu: bei Funkaenderungen muss die Assertion monitor lesen,
NIE das Profil — print detail zeigt aufgeloeste Werte, export die rohen, nur
monitor das, was auf der Luft ist. Genau diese Verwechslung war der Fehler.
Mgmt-IP kommt aus Nautobot (primary_ip4) statt hartkodiert. Passwoerter aus
$ENV, sonst aus ~/.secrets/credentials.env — mit eigenem KEY=VALUE-Parser, weil
die Datei WireGuard-[Interface]-Bloecke enthaelt, an denen `set -a; . datei` in
zsh still abbricht und alle Zeilen danach verschluckt. Fehlerausgaben
redacten das Passwort.
Getestet: count-GET, field-GET mit Query, monitor-POST (inkl. tx-power=18) und
der Fehlerfall, der korrekt abbricht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
-infra auf beiden APs und beiden Baendern disabled (User-Entscheid). Am Geraet
gegengeprueft: aktive-vaps 11 -> 9, w2infra/w5infra disabled=true auf ap1+ap2.
sec-/dp-/cfg-infra bleiben stehen, die Zone ist ohne Neuaufbau reaktivierbar.
Zur Rueckfrage "hidden statt disabled?": Verstecken spart KEINE Airtime. Eine
versteckte SSID sendet ihr Beacon weiter, sie laesst nur das SSID-Feld leer.
Airtime spart ausschliesslich das Abschalten der VAP.
Reconnaissance fuer die /ip firewall filter Compliance-Rule: core 25 Regeln,
branch 0, ap1+ap2 je 12 defconf-Reste (inert, inkl. "accept to local loopback
(for CAPsMAN)"). Zwei Entscheidungen vor dem Template-Bau festgehalten —
AP-Defconf abraeumen vs. als Soll schreiben, und branch als leer rendern.
Ohne die meldet die Rule sofort flaechendeckend Drift.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die neuen Funkparameter stehen jetzt in der SoT, nicht nur auf dem Geraet:
radios[5g].width 20/40/80mhz -> 20/40mhz, DEVICE_CHANNELS[ap2][5g] 149 -> 44.
Config-Context gepatcht, dann Backup -> Intended -> Compliance: 72/72, keine
Drifts. Ein kuenftiger Deploy kann die Fixes damit nicht zurueckdrehen.
Bemerkenswert: width fuer 2,4 GHz stand im Config-Context die ganze Zeit
korrekt auf 20mhz. Die SoT war richtig, das Geraet hat sie nicht befolgt —
der Beweis, dass das Problem der Inline-Override war und nicht die Datenlage.
Beim Nachpruefen, ob "72/72" die Funkparameter ueberhaupt abdeckt, sind zwei
Luecken aufgefallen (18 Compliance-Rules abgefragt):
- /interface wifi (Interface-Sektion) hat KEINE Rule. Die fuenf wifi-*-Features
decken nur die Profilobjekte ab. Die Inline-Overrides leben in der
Interface-Sektion — deshalb blieben Fund A und D seit 2026-08-08 unentdeckt,
waehrend die Flotte durchgehend "compliant" meldete.
- /ip firewall filter hat KEINE Rule, es gibt nur ip-firewall-nat. Die
TP5-Zeile "laeuft ueber ip-firewall-*-Features aus TP22" war damit
irreführend. Die 11 Etappe-2-Regeln und der kommende Deny-by-default sind
nicht drift-ueberwacht; "72/72" sagt ueber die Firewall nichts aus.
-> als Vorbedingung fuer TP5 Etappe 3 eingetragen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP5 Etappe 2: 11 Whitelist-Regeln auf crs326-core, abgeleitet aus 43.027
Logzeilen (21 h) statt geraten. D1 = MAIN->INFRA pauschal, D4 = MGMT named
sources (HA:8728, Nautobot:22, MAIN, cf-mesh), D5 = 8123 + MQTT.
Log-Regel ist im Moment des Deploys verstummt; Zaehler steht. Etappe 3 bleibt
gated auf ein mehrtaegiges stilles Fenster + D2 (iPhone aus dem IOT-SSID).
TP25 neu — WLAN-Stabilisierung, Sammel-TP fuer Christophs Beobachtungen 1-6.
Schritte 1-3 durch, alles am Geraet gegengeprueft:
- w2-iot trug einen channel.*-Override auf einem Slave-VAP (auf ap1 sogar
2ghz-n gegen einen 2ghz-ax-Master) -> Mechanismus hinter "-iot mal da,
mal nicht". Danach auf beiden APs BR/running.
- 2,4 GHz lief auf 40 MHz, obwohl ch-2g width=20mhz sagt: ein Inline-Override
auf wifi2 gewinnt gegen das Profil. Jetzt 20 MHz, ap1 ch1 / ap2 ch11.
- ap2s 5-GHz-Radio sendete mit 9 dBm, jetzt 18. Beide APs 40 MHz,
ueberlappungsfrei (5170-5210 / 5210-5250).
Drei Korrekturen an eigenen Annahmen:
- Die 9 dBm sind NICHT das ETSI-Band C. Der Wechsel ins Indoor-Band liess sie
bei 9; erst die Breite brachte 18. "80 MHz generell" traegt auch nicht,
ap1 fuhr 80 MHz mit 18. Mechanismus offen, Hypothese + Test in TP25.
- `!channel` loescht Inline-Overrides nicht, nur !channel.width einzeln.
- Frequenz vor Breite zu aendern hat ap2 kurzzeitig in denselben 80-MHz-Block
wie ap1 geschoben. Breite VOR Frequenz.
Die ch149-Notiz ist bis 03f328f (2026-06-18) zurueckverfolgt: geloest wurde
Co-Channel, nicht DFS. "non-DFS" war nachtraeglich mitgeschriebene Begruendung
fuer das FCC-Standardpaar 36/149, keine geprueft Anforderung. Und
skip-dfs-channels=10min-cac schliesst DFS gar nicht aus, nur das
Wetterradar-Band -> 5500-5700 liegt als Reservekanalraum brach.
TP16.3 neu — cloudflared-Reduktion: der Mesh IST schon der private Datenpfad
(137 Zeilen im TP5-Log belegen es), Container braucht nur der oeffentliche
Ingress. Mesh-Hostname-Routes fuer public hostnames sind Egress, nicht
Publishing — Verwechslungsfalle.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neue Compliance-Feature ip-service (17->18 Regeln, 68->72 Checks). Sollzustand
einheitlich im Template: ssh/www/winbox/api = 10.40.0.0/16,100.96.0.0/12;
ftp/telnet/api-ssl disabled. Deploy gestaffelt (ap2 zuerst, am Geraet
gegengeprueft), Job liegt als 'mgmt-acl' in gc-configplan.py.
Befund war invertiert: branch/ap1/ap2 hatten GAR KEINE Address-Beschraenkung
und waren laengst per Mesh erreichbar; winbox war auf allen vier offen. Aus dem
Erreichbarkeits-Fix wurde eine Haertung. ftp/telnet/api-ssl dabei abgeschaltet.
CF-Schalter 'Allow all Cloudflare One traffic to reach enrolled devices':
recherchiert, bleibt AUS - er oeffnet die Client<->Client-Richtung, unsere laeuft
ohne ihn. Kein API-Feld, CF-Docs widersprechen sich (Profil- vs. globale
Einstellung).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.5 Abnahme bestanden: 0% Ping-Loss auf alle BF-VLANs (vorher 100%), TCP mit
echtem Datenfluss ok, FQDN-Smoke beweist cloudflared-Public-Teil unberuehrt.
4.6 Auflage #4 erfuellt: Ist-Stand als intended config nach Nautobot,
65/68 -> Template ergaenzt -> 68/68 keine Drifts.
Zentrale Falle dokumentiert: /ip service address=10.40.0.0/16 sperrt das
Router-Mgmt aus der Mesh-Range 100.96.0.0/12 aus - Ping geht, SSH/REST/MikroMCP
sterben. Fuer branch/ap1/ap2 noch offen. Und: nc -z ueber WARP ist kein
Reachability-Beweis, der CF-Proxy terminiert den Handshake.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Prereqs: use_zt_virtual_ip=true, Device-Profil 'Cloudflare Mesh', Split-Tunnel
auf beiden Profilen (100.64/10 -> /11 + 100.112/12).
Geraet: cf-mesh, 100.96.0.6/32, Peer 162.159.193.2:2408, Handshake steht,
Route 100.96.0.0/12 aktiv. Backup vorher (Auflage #4).
4.4 Weg A hat funktioniert - vnet-Gotcha trat NICHT ein.
Zwei Werkzeug-Fallen dokumentiert: MikroMCP manage_wireguard_interface kann
keinen Privkey annehmen (CF liefert ihn aber), und manage_wireguard_peer
verarbeitet endpoint 'IP:Port' falsch (endpoint-port=0 -> kein Handshake).
Offen: Dashboard-only-Schalter 'Allow all Cloudflare One traffic to reach
enrolled devices' + Ping-Abnahme 4.5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POST /warp_connector erfolgreich -> d1da7c8a-... Der LXC-Fallback ist vom Tisch.
Blocker war der Token, nicht der Plan: alter User-Token hatte 2 fehlende
Permissions, ersetzt durch account-owned Token (gueltig bis 2027-01-09).
Zwei Fallen dokumentiert: account-owned Tokens verifizieren an
/accounts/{id}/tokens/verify (am /user-Pfad melden sie faelschlich
'Invalid API Token'), und Zone-Permissions brauchen eine eigene Policy-Zeile
('Account tag in access policy must match tag in request uri').
Verifiziertes Permission-Set inkl. IDs in 4.0. Am Geraet weiterhin nichts angefasst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POST /warp_connector -> 10000/403, identisch zu 2026-07-17. Neu: Gegenproben
zeigen, dass auch 4.1 blockiert ist (devices/settings GET 403) — es fehlen ZWEI
Permissions, nicht eine. MCP-Read-Gegenprobe belegt: Account kann es, Token darf
nicht -> Free-Plan-Frage bleibt offen. Am Geraet wurde nichts angefasst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Straenge, die sich dieselben Dateien teilen — deshalb ein Commit.
1) COMPLIANCE-DRIFTS BESEITIGT (User: "beseitige autonom alle") -> 68/68, 0 Drifts
Entfernt wurden die 4 verbliebenen `extra`-Drifts (der fuenfte, core 10.40.41.211,
war schon ueber TP19-vlan1-core-address gefallen):
- ap1 + ap2: Werks-defconf `/ip dns static router.lan -> 192.168.88.1`. Auf beiden
APs der einzige statische Eintrag, die IP existiert im Netz nicht. Der Core hat
sein eigenes, korrektes router.lan -> 10.40.99.1 (im Template, compliant).
- crs326-branch: Bring-up-Rest SVI vlan10 + 10.40.10.2, Adresse zuerst.
Richtung bewusst "am Geraet entfernen" statt "ins Template aufnehmen" — genau so
steht es seit 2026-08-13 im Switch-Zweig des Templates. Der frueher notierte
Vorbehalt "potenzielle Rettungspfade" ist per User-Entscheid aufgehoben; der
Mgmt-Fallback aus VLAN10 auf dem branch entfaellt damit (Rueckweg = MAC-Winbox am
selben Draht).
Weg: 3 manuelle GC-ConfigPlans, kein Direkt-Write. Vorher /system backup je Geraet.
Deploy gestaffelt — erst die APs, am Geraet gegengeprueft, dann branch.
Verifikation am GERAET, nicht am Job: DNS-Statics total=0 bei unveraenderten 28
bzw. 3 WLAN-Clients; branch nur noch vlan99 + 10.40.99.2/24; Ping vom Core 4/4.
Entscheidende Gegenprobe: /interface bridge vlan/export byte-identisch — `bridge`
steht dort statisch als tagged-Member von VLAN10, das Entfernen des SVI hat also
weder Traffic-Wirkung noch neuen Drift. Danach Backup -> Intended -> Compliance,
alle 4 Geraete mit frischem Success-Datum.
Neue API-Falle, die erklaert warum es bisher kein Skript gab:
POST /plugins/golden-config/config-plan/ ist 405 — das ViewSet ist read-only.
ConfigPlans entstehen nur ueber den Job "Generate Config Plans" (plan_type=manual
+ commands-TextVar). plan_type=missing erzeugt ausserdem nur add-Zeilen, also muss
alles Entfernende zwangslaeufig ein manueller Plan sein.
Neu: nautobot/gc-configplan.py — loest Device-UUIDs einzeln per Name auf und
assertet plan.device UND config_set gegen das Ziel (die alphabetische
Sortier-Falle aus TP21.1 kann damit nicht wiederkommen), verweigert config_sets
mit <<REDACTED>> (Regel 1) und print-Zeilen, kann gestaffelt deployen
(--deploy-ids) und kapselt Backup -> Intended -> Compliance (--refresh-compliance).
Dry-Run ist Default.
2) TP16.1: GATE OFFEN, Runbook ausfuehrungsreif, Governance-Ausnahme #4
Die Bedingung "gated bis TP21 den CRS326 abdeckt" ist seit der Adoption am
2026-08-13 erfuellt. §3 neu gemessen, §4.3 von Platzhalter auf echte Werte.
Die letzte inhaltliche Unbekannte hat sich erledigt: "Rueckweg-Routing TBD" —
der Core IST L3-Gateway aller VLANs, es braucht keine Zusatzroute. wg-hub liegt
auf demselben Geraet und ist damit direktes Vorbild statt fernes Muster.
Klarstellung, weil leicht zu verwechseln: das Mesh ersetzt die Tunnel NICHT. Es
loest nur den privaten Zugang (10.40.0.0/16 per IP, inkl. ICMP); die oeffentlichen
FQDNs bleiben auf cloudflared. Relevant dabei: die Route 10.40.0.0/16 zeigt auf
bf-pve — und der faehrt derzeit nur einen Connector.
Ausnahme #4 (User 2026-08-16): die WG-Zeilen des Mesh-Bring-ups auf crs326-core
duerfen direkt gesetzt werden. Grund ist strukturell, nicht bequem — TP22-Regel 1
schliesst jede <<REDACTED>>-Sektion vom Push aus, ein Privkey ist ueber Golden
Config gar nicht deploybar. Auflage: Backup vorher, intended config danach zurueck
nach Nautobot. Scope: nur dieser Bring-up.
Damit das ein einmaliger Bootstrap bleibt, ist das Secret-Handling-Design
dokumentiert: ein privater Schluessel ist Geraete-Identitaet, keine Konfiguration
(wie ein SSH-Hostkey). Der private Teil entsteht am Geraet und geht nie weg, nur
der oeffentliche kommt in die SoT und wird in die Peer-Configs gerendert.
Stufe 2 (nautobot-secrets-providers + Vault) lohnt bei 4 Geraeten und einem Key
nicht. Nebenbefund: die WG-Peers fm/dw stehen mit hartkodierten public-keys im
Jinja-Template — Public Keys sind Daten, keine Templatezeilen.
3) TP24 — USV aus TP15 herausgeloest (User-Entscheid)
Die DC-USV war der letzte offene Rest in TP15 und hat mit Switching/Routing
sachlich nichts zu tun (eigene Einkaufs-, Verkabelungs- und Elektrik-Logik).
TP15 ist damit inhaltlich zu. TP24 traegt jetzt 48V-Bus, MeanWell/LiFePO4,
Laufzeiten, DC-Eingangs-Tabelle und die 5 offenen Entscheidungen — darunter neu
die Standortfrage, die sich durch den Core-Umzug ins UG neu stellt.
4) DOKU-AUFRAEUM-SESSION A-E abgearbeitet
- Ist-Stand-Block neu geschrieben, live gegen die Geraete geprueft. Alte Fassung
als ausklappbare Historie, ⚠️-Provisorium entfernt.
- Reihenfolge-Abschnitt auf den echten Rest-Pfad TP5 -> TP6 eingedampft (Punkt 3
sagte noch "Jetzt: Omada-PVID-Fix").
- Stale ap1-als-Router-Aussagen in TP3/TP4/TP15/TP16.1/TP21/TP-R korrigiert —
fortgeschrieben, nicht ueberschrieben.
- CLAUDE.md: Mac mini .41.167 -> .20.167 (war stale, live per ARP bestaetigt),
branch-Uplink "sw1 GE8" -> "core ether8", ALLNET-/Omada-Gotchas als Historie.
- switch/ als Archiv gekennzeichnet (Geraet ausgebaut, Runner nicht ausfuehrbar).
- omada-mcp + CF-Ingress live gegengeprueft: beides sauber, Punkt abgehakt.
Nebenbefund, eingetragen aber nicht angefasst: das CF-Tunnel-HA ist degradiert
(bf-nas und bf-pve mit je nur einem Connector), und vier tote Alt-Tunnel tragen
VLAN1-Origins — darunter die Aufloesung des "unidentifizierten VLAN1-Geraets
.41.133" aus TP19 (es ist das coolify-Origin).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Container war bereits beendet; entscheidend war die Restart-Policy.
Mit `always` waere er beim naechsten Daemon-Neustart wiedergekommen, ein
blosses `docker stop` haette also nicht gehalten.
Nebenbefund, nicht von mir ausgeloest: grafana, drawio-server und hms-mqtt
wurden am 2026-08-16 um 17:14:54-17:15:06 CEST innerhalb von zwoelf
Sekunden per Signal beendet (grafana exit 0 mit "System signal:
terminated", drawio-server 143, hms-mqtt 137). Kein OOM, Speicher frei,
restarts=0. Folge: das Prometheus-Ziel grafana steht auf down, n8n und
prometheus weiter up.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Abnahme bestanden: out:bridge = 0 ueber ein 10-Minuten-Fenster (Logdatei
vorher geleert). Vorher waren vlan20 -> bridge 76 % des gesamten
Inter-VLAN-Verkehrs; die Rate fiel von ~166 auf ~34 Zeilen/min.
Beobachtete Matrix (339 Zeilen / 10 min) als Arbeitsmaterial fuer Etappe 2
festgehalten. Zwei Befunde daraus:
- D4 ist belegt statt geschaetzt: der Management-Pfad ist HA (10.40.20.105),
das ueber seine mikrotik-Integrationen 8728 auf branch/ap1 pollt (je 67x).
Ohne Whitelist sperrt der spaetere Drop die Netzverwaltung aus.
- Neuer Merkposten: same-VLAN-Verkehr erreicht die forward-Kette —
vlan10 -> vlan10 unicast mDNS, erzeugt vom mDNS-Repeater auf dem Core.
Harmlos, aber ein blanker Drop wuerde Discovery innerhalb von MAIN
beschaedigen.
Damit sind drei Whitelist-Zeilen bekannt, bevor Etappe 2 beginnt:
LAN->WAN, der Mgmt-Pfad, und same-VLAN-mDNS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
synopkg stop/start ContainerManager auf nas-bf. Alle 14 Container aus der
Baseline sind zurueck, zusaetzlich kam hms-mqtt hoch (Restart-Policy, lief
vorher nicht).
Der Neustart hat den Haenger behoben: `docker system df` beendet sich wieder
(vorher rc=124 nach Ausgabe der Tabelle). Er reicht aber nicht — der Aufruf
bleibt mit 33s bis ueber 120s weit ueber dem pyportainer-Timeout, die
HA-Integration bleibt auf setup_retry.
Gemessen, wo die Zeit hingeht: images -q 84ms, ps -aq 95ms, volume ls 65ms,
system df 33-92+s. Also vollstaendig in der Groessenberechnung (Durchlauf der
overlay2-/Volume-Verzeichnisse auf NAS-Platten) — Plattformnachteil, kein
Defekt.
Aussichtsreichster Weg dokumentiert: eigener Portainer-Benutzer fuer HA ohne
Zugriff auf ep14. Zwei widerlegte Zwischenthesen sind als solche festgehalten
(odroid-m1 war es nicht; es ist kein Groessenproblem).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pve: /etc/network/interfaces vmbr0 von inet static auf inet manual, Adresse
raus, angewendet per `ip addr del` ohne ifreload -a. Alle 9 Gaeste weiter
running, Storage aktiv, nur noch vmbr0.20 traegt eine IP.
core: 10.40.41.211 ueber Nautobot GC entfernt. Mgmt .99.1 + 10.40.10.1
intakt, Compliance 17/17 gruen — der letzte offene Drift ist damit weg.
Prometheus: der pauschale 41->20-Ersatz war eine Falle. Gemessen statt
angenommen — nur grafana und n8n liefern echte Metriken. gitea hat /metrics
nicht aktiviert, vaultwarden gibt 404, portainer /api/status liefert JSON
statt Prometheus-Format, node/alertmanager/qdrant sind exited, pihole ist
abgewaehlt. 8 Jobs + alerting-Block auskommentiert, 3 Ziele aktiv und up.
Zwei Korrekturen an eigenen Aussagen:
- Die tote Portainer-Umgebung odroid-m1 war NICHT die Ursache des
HA-Hangs. Sie ist entfernt, das Symptom blieb. Echte Ursache laut
HA-Debug-Log: `docker system df` auf ep14 kommt nicht zurueck.
- Auf der NAS ist prometheus.yml fuer den Login-User nicht schreibbar
(65534:65534, Verzeichnis gehoert adm.christoph). Zwei `cat >`-Pushes
sind still gescheitert. Schreiben nur per sudo tee + md5sum-Gegenprobe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Etappe 1 ist aufgebaut und verifiziert, wird aber vor der Sammelphase
pausiert (User-Entscheid): 76 % des beobachteten Inter-VLAN-Verkehrs waren
.41.x-Altlasten. Eine Whitelist daraus haette nach dem Aufraeumen nicht
mehr gegolten.
- Log-Regel disabled=yes, Memory-Logging zurueck auf topics=info
- Kollektor + Logging-Action bleiben stehen -> Wiederaufnahme = zwei Zeilen
(routeros/tp5-etappe1-pause.rsc dokumentiert beide Richtungen)
- D2 vollzogen: iPhone im MAIN-SSID, .30.201 im ARP auf failed
TP19 bekommt die konkrete Restliste, die der Log-Lauf sichtbar gemacht hat:
prometheus (.20.151) scrapet 10 tote 10.40.41.x-Ziele, .20.105 zieht auf
pve unter der alten .41.100. Umzugsregel 41->20 bei gleichem letzten Oktett.
Der gemeldete Timeout auf .20.100:8006 ist KEIN Firewall-/Portproblem:
pveproxy lauscht auf *:8006, pve-firewall disabled, HTTP 200 in 0,06 s aus
VLAN10 und VLAN20. Notiert ist auch die Fehlerquelle meines ersten Tests -
`timeout` existiert auf macOS nicht und meldet falsch-negativ.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Log-only-Regel am Ende der forward-Kette (blockiert nichts) plus Syslog-
Kollektor, ausgerollt ueber Nautobot GC als manual Config Plans.
- routeros/tp5-etappe1-log-lauf.rsc: der ausgerollte Endzustand + die am
Geraet belegten Lehren aus dem Rollout
- nautobot/gc-manual-plan.py: Push-Werkzeug (assertet plan.device, liest
Plan-Status statt Job-Status, strippt Kommentarzeilen)
Zwei Korrekturen an bisherigen Annahmen:
- Ein gescheiterter Netmiko-Deploy hinterlaesst einen TEIL-Zustand. Die
TP22-Notiz "sauberer Fehlschlag" galt dem NAPALM-Weg.
- Bindestriche in name= werden von RouterOS abgelehnt, Quoten hilft nicht.
Die zuerst notierte target=/remote=-Erklaerung war falsch und ist raus.
Die Log-Regel steht auf out-interface-list="!WAN": bare fing sie auch allen
Internet-Verkehr. LAN->WAN ist eine garantierte Whitelist-Zeile, also
Rauschen - und ein Merkposten fuer Etappe 3, wo der Drop aus demselben
Grund nicht bare stehen darf.
D2 entschieden: iPhone .30.201 wird ins MAIN-SSID umgehaengt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Dauersweep von .10.82 auf alle Shellys ist lanscan.app — ein Ad-hoc-Scan vom
Arbeitsplatz, kein Dienst. Also keine permanente MAIN->IOT-ICMP-Regel, sondern
Teil der selbstverfallenden JIT-Admin-Gruppe (deckt sich mit D4).
Hinweis fuer den Log-Lauf ergaenzt: der Scan erzeugt sonst Rauschen in Etappe 1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User-Constraint 2026-08-14: vw wird NICHT WARP-/Access-geschuetzt, dauerhaft.
Begruendung ist technisch, nicht Bequemlichkeit — die Bitwarden-Clients koennen
den interaktiven Access-Login nicht (dasselbe Muster wie der 400er der
HA-Companion-App). Ein Passwortmanager hinter einem Client, den man im Notfall
nicht installieren kann, ist ein Aussperr-Risiko gegen den eigenen Schluesselbund.
Die TP16-Schritt-5-Absicht "vw von bypass auf geschuetzt heben" ist gestrichen.
Neu: TP16.2 — Haertung aller bypass-Dienste (vw, hass, gitea) in Schichten:
- Schicht 0 (vorhanden): keine offenen Ports, alles ueber CF-Tunnel.
- Schicht 1: Access nur auf /admin* als eigene, spezifischere Application —
CF wertet die spezifischste App zuerst. Das Admin-Panel wird nur per Browser
bedient, die Client-Pfade (/api, /identity) bleiben bypass. Kein Client bricht.
- Schicht 2: App-eigene Limits (Vaultwarden LOGIN_RATELIMIT_* sind default an),
Signups aus, 2FA erzwingen; HA ip_ban_enabled.
- Schicht 3: CF WAF/Rate-Limiting gezielt auf die Login-Endpunkte.
- Schicht 4: CrowdSec/fail2ban mit CF-Bouncer — Bans an der Edge, alle Dienste.
Knackpunkt und Schritt 1: hinter dem Tunnel sieht die App nur die IP des
cloudflared-Containers. Jede IP-Sperre bannt sonst den Tunnel statt den
Angreifer = Selbstaussperrung. Genau dieser Defekt ist schon offen (HA
trusted_proxies fehlen .20.10/.20.167) — X-Forwarded-For/CF-Connecting-IP
sauber durchreichen ist Voraussetzung fuer Schicht 2-4.
Nebeneffekt: TP23s Managed-Networks-Weg ist entlastet — vw verlangt nie
Device-Identity, "WARP zuhause aus" kollidiert nicht mehr mit dem Access-Strang.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP23 — DNS-Policy & Self-Service-Ausnahmen (neu, Konzept entschieden):
- Architektur: Filterliste bleibt zentral bei Cloudflare, lokal nur die Diffs.
Kein RAM-Thema auf dem Core, eine Policy-Quelle, gleiche Regeln zuhause wie
unterwegs.
- Resolver-Wahl AdGuard Home (laeuft schon). Pi-hole disqualifiziert: spricht
kein DoH (braeuchte cloudflared-Sidecar) + belegter v5->v6-Bruch. Technitium
als dokumentierte Alternative.
- AGHs fehlendes Gruppen-Objekt ist hier unkritisch: Clients per CIDR = ein
VLAN ist eine Gruppe. Die Segmentierung ist bereits die Policy-Grenze.
- WARP im LAN via Managed Networks abschaltbar (Beacon auf NAS/pve); loest die
ICMP-Falle vom 2026-08-13. Side effect dokumentiert: kollidiert mit dem
offenen TP16-Schritt 5 (vw von bypass auf WARP-geschuetzt).
- 802.1X loest die IoT-Identitaet NICHT (kein Supplicant, MAB ist wieder MAC)
-> TP8 bleibt Sicherheitsthema, nicht DNS-Identitaetsquelle.
- Reihenfolge-Regel: TP5 darf die DNS-Bypass-Sperre erst schliessen, wenn die
Ausnahme-Oberflaeche steht — der bisherige Workaround "Client auf 1.1.1.1"
IST dieser Bypass.
Weitere Korrekturen:
- TP7.1 (SSDP-Reflector) aus "vorgemerkt" in das TP5-Paket gezogen: iOS-App und
HA finden die Sonos, nur die macOS-Desktop-App nicht — SSDP quert die
VLAN-Grenze nicht. Kein Firewall-Problem, die Regel ist laengst offen.
- Ziel-Absatz (c): cudy1-VLAN1-Leak erledigt (core ether11 ohne Link,
Nautobot Offline). (b): st-main rrm/wnm ist seit TP3.3 kein Provisorium mehr,
sondern Teil der Golden Config.
- TP7: mdns-repeat-ifaces auf den Live-Stand des Core nachgezogen (ohne
bridge — mit dem VLAN1-Retirement erwartbar, war nie dokumentiert).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP5 (Deny-by-default) ist nach TP22 der kritische Pfad und jetzt einsatzbereit
vorbereitet — auf Live-Erhebung von crs326-core statt aus der Doku.
Neu:
- docs/tp5-deny-by-default-runbook.md: Ist-Stand forward/input/NAT/Interface-
Listen, Inter-VLAN-Flow-Matrix aus conntrack + Countern, offene Entscheidungen
D1–D6, 4 Etappen (Etappe 1 = reiner Log-Lauf ohne Blockierung), Rollback.
- docs/doku-cleanup-session.md: Arbeitsliste A–E für die Aufräum-Session
(Ist-Stand-Block, Reihenfolge-Liste, stale "ap1 = Router"/CAPsMAN-Aussagen).
Statuskorrekturen in teilprojekte.md:
- TP21.1 Punkt 4: TV-End-to-End-Beweis erbracht (Ping 5/5, MAC auf ether4/VID40
gelernt, RX 1.338 -> 6.909 Pakete). Das Kabel-Follow-up entfaellt — geloest
wurde am Port, nicht am Kabel.
- TP19.1: WIP -> erledigt (ap2 seit TP3-Rebuild auf .99.12, sw1/sw2 ausgebaut
und in Nautobot Decommissioned).
- TP5: Holes + WAN-Seal auf crs326-core re-verifiziert — die Verifikation vom
2026-07-02 galt ap1, das seit 2026-08-08 Werksreset ist. Befund: die 5
mDNS-Input-Regeln sind hinter TP10-seal-lan wirkungslos (0 Pakete).
- Ist-Stand-Block als Historie markiert, "Naechster Schritt" auf TP5 -> TP6.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TP22 Schritt 5 — Datenmodell as-built aus dem Geraet erhoben (bridge/port,
bridge/vlan, bridge/host + ARP/Leases), nicht aus der Doku:
- crs326-core von 5 auf 26 Ports; 3 waren "GEPLANT (tentativ)", ether1 zeigte
noch auf das tote sw1 #12
- Standort-Fehler: crs326-branch + ap2 standen auf Technik UG, real Technik OG
- sw1/sw2/cudy2 -> Decommissioned (Endzustand), cudy1 -> Offline;
sw1-Duplikat-Ports (gi*) entfernt
- Schritt 4 entschieden: keine Secret-Injection (Governance-Regel 1 deckt es ab)
TP21.1/4 — core ether4 geklaert und behoben: dort haengt das Wohnzimmer-
Sideboard. Der Port war als ap1-Trunk vorkonfiguriert, pvid=40 nahm untagged an
(Upstream ok), Egress war tagged -> TV bekam nichts. Diagnose ueber TX/RX-
Asymmetrie + ARP failed bei frischem bound-Lease (ein bound-Lease beweist nur
den Upstream: INIT-REBOOT-REQUEST braucht kein ACK). Auf untagged VLAN40
gezogen, Kabel bleibt auf Port 4 (Patchfeld-Nummerierung ist Infrastruktur).
TP3.3 — Steering-Regression aus dem TP3-Rebuild behoben: /interface wifi
steering war auf BEIDEN APs leer. 802.11r/FT macht die Uebergabe nur schnell,
ausgeloest wird sie von 802.11k/v -> sticky client bis zum Abriss. st-main
(rrm/wnm, neighbor-group bf-main) wiederhergestellt und ins GC-Template
aufgenommen, damit eine Neuprovisionierung es nicht wieder still verliert.
Compliance 20/20 -> 63/68 (dieselben 5 bekannten Altlasten):
- neue Features wifi-steering, bridge-port, bridge-vlan
- der L2-Layer war bisher komplett unueberwacht (core-Zweig hatte gar keine
Bridge-Sektion, AP-Zweig nur VLAN ohne Ports)
- Bridge-Sektionen bewusst als Literal-Block statt aus DCIM abgeleitet: pvid aus
untagged_vlan zu generieren haette die akzeptierten Schiefstaende (core ether3,
core ether2, branch ether9-23) zu Dauerdrift gemacht
Alle Geraete-Aenderungen liefen ueber Nautobot-GC-ConfigPlans mit /system backup
davor, keine Direkt-Writes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nimmt die 4 Live-Geräte (crs326-core/-branch, ap1, ap2) real unter Golden
Config: Backup -> Compliance -> intended -> kontrollierter Push. Damit greift
der Governance-Entscheid "Config exklusiv über Nautobot" operativ.
Secret-Leak geschlossen (Anlass, ungeplant gefunden)
Es gab keine ConfigReplace-Regeln, deshalb hatte der Backup-Job den
ap1-/export ungefiltert nach Gitea geschrieben: der live genutzte
WG-Hub-private-key und 6 WLAN-PSKs lagen dort im Klartext.
- nautobot/ingest-gc-scrubbing.py: 5 ConfigReplace-Regeln, Maske
"<<REDACTED>>". RouterOS quotet nur bei Bedarf (4 von 6 PSKs standen
unquotiert), daher Alternation mit der quotierten Variante zuerst --
\S+ ist greedy und würde bei einem PSK mit Leerzeichen den Rest
exponieren. Regex-Selbsttest läuft bei jedem Aufruf.
- Gitea-Repo neu angelegt (History-Rewrite verworfen: Gitea hält
unerreichbare Blobs bis zum server-seitigen gc). Verifiziert: 0
unmaskierte Secrets über alle 4 Geräte. User-Entscheid: nicht rotieren.
- push-gc-template.py: Pre-Push-Secret-Guard, --dry-run, -m, sha optional.
Template
- AP-Zweig (role == "Wireless AP"), datengetrieben aus ConfigContext
ap-common + local_config_context_data; ap1/ap2 differieren nur in 4
Werten. RadioProfile verworfen (hängt an einem Controller, den es seit
der CAPsMAN-Abschaffung nicht gibt).
- crs326-core-Zweig von Slash- auf /export-Form (Space-Form, Attribute
alphabetisch), stale disabled=yes aus der Cutover-Ära entfernt.
- Switch-Zweig für crs326-branch.
- Mgmt-Nummernplan korrigiert: ap2 und branch waren in den DNS-Statics
vertauscht, ap1 zeigte auf ein nicht existierendes .99.3.
Verbindlich: core .99.1 | branch .99.2 | ap1 .99.11 | ap2 .99.12.
Ergebnis: ap1 intended == Geräte-Ist (0 Drift), core 68/69 Zeilen
byte-identisch. 14 ComplianceRules, 51/56 compliant -- die 5 Restdrifts
sind echte Altlasten (Rettungspfade, Aufräumen gehört zu TP19).
Deploy (nautobot_config.py, Image gc9)
enable_plan/enable_deploy an. napalm-ros ist READ-ONLY: der Default-
Dispatcher wählt NAPALM (Platform trägt napalm: ros), Backup geht,
merge_config scheitert grundsätzlich mit leerer Fehlermeldung. Fix =
custom_dispatcher auf NetmikoMikrotikRouteros, in den Golden-Config-
Settings (nicht den Nornir-Settings). Pilot-Deploy: DNS-Statics auf dem
Core korrigiert, per Purge-vor-Add, weil plan_type=missing nur add
erzeugt und sonst Duplikate entstanden wären.
Governance-Regeln in docs/teilprojekte.md festgeschrieben: Pläne nur
feature-scoped (ein Voll-Push schriebe die Maske als PSK auf die APs),
AP-Template nie zeilenweise auf ein laufendes Gerät (vlan-filtering=no
reisst den Mgmt-Pfad ab).
CLAUDE.md: Power-Save-Fehldiagnose korrigiert
Der P750W war nicht im Power-Save, sondern schlicht ausgeschaltet; das
Ping-Symptom kam vom lokal mitlaufenden WARP-Client (cloudflared =
QUIC-Proxy, kein ICMP). Die Merkregel "DHCP-geht-aber-Ping-nicht =
ARP/Power-Save" ist damit widerlegt und entfernt; strukturell schliesst
TP16.1 diese ICMP-Lücke.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hardware-Tabelle + TP1: ALLNET Core-Switch als außer Betrieb markiert (2026-08-08,
User-Bestätigung) — durch crs326-core (L3-Router + Core-Switch) physisch abgelöst.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- APs werden als reine APs neu aufgesetzt (kein Zurückbau)
- WG-Hub behält ap1-Private-Key, damit Remote-Spokes keine Reconfig brauchen
- WiFi-PSKs lokal auf APs, nicht im Nautobot-Template
- Nautobot/GC-Setup für alle 4 MikroTik-Geräte als Ziel, Switches heute nicht neu provisionieren
Co-Authored-By: Claude <noreply@anthropic.com>
- routeros/tp15-core-l3-staged.rsc: ap1s Live-L3-Config 1:1 als staged
Config (alles Betriebsumlenkende disabled=yes, Cutover-Enable in einem
Rutsch). Reservierungen + WG-Privkey bewusst erst im Fenster maschinell
von ap1 geholt statt abgetippt.
- Fund/Luecke geschlossen: WG-Hub (TP10 FM/DW-VPN) haengt an ap1s
Public-Edge, im Handoff uebersehen -> migriert im selben Fenster mit.
- Fenster-Start-Entscheide: Governance = frische Direkt-Ausnahme #3
(REST/MikroMCP, danach intended->Nautobot); Rettungspfad iPhone-Hotspot.
- Prep-Gotchas dokumentiert: MikroMCP kann core noch nicht schreiben
(ENV nicht geladen), Mgmt-.99.11 tot (nur .41.211), WG-Keypair-Transfer,
Public-IP-Wechsel am WAN, vlan99 .1-vs-.11-Reconcile, VLAN1-Teardown.
- teilprojekte.md TP15 fortgeschrieben.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Portplan-Widerspruch aufgeloest (User): Core #15 = ap1 (Ziel kuenftig #4), #11 = cudy1.
Damit gilt die TP4-Variante (gi16 Arris -> gi15 Trunk -> ap1); 03-trunk-ap-ports.cli
(gi1 = ap1) ist STALE, vom Edge-Cutover 2026-07-01 ueberholt. gi16/gi8 bleiben
unverifiziert und sind in Nautobot als solche markiert.
Kernrisiko dokumentiert: crs326-core ersetzt sw1 UND wird L3-Router, an sw1 haengt ap1
(#15) mit Gateway/DHCP/DNS/WAN-Trunk -> Core-Tausch und L3-Umzug sind dasselbe Ereignis
und bedeuten ein Vollausfall-Fenster. Entscheid: Branch zuerst, Core eigene Session.
Rettungspfade liegen guenstig getrennt (Notebook-WLAN via cudy1 am Core #11,
Kabel-Plan-B am sw2/Branch P4).
Governance-Ausnahme #2 erteilt (User): CRS326-Grundconfig direkt via MikroMCP/Winbox
(Henne-Ei - GC kann nicht auf ein Geraet ohne IP pushen, Templates fehlen). Auflage:
Ist-Stand danach als intended config nach Nautobot. Gilt nicht fuer ap1/ap2.
Nautobot: cudy1/cudy2 als Cudy WR3600E V1.0 (Firmware 2.3.15-20250905-191956),
cudy1 -> Technik UG, cudy2 -> Technik OG/Decommissioning; Platzhalter-DeviceType
entfernt; sw1 gi8/gi11/gi15/gi16; crs326-core ether4 als Zielport fuer ap1.
Alle 8 Devices haben jetzt einen Bereich.
Neu: docs/tp15-crs326-session-handoff-prompt.md - kopierfertiger Auftrag fuer die
naechste Session (beide CRS326 bring-up, Portplan, NUR Branch-Tausch).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nautobot-Ingest (Ist, nicht Ziel):
- Locations: LocationType "Bereich"; Technik UG (Diele, kein Keller) = crs326-core,
Technik OG = crs326-branch, Wohnzimmer Sideboard = ap1
- Devices: ap2 -> Rolle "Wireless AP" + Offline; beide CRS326 Platform RouterOS
nachgetragen (fehlte -> haette jeden GC-Job auf ihnen verhindert);
sw1/sw2/cudy1 als Uebergangs-Devices ohne Platform
- IPAM: VLAN-Group BF, 9 VLANs (VLAN1 deprecated), 8 Prefixes je VLAN-gebunden
- ap1: 26 Interfaces inkl. MACs, ether2 als Trunk, 9 GW-IPs
- WLAN: logischer Controller bf-wlan (kein CAPsMAN), 6 SSIDs mit VLAN-Bindung,
2 RadioProfiles
Entscheide 2026-07-22:
- crs326-core wird L3-Router; Routing/DNS/DHCP wandern von ap1, APs werden reine APs.
Ueberschreibt die fruehere "Router bleibt ap1/ap2"-Zeile desselben Tages.
- CAPsMAN wird abgeschafft, beide APs von Nautobot identisch generiert.
- AP-Uplink wandert auf ether1 (PoE-Port). RouterOS nummeriert ab 1, nie ether0.
Befunde:
- Root Cause des ap1-VLAN1-Lecks: cfg-main-2g hat gar keinen datapath-Block ->
2,4-GHz-main taggt nicht, Bandwechsel = Subnetzsprung. Nicht das frame-types-Thema.
- Beide CRS326 laufen bereits (RouterOS 7.19.5, Werkszustand), beide auf 192.168.88.1
im selben L2 = IP-Konflikt.
- hAP ax2 PoE ist passiv 18-28V, nicht 802.3af/at; ether1 steht auf poe-out=auto-on.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- RB5009 final gestrichen (User-Entscheid 2026-07-22) — Router bleibt ap1/ap2,
Referenzen in teilprojekte.md + hw-refresh-requirements.md bereinigt.
- TP16.1 Ziel-Device von ap1 auf CRS326 Core-Switch retargeted (Doku-only,
Scharfschalten bleibt gated bis TP21 den CRS326 abdeckt), Runbook umbenannt
auf tp16.1-warp-mesh-native-crs326.md, cf-tunnel-mapping.md §14 + Handoff-
Prompt mitgezogen.
- TP21: docs/nas-vlan20/nautobot-image/ neu — der Dockerfile/nautobot_config.py/
allnet_sg8316m_driver.py, aus denen das laufende Custom-Image tatsächlich
gebaut ist (der bisherige Verweis auf scratch/nautobot-gc-build existierte
nirgends). Ergänzt napalm-ros + nornir-napalm + librouteros + gepinntes
setuptools<81 (pkg_resources-Regression), Nornir-Credentials auf
CredentialsNautobotSecrets umgestellt, Compliance/Intended-Config/SoT-Agg
aktiviert. Backup/Intended/Compliance-Pipeline live gegen ap1 verifiziert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Omada-PVID-Fix gestrichen (User-Entscheid 2026-07-22): Omada spielt seit der
TP15-Korrektur keine Rolle mehr im Netz → nicht wieder aufgreifen
- TP5 Deny-by-default folgt nach TP21/CRS326-Adoption (Holes + WAN-Seal stehen schon)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Frische Sonnet-Delegations-Session lief in die '10000 Authentication error'-Falle:
sie versuchte CF-Writes über den read-only MCP. Root Cause: .claude.json referenziert
nur die MCP-URL, NIE den Token in mcp/cloudflare/.env → kalter Agent kennt den Write-Pfad nicht.
- Handoff-Prompt: prominenter 'CF-KOMMUNIKATION'-Block (2 getrennte Pfade, exakte curl-
Kommandos, '10000 = kein Rechteproblem, Pfad wechseln'-Hinweis im Ablauf).
- cf-tunnel-mapping.md §11: gleiche Klarstellung als SSoT-Callout inkl. Verifikation
(no-op vnet-PATCH: MCP→10000, curl→success). 'Claude hat zig Tunnel erstellt' = immer
via curl+Token, NIE via MCP.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Governance-Callout (teilprojekte.md): Christoph erteilt Ausnahme von 'Config nur
via Nautobot' für alle (Vor)Arbeiten am zentralen CF-Tunnel-Zugang AUF AP1 (TP16/16.1,
native WG-Mesh-Zeilen). Scope-Grenze: nur ap1 — CRS326 (TP15) fällt vorerst NICHT
darunter, bleibt Nautobot-GC-pflichtig. Follow-up: ap1-Zeilen später in GC nachtragen.
- Neu: docs/tp16.1-session-handoff-prompt.md — kopierfertiger Auftrag für die
Delegations-Session (Sonnet), Governance-Gate jetzt als 'erteilt' statt 'erst fragen'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fehlschluss revidiert: ICMP-Häkchen ist Dashboard-only (nicht im API-Spec),
aber aktiv — belegt durch funktionierenden Ping ins FM-Netz. Kein To-Do.
bf-Ping-Verlust im Incident lag an QUIC-losen macmini-Connectoren (post-http2),
nicht am Flag. Re-Check trotzdem nach Scharfschalten (§4.5).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Primärquellen (animmouse Mesh-on-MikroTik + wgcf-connector) und offizielle
CF-Docs/OpenAPI-Spec gegengelesen — Lead bestätigt, 6 Härtungen eingearbeitet:
- Produkt seit 2026-04-14 offiziell 'Cloudflare Mesh' (API bleibt /warp_connector,
im Spec bestätigt inkl. Token- und HA-Endpoints; Node-Limit 50/Account)
- NEU: ICMP-Proxy-Prerequisite — Dashboard-only (nicht im API-Spec), 1 Klick
Traffic settings→Proxy→ICMP, sonst bleibt das Abnahmekriterium Ping tot
- Split-Tunnel-Exclude auf BEIDEN Device-Profilen (Default + Mesh)
- vnet-Gotcha beim Route-Umzug ('virtual networks only for cloudflared') →
Weg A PATCH / Weg B DELETE+POST; CF-API-Writes sind WARP-unabhängig (Rollback safe)
- v4-only-Entscheid (Mesh-IPv6-site-to-site laut Guide broken, kein NAT66)
- keepalive 1m ok, .conf-Inhalte präzisiert (IPv6+DNS ignorieren)
Runbook ausführungsreif für die Delegations-Session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Incident-Nachgang 2026-07-16: ICMP über den cloudflared-WARP-Pfad ist strukturell
kaputt (TCP ok überall, Ping fm 36%/bf 100%/dw 100% Loss) — cloudflared ist ein
QUIC-L7-Proxy, kein WireGuard. Richtungsentscheid: Private Access (unterwegs ->
10.40.0.0/16 inkl. ICMP) wandert vom cloudflared-Proxy auf einen nativen
Cloudflare-Mesh-Node (WireGuard) auf ap1 -- kein Container/TUN/LXC/neue HW
(RouterOS-Container haben kein /dev/net/tun -> hAP ax3 löst es nicht, zudem WiFi6).
Public-FQDNs bleiben unverändert auf dem cloudflared-3-Tunnel-HA.
- Neu: docs/tp16.1-warp-mesh-native-ap1.md (Konzept + vollständiges Runbook +
gemessener Account-Ist-Stand, Team emsenhuber.cloudflareaccess.com)
- cf-tunnel-mapping.md §13: ICMP-Dreiländer-Befund; "bf-pve wegen USV" REVIDIERT
(Begründung invertiert -- bf-pve-Connectoren laufen auf NAS+macmini, nicht pve)
- cf-tunnel-mapping.md §14 + teilprojekte.md TP16.1: Richtungsentscheid dokumentiert
Scharfschalten = eigene Session (CF-Prereqs sind account-weit, treffen Live-WARP).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Incident 2026-07-16: User unterwegs, keine BF-IPs mehr über WARP. Root Cause:
cloudflared-bfnas/-bfpve auf macmini flappten unter QUIC/UDP (Docker-Desktop-
Bridge-NAT) -> bf-nas/bf-pve von 2 auf 1 Connector degradiert. Fix: beide auf
TUNNEL_TRANSPORT_PROTOCOL=http2 umgestellt, rollend, wieder volle HA.
Nebenbefund per Audit-Log: User hatte die WARP-Private-Network-Route selbst
neu angelegt, zeigt jetzt auf bf-pve statt bf-nas. Bewusst so belassen -
pve ist USV-gepuffert, NAS/macmini nicht. cf-tunnel-mapping.md §11 damit
überholt, §13 als neue Baseline.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TP20: Postgres-16-LXC (105, pve, 10.40.20.20) provisioniert, UTF8/en_US.UTF-8,
wal_level=replica, DB+Rolle nautobot angelegt, End-to-End verifiziert. archive_mode
bewusst noch aus bis TP18/pgBackRest steht.
TP21: Nautobot-Stack (ghcr.io/nautobot/nautobot:3.1.7) als Portainer-Stack auf NAS
live (App+Worker+Scheduler+Redis), DB=platform-pg, API-Smoke-Test grün. Healthcheck-
gated Worker/Scheduler-Start ergänzt (Migration-Race-Condition beim Erstboot gefixt).
TP19.1: sw2 jetzt final auf 10.40.99.12 (statisch) — Christoph über Klickanleitung.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TP2.1 (sw2-Standalone-Recovery) von Christoph solo abgeschlossen. TP19-Live-Sweep
auf ap1 zeigt VLAN1 schon viel weiter zurückgebaut als dokumentiert (defconf-DHCP
bereits disabled, cudy1→VLAN10 umgenutzt, cudy2 tot) → neuer Unterpunkt TP19.1 für
den VLAN99-MGMT-Cutover. TP14.1-Rest obsolet (kein Omada-Re-Adopt mehr), TP14.3
DNS-Sweep fertig (nas/docker-Records auf ap1 korrigiert, omada/omada-mcp/fritzbox-
Records entfernt, da Controller von Christoph komplett gelöscht wurde). RouterOS-
Config-Backups (enthalten Live-WiFi-Passphrasen) neu gitignored.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dirtyvader-main-Clients bekommen zeitweise VLAN1-IPs (10.40.41.x) statt
VLAN10 — gleiches Dual-DHCP-Race-Muster wie beim ap2-Fix (TP3.1,
2026-07-06), aber die admit-only-vlan-tagged-Härtung fehlt bisher auf ap1.
Zwei-Phasen-Runbook angelegt: Phase A (TP3.1-Scope, Akutfix ap1) vor
Phase B (TP19-Scope, voller VLAN1+cudy-Teardown, macht Phase A obsolet).
TP19 auf hochdringlich gesetzt, da VLAN1 jetzt ein aktiver Bug ist statt
nur Cleanup.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
sw2-Controller-Link brach beim VLAN20-Umzug (TP14.1), Werks-Reset beim
Rettungsversuch, fehlerhafte Wiederherstellung — Controller-Zustand jetzt
invalid. sw2 wird ohne Managementsoftware neu aufgesetzt (TP2 als Playbook,
neue Portbelegung offen). TP15 korrigiert: Omada bekommt keine Rolle mehr,
auch nicht WLAN (bleibt bei hAP ax²/CAPsMAN) — reines MikroTik-Ecosystem.
TP19-Update: Shelly wieder da, SwitchBot-Move erst nach VLAN1-Retirement.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
vmbr0.20 (kaputte Netzadresse statt Host-IP) auf 10.40.20.100/24 korrigiert,
Default-GW live geflippt (ifreload -a, kein Reboot). CF-Ingress bf-pve
(pve/j44d6tua-ssh) + ap1-DNS nachgezogen; dabei Alt-Bug gefunden und gefixt
(pve-mcp.bf.lan zeigte noch auf .41.173 statt .20.173).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neuer TP-Konzeptstand aus der Storage-Skalierungs-Diskussion: selbst
gehosteter, geo-verteilter S3-Objektspeicher (Garage) über BF/FM/DW als
Cold-Tier — statt Cloud oder größerem Einzel-NAS.
Kernentscheide festgehalten: Engine=Garage (WAN-tolerant; Ceph/MinIO/
SeaweedFS als Fallback begründet), Disk-Layout=JBOD statt RAID
(Redundanz nur über Sites, RF=3), Variante kalt=Objektspeicher/heiß=
lokal. Inkl. Dimensionierung (10 TB nutzbar Anker), Kostenmodell
(capex/opex, per-Site + kumulativ, JBOD-vs-RAID1-Ersparnis) und Impacts
auf Syno-Rolle, Backup-Kette und Container-Hosts (TP14/15/10/16).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Entscheidung: alle Shellys bekommen statische IP (10.40.30.<octet>, gw/dns .30.1)
+ in-pool DHCP-Reservierung als Backup. set_sta auf static=true (Default) umgestellt
(Ziel-IP aus Oktett), _sta_cfg-Helper.
- pool-v30 auf .100-.250 erweitert (Reservierungen jetzt in-pool, User-Konvention).
- s24 (14:33:5c:d8:2d:7c) ins inventory/bf.csv + .30.204-Reservierung.
- Voller HA-Device-Scan (alle MAC-Geräte, nicht nur configuration_url): fand
Apple TV 4K + Philips TV (aus, VLAN40) — vor cudy-Teardown VLAN verifizieren;
Apple TV = vmtl. Thread-Border-Router (TP17.1). Tasmota bestätigt tot (MAC nicht im Netz).
- .41.246/.247 = cudy1/cudy2 (Teardown-Ziele) dokumentiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Live-Abgleich Projektstatus vs. echter Netzstand (MikroMCP/pve-mcp/HA):
- VLAN20 verifiziert: NAS .20.10, Mac mini .20.167, pve-LXC .20.126 alle live;
einziger Host noch in VLAN1 = pve-Host-Mgmt .41.100 (verbleibende Host-Migration).
- TP17 Shelly: Migration schon ~6/26 durch (s14/16/18/22/23/24 stabil auf .30.2xx);
16 VLAN1-Shellys verbleiben; alle VLAN30-Reservierungen stehen; s6-Reservierung
.30.213 MAC gefixt (0C:72..9E -> real D0:CF:13:D8:18:FC).
- HA-Cross-Check aller IPv4-Geräte: .30.204 = Shelly Bad/Spiegelschrank (=vmtl. s24);
Nicht-Shelly-VLAN30-Mover SwitchBot/.184 + Tasmota Nous A1 + 1 offen; .41.246 unident.
- Neues Runbook docs/tp17-shelly-go-runbook.md: 16er-Migrationstabelle, Go-Sequenz,
Scope-Erweiterung (WLAN+IP+einheitliches Geräte-PW via Shelly.SetAuth),
Gen4->Thread/Matter-Projektion (TP17.1, experimentell), VLAN1-Leerstand-Verdikt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Projekt-Skill unter .claude/skills/projektstatus/ — liest SSoT docs/teilprojekte.md
frisch, gruppiert alle TP in Themenblöcke (inkl. TP17 Shelly, TP14-Migration) und
rendert ASCII-Statusbaum + kritischen Pfad.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vw von bypass/everyone auf non_identity(Heim-IP)+allow(email:christoph) umgestellt
(reusable-Policy via App-PUT detacht). Neuer 🔴 Fund dokumentiert: Wildcard
*.emsenhuber.net login_method:github/google = jeder Eingeloggte erreicht alles
(user-gated). hass-400 = HA-Origin (nicht Access), gateway-dw WG offen. §10.6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root-Cause endgültig (User-Diagnose bestätigt): ein cloudflared ist blind NUR
für macvlan/ipvlan-Container auf seinem EIGENEN Host → mehrere Connectoren auf
1 Tunnel + Round-Robin = 1/N garantierte 1033 ("jeden 3. Schuss eine Niete").
Kein Route→Connector-Pinning innerhalb eines Tunnels → HA nur über getrennte
Tunnel: reziprokes Per-Host-Design (jeder Dienst von den anderen Hosts bedient,
3 Tunnel/2 cloudflared je Host = voll HA gegen Single-Host-Ausfall).
- cf-tunnel-mapping.md §9: Invariante + Live-Inventory v119 (Access-Modi,
DOWN-Origins pbs/nginx-bf/hermes×2) + Ziel-Design + Umsetzungsreihenfolge;
Abschnitte 1-8 als Historie markiert.
- teilprojekte.md TP16 umgeschrieben: Root-Cause, reziprokes HA, Access-Strang
(hass-400=CF-Access→WARP, vw=bypass→schützen), Status "dokumentiert,
Umsetzung = eigene Session".
- Reine Doku, keine Tunnel-/DNS-/Container-Änderung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- pve-mcp „Failed to connect" = mcp-pve 0.4.8 kann nur 1 MCP-Session
("Server already initialized") → Upgrade 0.6.1 (Per-Session), ✔ Connected.
omada-mcp war/ist gesund (frische Session-ID pro Init).
- Kollateral: VLAN20-Host-DNS auf NAS+LXC zeigte noch auf totes .41.254
→ docker-pull scheitert; LXC pct set .20.1, NAS Synology-DHCP-DNS-Falle.
Neuer Gotcha in CLAUDE.md.
- TP16 (neu, hochdringlich): FQDNs via CF „sehr unsicher" = #1033-Round-Robin
zurück; Live-Snapshot 2026-07-10: bf-Tunnel 2 statt 3 Connectoren, alle
frisch (2026.7.1), Origins nach VLAN20-Move erneut asymmetrisch zu auditieren.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Requirements/Architektur zur Ablösung von ALLNET-Core + 2 Branch-Switches:
Strom-Baseline, Energieeffizienz, zentrales Management, DC-USV-Konzept.
Status: Entwurf; verweist auf TP15 in teilprojekte.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 6 NAS-Origins .41→.20 repointet (ha-mcp, NAS-ssh, gitea, vw, grafana, pve-mcp), v115→v116.
- Befund: pve-Connector erreicht VLAN20 (vw 200 via Tunnel); 502 direkt nach Ingress-PUT = transient.
- grafana 502 = Container exited, kein Routing-Problem. Kein pve-Static-Route nötig.
- Stufe-4-Connector-Vantage löst sich mit pve→VLAN20 (PVID1-Cutoff).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diagnose der Docker-Container-Fehler nach NAS-NIC-Wechsel auf VLAN20:
- Config-Only-Macvlan-Falle (Portainer 2-Schritt, Driver=null → kein Attach)
- Macvlan-Parent ovs_eth0 exklusiv → default_external muss weg für vlan20
- default_internal (172.18) existiert nicht mehr (Range von gitea_default belegt)
RUNBOOK: IP-Mapping .41.X→.20.X (Oktett behalten), Phase-A-Teardown,
Post-Steps (ap1-DNS, CF-Ingress-Repoint, omada-Inform .20.175), CF-Access
claude-mcp-Profil-Status.
Stack-Compose-Files + Inspect-JSONs (docs/nas-vlan20/stacks/, inspect_*.json)
via .gitignore ausgeschlossen — enthalten Live-Secrets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TP3.2 = P750W/Discovery erledigt; offene Coverage-Kur (Dead-Spot-Map →
Platzierung/3.AP/Outdoor, Nachbar-Kanal-Scan, INFRA-auf-ap1) als
kaltstart-taugliches TP3.3 für die Fortsetzungs-Session ausgelagert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
macOS-Desktop-Sonos-App braucht SSDP über VLAN-Grenze; iOS/HA reichen für den
Alltag nicht, sobald der User die Desktop-App nutzen will. Reflector-Container
auf NAS/pve (nicht am hAP), Scope vlan10↔vlan40.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Alle Sonos jetzt auf VLAN40 (10.40.40.0/24), IPs per MAC DHCP-reserviert.
Korrigierte IPs (Arbeitszimmer .199/.200 → .191/.192, Arc hält .199).
Discovery-Merkregel dokumentiert: iOS-App + Home Assistant = mDNS/zeroconf
(_sonos._tcp.local.) → über Repeater lösbar; macOS-Desktop-App = SSDP
(quert VLAN nicht, kein Reflector gebaut); Spotify = Cloud.
Passend zur Router-Änderung (nicht im Repo): mdns-repeat-ifaces=
vlan10,vlan20,vlan40 (vlan20 für HA ergänzt) + forward/input-Regeln
vlan20<->vlan40. HA discovert per zeroconf selbst → self-healing der IPs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Liwest hat die FritzBox dauerhaft gegen ein Arris-Kabelmodem getauscht
(2026-07-01). WAN läuft jetzt über den Core-Switch statt ether1, ap1
zieht die öffentliche Liwest-IP direkt. Telefonie entfällt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Root cause: ap2 (CAP, local forwarding) hatte bridge vlan-filtering=no →
datapath.vlan-id wurde nie getaggt → alle WLAN-Clients (main/media/iot/…)
egressten ungetaggt in VLAN1 → OG-iPhone-Drops beim Roaming ap1↔ap2.
Fix wie ap1: VLAN1 untagged=bridge,ether2 (Mgmt), 10/30/40/50/90 tagged
auf ether2 + wifi1/wifi2 als tagged-Member (nur Master-Radios sind
Bridge-Ports, CAPsMAN legt das auf dem CAP nicht an). As-built +
teilprojekte.md TP3.1 + CLAUDE.md-Gotcha. OG-Funktionstest offen (User).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docs/cf-tunnel-mapping.md: Single Source of Truth zur #1033-Diagnose
(bf-Tunnel = Round-Robin über 3 Connectors macmini/pve/NAS)
- mcp/cloudflare/: README + .env.example (echtes .env via mcp/.gitignore ausgeschlossen)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ursache verifiziert: 1 Tunnel, gleicher Token auf 2 Connectors (pve+nas) →
Round-robin trifft Origins, die nur von einem Host routbar sind → sporadisch #1033.
Ziel: HA-Connector-Paar in VLAN20, Origins auf 10.40.20.x, Rogues weg.
Reihenfolge: #1033 → FB-Bridge → IP-Migration. cf-mcp (Remote-OAuth) braucht
frische Session; Handoff ist self-contained mit Startschritten + Fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
peer dw gesund, aber dw→BF stumm: .41-Infra hat FB-Default-GW (ap1-DHCP
auf bridge disabled) → Antworten an Spoke-Netze landen bei der FB ohne
Route → Blackhole. "Funktionierende" Gegenrichtung war WARP, nicht Tunnel.
Fix (Interim, Double-NAT): 2 Statikrouten auf der BF-FB,
10.95.10.0/24 + 10.101.0.0/24 → 10.40.41.1 (ap1). Transparent, FM mit
abgedeckt. DW ohne WARP getestet ✅. Beim Bridge-Cutover obsolet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DW/Geli on-site abgeschlossen (2026-06-27): Geli auf 10.95.10.0/24
renumbert, FB-WG single 10.95.10.1/24, alter FB↔FB-WG geswappt.
End-to-End verifiziert (macmini/Linz → Gelis 24/7-APs .246/.247,
echte LAN-IPs, kein 10.255.255.x-NAT-Leak). FM+DW live im Double-NAT.
Doku/Status von "🅿️ vertagt/geparkt" auf Ist-Stand gezogen, Bridge-Gate
an allen Stellen aufgelöst, stale 192.168.178-Referenzen bereinigt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- tp10-vpn-migration.md zur Single Source of Truth umgeschrieben: widerspruechliche
alte Transfernetz-Tabelle/MyFRITZ-Endpoint entfernt, aktueller Stand (Proxy-ARP
LAN-IP, DDNS bf4.emsenhuber.net, dual-range DW, geparkter ap1-Hub, vertagt+
gebuendelt mit Bridge-Cutover, v6-Variante) konsolidiert.
- teilprojekte.md TP10-Eintrag von verbose Saga auf kompakten Status + Verweis gekuerzt.
- tp10-context-digest.md neu: ultrakompakter Handoff (lokal via Ollama nemotron-3-nano:4b
destilliert, fakten-gegengeprueft) fuer kleines Kontextfenster.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
routeros/tp3-capsman.rsc: ap1=Manager+AP (Radios lokal), ap2=CAP (Provisioning).
5 SSIDs über beide APs/Bänder mit wifi-datapath vlan-id: main(10), iot(30, nur 2,4 GHz),
media(40), untrusted(50), guest(90); infra(20)/mgmt(99) vertagt. WPA3/WPA2+3, FT auf
main+media. Passphrase als Platzhalter __TEMP_PSK__ (echter Temp-Wert in gitignored
routeros/.secrets/tp3-capsman.psk). Ersetzt capsman-flat-asbuilt/ap1-manager/ap2-cap.rsc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
/ip/dns mdns-repeat-ifaces re-originiert mDNS vom Router (input→output),
daher unabhängig von TP5-forward. Verifikation + Rollback + offene TP5-Punkte
(forward MAIN↔MEDIA, input UDP 5353) und SSDP/IOT-Defer dokumentiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- mcp/sonos/sonos-inv.py: SSDP + ZoneGroupTopology-API, Seed-je-VLAN-Partition,
--json / --verify. Kein MCP-Container (User-Entscheid), kein Daemon, stdlib-only.
- docs/sonos-inventar.md: Bestand + Migrationsklassen.
- Kernbefund: echter WLAN-Umzug = 6 Geräte (3× One SL + HT-Bond Arc/Amp/Sub);
Schlafzimmer-Paar nur Switch-Port; Arbeitszimmer-Paar fertig. Alle S2 →
:1400/wifictrl tot → Umzug via TP3-Cutover, nicht am Gerät.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entscheidung: TP10 nicht mehr als Parallel-Migration vorab, sondern zusammen
mit dem permanenten FB-Bridge-Cutover. Grund: VPN-auf-FB und FB-Bridge
schließen sich aus (Bridge = Modem = keine VPN-Terminierung) -> Migration muss
am Bridge-Tag passieren; dann hat ap1 die echte Public-IP -> kein
Port-Forward-Umweg, Spokes zeigen direkt auf ap1/DDNS. FM-PoC hat den
WG-Spoke-Fix bewiesen (de-risked).
Park-Zustand ap1: Peers disabled, WG-Routen entfernt (FM/DW wieder über die FB),
wg-hub bleibt (Key erhalten), Firewall bleibt (TP5-Vorarbeit). Beide VPN vorerst
über die FB: FM=IPsec, DW=FB-WG. Resume = Bridge-Tag (Klickanleitung,
FB-LAN-IP als Interface-Address).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Gelis CGNAT ist nur v4 → ihre FB über natives v6 erreichbar (Port offen).
WARP (schon im Einsatz) liefert Christoph outbound-v6 trotz Liwest-v4-only.
- PoC = ad-hoc Fernwartung; Daueform = direktes WG ap1↔Geli-FB über echtes
v6 (HE-6in4, da Liwest auch mit Fiber kein v6) statt Hub-Spoke-Gymnastik.
- Endgeräte (Note10, Cudy) bleiben v6-agnostisch: v6 nur äußerer Transport,
LAN bleibt IPv4. Nicht für Telefonie.
- teilprojekte.md: TP10 von ⏸ PAUSIERT auf 🅿️ VERTAGT (Bridge-Cutover-Bündelung).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FM-Cutover-Versuch gescheitert: .conf importiert, Handshake grün, IPsec voreilig
deaktiviert -> FM unerreichbar. Diagnose-Fehler: nur FB-eigene .254 gepingt (FB
antwortet aus Tunnel-IP 10.255.255.2 -> OS verwirft); echte FM-LAN-Hosts nie
getestet -> NAT-These unbewiesen. Research (Bouni) bestätigt FB<->MikroTik
LAN-LAN ohne NAT ist machbar. FM auf IPsec zurückgestellt; ap1-WG-Hub bleibt inert.
- routeros/fritzbox-wg-lanlan-klickanleitung.md: Diagnose->Fix->Verify, Echt-Host-
Test ZUERST (10.101.0.10, nicht .254), IPsec bleibt Sicherheitsnetz.
- teilprojekte.md / tp10-vpn-migration.md: Status ⏸ + Incident dokumentiert.
Spoke-.conf mit Private-Keys bleiben gitignored in routeros/.secrets/ (die
ungetrackten Duplikate in routeros/ Root sind bewusst NICHT committet).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verifiziert am VLAN1-Host (FB-nah): FB annonciert 2002::-Prefix per RA,
curl -6 klappt, ping6 Google v6 = 100% Loss (flatterhaftes 6to4).
Intern NICHT durchgereicht: Mac mini (VLAN20 hinter ap1) v6-los —
ap1 kein RA/DHCPv6-PD, Branch-Switch nicht v6-konfiguriert,
Core-Switch v6-Fähigkeit unklar. 6to4 untauglich für RT-Medien;
saubere Alt = 6in4-Tunnelbroker (HE). Geli-CGNAT-Bypass unberührt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Liwest bietet kein natives IPv6 (techn. Support bestätigt).
- Christophs 6to4-Versuch am Mac mini/LAN NICHT nutzbar (stf0 down,
keine globale v6, kein v6-Route/Internet) → kein funktionierendes
v6 auf Christophs Seite; ap1/TP4 bleibt v4-only.
- 6to4 = legacy/relay/hohe Latenz → keine Basis für Echtzeit-Medien;
saubere Alt bei Bedarf = 6in4-Tunnelbroker (HE).
- Geli-seitiger CGNAT-Bypass (ihr natives v6, Telegram-Reflector-Leg)
bleibt davon unberührt — der billige Hebel braucht Christoph-v6 nicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- pve: Hypervisor zählt zu INFRA (User-Entscheid) → 10.40.20.100 (VLAN20),
MGMT/VLAN99 = nur noch Switch/AP-Mgmt.
- Mac mini ✅ live auf 10.40.20.167 (Omada Access-INFRA ohne VLAN1).
Kontext (live, nicht im Repo):
- Omada: Access-IOT/-UNTRUSTED/-GUEST/-MGMT Profile angelegt (Satz komplett).
- ap1 DNS: macmini.bf.lan → 10.40.20.167.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eigenständiges Arbeitspaket: finale statische IPs je Gerät in den
Ziel-VLANs (INFRA 20 / MGMT 99), Host-Oktett beibehalten, Vorschläge
zum Bestätigen.
Kontext (live in dieser Session umgesetzt, nicht im Repo):
- Omada PVID-Fix Teil 1: P3/P6 Sonos→Access-MEDIA (VLAN40),
P5 Drucker→Access-MAIN10 (VLAN10).
- ap1 srcnat: accept 10.40.0.0/16 vor Masquerade → Inter-VLAN ohne SNAT.
- Voraussetzung erfüllt: VLAN1↔VLANx-Routing via statischer FB-Route → ap1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Toolkit, um den FB-Bridge/Passthrough-Cutover (Liwest) autonom auf ap1 zu
testen, während Claude/MikroMCP offline ist (Test-Client auf install-wifi,
LAN4-Umstecken kappt den Live-Pfad).
- wan-cutover-test.rsc: wantest-probe (schichtweise Diagnose: ether1-IP,
default-gw, WAN-Reach via :resolve@1.1.1.1, DoH end-to-end) + wantest-run
(blockierender Loop, Hintergrund-fähig). Persistentes Disk-Logging nach
wan-test.0.txt.
- wan-macclone-test.rsc: CM-MAC-Clone (0C:72:74:36:90:99) mit eingebautem
Auto-Revert (~90s), scheduler-frei.
- wan-cutover-runbook.md: Solo-Runbook für den User (Console altes WiFi →
10.40.41.1).
Scheduler-frei, weil device-mode=home auf ap1 /system scheduler und /tool
fetch blockiert. Reachability via :resolve statt ping ([/ping] gibt in
7.23 nil; ICMP hier geblockt). Public-IP 86.56.201.104 bereits bewiesen
(kein Liwest-MAC-Lock).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Variante A (BIND/RFC2136) verworfen: HW-Vorgabe "Container nur am Router
oder gar nicht, keine NAS/pve-Abhaengigkeit" + hAP kann praktikabel keinen
DNS-Container hosten (live: ~90MB frei, kein USB, Flash-Wear).
- research-Doc umgeschrieben: Entscheidung + Variante A als parkierter Anhang
- teilprojekte TP4 auf finale Entscheidung
- technitium/ -> dns/ umbenannt + README
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ersetzt manuelles Referenzieren von Zusatzdateien beim Sessionstart.
HANDOVER.md als Archiv-Dokument markiert; teilprojekte.md bleibt kanonisch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Was du sofort wissen musst (Inventur 2026-08-27)
- **`bf-infra`** ist aktiver Master, **lokal, kein Gitea-Remote** (Working-Copy). Verloren bei Festplattencrash.
- **`admin/bf-network-r6`** (Gitea) ist Archiv, letzte aktive Commits 2026-08-25 → read-only-Header.
- **`admin/bf-golden-config`** (Gitea) ist Bot-Master (Nautobot 2×/Tag), nicht manuell.
- **`admin/blaueblueten-n8n`** (Gitea) ist Master für terpene-Repo.
- **`inventory/` ist tot** (Pipeline seit 2025-06 stale). Live-Daten aus MikroMCP/CF/Portainer.
- **`mcp/INVENTORY.md`** ist BF-Netz-SSoT; `~/.claude.json`/`opencode.jsonc` sind globalere Werkzeugkästen.
- **terpene.teilzeitladen.xyz**: Worker läuft auf Mac mini (`10.40.20.167:8890`), **kein Caddy-Block, kein CF-Tunnel** — Backfill via DB-Migration blockiert (Handoff 2026-08-27).
## TP-Management (2026-08-26)
Wenn während einer Session ein neues Teilprojekt, eine Abhängigkeit oder ein Querschnittsthema sichtbar wird, das bisher in keinem TP abgebildet ist:
- Vorschlagen und mit dir abstimmen (nicht eigenmächtig anlegen).
- Auf dein Okay hin anlegen: Quick-Index-Zeile + `### TP<n>`-Abschnitt mit Status `🔜`, Scope,
Abhängigkeiten, Abgrenzung. Nächste freie Nummer vergeben (höchste vergebene + 1; Lücken aus
**Abgeschlossene TPs** stehen seit 2026-08-23 in `docs/teilprojekte-archiv.md` (Volltext, unverändert, mit Inhaltsverzeichnis). **Ein TP wandert erst ins Archiv, wenn nichts mehr daran zu tun ist** — und der **Ist-Stand-Block wird bei jeder Änderung mitgezogen**, nicht nur der betroffene TP-Abschnitt.
- **P750W (Brother, VLAN30) läuft auf `dirtyvader-iot`** (User-bestätigt 2026-08-08) — **kein** Access-List-Pin nötig; die alte „nur am co-located L3-GW-AP erreichbar"-Logik ist mit L3-GW auf dem Core hinfällig. Coverage-Kanten/Terrasse grenzwertig (−76..−89 dBm); TX am AT-Max (18/15 dBm); echter Fix = Platzierung. SSoT `docs/wifi-p750w-coverage-and-map.md`. ⚠️ **Power-Save ist KEIN Thema dieses Netzes** — die früher hier stehende Merkregel „DHCP-geht-aber-Ping-nicht = ARP/Power-Save" war eine Fehldiagnose (2026-08-13 korrigiert: der Drucker war schlicht ausgeschaltet, das Ping-Symptom war WARP, s.u.). Nicht wieder einführen.
- **Ping auf JEDE lokale IP tot, aber Web/App/Print (TCP) geht überall = WARP-Client lokal versehentlich noch aktiv** (2026-08-13 live beobachtet, BF vor Ort): `cloudflared`/WARP ist QUIC-Proxy, kann **kein ICMP**, reicht TCP aber durch — auch wenn man physisch im BF-LAN steht, nimmt der Client bei aktivem WARP trotzdem den Tunnel-Umweg. **Fix: WARP trennen**, kein Router-Eingriff nötig. **Vor jeder Firewall-/Mangle-/VLAN-Suche zuerst prüfen**, wenn das Symptom „Ping auf ALLES tot, TCP geht" lautet — das ist ein Client-, kein Netzproblem. Strukturell schließt **TP16.1** (natives WireGuard-CF-Mesh auf `crs326-core` statt cloudflared-QUIC) genau diese ICMP-Lücke. Memory `ref_warp_local_icmp_trap`.
---
## Lessons for Sessions (2026-08-27, aus der Inventur-Session)
Verhaltensregeln für nachfolgende AI-Sessions — kleiner, klarer, weniger Drift:
- **Bestandsaufnahme vor Plan.** Erst was ist da, wo ist der Schaden — dann Vorschläge. Nicht umgekehrt.
- **Eine große Fragenrunde statt vieler kleiner.** Wenn der Plan von Annahmen abhängt, sammle die Annahmen in **einer** Runde, nicht in 3–4 Mikrorunden.
- **Master-Frage früh stellen.** Bei jedem Repo, jeder Datei, jedem Tooling: „Was ist die SSoT, wo lebt der Master, was ist Mirror?" — **bevor** du eine Lösung vorschlägst.
- **Drift zuerst, Lösungen später.** Drift-Tabelle posten + fragen, was richtig ist. Keine Lösungen vor dem Befund.
**Checkliste vor jedem Edit-Vorschlag:**
1. Habe ich die SSoT für die Datei/das Repo benannt?
2. Habe ich die Drift zwischen Doku und Live dokumentiert (nicht stillschweigend korrigiert)?
3. Habe ich **eine** Fragenrunde mit allen offenen Annahmen gestellt?
4. Habe ich für jeden Edit **deine** Bestätigung eingeholt (nicht nur für den Plan-Output)?
- AdGuard-Paar `agh-bf1`/`agh-bf2` aufgebaut, DHCP noch nicht umgestellt (TP23 Stufe 2 / TP31 Schritt 4)
- Caddyfile Reverse-Proxy seit 2026-08-25 (TP31), 16 Sites BF-intern
- terpene.teilzeitladen.xyz: Worker läuft auf Mac mini (10.40.20.167:8890), **kein Caddy-Block, kein CF-Tunnel** — Backfill via DB-Migration blockiert (Handoff 2026-08-27)
## Übergangspfad von bf-network-r6 → bf-infra
1. README + Strukturen aktualisiert (dieses File)
2. bf-network-r6 im Gitea auf read-only, Header mit Verweis (deine Aktion)
> **Vorgänger:** [`handoff-20260825-agh-dns-cutover.md`](handoff-20260825-agh-dns-cutover.md) — diese Datei ersetzt sie nicht, sie **baut darauf auf**. Die drei Funde dort (Rewrites veraltet/nicht wertlos · Redundanz reziprok · Firewall-Vorrat falsch) gelten unverändert und sind hier nicht wiederholt; lies sie **zuerst**.
>
> **Heute (2026-08-26) dazugekommen:** Standortsuffix als Regel + `nas.emsenhuber.net` ist tot.
## Was am 2026-08-26 passiert ist
- **`nas.emsenhuber.net`-Rewrite aus AGH entfernt** (`adguard/AdGuardHome.yaml:208` war die einzige Stelle). Commit `1d569fa`. Der Name war reine AGH-Insel: kein CF-CNAME, kein Caddyfile-Eintrag (Caddy hatte von Anfang an `ds-bf.emsenhuber.net` für Synology-DSM), `dig nas.emsenhuber.net @1.1.1.1` = NXDOMAIN. **Für niemanden ändert sich die Auflösung.**
- **Regel dokumentiert** (`docs/teilprojekte.md` TP31-Abschnitt, direkt unter SoT-Tabelle):
Hosts, die es an mehreren Standorten gibt, heißen **immer**`<host>.<site>.emsenhuber.net` —
`nas.bf.…`, `nas.fm.…`, `nas.dw.…`. Kein gemeinsamer Name ohne Suffix. Caddy bleibt **pro Standort
eigenständig** (BF-Caddy kennt `ds-bf`, FM-Caddy kennt `ds-fm`); die AGH-Instanzen je Site halten
die lokale `<host>.<site>`-Auflösung.
## Was **nicht** in dieser Session gemacht wurde (und warum)
- **Andere AGH-Rewrites ohne Suffix wurden NICHT umbenannt** — `macmini.emsenhuber.net`,
-`admin/blaueblueten-n8n` (Gitea) = Master für terpene-Repo, aktiv.
- Inventar-Pipeline gelöscht (XLSX stale seit 2025-06-05, vor Core-Cutover; Live-Daten via MikroMCP/CF/Portainer).
- Architektur-Vorschlag: **Caddyfile als Generated aus Nautobot/GC**, nicht handgeschrieben (TP34).
## Drift-Befund (Phase 0)
| # | Quelle A | Quelle B | Konflikt | Einschätzung „wahrscheinlich richtig" |
|---|---|---|---|---|
| **D1** | `inventory/bf.csv`/`bf.md` (219×`10.40.41.x`) | CLAUDE.md / teilprojekte.md (`10.40.20.x`) | Inventar führt altes VLAN1-Subnetz | Inventar war tot; **gelöscht**. CLAUDE.md ist richtig. |
| **D2** | Caddyfile → `10.40.20.167:5678` | Mac mini ARP-reachable | Konsistent | Caddyfile ist richtig, Tunnel ist nur Ingress für CF-CNAMEs. |
| **D3** | `cf-tunnel-mapping.md` §15-Tabelle: `terpene-db` 1 Connector | Live CF-API: `terpene-db` 4 Connectoren | Doku-Drift | Live ist richtig, Doku-Stand 08-25. |
| **D4** | `STATUS.md` Z.47: „Ingress `terpene.teilzeitladen.xyz` → `macmini:8890`" | Live: kein Tunnel hat diesen Hostname | Doku-Lüge | STATUS.md ist veraltet; **kein CNAME, kein Ingress**. Worker läuft nur über CF-Workers-Custom-Domain `420.teilzeitladen.xyz`. |
| **D10** | Gitea `bf-network-r6/docs/cf-tunnel-mapping.md` | Lokal `~/dev/bf-infra/docs/cf-tunnel-mapping.md` | Gitea ist 1 Comm voraus, lokal ist Import-Stand | Gitea ist Master; Lokal ist veraltet (kein Sync). |
**Dringlichkeit:**`bf-infra` ohne Remote = alle Edits nur lokal, kein Backup. **Festplattencrash = Datenverlust.**
## Inventar-Entscheidung
- Pipeline war seit **2025-06-05** tot: `IPs.xlsx` (Quelle) ist nicht aktualisiert, `build.py` rendert nur.
- Inventar ist seit Core-Cutover (2026-08-08) **inhaltlich falsch** (alle IPs `10.40.41.x`).
- Live-Daten kommen jetzt aus **MikroMCP** (ARP/DHCP/Interface je Router), **CF-API** (Tunnel/Ingress), **pve-mcp** (VM/LXC), **Portainer/Komodo** (Container).
- **Entscheidung: Inventar-Datei löschen.** Live-Tooling deckt den Bedarf.
## Architektur-Vorschlag (TP34 — Caddyfile via Nautobot/GC)
### Warum
Heute ist der Caddyfile (16 Sites, `bf-infra/caddy/Caddyfile`) **manuell gepflegt**. Problem:
- **Manuelle Edits** erlauben Drift.
- **Keine generische Schnittstelle**: andere Projekte (terpene, blaueblueten-n8n) können keine Sites anlegen, ohne Christoph zu fragen.
- **Kein Compliance-Check**: ein fehlerhafter Block bleibt stehen, bis jemand manuell vergleicht.
- **Keine Transaktionen**: ein kaputter Eintrag bricht die ganze Datei.
### Zielbild
Caddyfile wird **generated** aus einem **Nautobot-Datenmodell** + **Golden Config Pipeline**, identisch zum bestehenden Workflow für Router-Configs.
### Datenmodell (Skizze)
Nautobot-Entities:
- **Site**: `bf`, `fm`, `dw` (Standort, gehört zu ggf. `cf-public` Catch-all)
- **SiteBinding**: Host ↔ Backend (m:n, falls mehrere Backends pro Host)
### GC-Workflow (Skizze)
1.**Generate**: Golden Config rendert aus Nautobot-Daten den Caddyfile.
2.**Diff**: gegen die Live-Version auf `caddy-bf1` (Caddy-Admin-API `:2019/config/`).
3.**Compliance**: Pflichtfelder (jeder Host braucht Backend, jeder Backend braucht Protokoll), keine hardcoded IPs in Caddyfile, keine `tls_insecure_skip_verify` ohne Annotation.
4.**Transaktion**: Snapshot vor Deploy, Rollback bei Fehler.
### Erster Anwendungsfall: terpene.teilzeitladen.xyz
- Access: CF-Access mit Service-Token `terpene-verify-v2`
- **Vorteil**: terpene-Caddyfile-Block wird in 30 Sekunden via `nautobot/gc-configplan.py` deployed, mit Diff und Rollback. Backfill-SQL ist dann via `admin/migrate` callbar.
| Caddyfile-Master wandert zu Nautobot/GC (TP34) | nach terpene | nach Quick-Win |
## Offene Punkte (für nächste Session)
- **terpene-Caddy-Block** (zeitkritisch): Quick-Win vor TP34, manueller Eintrag in `bf-infra/caddy/Caddyfile` für `terpene.teilzeitladen.xyz → http://10.40.20.167:8890`. Mit Commit-Kommentar, dass das nicht das Pattern ist.
- **`STATUS.md` Z.47** korrigieren: Streichen oder Realität einarbeiten.
- **`~/.claude.json``terpene-pg`**: deine Aktion (pg_hba-Erweiterung oder austragen).
- **TP34 Implementierung**: Runbook + Nautobot-Datenmodell-Skizze, sobald terpene-Caddy-Block committed ist.
## Selbstkritik / Lessons Learned für Sessions
- **Bestandsaufnahme vor Plan.** Erst was ist da, wo ist der Schaden — dann Vorschläge. Nicht umgekehrt.
- **Eine große Fragenrunde statt vieler kleiner.** Wenn der Plan von Annahmen abhängt, sammle die Annahmen in einer Runde, nicht in 3–4 Mikrorunden.
- **Master-Frage früh stellen.** Bei jedem Repo, jeder Datei, jedem Tooling: „Was ist die SSoT, wo lebt der Master, was ist Mirror?" — bevor du eine Lösung vorschlägst.
- **Drift zuerst, Lösungen später.** Drift-Tabelle posten + fragen, was richtig ist. Keine Lösungen vor dem Befund.
## Stand
- 2026-08-27
- Inventur-Session mit Christoph
- Commits: `8d2b4a7` (Aufräumen) + dieser Handoff-Commit
> **Konzept + Architektur-Skizze:** [`docs/handoff-20260827-inventur-und-architektur.md`](handoff-20260827-inventur-und-architektur.md) — bitte dort weiterlesen (Architektur-Abschnitt).
- **Scope:** Reverse-Proxy-Hosts werden im **Nautobot-Datenmodell** gepflegt (Site, Host, Backend-Spec). **Golden Config** rendert den Caddyfile aus den Daten, Diff-Check gegen die Live-Version auf `caddy-bf1`, Compliance-Checks + Transaktionen identisch zum bestehenden Workflow für Router-Configs.
- **Auslöser (Inventur 2026-08-27):** der Caddyfile (`bf-infra/caddy/Caddyfile`) ist heute **manuell gepflegt** — kein Drift-Check, keine Transaktionen, andere Projekte können keine Sites anlegen ohne Christoph. Lösung: **Nautobot/GC**, kein Caddy-API-Sidecar (kein zweites SSoT).
- **Erster Anwendungsfall:** `terpene.teilzeitladen.xyz → http://10.40.20.167:8890` (Mac-mini-Backend, dort PostgREST + sync + web via lokalem Caddy `:8890`). Vor TP34: manueller Quick-Win-Caddy-Block.
- **Abh.:** TP22 (GC-Pipeline) ✅ vorhanden · TP23 (DNS-Policy + Caddy-Voraussetzungen) ✅ Stufe 1. Hängt an **nichts**, eigene Implementierung im Runbook nach dem Quick-Win.
- **Status:** 🔜 Stub; Konzept + Architektur-Skizze vollständig in Handoff-Datei. Implementierung in eigenem Runbook nach terpene-Caddy-Quick-Win.
docker,10.40.41.16,pve:docker:adguard_bf1,BC:24:11:10:3A:98,130,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923)
docker,10.40.41.17,pve:docker:adguard_fm1,,,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923)
docker,10.40.41.18,pve:docker:adguard_dw1,,,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923)
| ip | hostname | mac | pve_ct | server_ip | server_mac | note |
|---|---|---|---|---|---|---|
| 10.40.41.16 | pve:docker:adguard_bf1 | BC:24:11:10:3A:98 | 130 | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) |
| 10.40.41.17 | pve:docker:adguard_fm1 | | | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) |
| 10.40.41.18 | pve:docker:adguard_dw1 | | | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) |
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.