SSoT: Status-Marker aus den TP-Headern entfernt, Sync-Werkzeug auf Anlege-Richtung festgelegt
Die `### TPnn`-Header trugen weiterhin Status-Anspruche (▸ ✅ FERTIG …, ▸ ⏳ CUTOVER …),
obwohl Index/Status seit dem TP36-Cutover in Gitea liegt. Das war eine dritte Statusquelle,
die den Labels nachlief — Header-Marker datierten teils Wochen vor dem Issue-Update.
- 75 Header (32 aktiv + 43 Archiv) auf `### TPnn · Gitea #N — <Titel> — <Caveat>` umgestellt.
Caveats, Warnungen, Querverweise und Archiv-Links bleiben erhalten, nur der Status faellt weg.
Status-Marker im Fliesstext (Messchronik, Unterpunkte) bleiben — sie beschreiben Historie.
- TP47 fehlte als Gitea-Issue komplett (nur in der Datei seit 808d3a1) -> als #74 angelegt.
- bin/gitea-tp-sync.py schrieb in die falsche Richtung: der Abgleich leitete den Zielzustand
aus dem Datei-Marker ab (fest ✅) und haette #24 (TP34, bewusst status:dropped) auf status:done
gezogen. Jetzt werden nur noch FEHLENDE Archiv-Issues angelegt, bestehende nie angefasst.
- CLAUDE.md: Header-Form + Werkzeug-Richtung festgehalten.
- Announcement 2026-10-03 für die naechste Session.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
12
CLAUDE.md
12
CLAUDE.md
@@ -17,8 +17,18 @@ DNS/DHCP-Ablösung, WLAN via **CAPsMAN auf dem Core** (TP28, 2026-08-17), Firewa
|
||||
- **SSoT-Dreiteilung:** **Index/Status = Gitea-Issues** (`admin/bf-infra`, Labels `status:*`/`thema:*`) ·
|
||||
**Prosa/Detail = Repo** (`docs/teilprojekte.md` aktiv + `teilprojekte-archiv.md`, `### TPnn`-Abschnitte) ·
|
||||
**Live-Gerätedaten = Nautobot** (Compliance-Zahl, RouterOS-Version …). Ein Status ändert sich **in Gitea**,
|
||||
nicht mehr in einer Repo-Datei. Sync-/Abgleich-Werkzeug fürs Archiv: `bin/gitea-tp-sync.py` (Dry-Run default,
|
||||
nicht mehr in einer Repo-Datei. Archiv-Backfill-Werkzeug `bin/gitea-tp-sync.py` (Dry-Run default,
|
||||
Token aus `~/.hermes/.env`, **nie ausgeben**).
|
||||
- 🔴 **Die TP-Header in beiden Dateien tragen KEINEN Status mehr** (seit 2026-10-03). Form:
|
||||
`### TP25 · Gitea #17 — <Titel> — <Caveat>`. Der `· Gitea #N`-Zeiger ist die Brücke zum Issue.
|
||||
Wer einen Status sucht, liest das **Label im Board** — nicht den Datei-Kopf. Der alte `▸ ✅ FERTIG …`-Anspruch
|
||||
war eine dritte Statusquelle und ist entfernt; die Header-Marker waren teils älter als die Issues.
|
||||
⚠️ **Status-Marker im Fließtext** (in `└─`-Zeilen, Unterpunkten, Messchronik) bleiben erlaubt — sie
|
||||
beschreiben historische Ereignisse, keinen aktuellen Stand.
|
||||
- 🔴 **`bin/gitea-tp-sync.py` schreibt nur noch NEUE Issues** für Archiv-TPs, die im Board fehlen.
|
||||
Existierende Issues werden **nie** angefasst — kein Label-, kein State-Patch. Die Vorgängerversion
|
||||
glich bestehende Issues gegen den Datei-Marker ab und zog so #24 (`status:dropped` → `done`) und
|
||||
#32 auf falsche Labels. **Richtung Datei → Gitea ist nur fürs *Anlegen* zulässig, nie für *Status*.**
|
||||
- **Branch-Konvention:** Branch `tpNN-kurz` **jederzeit** mitten in der Session möglich (`git switch -c`,
|
||||
uncommittete Arbeit wandert mit); für Multi-Session-TPs der Normalfall. **Merge nach `main`, sobald der
|
||||
Code/Config des TP steht.** Weil Steuerungs-Updates nach **Gitea** gehen (nicht in `teilprojekte.md`),
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
TP36 (reframed) — teilprojekte.md Index/Status → Gitea Issues (admin/bf-infra).
|
||||
TP36 (reframed) — Archiv-Backfill: fehlende Archiv-TPs als Gitea-Issues anlegen.
|
||||
|
||||
Idempotenter Sync (get-or-create, Match ueber "TPnn" im Titel):
|
||||
- Archiv-Header in docs/teilprojekte-archiv.md -> closed Issues (nur TPs, die in Gitea
|
||||
NICHT offen sind; ein reopentes TP mit Archiv-Zeiger bleibt offen).
|
||||
- Labels status:* (Marker) + thema:* (Gruppierung) werden vorab get-or-create.
|
||||
🔴 RICHTUNG (seit 2026-10-03): **Gitea ist die SSoT fuer Index/Status.** Dieses Werkzeug
|
||||
liest die Datei NUR, um zu pruefen, ob jedes archivierte TP ein Issue hat. Es schreibt
|
||||
**ausschliesslich** NEUE Issues fuer noch nicht existierende Archiv-TPs — existierende
|
||||
Issues werden NIE angefasst (kein Label-, kein State-Patch).
|
||||
|
||||
Warum das wichtig ist: die Vorgaenger-Version glich auch bestehende Issues ab und leitete
|
||||
den Zielzustand aus dem Datei-Marker ab (fest `✅`). Damit konnte sie ein bewusst gesetztes
|
||||
Label ueberschreiben — so wurde #24 (TP34, `status:dropped`) auf `status:done` und #32
|
||||
(TP43) auf ein falsches `thema:` gezogen. Die Richtung Datei → Gitea fuer *Status* ist
|
||||
seit dem TP36-Cutover (2026-09-07) falsch; sie bleibt hier nur fuer das *Anlegen* erhalten.
|
||||
|
||||
Abgrenzung:
|
||||
- Aktive TPs: werden DIREKT als Gitea-Issue gepflegt (nicht hier).
|
||||
- Status/Thema/State bestehender Issues: aendert nur der Mensch im Board.
|
||||
- Per-TP-Prosa: bleibt in docs/teilprojekte.md / teilprojekte-archiv.md.
|
||||
|
||||
SSoT-Modell (seit TP36-Cutover 2026-09-07): Gitea fuehrt Index+Status — aktive TPs werden
|
||||
DIREKT als Gitea-Issue angelegt/gepflegt, NICHT mehr aus einer Datei-Tabelle abgeleitet
|
||||
(die Quick-Index-Tabelle wurde aus teilprojekte.md entfernt). Dieses Werkzeug haelt nur noch
|
||||
die ARCHIVIERTEN (closed) TPs mit teilprojekte-archiv.md idempotent abgeglichen und fasst
|
||||
offene Issues nie an. Die per-TP-Prosa bleibt in docs/teilprojekte.md / teilprojekte-archiv.md.
|
||||
Token: ~/.hermes/.env (GITEA_ACCESS_TOKEN, GITEA_HOST) — wird NIE ausgegeben.
|
||||
|
||||
Aufruf:
|
||||
python3 bin/gitea-tp-sync.py # Dry-Run (default) — zeigt, was passieren wuerde
|
||||
python3 bin/gitea-tp-sync.py --commit # legt Labels + Issues an / gleicht sie ab
|
||||
python3 bin/gitea-tp-sync.py # Dry-Run (default) — zeigt, was fehlt
|
||||
python3 bin/gitea-tp-sync.py --commit # legt fehlende Archiv-Issues an
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
@@ -33,16 +39,6 @@ HERMES = Path.home() / ".hermes" / ".env"
|
||||
OWNER_REPO = "admin/bf-infra"
|
||||
COMMIT = "--commit" in sys.argv
|
||||
|
||||
# Marker -> (status-label, gitea-state)
|
||||
MARKER = {
|
||||
"🔜": ("status:todo", "open"),
|
||||
"⏳": ("status:wip", "open"),
|
||||
"⏸️": ("status:paused", "open"),
|
||||
"💡": ("status:idea", "open"),
|
||||
"🟢": ("status:concept", "open"),
|
||||
"✅": ("status:done", "closed"),
|
||||
"❌": ("status:dropped", "closed"),
|
||||
}
|
||||
LABEL_COLORS = {
|
||||
"status:todo": "#ededed", "status:wip": "#fbca04", "status:paused": "#c5def5",
|
||||
"status:idea": "#d4c5f9", "status:concept": "#bfdadc", "status:done": "#0e8a16",
|
||||
@@ -105,23 +101,31 @@ def api(method, path, body=None):
|
||||
|
||||
# --------------------------------------------------------------------------- parse
|
||||
def parse_archiv(exclude_nums):
|
||||
"""Archiv-Header -> archivierte TPs. exclude_nums = TP-Nummern, die in Gitea OFFEN sind
|
||||
(reopente TPs mit Archiv-Zeiger) -> die bleiben offen, nicht als closed abgleichen."""
|
||||
"""Archiv-Header -> archivierte TPs, die ein Issue bekommen SOLLEN.
|
||||
|
||||
Header-Form seit 2026-10-03: `### TP25 · Gitea #17 — WLAN-Stabilisierung — …`
|
||||
Der Status-Anspruch (frueher `▸ ✅ FERTIG …`) ist entfernt; die Datei traegt keinen
|
||||
Status mehr. Der Gitea-Zeiger `· Gitea #N` ist die Bruecke, falls er schon da ist.
|
||||
|
||||
exclude_nums = TP-Nummern, die in Gitea OFFEN sind -> die brauchen kein neues Issue.
|
||||
"""
|
||||
out = []
|
||||
hdr = re.compile(r"^#{2,4}\s*(TP[\d.\-A-Za-z]+)\s*—\s*(.+?)\s*▸", )
|
||||
hdr = re.compile(r"^#{2,4}\s*(TP[\d.\-A-Za-z]+)\b\s*(?:·\s*Gitea\s*#(\d+)\s*)?—\s*(.+?)\s*$")
|
||||
seen = set()
|
||||
for line in ARCHIV.read_text().splitlines():
|
||||
m = hdr.match(line)
|
||||
if not m:
|
||||
continue
|
||||
tp, title = m.groups()
|
||||
tp, issue_no, title = m.groups()
|
||||
num = tp[2:]
|
||||
if num in exclude_nums or num in seen:
|
||||
continue
|
||||
seen.add(num)
|
||||
short = re.sub(r"\*\*|`", "", title).strip()[:80]
|
||||
out.append({"tp": tp, "num": num, "marker": "✅",
|
||||
"title": short, "date": "", "src": "archiv"})
|
||||
# Caveat hinter dem zweiten ` — ` abschneiden; nur der Kurztitel gehoert ins Issue.
|
||||
short = re.split(r"\s+—\s+", title)[0]
|
||||
short = re.sub(r"\*\*|`", "", short).strip()[:80]
|
||||
out.append({"tp": tp, "num": num, "issue": issue_no,
|
||||
"title": short, "src": "archiv"})
|
||||
return out
|
||||
|
||||
|
||||
@@ -173,43 +177,44 @@ def main():
|
||||
print(f"Geparst: {len(items)} archivierte TP (aktive TPs = SSoT in Gitea: "
|
||||
f"{len(open_nums)} offen, nicht angetastet)\n")
|
||||
|
||||
created = updated = 0
|
||||
created = skipped = 0
|
||||
for it in items:
|
||||
status_label, state = MARKER.get(it["marker"], ("status:todo", "open"))
|
||||
# Archiv-TPs sind abgeschlossen -> neu angelegte Issues gehen direkt auf closed.
|
||||
status_label, state = "status:done", "closed"
|
||||
labels = [status_label]
|
||||
th = THEME.get(it["num"])
|
||||
if th:
|
||||
labels.append(f"thema:{th}")
|
||||
title = f"{it['tp']} — {it['title']}"
|
||||
body = (f"Steuerungs-SSoT: Index/Status hier in Gitea; **Prosa/Detail** im Repo unter "
|
||||
f"`docs/{'teilprojekte-archiv.md' if it['src']=='archiv' else 'teilprojekte.md'}` "
|
||||
f"(Abschnitt `{it['tp']}`).\n\n"
|
||||
f"- Status: {it['marker']} ({status_label})\n"
|
||||
+ (f"- Abschluss: {it['date']}\n" if it["date"] else ""))
|
||||
f"`docs/teilprojekte-archiv.md` (Abschnitt `{it['tp']}`).\n\n"
|
||||
f"- Status: ✅ ({status_label})\n"
|
||||
f"- Angelegt aus dem Archiv-Backfill (`bin/gitea-tp-sync.py`).\n")
|
||||
want_ids = [label_id[l] for l in labels if l in label_id]
|
||||
|
||||
cur = by_tp.get(it["tp"])
|
||||
if cur is None:
|
||||
print(f" [{'+' if COMMIT else 'DRY'}] NEW {title} {labels} state={state}")
|
||||
if COMMIT:
|
||||
sc, res = api("POST", f"/repos/{OWNER_REPO}/issues",
|
||||
{"title": title, "body": body, "labels": want_ids})
|
||||
if state == "closed" and isinstance(res, dict) and res.get("number"):
|
||||
api("PATCH", f"/repos/{OWNER_REPO}/issues/{res['number']}", {"state": "closed"})
|
||||
created += 1
|
||||
else:
|
||||
have = {l["name"] for l in cur.get("labels", [])}
|
||||
drift = (have != set(labels)) or (cur.get("state") != state)
|
||||
if drift:
|
||||
print(f" [{'~' if COMMIT else 'DRY'}] UPD #{cur['number']} {title} "
|
||||
f"{sorted(have)}->{labels} state {cur.get('state')}->{state}")
|
||||
if COMMIT:
|
||||
api("PATCH", f"/repos/{OWNER_REPO}/issues/{cur['number']}",
|
||||
{"labels": want_ids, "state": state})
|
||||
updated += 1
|
||||
if cur is not None:
|
||||
# 🔴 Existierendes Issue: NICHT anfassen. Weder Label noch State noch Body.
|
||||
# Status/Thema aendert nur der Mensch im Board (Gitea = SSoT seit TP36-Cutover).
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# Fehlt das Issue, obwohl der Header schon einen Zeiger traegt? -> Zeiger ist stale.
|
||||
hint = f" ⚠ Datei-Header nennt bereits Gitea #{it['issue']} — Issue fehlt!" if it.get("issue") else ""
|
||||
print(f" [{'+' if COMMIT else 'DRY'}] NEW {title} {labels} state={state}{hint}")
|
||||
if COMMIT:
|
||||
sc, res = api("POST", f"/repos/{OWNER_REPO}/issues",
|
||||
{"title": title, "body": body, "labels": want_ids})
|
||||
if isinstance(res, dict) and res.get("number"):
|
||||
api("PATCH", f"/repos/{OWNER_REPO}/issues/{res['number']}", {"state": "closed"})
|
||||
print(f" -> #{res['number']} angelegt (closed). Zeiger in "
|
||||
f"docs/teilprojekte-archiv.md nachtragen: `· Gitea #{res['number']}`")
|
||||
else:
|
||||
print(f" !! Anlegen fehlgeschlagen: {res}")
|
||||
created += 1
|
||||
|
||||
print(f"\n{'Angelegt' if COMMIT else 'Wuerde anlegen'}: {created} · "
|
||||
f"{'Abgeglichen' if COMMIT else 'Wuerde abgleichen'}: {updated}")
|
||||
f"unveraendert gelassen (SSoT = Gitea): {skipped}")
|
||||
if not COMMIT:
|
||||
print("Dry-Run — nichts geschrieben. Mit --commit ausfuehren.")
|
||||
|
||||
|
||||
@@ -13,6 +13,24 @@ zeigt die Einträge, die seit dem letzten `/news`-Lauf dazugekommen sind (Rest a
|
||||
|
||||
---
|
||||
|
||||
## 2026-10-03 — TP-Header tragen keinen Status mehr (SSoT-Drift geschlossen)
|
||||
**Betrifft:** alle, die `docs/teilprojekte.md` oder `teilprojekte-archiv.md` lesen oder editieren, und
|
||||
alle, die ein TP anlegen/abschließen.
|
||||
**Aktion:** Die `### TPnn`-Header haben die Form `### TP25 · Gitea #17 — <Titel> — <Caveat>`.
|
||||
Der Status-Anspruch (`▸ ✅ FERTIG (2026-09-15)`, `▸ ⏳ CUTOVER …`) ist **entfernt** — er war eine
|
||||
dritte Statusquelle neben Issue und Prosa und lief den Labels nachweislich hinterher. **Wer einen
|
||||
Status braucht, liest das `status:*`-Label im Gitea-Board**, nicht den Datei-Kopf — `· Gitea #N`
|
||||
ist die Brücke. Status-Marker **im Fließtext** (Messchronik, `└─`-Zeilen) bleiben: sie beschreiben
|
||||
Historie, keinen Stand.
|
||||
|
||||
Dazu zwei Befunde, die dabei behoben wurden:
|
||||
- **TP47 existierte nur in der Datei**, ohne Gitea-Issue (seit Commit `808d3a1`, 2026-09-27) — jetzt
|
||||
**#74**. Das war ein echter SSoT-Bruch, kein fehlender Zeiger.
|
||||
- **`bin/gitea-tp-sync.py` schrieb in die falsche Richtung**: der Abgleich leitete den Zielzustand
|
||||
aus dem Datei-Marker ab (fest `✅`) und hätte #24 (TP34, bewusst `status:dropped`) auf `status:done`
|
||||
gezogen. Das Werkzeug schreibt jetzt **nur noch fehlende** Archiv-Issues neu und fasst bestehende
|
||||
**nie** an.
|
||||
|
||||
## 2026-09-12 — Golden-Config-Backups laufen jetzt täglich (vorher KEIN Scheduler)
|
||||
**Betrifft:** alle, die sich auf GC-Backups/Compliance oder `gc-snapshot.py`-Werte verlassen.
|
||||
**Aktion:** Es gab **nie** einen automatischen GC-Backup-Zeitplan — Backup/Intended/Compliance liefen
|
||||
|
||||
52
docs/handoff-20260928-core-wghub-ping-fix.md
Normal file
52
docs/handoff-20260928-core-wghub-ping-fix.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Handoff 2026-09-28 — Core erreicht FM/DW-Spoke-Netze nicht aus eigener Kraft
|
||||
|
||||
## Kontext / Auslöser
|
||||
Christoph konnte von Notebook + macmini immer `10.101.0.254` (FM-Standort-GW) pingen, eine
|
||||
überforderte Vorgänger-Session hatte behauptet, der Core „komme dort nicht hin". Befund
|
||||
sollte jetzt geprüft und ausgeräumt werden.
|
||||
|
||||
## Befund (alles live verifiziert 2026-09-28, crs326-core)
|
||||
| Quelle | → 10.101.0.254 (FM-GW) | → 10.101.0.10 (FM-Host) |
|
||||
|---|---|---|
|
||||
| macmini (VLAN20, gw 10.40.20.1) | ✅ 0 % Loss | ✅ 0 % Loss |
|
||||
| Notebook (VLAN10, gw 10.40.10.1) | ✅ 0 % Loss | ✅ 0 % Loss |
|
||||
| **Core default** (`/ping` ohne src) | ❌ **100 % Loss** | ❌ **100 % Loss** |
|
||||
| **Core mit `src-address=10.40.10.1`** | ✅ **0 % Loss** (ttl 64) | ✅ **0 % Loss** (ttl 63) |
|
||||
|
||||
## Root Cause
|
||||
`wg-hub` (TP10 Multi-Site VPN Hub) hat **keine IP-Adresse** — weder live
|
||||
(`/ip address print where interface="wg-hub"` → leer) noch im GC-Template
|
||||
(`mikrotik_routeros.j2:379`, nur listen-port/mtu/name/private-key).
|
||||
|
||||
FM-seitig erlaubt die FritzBox als AllowedIPs Richtung Hub `10.40.0.0/16`
|
||||
(`routeros/fritzbox-wg-lanlan-klickanleitung.md`). Weitergeleiteter Client-Traffic
|
||||
(Quell-IP 10.40.x) liegt in diesem Raum → läuft. **Core-eigener** Traffic ohne
|
||||
explizite Quell-IP: RouterOS wählt mangels IP auf wg-hub eine Quell-IP **außerhalb**
|
||||
von 10.40.0.0/16 (vermutlich WAN `90.146.33.177`) → FM routet die Antwort nicht zurück
|
||||
→ Timeout. Der Tunnel selbst ist up (FM-Peer last-handshake ~1m45s, rx 140.8 GiB).
|
||||
|
||||
## SSoT / Governance
|
||||
Die Core-Config liegt im GC-Template `nautobot/mikrotik_routeros.j2`. Dort existieren:
|
||||
- `:375` `/ip route add ... dst-address=10.101.0.0/24 gateway=wg-hub comment="TP10: FM spoke"`
|
||||
- `:376` `/ip route add ... dst-address=10.95.10.0/24 gateway=wg-hub comment="TP10: DW spoke"`
|
||||
- `:379-381` wg-hub Interface + fm/dw Peers (Privkey redacted)
|
||||
|
||||
Ein Fix gehört **ins Template**, nicht als Direkt-Write aufs Gerät (GC-Compliance-Regel).
|
||||
Deploy via `nautobot/gc-configplan.py` / GC-Job „Backup → Intended → Compliance".
|
||||
|
||||
## Fix-Optionen (noch nicht entschieden)
|
||||
1. **`preferred-source` auf die zwei TP10-Routen** (Zeile 375/376, z. B. `10.40.10.1`).
|
||||
Kein FM-Eingriff nötig (FM erlaubt 10.40.0.0/16 bereits). Minimal-invasiv. **Empfohlen.**
|
||||
2. wg-hub eine IP geben (z. B. dedizierte Adresse aus 10.40.0.0/16) — mehr Risiko, IP-Raum-
|
||||
Eingriff, FM-Abgleich nötig.
|
||||
3. FM-seitig AllowedIPs um die Core-WAN-IP erweitern — FritzBox-WG-Config eingeschränkt, nicht sauber.
|
||||
|
||||
## Offene Entscheidungen
|
||||
- Welche `preferred-source`-IP? (10.40.10.1 = MAIN-SVI ist naheliegend.)
|
||||
- TP10 ist im Archiv „KERN DURCH, offen nur DDNS-Updater". Neuer Befund → TP10-Issue
|
||||
`reopen` + Prosa zurück nach `teilprojekte.md`, oder als eigenes kleines TP? (Christoph-Entscheid.)
|
||||
- Fix jetzt ausführen oder nur dokumentieren?
|
||||
|
||||
## Aufwandsschätzung (Core-Ping-Fix)
|
||||
Klein. 2 Zeilen Template-Edit + ein GC-Deploy-Zyklus (~30–60 min inkl. Backup/Intended/Compliance)
|
||||
+ Ping-Verifikation. Kein Hardware-/FM-Eingriff bei Option 1.
|
||||
@@ -77,7 +77,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
---
|
||||
<a id="tp1"></a>
|
||||
|
||||
### TP1 — ALLNET Core-Switch finalisieren ▸ ✅ FERTIG (2026-06-15) → ❌ Gerät AUSSER BETRIEB (2026-08-08, durch crs326-core ersetzt)
|
||||
### TP1 · Gitea #34 — ALLNET Core-Switch finalisieren — → ❌ Gerät AUSSER BETRIEB (2026-08-08, durch crs326-core ersetzt)
|
||||
- ✅ GE8 Trunk (native vlan1, tagged 10/20/30/40/50/90/99/100) — war bereits aktiv.
|
||||
- ✅ VLAN 40 umbenannt: UNTRUSTED → **MEDIA** (`switch/cli/04-vlan50-media-untrusted.cli`).
|
||||
- ✅ VLAN 50 angelegt + benannt: **UNTRUSTED**.
|
||||
@@ -86,7 +86,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp2"></a>
|
||||
|
||||
### TP2 — Omada Access-Switch + Controller ▸ ✅ FERTIG (2026-06-15)
|
||||
### TP2 · Gitea #35 — Omada Access-Switch + Controller
|
||||
- ✅ Omada Controller 6.2.10.17 auf DS923 (macvlan `.175`): `omada/docker-compose.yml`, Stack via Portainer endpointId=14. **Wizard abgeschlossen** (configured=true), Creds in `mcp/omada/.env`.
|
||||
- ✅ pve-mcp (samik081) in Claude Code eingetragen (`~/.claude/settings.json`, SSE `.173:3000`).
|
||||
- ✅ omada-mcp **live** auf **pve-LXC (`.126`, endpointId=2), ipvlan-IP `.176`**, Stack Id=200, URL in `~/.claude/settings.json`.
|
||||
@@ -122,7 +122,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp2-1"></a>
|
||||
|
||||
### TP2.1 — Omada-Switch (sw2/ES208G) → Standalone-Recovery (kein Controller) ▸ ✅ FERTIG (2026-07-16, User solo)
|
||||
### TP2.1 · Gitea #36 — Omada-Switch (sw2/ES208G) → Standalone-Recovery (kein Controller) — User solo)
|
||||
- **Root Cause:** beim VLAN20-Umzug des Omada-Controllers (TP14.1, 2026-07-10) ist die Controller↔sw2-Verbindung zerbrochen (sw2 seither „Disconnected", ursprünglich als reiner Mgmt-Loss vertagt). Beim Rettungsversuch hat der User versehentlich einen **Werks-Reset** am Switch ausgelöst. Ein anschließender Wiederherstellungsversuch (durch Claude) hat Teile der Config **unbemerkt halluziniert** — der damalige „wiederhergestellte" Stand war **nicht vertrauenswürdig**.
|
||||
- **Entscheidung (User 2026-07-15): Controller-Zustand als invalid betrachtet, sw2 komplett neu — diesmal OHNE Managementsoftware.** Kein Omada-Controller-Re-Adopt, kein Omada-Ecosystem-Anschluss (s. TP15-Korrektur — Omada bekommt generell keine Rolle mehr, auch nicht WLAN). sw2 direkt über eigenes Web-UI konfiguriert, wie ein eigenständiger Switch.
|
||||
- **✅ 2026-07-16 (User-Aussage): „voll durch, Funktionsweise erfolgreich getestet."** Nach dem gescheiterten Claude-Versuch hat der User sw2 **komplett allein** neu aufgesetzt (Runbook `docs/tp2.1-omada-switch-standalone-runbook.md` als Playbook-Referenz, nicht Schritt-für-Schritt-Log). **Keine formale Einzelschritt-Verifikation dieser Session** (kein Port-für-Port-Protokoll, keine Live-Prüfung durch Claude) — Status beruht auf User-Bestätigung „es geht einfach", nicht auf eigener Nachkontrolle.
|
||||
@@ -132,7 +132,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp3"></a>
|
||||
|
||||
### TP3 — WLAN ▸ 📜 **VOLLSTÄNDIG HISTORISCH — der Ist-Stand steht in TP28, nicht hier**
|
||||
### TP3 · Gitea #37 — WLAN
|
||||
> 🔴 **Lesehinweis (überarbeitet 2026-08-19): dieser gesamte TP ist Geschichte, von der ersten bis zur
|
||||
> letzten Zeile.** Er beschreibt zwei überholte Zustände nacheinander — die **CAPsMAN-Ära (Juni/Juli
|
||||
> 2026)** und danach den **Standalone-Rebuild vom 2026-08-08**. Beides gilt nicht mehr:
|
||||
@@ -170,7 +170,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp3-1"></a>
|
||||
|
||||
### TP3.1 — ap2 VLAN-Trunk-Fix ▸ ✅ Config live (2026-07-01) — `routeros/tp3.1-ap2-vlan.rsc`
|
||||
### TP3.1 · Gitea #38 — ap2 VLAN-Trunk-Fix — `routeros/tp3.1-ap2-vlan.rsc`
|
||||
- **Root Cause:** ap2 (CAP, local forwarding) hatte `bridge vlan-filtering=no` → `datapath.vlan-id` wurde nie
|
||||
auf die Leitung geschrieben → **ALLE** WLAN-Clients auf ap2 (main/media/iot/…) egressten **ungetaggt in VLAN1**
|
||||
(defconf/`10.40.41.x`) statt ins Ziel-VLAN. Symptom: iPhone (VLAN10) im OG „verbunden, aber sporadisch kein
|
||||
@@ -208,7 +208,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp3-2"></a>
|
||||
|
||||
### TP3.2 — WLAN Coverage / P750W-Discovery ▸ ✅ **ABGESCHLOSSEN (2026-08-17, User-Test erfolgreich)** — `docs/wifi-p750w-coverage-and-map.md`
|
||||
### TP3.2 · Gitea #39 — WLAN Coverage / P750W-Discovery — `docs/wifi-p750w-coverage-and-map.md`
|
||||
- ✅ **Brother P750W (VLAN30) gelöst:** DHCP-`client-id`-Fix (matcht über MAC → feste `10.40.30.5`); **an ap1 gepinnt**
|
||||
(geordnete wifi-access-list `accept w2-iot` → blanket `reject`, überlebt ap2-Re-Provision) — dozende Legacy-Clients
|
||||
nur am co-located-GW ap1 per ARP erreichbar, CAP ap2 nicht; mDNS `vlan30` in `mdns-repeat-ifaces`+5353 → in MAIN
|
||||
@@ -221,7 +221,7 @@ Dazu am Ende: **[TP25 (Kondensat)](#tp25)** + **[TP25 (Langfassung)](#tp25-lang)
|
||||
|
||||
<a id="tp3-3"></a>
|
||||
|
||||
### TP3.3 — WLAN Coverage-Kur ▸ 📜 **IN TP25 AUFGEGANGEN (2026-08-17)** — offene Arbeit steht dort, nicht hier
|
||||
### TP3.3 · Gitea #40 — WLAN Coverage-Kur — offene Arbeit steht dort, nicht hier
|
||||
> ⚠️ Der Header sagte bis 2026-08-19 „🔜 TODO (Fortsetzung, neue Session)" — dieselbe Falle wie bei TP3:
|
||||
> ein Status, der nicht mitgezogen wurde. Der Re-Walk und die Dead-Spot-Kartierung sind **Schritt 5 von
|
||||
> TP25** und zwar bewusst **nach** den Funkparameter-Fixes; die 802.11k/v-Reparatur ist am 2026-08-13
|
||||
@@ -260,7 +260,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp4"></a>
|
||||
|
||||
### TP4 — Router-Cutover (hAP#1 = Router + WAN-Edge) ▸ ✅ FERTIG (2026-07-01) — ⚠️ **Rolle seit 2026-08-08 auf `crs326-core`** (TP21.1); alles unten beschreibt den damaligen ap1-Aufbau und gilt als **Historie/Referenz**, nicht als Ist
|
||||
### TP4 · Gitea #41 — Router-Cutover (hAP#1 = Router + WAN-Edge) — ⚠️ **Rolle seit 2026-08-08 auf `crs326-core`** (TP21.1); alles unten beschreibt den damaligen ap1-Aufbau und gilt als **Historie/Referenz**, nicht als Ist
|
||||
- ✅ **Bridge VLAN-Filtering aktiviert** (`vlan-filtering=yes`); VLAN-Tabelle: VLAN1 untagged bridge+ether2, VLANs 10/20/30/40/50/90/99/100 tagged bridge+ether2.
|
||||
- ✅ **VLAN-Subinterfaces:** vlan10/20/30/40/50/90/99 auf bridge; je GW `.1` (10.40.10.1 … 10.40.99.1).
|
||||
- ✅ **DHCP:** dhcp-v10…dhcp-v99 je auf eigenem VLAN-Interface, pools .100-.200, GW+DNS = VLAN-GW.
|
||||
@@ -275,7 +275,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp5"></a>
|
||||
|
||||
### TP5 — Firewall & Inter-VLAN-Policy ▸ ✅ **DURCH (2026-08-18): deny-by-default in BEIDEN Ketten scharf** · **+ E5 (2026-08-19)** — 📋 `docs/tp5-deny-by-default-runbook.md`
|
||||
### TP5 · Gitea #42 — Firewall & Inter-VLAN-Policy — + E5 (2026-08-19)** — 📋 `docs/tp5-deny-by-default-runbook.md`
|
||||
> 📌 **„DURCH" heißt nicht „abgeschlossen".** E5 (MAIN→IOT) kam einen Tag nach dem Drop — unter deny-by-default
|
||||
> braucht **jeder** neue Dienst über eine VLAN-Grenze seine Regel. Weitere Etappen sind normaler Betrieb,
|
||||
> kein Rückschritt. Der Weg dahin ist immer derselbe: **erst den Drop-Log lesen**, dann die Regel schreiben.
|
||||
@@ -411,7 +411,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp6"></a>
|
||||
|
||||
### TP6 — QoS/CAKE + Call-Quality-A/B-Test ▸ ✅ **GESCHLOSSEN 2026-08-23 — CAKE gebaut, gemessen, wieder ausgebaut.** ⚠️ **Die Erklaerung darin ist von TP6.1 ueberholt: nicht DOCSIS, sondern fehlende Klassentrennung.**
|
||||
### TP6 · Gitea #43 — QoS/CAKE + Call-Quality-A/B-Test — ⚠️ **Die Erklaerung darin ist von TP6.1 ueberholt: nicht DOCSIS, sondern fehlende Klassentrennung.**
|
||||
> 🔴 **ZUERST LESEN — diese Analyse ist teilweise widerlegt (2026-08-23, durch TP6.1).**
|
||||
> Unten steht, die ~30 ms entstuenden im DOCSIS-Uplink und seien unabaenderlich. **Sie sind es
|
||||
> nicht.** TP6.1 holt dieselbe Strecke unter derselben Saettigung auf **11,0 ms** — allein durch
|
||||
@@ -550,7 +550,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp6-1"></a>
|
||||
|
||||
### TP6.1 — Saettigung vermeiden statt Bufferbloat bekaempfen ▸ ✅ **LIVE UND GEMESSEN (2026-08-23): 40,8 → 11,0 ms unter Last**
|
||||
### TP6.1 · Gitea #44 — Saettigung vermeiden statt Bufferbloat bekaempfen
|
||||
> **Der Gedanke kam von Christoph** beim TP6-Abschluss („dann koennten wir zumindest den Sync
|
||||
> von der NAS zurueckhalten“) — und er hat mein TP6-Urteil zu Recht angezweifelt.
|
||||
>
|
||||
@@ -601,7 +601,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp7"></a>
|
||||
|
||||
### TP7 — Media-Discovery (mDNS) für VLAN 40 ▸ ✅ FERTIG (2026-07-02) — `docs/tp7-mdns.md`
|
||||
### TP7 · Gitea #45 — Media-Discovery (mDNS) für VLAN 40 — `docs/tp7-mdns.md`
|
||||
- ✅ **Built-in mDNS-Repeater** aktiv — **Live-Stand `crs326-core` (verifiziert 2026-08-14):**
|
||||
`mdns-repeat-ifaces=vlan10,vlan20,vlan30,vlan40,vlan90` → MAIN/INFRA/IOT/GUEST ↔ MEDIA. Reversibel (Feld leeren).
|
||||
📌 **`bridge` (=VLAN1) ist nicht mehr dabei** — mit dem VLAN1-Retirement erwartbar und korrekt, war aber nie nachgezogen.
|
||||
@@ -618,7 +618,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp7-1"></a>
|
||||
|
||||
### TP7.1 — SSDP-Relay (macOS-Sonos-App über VLAN-Grenze) ▸ ✅ **LÄUFT (2026-08-18)** — User-bestätigt: „sonos ist da!"
|
||||
### TP7.1 · Gitea #46 — SSDP-Relay (macOS-Sonos-App über VLAN-Grenze) — User-bestätigt: „sonos ist da!"
|
||||
- ✅ **Umsetzung:** eigener LXC **108 `mcast-relay`** auf pve (Ubuntu 24.04, 1 Kern, 256 MB, `onboot`),
|
||||
zweibeinig: `eth0` = **10.40.10.21** (VLAN10), `eth1` = **10.40.40.21** (VLAN40), Default-Route nur
|
||||
über VLAN10, **kein IP-Forwarding**. Dazu `core ether13` (pve-Port) um `tagged vlan10, vlan40`
|
||||
@@ -659,7 +659,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp7-2"></a>
|
||||
|
||||
### TP7.2 — HA↔Sonos static-host binding + VLAN1/GUEST-Discovery ▸ ✅ FERTIG (2026-07-03) — `docs/sonos-inventar.md`
|
||||
### TP7.2 · Gitea #47 — HA↔Sonos static-host binding + VLAN1/GUEST-Discovery — `docs/sonos-inventar.md`
|
||||
- **Root Cause (widerlegt frühere Doku):** HA-`media_player.*`-Sonos alle `unavailable`. HA sitzt **nicht** auf
|
||||
VLAN 20, sondern noch auf `10.40.41.105` (VLAN-1-Transfernetz, IP-Migration steht aus). Der mDNS-Repeater
|
||||
deckte VLAN 1 **nicht** ab, und die HA-Sonos-Integration ist **SSDP-abhängig** (`manifest dependencies:[ssdp]`,
|
||||
@@ -682,7 +682,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp9"></a>
|
||||
|
||||
### TP9 — Gateway-/Router-HA ▸ ❌ OBSOLET (User-Entscheid 2026-08-08)
|
||||
### TP9 · Gitea #48 — Gateway-/Router-HA
|
||||
- ❌ **Verworfen (User-Begründung 2026-08-08, „ganz klar nein"):** am `crs326-core` führt ohnehin **nie ein Weg vorbei** — er ist der unumgängliche L3-Durchleitungspunkt. Ein zweites Gerät / VRRP **beseitigt diesen SPOF nicht**, sondern baut nur **zusätzliche Sollbruchstellen** ein (2× Config-Sync für DHCP/DNS/Firewall/NAT, Split-Brain-Risiko, VRRP-Eigenfehler) → netto ein Zuverlässigkeits-**Verlust**, kein -Gewinn. Die Frage ist nicht „Aufwand vs. Nutzen", sondern „mehr Fehlerquellen einbauen?" → nein. DR-Weg = Config-Backup-Restore (+ ggf. AP-Reprovisionierung). VRRP-Skizze unten = nur noch historische Recherche.
|
||||
- **„Was, wenn ap1 ausfällt?"** → **VRRP** löst Gateway-Failover je VLAN ~gratis (kreuzweise Master/Backup).
|
||||
⚠️ **Haken (nicht Last):** DHCP/Firewall/NAT/DNS müssen auf **BEIDEN** APs **identisch** gepflegt sein, sonst „Gateway up, Internet tot".
|
||||
@@ -691,7 +691,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp10"></a>
|
||||
|
||||
### TP10 — Multi-Site VPN ▸ ✅ KERN DURCH (2026-06-27) — beide WG live auf ap1-Hub (`docs/tp10-vpn-migration.md`)
|
||||
### TP10 · Gitea #49 — Multi-Site VPN — beide WG live auf ap1-Hub (`docs/tp10-vpn-migration.md`)
|
||||
> **Details/Cutover/Gotchas/Eckdaten → `docs/tp10-vpn-migration.md` (Single Source of Truth).** Research: `docs/research/vpn-comparison.md`.
|
||||
- **✅ KERN DURCH (2026-06-27) + EDGE-CUTOVER (2026-07-01):** beide AVM-Tunnel → **2× WireGuard mit Hub auf ap1** migriert. Live: `peer fm`
|
||||
(`10.101.0.0/24`, bidirektional, myfritz-Endpoint) **und** `peer dw` (`10.95.10.0/24`, CGNAT-Dial-in) mit frischem
|
||||
@@ -711,7 +711,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp14"></a>
|
||||
|
||||
### TP14 — Host/Container-IP-Migration VLAN1→VLAN20 (Docker-Cutover NAS+pve) ▸ ✅ DURCH (2026-07-13; live re-verifiziert 2026-08-08) — `docs/nas-vlan20/RUNBOOK.md`, Handoff `docs/nas-vlan20/handoff/`
|
||||
### TP14 · Gitea #50 — Host/Container-IP-Migration VLAN1→VLAN20 (Docker-Cutover NAS+pve) — live re-verifiziert 2026-08-08) — `docs/nas-vlan20/RUNBOOK.md`, Handoff `docs/nas-vlan20/handoff/`
|
||||
- ✅ **ABGESCHLOSSEN — Migration komplett** (Live-Check 2026-08-08 vom core: NAS `.20.10`, pve `.20.100`, Docker-LXC `.20.126`, platform-pg `.20.20`, Nautobot `.20.30` alle 0% Loss). Alle Hosts + Container auf VLAN20. **TP14.4** (CF-Access-Token-Rotation) = kleiner, nicht-blockierender Standalone-Follow-up (CF/TP11-Umfeld); **TP14.5** war nie ein eigener Change (nur ein Reihenfolge-Gate) → erfüllt, TP5 damit entblockt.
|
||||
- ✅ **NAS (DS923, ep14) migriert (2026-07-09/10):** Docker von `default_external` (macvlan .41) auf **ein** `vlan20`-Macvlan (10.40.20.0/24, gw .1, parent `ovs_eth0`); DSM-Cutover `.20.10`; Portainer-Endpoint `.20.10:9001`. **Root-Cause der Dauerfehler** = Portainer **Config-Only-Macvlan-Falle** (`Driver:null`, kein Container-Attach) + Macvlan-Parent-Exklusivität (`default_external` muss weg für `vlan20`) + `default_internal` (172.18) weg. Container laufen auf `.20.x`.
|
||||
- ✅ **CF-Ingress v116 (2026-07-10):** 6 NAS-Origins .41→.20 (SSoT `docs/cf-tunnel-mapping.md` §8); `vw` 200 via Tunnel = pve→VLAN20-Routing steht (502 direkt nach Ingress-PUT = transient).
|
||||
@@ -723,7 +723,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp14-1"></a>
|
||||
|
||||
### TP14.1 — Session A: NAS fertigstellen ▸ ✅ DURCH (2026-07-10); Omada-Inform/sw2 VERTAGT
|
||||
### TP14.1 · Gitea #51 — Session A: NAS fertigstellen — Omada-Inform/sw2 VERTAGT
|
||||
- ✅ **Alle ep14-Container auf vlan20 redeployed + verifiziert running/.20.x** (via Portainer-Stack-Redeploy, Env preserved, Volumes intakt): oc-stack(112 → prometheus `.151`/node-exporter `.154`/grafana `.109`), default(72 → hms-mqtt `.124`), nginx(101 → dashboard-web `.148`), oc-central(160 → qdrant `.159`), oc-charlie(158 → `.162`+cf), oc-johnny2(150 → `.161`+cf), gitea(111 → `.157`, DB `.20.23:3306` erreichbar ✓), drawio(107 → `.139`, intern; CF-CNAME war eh gelöscht).
|
||||
- ✅ **pve-mcp NEU** als Stack (id 202, vlan20-only `.20.173`), verbunden mit Proxmox `.41.100` (v9.0.11) — ⚠️ **StreamableHTTP am Root-Pfad `/`, NICHT `/sse`** (mcp-pve v0.4.8, `MCP_TRANSPORT=http`). `~/.claude.json` `mcpServers.pve-mcp` NEU angelegt `{type:http, url:http://10.40.20.173:3000/}` (war vorher gar nicht drin) → wirkt nach Claude-Code-Restart.
|
||||
- ✅ **Tunnel-Smoke** (CF-Ingress v116 zeigte schon auf `.20`): gitea 200, grafana 302, vw 200 — Origins existieren jetzt real.
|
||||
@@ -734,7 +734,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp14-2"></a>
|
||||
|
||||
### TP14.2 — Session B: pve-Docker-LXC (.126) → VLAN20 ▸ ✅ DURCH (2026-07-10) (ipvlan)
|
||||
### TP14.2 · Gitea #52 — Session B: pve-Docker-LXC (.126) → VLAN20
|
||||
- ✅ ep2-Container auf `vlan20`: **omada-mcp `.20.176`** (OMADA_BASE_URL→`.20.175`), **adguard_bf1 `.20.16`**, **adguard_fm2 `.20.17`** — alle running/reachable (health 200, adguard 302). Transf. Files `docs/nas-vlan20/stacks/{195-adguard,200-omada-mcp}.yml`.
|
||||
- ✅ LXC 400 (`docker`) net0 → `tag=20, ip=10.40.20.126/24, gw=10.40.20.1` (⚠️ **Retag brauchte Christoph** — Token `claude@pam!claude` hat kein `VM.Config.Network`; UI-Edit, dann Reboot via API mit `VM.PowerMgmt`). Portainer wandert auf `https://10.40.20.126:9443`.
|
||||
- 🐞 **Gotcha: in-Container-Iface heißt jetzt `veth20`, NICHT `eth0`** (UI setzte Name analog net1=veth16) → Docker `vlan20`=ipvlan **`parent=veth20`** (nicht eth0 wie im Runbook). cloudflared(host)/portainer(bridge) unberührt.
|
||||
@@ -744,13 +744,13 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp14-2a"></a>
|
||||
|
||||
### TP14.2a — pve-mcp Single-Session-Fix + VLAN20-Host-DNS ▸ ✅ (2026-07-10)
|
||||
### TP14.2a · Gitea #53 — pve-mcp Single-Session-Fix + VLAN20-Host-DNS
|
||||
- **pve-mcp „Failed to connect":** Ursache = **mcp-pve v0.4.8** kann im HTTP-Transport nur **eine** MCP-Session (ein globaler `StreamableHTTPServerTransport`, `sessionIdGenerator` gesetzt) → erster Client nach Boot belegt den Slot, jeder weitere Init (neue Claude-Code-Session, `claude mcp list`-Healthcheck, Reconnect) = `400 "Server already initialized"`. **omada-mcp NICHT betroffen** (frische Session-ID pro Init → Per-Session-Transport). **Fix = Upgrade auf 0.6.1** (Per-Session-Map, `serverFactory()` je Session, gleiche Env-Vars = Drop-in); Stack 202 neu deployed, Container `.20.173` = 0.6.1, `Connected to Proxmox VE 9.0.11`, `tools/list` liefert `pve_*`, **Claude Code ✔ Connected**. 3× init hintereinander = 3× 200 mit verschiedenen session-ids (verifiziert).
|
||||
- **Kollateral-Fund — VLAN20-Host-DNS kaputt (beide Docker-Hosts):** nach dem VLAN20-Umzug zeigten **NAS** *und* **pve-LXC** `/etc/resolv.conf` noch auf totes `.41.254` → `docker pull` ghcr.io scheitert (`EAI_AGAIN` / 5s-Resolver-Timeout; Egress zu ghcr-IP `140.82.x:443` = OK 31 ms, also **nur Resolver tot**, nicht Egress). Fixes: **LXC** `.20.126` → `pct set 400 --nameserver 10.40.20.1` (Christoph). **NAS** → DSM-„Allgemein"-DNS war `.20.1`, ABER die **Netzwerkschnittstelle zog DNS per DHCP** und überschrieb `resolv.conf`; Fix = Schnittstelle „DNS manuell" `10.40.20.1` (Christoph) → NAS pullt wieder direkt. **Merkregel Synology:** GUI-DNS ≠ was `dockerd` liest (Quelle `/etc/resolv.conf`, per DHCP überschreibbar). **Workaround solange NAS-DNS tot:** `docker save`(LXC, hat DNS) → **gzip** (191-MB-tar reißt am Portainer-Agent-Socket-Proxy „context canceled"; ~70 MB gz geht) → Portainer `POST /endpoints/14/docker/images/load` → Stack-Redeploy `pullImage:false`. Gotcha: laufende Container frieren den `127.0.0.11`-Upstream zum Erstellzeitpunkt ein (Recreate nötig; für pve-mcp egal — Proxmox per IP `.41.100`). Memory `ref_pve_mcp_singlesession_and_vlan20_dns`.
|
||||
|
||||
<a id="tp14-3"></a>
|
||||
|
||||
### TP14.3 — Session C: Dormante Stacks vlan20-tauglich + Referenz-Sweep ▸ ✅ Referenz-Sweep durch (2026-07-16); dormante Stacks weiter bewusst nicht deployt
|
||||
### TP14.3 · Gitea #54 — Session C: Dormante Stacks vlan20-tauglich + Referenz-Sweep — dormante Stacks weiter bewusst nicht deployt
|
||||
- ✅ **Dormante Stacks bereitgestellt (2026-07-11):** `transform.py` auf core(43)/openclaw(92)/openclaw2(97)/oc20260307(119)/openspeedtest(74)/speedtest_tracker(80)/technikscheiss(42) → **`.new.yml` + `.orig.yml`** in `docs/nas-vlan20/stacks/` (gitignored). **Nicht deployt** (User: „im Bedarfsfall später", Container-Zukunft ungewiss). 42/43 waren `default_internal` → jetzt vlan20-only (DHCP-.20.x). ⚠️ **Deploy-Caveats:** externe Refs bewusst NICHT umgeschrieben (`DB_HOST=.41.122` [pre-existing tote openclaw-DB, in 80+119], `OLLAMA_BASE_URL=.41.129`, `REDIS_URL=.41.111` in 119); **Kollision** `43-core` will `.20.23` = gitea-DB-IP (nicht gleichzeitig deploybar).
|
||||
- ✅ **Referenz-Sweep `.41→.20` (2026-07-16, im Rahmen der TP19-Backup-Vorbereitung live gefunden + gefixt):** ap1 `/ip dns static` hatte noch `nas.bf.lan→.41.10` und `docker.bf.lan→.41.126` **stale** — korrigiert auf `.20.10`/`.20.126` (MikroMCP `manage_dns_entry`, dry-run+apply). Zusätzlich per User-Entscheid **Omada-Controller + omada-mcp komplett gelöscht** (overkill für 1 Switch auf der Abschussliste) → DNS-Einträge `omada.bf.lan`/`omada-mcp.bf.lan` entfernt statt migriert. `fritzbox.bf.lan` (totes Gerät, physisch weg seit 2026-07-01) ebenfalls entfernt. `docs/ip-plan.md` + CLAUDE.md nachgezogen.
|
||||
- ✅ **ERLEDIGT/GEGENSTANDSLOS (live geprüft 2026-08-16):** ~~`~/.claude.json` (omada-mcp-Eintrag verwaist), CF-Ingress-Rest (`omada`/`omada-mcp`-Hostnames, ungeprüft)~~
|
||||
@@ -760,7 +760,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp14-5"></a>
|
||||
|
||||
### TP14.5 — Session E: Freigabe-Gate → TP5-Firewall ▸ ✅ ERFÜLLT (2026-08-08) — kein eigener Change
|
||||
### TP14.5 · Gitea #55 — Session E: Freigabe-Gate → TP5-Firewall — kein eigener Change
|
||||
- Gate „TP14.1–14.3 durch (alle Origins/Connectoren in VLAN20)" ist erfüllt → **TP5 (Deny-by-default) ist entblockt.** Reines Reihenfolge-Gate, kein eigener Change.
|
||||
|
||||
<a id="tp15"></a>
|
||||
@@ -771,7 +771,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
> auf tote Adressen — `backup-ap1.py` allerdings auf eine **lebende falsche** (`10.40.10.1` ist die
|
||||
> VLAN10-SVI des Core, nicht ap1) und hätte still das falsche Gerät gesichert.
|
||||
>
|
||||
### TP15 — HW-Refresh: Switching + Router ▸ ✅ **ABGESCHLOSSEN (2026-08-08)** — Bring-up beider CRS326 + Branch-Tausch (2026-07-23) **und** Core-Tausch/L3-Umzug (2026-08-08, Durchführung s. TP21.1) sind durch — `docs/hw-refresh-requirements.md`, Memory `project_mikrotik_commit_nautobot_gc`
|
||||
### TP15 · Gitea #56 — HW-Refresh: Switching + Router — Bring-up beider CRS326 + Branch-Tausch (2026-07-23) **und** Core-Tausch/L3-Umzug (2026-08-08, Durchführung s. TP21.1) sind durch — `docs/hw-refresh-requirements.md`, Memory `project_mikrotik_commit_nautobot_gc`
|
||||
> 🔌 **Scope-Änderung 2026-08-16 (User-Entscheid): die DC-USV ist aus diesem TP herausgelöst und heißt jetzt **TP24**.** Sie war der letzte offene Rest hier, hat mit Switching/Routing sachlich nichts zu tun und trägt eigene Entscheidungen (Elektrik, Batterie, Standort). TP15 ist damit inhaltlich zu.
|
||||
> *Vorherige Header-Fassung (Stand 2026-08-05, überholt): „🟢 CRS326-Bring-up + Branch-Tausch DURCH (2026-07-23); Core-Tausch/L3-Umzug **vorbereitet, Cutover-Config materialisiert (2026-08-05)**, Cutover = nächstes Wartungsfenster."*
|
||||
- ✅ **BRING-UP BEIDER CRS326 + BRANCH-TAUSCH gegen sw2 — DURCH (2026-07-23, Claude via REST unter Governance-Ausnahme #2).** Ablauf/As-built:
|
||||
@@ -825,7 +825,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp16-1"></a>
|
||||
|
||||
### TP16.1 — Private Access via native Cloudflare Mesh (WireGuard) auf `crs326-core` ▸ ✅ **ABGESCHLOSSEN (2026-08-17)** — `docs/tp16.1-warp-mesh-native-crs326.md`
|
||||
### TP16.1 · Gitea #57 — Private Access via native Cloudflare Mesh (WireGuard) auf `crs326-core` — `docs/tp16.1-warp-mesh-native-crs326.md`
|
||||
- ✅ **Kernergebnis: ICMP ist repariert.** Privater Zugang unterwegs läuft über **natives WireGuard auf `crs326-core`** statt cloudflared-QUIC — **0 % Ping-Loss auf alle BF-VLANs, vorher 100 %**. Genau das Symptom aus dem Incident 2026-07-16, das dieses TP ausgelöst hat. Öffentliche FQDNs unberührt auf dem 3-Tunnel-HA (TP16). Compliance **68/68**.
|
||||
- ✅ **§4.0 erledigt 2026-08-17: Mesh-Node angelegt.** `bf-core-mesh` = **`d1da7c8a-2736-4cbb-8af1-32db5393fb9c`**, Register-Token in `mcp/cloudflare/.env` (`CF_MESH_REGISTER_TOKEN`, gitignored). ➡️ **Die seit 2026-07-17 offene Free-Plan-Frage ist beantwortet: der Free-ZT-Plan erlaubt Cloudflare Mesh — der LXC-Fallback ist vom Tisch.**
|
||||
- 🔑 **Der Weg dahin war ein Token-Problem, kein Plan-Problem (kostete 2 Anläufe).** Der alte User-Token hatte **zwei** fehlende Permissions (§4.0 *und* §4.1 — `devices/settings` war schon lesend `403`). Ersetzt durch einen **account-owned** Token (`9984078812bc…`, ⏰ **gültig bis 2027-01-09**). Zwei Fallen, beide sehen aus wie „Token kaputt": (1) Account-Tokens verifizieren an `/accounts/{id}/tokens/verify` — am alten `/user/tokens/verify` melden sie `1000 "Invalid API Token"`, **während alle echten Endpoints 200 liefern**; (2) Dashboard-Fehler `"Account tag in access policy must match tag in request uri"` = eine **Zone**-Permission (`DNS`) steckt in der Policy-Zeile mit **Account**-Ressourcen → braucht eine eigene Zeile. Verifiziertes Soll-Set + Permission-IDs in `docs/tp16.1-…md` §4.0. **Merke: Dashboard sagt „Edit", API sagt „Write".**
|
||||
@@ -865,7 +865,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp17"></a>
|
||||
|
||||
### TP17 — Shelly-Übersiedelung VLAN1 → VLAN30 (IOT) + `shelly-mcp` ▸ ✅ **KOMPLETT (User-Bestätigt 2026-08-13): alle Shellys auf VLAN30** — Geräte-PW *(war TP17.2, seit 2026-08-24 **TP30** Posten #3)* — `mcp/shelly/`, Runbook `docs/tp17-shelly-go-runbook.md`
|
||||
### TP17 · Gitea #58 — Shelly-Übersiedelung VLAN1 → VLAN30 (IOT) + `shelly-mcp` — Geräte-PW *(war TP17.2, seit 2026-08-24 **TP30** Posten #3)* — `mcp/shelly/`, Runbook `docs/tp17-shelly-go-runbook.md`
|
||||
- ✅ **Abschluss 2026-08-13 (User-Bestätigt):** auch die zuletzt offenen saisonalen Shellys (s1/s2/s3/s12) sind inzwischen umgeklemmt — **alle Shellys auf `dirtyvader-iot`/VLAN30**, kein VLAN1-Shelly-Rest mehr. Migration-Teil von TP17 damit vollständig abgeschlossen.
|
||||
- ✅ **GO durchgezogen 2026-07-13 (16 Shellys VLAN1→VLAN30, 0 Fehler):** Pilot s26 + Welle A (s4–s9) + Welle B (s10/11/13/15/17/19/20/21/25) → alle auf `dirtyvader-iot`/`10.40.30.<octet>` verifiziert (SSID+IP+rssi). Mit den 6 Vorab-Migrierten (s14/16/18/22/23/24) = **22/26 auf VLAN30**; VLAN1-Sweep `.180-250` = **0 Shellys**. Restliche 4 saisonal ausgesteckte (s1/s2/s3/s12) inzwischen ebenfalls migriert (s.o.).
|
||||
- 🔧 **Anker-Verfahren (User-Idee, statt sta1-Backup):** je Gerät **vor** dem sta-Write die geräteeigene **AP-Funktion** aktiviert (`WiFi.SetConfig ap.enable` — Firmware verlangt WPA2, kein offenes AP → PSK=IOT-PSK, live/kein Reboot) = Notanker, falls VLAN30-Join scheitert (Gerät bleibt über `Shelly*-<mac>`-AP erreichbar, **kein physischer Reset**). Nach Verify alle 22 AP-Anker wieder `deanchor`t. Runner: `mcp/shelly/migrate.py` (`migrate`/`deanchor`/`auth`/`table`, Dry-Run default, stoppt bei erstem Fehler, reused `discover.py`).
|
||||
@@ -912,7 +912,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp19"></a>
|
||||
|
||||
### TP19 — cudy-Teardown + VLAN1-Client-Retirement ▸ ✅ **GESCHLOSSEN (2026-08-18)** — `docs/tp19-vlan1-cudy-teardown-runbook.md`
|
||||
### TP19 · Gitea #59 — cudy-Teardown + VLAN1-Client-Retirement — `docs/tp19-vlan1-cudy-teardown-runbook.md`
|
||||
- ✅ **Abschluss-Sweep 2026-08-18, alles live gegengeprueft (reine Reads):**
|
||||
- **VLAN1 ist leer:** `/ip arp` auf `bridge` = **0 Eintraege, 0 reachable**. Nicht Restverkehr,
|
||||
sondern gar nichts. Der Dual-DHCP-Race aus `project_vlan1_dhcp_incident` hat damit endgueltig
|
||||
@@ -1009,7 +1009,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
- **Teardown-Sequenz (angepasst an den Live-Stand):** VLAN1-Client-Sweep ist **schon fast leer** (nur sw1-Mgmt + pve-Interim reachable) → `defconf`/pool-v1 ist **bereits disabled** → cudy-Abbau **entfällt** (cudy1 umgenutzt statt abgebaut, cudy2 tot) → ✅ **SwitchBot + Twinkly erledigt (2026-07-16)** → **verbleibt:** Media-Check (B1.3), pve-`.41.100` abräumen (B1.5), Interim-Krücken bewerten (ap2 `frame-types=admit-only-vlan-tagged`, `st-main rrm/wnm`), Inventar/`ip-plan`/DNS `.41→Ziel` final.
|
||||
- Abh.: **TP14 ✅** (Hosts raus aus VLAN1), **TP17 ✅** (Shellys raus). Verwandt: `project_vlan1_dhcp_incident` (cudy-Dual-DHCP-Leak), TP5 (Deny-by-default danach sauberer). SSoT hier + `docs/tp19-vlan1-cudy-teardown-runbook.md`. Folge: **TP19.1**.
|
||||
|
||||
#### TP19.1 — VLAN99-MGMT-Cutover (sw1/sw2/ap2-Mgmt VLAN1 → VLAN99) ▸ ✅ ERLEDIGT (2026-08-14 nachgezogen) — alle lebenden Geräte auf VLAN99, die beiden Rest-Punkte gegenstandslos
|
||||
#### TP19.1 · Gitea #60 — VLAN99-MGMT-Cutover (sw1/sw2/ap2-Mgmt VLAN1 → VLAN99) — alle lebenden Geräte auf VLAN99, die beiden Rest-Punkte gegenstandslos
|
||||
- ✅ **Abschluss-Nachtrag 2026-08-14 (Status-Korrektur, kein neuer Change):** der Header stand noch auf „ap2 vertagt, sw1 offen" (Stand 2026-07-16) — beides ist durch spätere TPs eingelöst bzw. gegenstandslos geworden, ohne dass es hier nachgetragen wurde. Ist-Stand: **core `.99.1` · branch `.99.2` · ap1 `.99.11` · ap2 `.99.12`** — jedes lebende Netzgerät hat sein Mgmt auf VLAN99. **sw1/sw2 existieren nicht mehr** (physisch ausgebaut, in Nautobot per TP22 Schritt 5 auf *Decommissioned*). Damit ist TP19.1 vollständig; offen bleibt nur der VLAN1-**Client**-Teil, und der gehört zu TP19 (Hauptteil), nicht hierher.
|
||||
- **Scope:** die einzigen Dinge, die TP19s Hauptteil bewusst in VLAN1 belässt — sw1 (`.41.11`), sw2, ap2-Mgmt (`.41.2`) — auf VLAN 99 (MGMT, `10.40.99.0/24`) umziehen. Erst danach ist VLAN1 wirklich **komplett** weg, nicht nur als Client-Netz.
|
||||
- **User-Entscheid (2026-07-16):** kein eigenständiges TP-Nummer — bewusst als **Unterpunkt von TP19** geführt („VLAN1 killen"), nicht als TP22 o.ä.
|
||||
@@ -1024,7 +1024,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp20"></a>
|
||||
|
||||
### TP20 — Platform-Datenbank (Postgres Precious-Tier + MariaDB Tier-2) ▸ ✅ **Plattform live (2026-07-16)** — Nautobot-DB angelegt, vw-Migration (TP20.1) offen — Memory `project_mikrotik_commit_nautobot_gc`
|
||||
### TP20 · Gitea #61 — Platform-Datenbank (Postgres Precious-Tier + MariaDB Tier-2) — Nautobot-DB angelegt, vw-Migration (TP20.1) offen — Memory `project_mikrotik_commit_nautobot_gc`
|
||||
- ✅ **Platform-Postgres live (2026-07-16):** LXC 105 auf pve, `platform-pg.bf.lan` / `10.40.20.20`, Ubuntu 24.04 (native PG16-Paket, kein PGDG-Repo nötig — bewusste Abweichung von der sonstigen Debian/community-scripts-Konvention der übrigen pve-LXCs, aus PG16-Verfügbarkeitsgründen). Cluster mit `--locale en_US.UTF-8 -e UTF8` neu initialisiert (Erstinstallation lief in `C`/`SQL_ASCII`, für Nautobot ungeeignet, korrigiert). `wal_level=replica` gesetzt; **`archive_mode` bewusst noch NICHT an** — ohne pgBackRest/Garage-S3 (TP18) zum Prunen würde archivierte WAL unbegrenzt wachsen und die kleine 8GB-Disk füllen; wird nachgezogen sobald TP18 steht. Rolle+DB `nautobot` angelegt, `pg_hba.conf` erlaubt `scram-sha-256` aus `10.40.20.0/24`. End-to-End-Verbindungstest (Netzwerk, nicht nur localhost) erfolgreich. Creds in `postgres/.secrets` (gitignored, `chmod 600`).
|
||||
- **Auslöser:** Mehrere Dienste brauchen zentrale DB (Nautobot-SoT [TP21], Vaultwarden, HA-Recorder). Grundsatzentscheid statt Nautobot-Insellösung — „wir skalieren schneller als wir schauen können" (User).
|
||||
- ⚠️ **Abh.-Korrektur (User 2026-07-16): TP18 (Garage-S3) ist KEINE Vorbedingung mehr — „hat mit dem Netz nichts zu tun", transitiv aus der TP21-Kette entfernt.** pgBackRest→Garage-S3 (s.u.) wird **nachgezogen sobald Garage existiert**, blockiert aber nicht mehr den Start. `wal_level=replica`/`archive_mode` können mit einem Platzhalter/lokalen Archive-Ziel hochgezogen werden, produktives Off-Site-PITR kommt später.
|
||||
@@ -1048,7 +1048,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp21"></a>
|
||||
|
||||
### TP21 — Nautobot Golden Config (config-as-code Control-Plane) ▸ 🟢 **Plattform + Datenmodell + Templates live**
|
||||
### TP21 · Gitea #62 — Nautobot Golden Config (config-as-code Control-Plane)
|
||||
- 🔴 **BETRIEBSBEFUND 2026-08-18: der Stack hat sich zweimal in einer Nacht selbst umgebracht — Ursache
|
||||
war der Image-Healthcheck, nicht Celery.** `nautobot-worker` und `-scheduler` erben aus dem Image
|
||||
einen `HEALTHCHECK`, der alle **10 s** `nautobot-server health_check` startet — einen kompletten
|
||||
@@ -1112,7 +1112,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp21-1"></a>
|
||||
|
||||
### TP21.1 — Core-Cutover-Recovery (ap1 → crs326-core als L3-Router) ▸ ✅ NETZ WIEDER LIVE (2026-08-08); ~~Aufräum-Todos offen~~ → **alle fünf erledigt, letzter live gegengeprüft 2026-08-23** (s. Nachtrag am Ende)
|
||||
### TP21.1 · Gitea #63 — Core-Cutover-Recovery (ap1 → crs326-core als L3-Router) — ~~Aufräum-Todos offen~~ → **alle fünf erledigt, letzter live gegengeprüft 2026-08-23** (s. Nachtrag am Ende)
|
||||
> **Kern-Erkenntnis (wichtig gegen Doku-Verwirrung):** **`crs326-core` IST jetzt der produktive L3-Router.** Der Core-Cutover (TP15) wurde faktisch vollzogen — ap1 wurde plattgemacht/getrennt, core hat Routing/DHCP/DNS/NAT/WG-Hub übernommen. core-Mgmt = **`10.40.99.1`** (vlan99-SVI) bzw. same-subnet-Fallback **`10.40.10.1`** (RouterOS-Version 7.19.5 identifiziert das Gerät zweifelsfrei als CRS326, nicht als hAP/ap1). Die CLAUDE.md-Zeile „core grundkonfiguriert, NICHT produktiv" ist damit **überholt**.
|
||||
- **Verlauf:** Ausgangssymptom war ein L3-Ausfall-Eindruck (kein DHCP, „kein Routing nach .20.x"). Ursache = **unvollständiger Cutover**: core hatte L3-SVIs + Firewall, aber es fehlten DHCP-Server, WAN-Egress, WG-Hub und der DNS-Resolver-Upstream. ap1 (bisher alleiniges L3-Gerät) war bereits Werksreset + getrennt.
|
||||
- ✅ **DHCP wiederhergestellt** aus letztem ap1-Backup (`routeros/ap1-pre-core-cutover-20260806-073616.rsc`): 7 Server (`dhcp-v10…v99`) + 8 Networks + **54 statische Reservierungen** + Option `dns 1.1.1.1`. Reproduzierbar in `routeros/tp21-core-dhcp-from-ap1.rsc`. Legacy VLAN1 (pool-v1/defconf) + tote omada-inform-Option bewusst weggelassen.
|
||||
@@ -1153,7 +1153,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp22"></a>
|
||||
|
||||
### TP22 — Device-Adoption + Golden-Config Compliance-Push (RouterOS-Fleet) ▸ ✅ **DURCH (2026-08-13)**, Compliance-Backlog **abgearbeitet 2026-08-16 → 68/68, 0 Drifts** — alle 5 Schritte erledigt (Schritt 4 per Entscheid „keine Secret-Injection"); aus TP21 ausgelagert 2026-08-08
|
||||
### TP22 · Gitea #64 — Device-Adoption + Golden-Config Compliance-Push (RouterOS-Fleet) — Compliance-Backlog **abgearbeitet 2026-08-16 → 68/68, 0 Drifts** — alle 5 Schritte erledigt (Schritt 4 per Entscheid „keine Secret-Injection"); aus TP21 ausgelagert 2026-08-08
|
||||
- **Ziel:** die 4 Live-Geräte (crs326-core, crs326-branch, ap1, ap2) real unter **Nautobot Golden Config** nehmen — Backup → Compliance/Drift → intended → **Push (`enable_deploy`)**. Damit greift der Governance-Entscheid „Config exklusiv über Nautobot" operativ. Macht die aktuellen `routeros/.secrets/*.rsc`-Handoffs mittelfristig überflüssig.
|
||||
- **Stand aus TP21:** Plattform + Datenmodell + Git-Template + intended-config für core stehen; ap1/ap2 als reine APs zurückgeschrieben (`nautobot/ingest-ap-rebuild.py`, 2026-08-08). `enable_plan`/`enable_deploy` in `nautobot_config.py` noch **bewusst aus** (pull/read-only).
|
||||
- ✅ **Schritt 0 DURCH (2026-08-13) — Backup-Scrubbing + Repo-Neuanlage.** Vorgezogen aus Schritt 4, weil ohne Scrubbing jedes weitere Backup Secrets geleakt hätte.
|
||||
@@ -1234,7 +1234,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp26"></a>
|
||||
|
||||
### TP26 — `/ip firewall filter` unter Drift-Kontrolle ▸ ✅ **DURCH (2026-08-17)**
|
||||
### TP26 · Gitea #65 — `/ip firewall filter` unter Drift-Kontrolle
|
||||
> **Nachgetragen 2026-08-18.** TP26 existierte bis dahin nur als zwei Commits und eine `.rsc` — ohne
|
||||
> Abschnitt in dieser Datei. Genau die Lücke, die eine frische Session nicht finden kann.
|
||||
|
||||
@@ -1255,7 +1255,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp27"></a>
|
||||
|
||||
### TP27 — RouterBOOT-Firmware auf 7.24 nachziehen ▸ ✅ **DURCH (2026-08-17/18)**
|
||||
### TP27 · Gitea #66 — RouterBOOT-Firmware auf 7.24 nachziehen
|
||||
> **Nachgetragen 2026-08-18.** Auch TP27 hatte keinen Abschnitt — die Arbeit steckt in Christophs Commit
|
||||
> `b93514a` plus `routeros/tp27-routerboot-firmware-724.rsc` und
|
||||
> `docs/routerboot-firmware-klickanleitung.md`.
|
||||
@@ -1274,7 +1274,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp28"></a>
|
||||
|
||||
### TP28 — WLAN über CAPsMAN auf `crs326-core` ▸ ↩️ **WIEDER GEÖFFNET 2026-08-30**
|
||||
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core`
|
||||
|
||||
> Der Volltext steht seit dem 2026-08-30 wieder in
|
||||
> [`teilprojekte.md` → TP28](teilprojekte.md#tp28), weil mit **ap3** (cAP ax) ein dritter
|
||||
@@ -1284,7 +1284,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
|
||||
<a id="tp-r"></a>
|
||||
|
||||
### TP-R — Router-Capabilities-Sweep ▸ FERTIG (`docs/research/routeros-capabilities.md`)
|
||||
### TP-R · Gitea #67 — Router-Capabilities-Sweep — `docs/research/routeros-capabilities.md`)
|
||||
- **Leitsatz: nativ vor Container, NAS vor Router** (128MB-Flash-Limit).
|
||||
- **Sofort nativ (~0 RAM):** RoMON · Netwatch · Scheduler + Auto-Backup/Mail · SNMP→externes Monitoring · **mDNS-Repeater** · spectral-scan · **802.11r/k/v (Fast-Roaming statt Mesh)** *(die Sweep-Fassung nannte hier CAPsMAN — das ist seit 2026-08-08 abgeschafft; 11r/k/v läuft standalone weiter, s. TP3/TP3.3)* · Back-to-Home/WireGuard.
|
||||
- **Auf NAS:** FreeRADIUS(+LDAP) · NPM · icinga/Grafana · CF-Tunnel.
|
||||
@@ -1305,7 +1305,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
> Handoff-Punkte aufgelöst, Gitea #17 closed. Die 394-Zeilen-Herleitung (Messchronik A–G) steht
|
||||
> weiter unten unter [TP25 — Langfassung](#tp25-lang).
|
||||
|
||||
### TP25 — WLAN-Stabilisierung ▸ ✅ **FERTIG: Platzierung final (ap1 Sideboard · ap2 UG · ap3 OG), alle Handoff-Punkte aufgelöst (2026-09-15, [Steering-Handoff](handoff-20260915-tp25-steering-threshold-und-terrasse.md))** — ap2-UNTERPUNKT ✅ WIDERLEGT 2026-09-14 (In-situ, [Handoff](handoff-20260914-tp25-ap2-insitu-terrassse.md)): ap2 sendet auf 2 m mit −49…−51 dBm, stabil, 0 Roams — Hardware sauber, kein Tausch begründet. Terrasse = 5-GHz-Zellkante (−76…−81 vs. 2,4 GHz −65…−73), Thrash nur in der Band-Überlappungszone −70…−77. Hebel „Access-List-Band-Boden" in der Machbarkeitsprüfung GESCHEITERT (kein `band`-Property, cap-wifiN-Rejoin-Falle) — s. Block unten** — **FUND E ✅ GESCHLOSSEN 2026-09-02: die Abschlussmessung ist ruhig (4 reauth in 8,6 h, 0 Ausfälle, Verlauf 218→40→4) ⇒ `7.24.1` (TP27) war die Ursache, nicht `ft-over-ds`. Hebel 1 widerlegt+zurückgebaut, Hebel 2–4 entfallen, kein Geräte-Write** ([Handoff](handoff-20260902-tp25-fund-e-messung.md)) · Kern erledigt: 🟢 **(2026-08-22) Dead Spot Terrasse repariert** (43 % → 9 % Verlust, 20,4 s → 1,0 s). **Fund F ✅ aufgelöst (08-24, geräteseitig — kein Netzfehler)**, **5-GHz-Umfeldscan ✅ (08-24)**, Kanalplan für AP 3 ✅ gerechnet. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
### TP25 · Gitea #17 — WLAN-Stabilisierung — ap2-UNTERPUNKT ✅ WIDERLEGT 2026-09-14 (In-situ, [Handoff](handoff-20260914-tp25-ap2-insitu-terrassse.md)): ap2 sendet auf 2 m mit −49…−51 dBm, stabil, 0 Roams — Hardware sauber, kein Tausch begründet. Terrasse = 5-GHz-Zellkante (−76…−81 vs. 2,4 GHz −65…−73), Thrash nur in der Band-Überlappungszone −70…−77. Hebel „Access-List-Band-Boden" in der Machbarkeitsprüfung GESCHEITERT (kein `band`-Property, cap-wifiN-Rejoin-Falle) — s. Block unten** — **FUND E ✅ GESCHLOSSEN 2026-09-02: die Abschlussmessung ist ruhig (4 reauth in 8,6 h, 0 Ausfälle, Verlauf 218→40→4) ⇒ `7.24.1` (TP27) war die Ursache, nicht `ft-over-ds`. Hebel 1 widerlegt+zurückgebaut, Hebel 2–4 entfallen, kein Geräte-Write** ([Handoff](handoff-20260902-tp25-fund-e-messung.md)) · Kern erledigt: 🟢 **(2026-08-22) Dead Spot Terrasse repariert** (43 % → 9 % Verlust, 20,4 s → 1,0 s). **Fund F ✅ aufgelöst (08-24, geräteseitig — kein Netzfehler)**, **5-GHz-Umfeldscan ✅ (08-24)**, Kanalplan für AP 3 ✅ gerechnet. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
> 📚 **Kondensiert am 2026-08-23 (Doku-Session, Punkt F).** Dieser Abschnitt war mit 394 Zeilen
|
||||
> 18 % der Datei. Die **Langfassung steht vollständig und unverändert** im Archiv:
|
||||
> [`teilprojekte-archiv.md` → TP25 (Langfassung)](teilprojekte-archiv.md#tp25-lang) — Messchronik (A)–(G),
|
||||
@@ -1827,7 +1827,7 @@ Handoff: [`handoff-20260901-tp25-ap2-verdacht.md`](handoff-20260901-tp25-ap2-ver
|
||||
> Erklärungen — zweimal stand hier eine plausible Ursache, die die nächste Messung gekippt hat
|
||||
> (ETSI-Band C bei Fund B; „ap1 ans Sideboard" bei (F)/(G)). Wer TP25 fortsetzt, muss sehen können,
|
||||
> welche Wege schon abgelaufen sind.
|
||||
### TP25 — WLAN-Stabilisierung ▸ 🟢 **KERN ERLEDIGT (2026-08-22): Dead Spot Terrasse repariert** (43 % → 9 % Verlust, 20,4 s → 1,0 s). Offen nur noch **Fund F** (5:05-Takt IoT) und die Entscheidung **5 GHz auf 20 MHz**. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
### TP25 · Gitea #17 — WLAN-Stabilisierung — 43 % → 9 % Verlust, 20,4 s → 1,0 s). Offen nur noch **Fund F** (5:05-Takt IoT) und die Entscheidung **5 GHz auf 20 MHz**. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
> 🆕 **Messung 2026-08-20/21: [`tp25-wlan-roaming-messung-20260820.md`](tp25-wlan-roaming-messung-20260820.md)**
|
||||
> (Nebenprodukt der TP6-Messreihen, Core-Sampler im 2-s-Takt über 2,5 h, teils mit laufendem Videocall).
|
||||
> Drei Befunde:
|
||||
@@ -2223,7 +2223,7 @@ Handoff: [`handoff-20260901-tp25-ap2-verdacht.md`](handoff-20260901-tp25-ap2-ver
|
||||
|
||||
<a id="tp39"></a>
|
||||
|
||||
### TP39 — LXC-Hygiene auf pve: Resolver-Altlasten, `networking.service`, DB-Reverse-Lookup ▸ ✅ **ABGESCHLOSSEN (2026-09-01)**
|
||||
### TP39 · Gitea #68 — LXC-Hygiene auf pve: Resolver-Altlasten, `networking.service`, DB-Reverse-Lookup
|
||||
|
||||
**Auslöser:** ein 10-Sekunden-Hänger auf `gitea`, gefunden am Rand des TP16.3-§5-Flips. Er hatte mit
|
||||
dem Flip nichts zu tun, war aber nur deshalb sichtbar, weil zum ersten Mal jemand systematisch
|
||||
@@ -2302,7 +2302,7 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein.
|
||||
|
||||
---
|
||||
|
||||
### TP34 — Caddyfile via Nautobot/GC (generische Reverse-Proxy-Schnittstelle) ▸ ❌ **VERWORFEN (2026-09-08)**
|
||||
### TP34 · Gitea #24 — Caddyfile via Nautobot/GC (generische Reverse-Proxy-Schnittstelle)
|
||||
> ➡️ **Fortsetzung 2026-09-22: `TP34.2 — Interne DNS-Namen als Daten`** (Gitea #73, Prosa in
|
||||
> `docs/teilprojekte.md` → `### TP34.2`). Dort lebt der *Daten → gerenderte Config*-Gedanke weiter;
|
||||
> **verworfen bleibt nur das Caddyfile-Rendering** (dieser Abschnitt hier).
|
||||
@@ -2324,7 +2324,7 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein.
|
||||
---
|
||||
|
||||
<a id="tp44"></a>
|
||||
### TP44 — Cloudflare-Estate als Dokumentations-SSoT in Nautobot ▸ ✅ **DURCH (2026-09-10): Etappe 1 + Etappe 2 (Teil A IPAM-Prefixe, Teil B Live-Sync als täglicher Nautobot-Job)**
|
||||
### TP44 · Gitea #33 — Cloudflare-Estate als Dokumentations-SSoT in Nautobot
|
||||
> **Entscheid (User, 2026-09-02):** die volle CF-Estate (Tunnel + WARP-Connector + VPC-Service +
|
||||
> Hyperdrive + Workers + alle Access-Apps) als strukturierte, abfragbare SSoT in Nautobot abbilden —
|
||||
> **etappenweise: manuell jetzt, Sync später.** Nautobot kann CF nicht steuern → „SSoT" heißt
|
||||
@@ -2368,7 +2368,7 @@ gemessen hat. Beim Beheben kam eine zweite, unabhängige Altlast zum Vorschein.
|
||||
- **Beziehung zu TP37:** TP44 hat **TP37 Punkt 3** (CF-Connectoren) vorweggenommen — dieselbe native-Modell-
|
||||
Linie, die TP37 P1+2 (Substrat/Dienste) fortsetzt.
|
||||
|
||||
### TP41 — CF-Access-Reparatur + Zero-Trust-Konsolidierung ▸ ✅ **ABGESCHLOSSEN (2026-09-10)** — Auth-Kern seit 2026-09-01 komplett; **Gelis WARP-Client am 2026-09-10 via Android erfolgreich eingerichtet** (letzter Blocker weg, User-Bestätigung). Optionale Restpunkte (T6 Rate-Limit, geli-CGNAT-Policy-Cleanup) bewusst nicht gezogen; Keystore-Rotation läuft unter TP30 #7.
|
||||
### TP41 · Gitea #30 — CF-Access-Reparatur + Zero-Trust-Konsolidierung — Auth-Kern seit 2026-09-01 komplett; **Gelis WARP-Client am 2026-09-10 via Android erfolgreich eingerichtet** (letzter Blocker weg, User-Bestätigung). Optionale Restpunkte (T6 Rate-Limit, geli-CGNAT-Policy-Cleanup) bewusst nicht gezogen; Keystore-Rotation läuft unter TP30 #7.
|
||||
|
||||
**Auslöser:** CF-Access zwang Christoph **und Geli** täglich zum OTP-Login (soll: 30 Tage); GitHub/Google
|
||||
„funktionieren nicht". Root-Causes: Team-Domain-Rename `bf4`→`emsenhuber` (Provider-Callback veraltet),
|
||||
@@ -2426,14 +2426,14 @@ der Egress ohnehin Cloudflare (nicht diese IP) → der IP-Include wäre dann üb
|
||||
**Gitea-Least-Privilege** = eigener künftiger TP (jedes Projekt repo-scoped Login, Admin nur Claude/Christoph).
|
||||
- Bezug **TP11** (Monitoring): eine Plattenfüllstand-Warnung hätte das Wochen früher gezeigt.
|
||||
|
||||
### TP43 — dw-Standort-DNS-Uplink (site-spezifische Overrides) ▸ ♻️ **REOPENED 2026-09-11 → Volltext zurück in [`teilprojekte.md`](teilprojekte.md) (Abschnitt TP43)**
|
||||
### TP43 · Gitea #32 — dw-Standort-DNS-Uplink (site-spezifische Overrides)
|
||||
|
||||
Kurz zwischen 2026-09-11 verworfen und am selben Tag reopened: die 420-Prämisse war gegenstandslos
|
||||
(public CF-Worker, via WARP/TP41 gelöst), aber die **interne** BF-Namensauflösung über WG am dw blieb
|
||||
dabei offen (`portainer.bf.emsenhuber.net` am dw nicht erreichbar). Korrigierter Scope + verworfene
|
||||
420-Historie stehen jetzt aktiv in `teilprojekte.md`. Gitea-Issue #32 = `status:todo` · `thema:firewall-dns`.
|
||||
|
||||
### TP42 — Namens-Vereinheitlichung: ein interner Suffix bf.emsenhuber.net ▸ ✅ **DURCH (2026-09-02)** — ein interner Suffix `bf.emsenhuber.net`, `.bf.lan` raus, `.16` (adguard_bf1) abgebaut, Compliance 140/140. Offen nur der an **TP37** gekoppelte Nautobot-Doku-Teil.
|
||||
### TP42 · Gitea #31 — Namens-Vereinheitlichung: ein interner Suffix bf.emsenhuber.net — ein interner Suffix `bf.emsenhuber.net`, `.bf.lan` raus, `.16` (adguard_bf1) abgebaut, Compliance 140/140. Offen nur der an **TP37** gekoppelte Nautobot-Doku-Teil.
|
||||
|
||||
**Auslöser (2026-09-01, TP41-Randbefund):** live gemessen liefern die realen Client-Resolver
|
||||
`10.40.20.36`/`.37` `*.emsenhuber.net → 10.40.20.40` (Caddy) — korrekt. Daneben existiert aber ein
|
||||
|
||||
@@ -69,28 +69,28 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
>
|
||||
> 📊 **Index/Statustabelle → [Gitea-Board](https://gitea.emsenhuber.net/admin/bf-infra/issues)** (siehe Kopf dieser Datei). Hier unten folgt nur noch die per-TP-Prosa.
|
||||
|
||||
### TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt
|
||||
### TP5.1 · Gitea #1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall)
|
||||
- **Kontext (2026-07-08/09):** Airfryer „airschreier" (Philips/Versuni, ESP, `10.40.30.180`) bekam per DHCP-Option 6 `dns 1.1.1.1` als Override, weil das OTA-Update über den ap1-DoH-Gateway-Pfad nicht durchging (DoH-Latenz beim primitiven ESP-Stack — **kein** Content-Block, via Gateway-Logs bewiesen, s. `memory/ref_esp_ota_doh_not_block`). Nebenwirkung: public **1.1.1.1 = anonymer Consumer-Resolver ≠ accountgebundener Gateway-DoH** (`px35ynlol3.cloudflare-gateway.com`) → **DNS-Sicht auf das Gerät weg**, Gerät umgeht zudem die Filterung.
|
||||
- **(a) DNS-Redirect statt Geräte-Override** (der dauerhafte Fix): dst-nat „UDP/53 (+TCP/53) von Low-Trust-Src → auf einen *plain* Resolver umbiegen" gibt **Logging zurück UND** funktionierendes OTA (kein langsamer DoH-Pfad fürs Gerät). Redirect-Ziel-Optionen: (i) ap1-Resolver mit *nicht*-DoH-Upstream für dieses Src-Set, (ii) direkt public 1.1.1.1 (dann nur Flow-Logging), (iii) eigener plain-Resolver. Sauberer als „Gerät verschwindet auf 1.1.1.1". Verortung: Teil des UNTRUSTED-Internet-only-Pinnings (TP5-„Offen"); Entscheidung v50-DNS-Policy (gefiltert vs. plain) hängt dran.
|
||||
- **(b) Live-Torch als Ad-hoc-Observability:** DNS ist bei direktem 1.1.1.1 blind, **Flows nicht** (NATen über ap1). `torch` auf `vlan30`/`vlan50` gefiltert auf die Geräte-IP zeigt Ziel-IPs live (Versuni → AWS `eu-west-1` IoT erkennbar). Voraussetzung: Gerät aktiv. Merkregel: Airfryer nur online wenn er kocht → Capture ans Einschalten koppeln.
|
||||
- **Abh.:** UNTRUSTED-Move des Airfryers (Kandidat, s. VLAN50) + TP5-Deny-by-default. Kein Blocker.
|
||||
|
||||
### TP8 — Identity & Access-Control ▸ research-gated
|
||||
### TP8 · Gitea #2 — Identity & Access-Control
|
||||
- **RADIUS = FreeRADIUS auf der NAS** (✏️ User-Manager v5 kann **KEIN LDAP** → openldap nur via FreeRADIUS anbindbar).
|
||||
- **EAP-TLS (Zert) je Gerät + dynamische VLAN-Zuweisung** (RADIUS-Attribut `Tunnel-Private-Group-ID`). **Einfachste Heim-Alternative:** pro VLAN eine SSID mit **WPA3-PSK** (kein RADIUS) — Abwägung Komfort vs. Admin-Aufwand.
|
||||
- Abh.: TP3. (Research erledigt, s. TP-R.)
|
||||
|
||||
### TP11 — Monitoring & Mgmt-Control-Plane ▸ research-gated
|
||||
### TP11 · Gitea #3 — Monitoring & Mgmt-Control-Plane
|
||||
- MikroMCP + omada-mcp + **SNMP/icinga-mikrotik**, RoMON, NTP, **E-Mail-Alerts**, Netwatch. → Teil von `docs/research/routeros-capabilities.md`.
|
||||
- **CF-Tunnel #1033 Track A ✅ live (2026-06-30):** Round-Robin-1033er über 3 asymmetrische Connectors behoben
|
||||
durch Reduktion auf pve-only Connector (NAS + macmini scheiterten an pve-lokalen/stalen Origins). SSoT:
|
||||
`docs/cf-tunnel-mapping.md`. **Track B/C läuft über TP14** (Ingress bereits v116 .41→.20 für NAS;
|
||||
pve-Connector→VLAN20 via TP14 Session B = #1033-Zielbild).
|
||||
|
||||
### TP12 — IPv6 (intern + extern, 3 Standorte) ▸ research-gated
|
||||
### TP12 · Gitea #4 — IPv6 (intern + extern, 3 Standorte)
|
||||
- Konzept für FM/BF/DW. → TP-R.
|
||||
|
||||
#### TP12.1 — IPv6 im LAN (ULA) + v6-Firewall ▸ 🟠 **KONKRET GEWORDEN (2026-08-22), Treiber: Matter/Thread**
|
||||
#### TP12.1 · Gitea #5 — IPv6 im LAN (ULA) + v6-Firewall
|
||||
> **Anlass:** der runde IKEA-Fühler **TIMMERFLOTTE** (Matter over Thread) ließ sich nicht anlernen —
|
||||
> „pairing failed" in der Companion-App. Ursache ist **nicht** die Firewall, sondern dass zwischen
|
||||
> VLAN10 und VLAN20 **überhaupt kein IPv6 geroutet wird**. Damit ist TP12 vom Konzept-TP zu einem
|
||||
@@ -168,7 +168,7 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
**v6-Firewall nachbauen → dann erst Adressen vergeben.** Gehört unter TP12 (Gesamtkonzept 3 Standorte),
|
||||
ist aber allein für BF ausführbar.
|
||||
|
||||
### TP13 — „Botschafts-WLANs" ▸ 🔜 **AUSFÜHRBAR (Runbook 2026-08-19)** — `docs/tp13-botschafts-wlan-runbook.md` · fun/low-prio
|
||||
### TP13 · Gitea #6 — „Botschafts-WLANs" — `docs/tp13-botschafts-wlan-runbook.md` · fun/low-prio
|
||||
> 📌 Am 2026-08-19 überarbeitet: der Technikteil beschrieb noch Standalone-APs (SSIDs entstehen seit
|
||||
> TP28 am **Manager**, also ein Deploy statt zwei), und der Entwurf „nur `ssid=`, kein Security" war ein
|
||||
> **Denkfehler** — eine SSID ohne Security *ist* ein offenes WLAN, also genau der Fall, den der
|
||||
@@ -185,7 +185,7 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
- ⚠️ **Recht vor Scharfschalten prüfen (User privat, AT):** offenes WLAN + Portal berührt Impressumspflicht/Störerhaftung — **reine Namens-SSIDs ohne offenen Zugang sind unkritisch** (kein Fremd-Datenverkehr); im Zweifel nur die Beacon-Variante.
|
||||
- **Abh.:** ~~TP3-Rebuild ✅ (Standalone-APs — SSID-Änderung = 1 Deploy/GC-Job)~~ → **TP28 ✅** (CAPsMAN auf dem Core) + **TP22 ✅** (GC-Deploy-Pipeline). SSID-Änderung = **ein** Deploy auf den Core; Direkt-Edit am Gerät ist durch den Governance-Entscheid ausgeschlossen.
|
||||
|
||||
### TP14.4 — Session D: CF-Access-Profil für Claude ▸ ✅ **IN TP41 T4 AUFGEGANGEN (2026-09-01)** — `docs/tp14.4-cf-access-token-runbook.md` (historisch)
|
||||
### TP14.4 · Gitea #7 — Session D: CF-Access-Profil für Claude — `docs/tp14.4-cf-access-token-runbook.md` (historisch)
|
||||
> ✅ **Erledigt über TP41 T4 (2026-09-01), nicht als eigenständiger `claude-mcp`-Token:** der
|
||||
> `claude-mcp`-Service-Token war die Basis (`t4a.py`), wurde **→ `zt-svc` umbenannt + rotiert** und über
|
||||
> Gruppe `zt-automation` konsolidiert. `mcp/cloudflare/.env` trägt jetzt **beide** Keys
|
||||
@@ -201,7 +201,7 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
erneut rotieren. Abnahme = ein Aufruf **mit** den Headern (antwortet) **und** einer **ohne** (403) —
|
||||
der Erfolgsfall allein beweist nichts, der Hostname könnte auf `bypass` stehen.
|
||||
|
||||
### TP16 — CF-Tunnel: Round-Robin killen + reziprokes HA ▸ ✅ **HA WIEDER VOLL (2026-08-24)** — Kern 2026-07-10 — `docs/cf-tunnel-mapping.md §10 + §15`, #1033
|
||||
### TP16 · Gitea #8 — CF-Tunnel: Round-Robin killen + reziprokes HA — Kern 2026-07-10 — `docs/cf-tunnel-mapping.md §10 + §15`, #1033
|
||||
- ✅ **GEFIXT 2026-08-24 — Ursache war ein `docker stop`, kein QUIC-Flap.** Die beiden macmini-Connectoren
|
||||
(`cloudflared-bfnas`, `cloudflared-bfpve`) standen auf `Exited (0)`, **beide `finishedAt` auf derselben
|
||||
Sekunde `2026-07-21T13:00:53`**, bei korrekt gesetztem `restart=unless-stopped` und `http2`. Fix =
|
||||
@@ -249,7 +249,7 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
- Abh.: TP14.1/14.2 ✅. Verwandt: **TP11** (CF-Tunnel-Track-B/C + Access), #1033. SSoT: `docs/cf-tunnel-mapping.md`. Memory `project_cf_tunnel_1033`.
|
||||
- ✅ **Incident 2026-07-16 (User unterwegs, WARP „spinnt", keine BF-IPs mehr) ▸ Public-FQDN-Teil gefixt:** macmini-Connectoren (`cloudflared-bfnas`/`-bfpve`) flappten live unter QUIC/UDP (Docker-Desktop-Bridge-NAT) → `bf-nas`/`bf-pve` von 2 auf 1 Connector degradiert (HA faktisch weg, nicht down). Fix: beide auf `TUNNEL_TRANSPORT_PROTOCOL=http2` umgestellt (rollend, 0 Downtime), wieder voll HA. Konvention: macmini-Connectoren künftig immer `http2`. **ICMP-Befund (getrennt, strukturell):** TCP über die WARP-Route ging überall, ICMP nicht (fm 36 %/bf 100 %/dw 100 % Loss) — cloudflared ist QUIC-Proxy, kein WireGuard. **Kurz als „bf-pve-Route wegen USV" notiert (Commit `1c1a676`) → REVIDIERT** (Begründung invertiert: bf-pve-Connectoren laufen auf NAS+macmini, nicht pve). Details: `docs/cf-tunnel-mapping.md §13`. **→ Richtungswechsel für Private Access = TP16.1.**
|
||||
|
||||
### TP16.2 — Härtung der öffentlich erreichbaren Dienste (bypass-Strang) ▸ 📋 KONZEPT (2026-08-14), Umsetzung offen
|
||||
### TP16.2 · Gitea #9 — Härtung der öffentlich erreichbaren Dienste (bypass-Strang) — Umsetzung offen
|
||||
- 🔴 **HARTER CONSTRAINT (User 2026-08-14): `vw` wird NICHT WARP-/Access-geschützt.** Gilt dauerhaft, nicht „vorerst". **Begründung (technisch belastbar, nicht Bequemlichkeit):** die Bitwarden-Clients (Browser-Extension, Mobile, Desktop) können den **interaktiven Access-Login nicht durchführen** — dasselbe Muster, das die HA-Companion-App auf `400` laufen lässt. Ein Passwortmanager hinter einem Client, den man im Notfall (fremdes Gerät, Neuinstallation, Handyverlust) nicht installieren kann, ist ein **Aussperr-Risiko gegen den eigenen Schlüsselbund** — und damit gefährlicher als das, wovor die Maßnahme schützen soll. **Die frühere TP16-Schritt-5-Absicht „vw von bypass auf geschützt heben" ist damit gestrichen.**
|
||||
- **Ziel stattdessen: Schutz erhöhen, ohne Clients zu brechen** — gilt für **alle** bypass-Dienste (`vw`, `hass`, `gitea`).
|
||||
- ✅ **Schicht 0 — bereits vorhanden, nicht unterschätzen:** keine offenen Ports, **alles ausschließlich über CF-Tunnel** (3-Tunnel-HA, TP16), TLS terminiert an der Edge, DDoS-Schutz. Der Origin ist nicht direkt erreichbar. Das ist bereits mehr als bei den meisten Selfhostern.
|
||||
@@ -263,7 +263,7 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
|
||||
- **Reihenfolge:** (1) Client-IP-Weitergabe fixen (inkl. HA `trusted_proxies`) → (2) `/admin`-Pfade path-scoped schützen → (3) App-Limits + 2FA → (4) Edge-Rules → (5) CrowdSec/fail2ban mit CF-Bouncer.
|
||||
- **Abh.:** TP16 ✅ (Tunnel-HA). Verwandt: **TP20.1** (vw wandert auf Platform-Postgres — DB-HA ≠ Access, getrennt halten), **TP23** (dessen WARP-Managed-Network-Idee ist durch diesen Constraint **entlastet**: `vw` verlangt keine Device-Identity, also kollidiert „WARP zuhause aus" nicht mehr mit dem Access-Strang).
|
||||
|
||||
### TP16.3 — cloudflared-Reduktion: was der Mesh als Datenpfad kann (und was nicht) ▸ ✅ **ABGESCHLOSSEN 2026-09-01** — Flip (§5) + Abbau (§6) durch; öffentlich nur noch `bf-public` (+`fm`) — `docs/tp16.3-bf-public-ap-connector-runbook.md`
|
||||
### TP16.3 · Gitea #10 — cloudflared-Reduktion: was der Mesh als Datenpfad kann (und was nicht) — Flip (§5) + Abbau (§6) durch; öffentlich nur noch `bf-public` (+`fm`) — `docs/tp16.3-bf-public-ap-connector-runbook.md`
|
||||
|
||||
#### ✅ §6 Abbau — AUSGEFÜHRT 2026-09-01 (vom User vorgezogen, „es wird nichts mehr sein")
|
||||
|
||||
@@ -664,7 +664,7 @@ und Letzteres verlangt die **physische Bestätigung am Gerät** — ap1 Technik
|
||||
TP — siehe Quick-Index Zeile TP16.3. Bezug zu **TP35** Schicht 2: Reihenfolge ist TP16.3 → TP35.
|
||||
TP35 wartet mit Schicht 2, bis das Fronting steht.
|
||||
|
||||
### TP17.1 — Shelly Gen4 raus aus dem WLAN ▸ ❌ **VERWORFEN (2026-08-23) — Weg bewiesen, Ziel damit nicht erreichbar** — 📋 `docs/tp17.1-shelly-gen4-funkmigration-runbook.md`
|
||||
### TP17.1 · Gitea #11 — Shelly Gen4 raus aus dem WLAN — 📋 `docs/tp17.1-shelly-gen4-funkmigration-runbook.md`
|
||||
> ❌ **User-Entscheid 2026-08-23 nach dem Pilot: stoppen und zurückbauen.** Auslöser war Christophs
|
||||
> strukturelle Frage: *„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."*
|
||||
@@ -816,7 +816,7 @@ und Letzteres verlangt die **physische Bestätigung am Gerät** — ap1 Technik
|
||||
|
||||
</details>
|
||||
|
||||
### TP17.3 — Shelly-Regression nach der VLAN30-Migration ▸ ✅ **ERLEDIGT (2026-08-23, Folge-Session): beide Geräte repariert, Ursache `eco_mode` bewiesen** — offen nur noch der Flotten-Entscheid (gehört TP17.1) — aus TP17 herausgelöst, User-Meldung
|
||||
### TP17.3 · Gitea #12 — Shelly-Regression nach der VLAN30-Migration — offen nur noch der Flotten-Entscheid (gehört TP17.1) — aus TP17 herausgelöst, User-Meldung
|
||||
> **User-Meldung 2026-08-23:** „vor einiger zeit hast du an den shellys änderungen vorgenommen. das
|
||||
> hatte bei einigen einen bösen seiteneffekt: **lüfter-shelly musste ich doppelt drücken**. der übelste
|
||||
> ist jedoch der von **diele ug: seit deinen änderungen spinnt er herum und blinkt wie ein wilder.
|
||||
@@ -953,7 +953,7 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
4. Reboots der verbleibenden 13 `restart_required`-Geräte — **gefahrlos** (empirisch an `s26` belegt),
|
||||
deshalb kein eigener Termin, sondern Mitnahme bei TP17.1.
|
||||
|
||||
### TP18 — Souveräner Objektspeicher (Garage, Multi-Site, S3-Cold-Tier) ▸ 🔜 KONZEPT (2026-07-12)
|
||||
### TP18 · Gitea #13 — Souveräner Objektspeicher (Garage, Multi-Site, S3-Cold-Tier)
|
||||
- **Auslöser:** 9-TB-Syno-Backup-Volume **zu 2/3 voll**; reine Daten ~3 TB, Tendenz steigend, „schlagartiger" Bedarf nicht ausgeschlossen. „Wenn skalieren, dann jetzt Syno-Nachfolger mitdenken."
|
||||
- **Kriterien (User-priorisiert):** (1) **keine Fremd-Abhängigkeit / kein Cloud-Lock-in** (Cloud-Opex abschreckend); (2) **Multi-Site BF/FM/DW**; (3) **HA** (Standort-Verlust überlebbar); (4) **billig/teuer trennen** — Variante **„kalt = Objektspeicher, heiß = lokal"** genügt (kein Hot/Cold *innerhalb* des Stores nötig); (5) **horizontal + vertikal skalierbar**; (6) **S3-API als Branchenstandard**, den jedes Backup-Tool spricht.
|
||||
- **Entscheid Engine = Garage** (Deuxfleurs, Rust): einziger Kandidat, der **geo-verteilt über offenes Internet/WAN latenztolerant** ist (CRDT-Metadaten, eventually consistent) → passt aufs 3-Keller-Modell BF/FM/DW. **Ceph verworfen** (will Sub-ms-LAN, Single-Cluster-über-WAN = Anti-Pattern; zu schwer, ~1 GB RAM/TB). **MinIO** (AGPL + Console/Feature-Abbau 2025) und **SeaweedFS** (kann Hot/Cold + Erasure-Coding, aber komplexer, Multi-Site async) = **Fallback**, falls später feingranulares Tiering / EC-Effizienz bei zweistelligen TB dominant wird.
|
||||
@@ -970,14 +970,14 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
- **Offen (Modell scharfstellen):** realer Strompreis; ob **FM/DW eigene Nodes stellen** oder Christoph HW hinstellt; Backup-Tool-Wahl (restic vs Kopia); ob heißes Zeug künftig auf ZFS/pve statt Syno.
|
||||
- Abh.: **TP10** (WG-Multi-Site = Transport, Upload-BW-Constraint), **TP14** (Container-Hosts), **TP15** (Node-HW) / **TP24** (Stromversorgung), Muster von **TP16** (reziprokes Per-Host-HA). Kein Blocker für laufende TPs. SSoT dieser Session.
|
||||
|
||||
### TP20.1 — Vaultwarden → Platform-Postgres + Cross-Site-HA ▸ 🔜 KONZEPT (2026-07-14, ausgelagert aus TP20)
|
||||
### TP20.1 · Gitea #14 — Vaultwarden → Platform-Postgres + Cross-Site-HA — ausgelagert aus TP20)
|
||||
- **Ziel:** `vw` (`.20.127`, heute MariaDB) auf den Precious-Tier holen **und** das eigentliche User-Ziel erfüllen: **DB-Replikation über 2 Sites** (Standort-Verlust überlebbar).
|
||||
- **Phase 1 — Migration (single-site):** vw **MariaDB→Postgres** (Export → Import in Tier-1-DB `vaultwarden` → `DATABASE_URL` umstellen → verifizieren). Danach ist vw precious + im pgBackRest/PITR-Schirm von TP20. *(Alternative verworfen: vw auf MariaDB lassen + MariaDB-Repl — zugunsten EINER Replikations-/Backup-Mechanik im Precious-Tier.)*
|
||||
- **Phase 2 — Cross-Site-Standby:** `db-platform-standby`-LXC am 2. Standort → `pg_basebackup`/Streaming-Replication über **WG (TP10)** → **manuelles Promote-Runbook**. Repliziert den ganzen Tier-1-Cluster (vw = HA-Ziel, Nautobot bekommt Gratis-DR-Kopie). **Patroni + 3. Witness** nur, falls später Auto-Failover statt manuellem Promote gewünscht.
|
||||
- **Verwandt/Abgrenzung:** vw ist auch in **TP16** offen (CF-Access: `bypass`→WARP-geschützt) — **DB-HA ≠ Access**, getrennt behandeln. Reziprokes 2-Site-Muster analog **TP16**/**TP18**.
|
||||
- Abh.: **TP20** (Tier-1 Postgres muss stehen), **TP10** (WG-Transport für Phase-2), **TP18** (Backup-Schirm). Kein Blocker für TP21.
|
||||
|
||||
### TP23 — DNS-Policy & Self-Service-Ausnahmen ▸ ⏳ **STUFE 5 WIEDER OFFEN (Redesign 2026-09-12): Self-Service deckt die DAU-Requirements nicht ab → Stufe 6 bleibt dahinter gated**
|
||||
### TP23 · Gitea #15 — DNS-Policy & Self-Service-Ausnahmen
|
||||
> 🔴 **Redesign 2026-09-12 — Stufe 5 reopened.** Bei „Stufe 6 angehen" fiel auf: die 09-04-Stufe-5
|
||||
> (single-domain, temp-only 15m/1h/4h, **eine** Ausnahme gleichzeitig, **HA-Neustart bei neuer
|
||||
> Domain**, `allow-domain` global statt pro Person) deckt die Nutzer-Requirements **nicht** ab
|
||||
@@ -1074,7 +1074,7 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
- ⚠️ **802.1X löst die IoT-Identität NICHT:** Consumer-IoT (Shelly, Sonos) hat keinen 802.1X-Supplicant; der Standardweg ist **MAB** = wieder MAC-basiert → **kein Identitätsgewinn gegenüber der DHCP-Reservierung**. **TP8 bleibt richtig, aber als Sicherheitsthema** (dynamische VLAN-Zuweisung, kein MAC-Spoofing bei Managed-Geräten), nicht als DNS-Identitätsquelle.
|
||||
- **Abh.:** **TP21.1 TODO 1** (DoH auf core), **TP5** (Firewall/Bypass-Sperre — Reihenfolge s.o.), **TP16 Schritt 5** (Access-Kollision), **TP16.1** (falls WARP zuhause bleiben soll), **TP8** (nur Sicherheit). **Kein Blocker für TP5 → TP6**, aber TP5 darf die Bypass-Sperre nicht vorziehen.
|
||||
|
||||
### TP24 — Unterbrechungsfreie Stromversorgung (DC-USV, 48V-Bus) ▸ 🔜 KONZEPT — **aus TP15 herausgelöst (User-Entscheid 2026-08-16)** — `docs/hw-refresh-requirements.md §9`
|
||||
### TP24 · Gitea #16 — Unterbrechungsfreie Stromversorgung (DC-USV, 48V-Bus) — aus TP15 herausgelöst (User-Entscheid 2026-08-16)** — `docs/hw-refresh-requirements.md §9`
|
||||
- **Warum ein eigener TP:** Die USV hing bisher als Unterpunkt in TP15 (HW-Refresh Switching/Router) mit. TP15s Kernauftrag — CRS326-Beschaffung, Bring-up, Core-Tausch — ist seit 2026-08-08 **durch**; die Stromversorgung ist als einziger Rest übrig geblieben und hat mit Switching sachlich nichts zu tun. Sie ist ein **eigenständiges Infrastruktur-Thema mit eigener Einkaufs-, Verkabelungs- und Entscheidungslogik** (Elektrik, Batterie, Standort) und blockiert nichts auf dem kritischen Pfad. Darum eigener TP.
|
||||
- **Was es ist (Begriffsklärung):** eine **Pufferbatterie für die Netz-/Infrastruktur-Hardware** — **keine** klassische AC-USV mit 230-V-Steckdosen. Ein 48-V-Gleichspannungsbus versorgt die Geräte **direkt an ihrem DC-Eingang**; die Batterie hängt am selben Bus und übernimmt bei Netzausfall ohne Umschaltlücke. Der Umweg AC→DC→AC→DC (und damit dessen Dauerverlust) entfällt.
|
||||
- **Zielbild (Aufbau, unverändert gültig aus der TP15-Recherche):**
|
||||
@@ -1102,7 +1102,7 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
- **Abh.:** keine harten. **TP15 ✅** (die zu versorgende Hardware steht und hat DC-Eingänge). Verwandt: **TP18** (Garage-Nodes brauchen je Site eine Stromversorgung), **TP11** (USV-Zustand ins Monitoring). **Kein Blocker für TP5/TP6.**
|
||||
- **Historie:** war bis 2026-08-16 Unterpunkt von TP15 („🔋 DC-USV: MeanWell LRS-150-48 + DDR-120-48 + LiFePO4 20Ah (~€190), 48V-Bus; CRS326 DC-input passt"). Vollständige Recherche inkl. Schaltbild, Effizienzvergleich und Gerätetabelle: `docs/hw-refresh-requirements.md §9` (+ §10 D/E/F für die offenen Fragen).
|
||||
|
||||
### TP25 — WLAN-Stabilisierung ▸ ✅ **FERTIG (2026-09-15)** → [Archiv](teilprojekte-archiv.md#tp25)
|
||||
### TP25 · Gitea #17 — WLAN-Stabilisierung — → [Archiv](teilprojekte-archiv.md#tp25)
|
||||
|
||||
> **Abgeschlossen:** Platzierung final (ap1 Sideboard · ap2 Technik UG · ap3 Technik OG), Fund E
|
||||
> geschlossen (`7.24.1` war die Ursache, nicht `ft-over-ds`), alle vier Handoff-Punkte aufgelöst,
|
||||
@@ -1110,7 +1110,7 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
|
||||
<a id="tp28"></a>
|
||||
|
||||
### TP28 — WLAN über CAPsMAN auf `crs326-core` ▸ ✅ **ap3 LIVE (2026-08-30)** — wieder geöffnet und durchgezogen
|
||||
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core` — wieder geöffnet und durchgezogen
|
||||
|
||||
> **Der CAPsMAN-Kern ist und bleibt ✅ KOMPLETT (2026-08-18)** — der Abschnitt darunter ist
|
||||
> unverändert der Archivtext inkl. Post-Mortem. Wieder geöffnet wurde das TP am 2026-08-30,
|
||||
@@ -1325,7 +1325,7 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
|
||||
der Port ist untagged-Member von VLAN40 bei `pvid=1`.
|
||||
|
||||
|
||||
### TP29 — Anwesenheitserkennung fürs Energiesparen ▸ 💡 **IDEE, noch nicht auf dem kritischen Pfad** (angelegt 2026-08-21)
|
||||
### TP29 · Gitea #19 — Anwesenheitserkennung fürs Energiesparen
|
||||
> **User-Formulierung (2026-08-21):** „Personen im Haus orten mit BT (Shellys), WiFi und Radar. So
|
||||
> kommen wir dem Ziel der Energieersparnis ohne Komfortverlust groß näher."
|
||||
|
||||
@@ -1351,7 +1351,7 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
|
||||
dahin kommt. **Kein Blocker für irgendetwas.**
|
||||
|
||||
<a id="tp30"></a>
|
||||
### TP30 — Credentials: neu setzen & rotieren (Sammelbecken) ▸ 🔜 **ANGELEGT 2026-08-24, bewusst GEBÜNDELT gegen Projektende**
|
||||
### TP30 · Gitea #20 — Credentials: neu setzen & rotieren (Sammelbecken)
|
||||
> **User-Entscheid 2026-08-24:** „ich würde gerne daraus einen eigenen punkt machen. ich bin mir
|
||||
> sicher, dass es noch öfters passwörter zu rotieren geben wird. das machen wir dann alles gegen
|
||||
> projektende." — nachgeschärft am selben Tag: **„tp30 wird unser sammelbecken für credentials,
|
||||
@@ -1637,7 +1637,7 @@ unabhängig vom gebündelten Durchgang.**
|
||||
|
||||
|
||||
<a id="tp31"></a>
|
||||
### TP31 — Reverse Proxy für innen und außen; cloudflared von sechs Knoten auf einen ▸ ✅ **ABGESCHLOSSEN 2026-09-01**
|
||||
### TP31 · Gitea #21 — Reverse Proxy für innen und außen; cloudflared von sechs Knoten auf einen
|
||||
> ✅ **Durch — Schritt 5+6 sind über den Piloten [TP16.3](#tp163) miterledigt (2026-09-01):** `bf-public`
|
||||
> **healthy, 12 Connectoren** auf ap1/ap2/ap3; `vw`/`hass`/`n8n`/`gitea` laufen über CF → **Caddy**
|
||||
> (`https://10.40.20.40:443`), die drei Alttunnel `bf-nas`/`bf-pve`/`bf-mm` **gelöscht**. Damit steht das
|
||||
@@ -1887,7 +1887,7 @@ diesmal mit Datenverlust statt 530ern. **Automatisches Ingress-Failover erst, we
|
||||
- 📋 **Vollständiger Plan mit allen Abwägungen:** `~/.claude/plans/expressive-pondering-clarke.md`
|
||||
|
||||
<a id="tp32"></a>
|
||||
### TP32 — Nummern- und Adress-Systematik ▸ 🟢 **KONZEPT STEHT (2026-08-25), Startreihenfolge bereits repariert**
|
||||
### TP32 · Gitea #22 — Nummern- und Adress-Systematik
|
||||
> **User-Auftrag 2026-08-24:** „du/ich sollst in der lage sein, selbstständig nach einem vorgegebenen
|
||||
> system freie ips vergeben zu können … und diese systematik findet sich in anderen netzen künftig auch
|
||||
> wieder" · „ich meine 100 sollte künftig für die core services stehen."
|
||||
@@ -1998,7 +1998,7 @@ gewachsen, nicht geplant. Merkregel: **„Bestand bleibt, wo er ist" gilt nur, s
|
||||
wo er ist, ohne nachzusehen.**
|
||||
|
||||
|
||||
### TP33 — Sonos aus der Ferne bedienen (VPN/WARP) ▸ 💡 **IDEE, bewusst zurückgestellt** (angelegt 2026-08-25, User-Entscheid „später entscheiden")
|
||||
### TP33 · Gitea #23 — Sonos aus der Ferne bedienen (VPN/WARP) — angelegt 2026-08-25, User-Entscheid „später entscheiden")
|
||||
|
||||
- **Auslöser:** beim Sonos-Fall vom 08-25 kam die Frage auf, ob die Player auch **von unterwegs**
|
||||
auffindbar sein sollen. Antwort für jetzt: **nein, später entscheiden** — hier nur festgehalten,
|
||||
@@ -2017,7 +2017,7 @@ wo er ist, ohne nachzusehen.**
|
||||
|
||||
---
|
||||
|
||||
### TP35 — MCP-Schichtung global/projekt/user + 3-Schicht-CLAUDE.md + Announcement-Mechanismus + Backup-Guard ▸ ✅ **ABGESCHLOSSEN 2026-09-12** — 5/6 Schichten durch (MCP-Schichtung FQDN→IP, Credentials-`{env:}`-Flip angewandt+verifiziert, globale CLAUDE.md-Schicht, `/news`, Backup-Guard, `/projektstatus`-Skill). Schicht-3-**pro-Projekt**-Rollout laut Abgrenzung eigene Session je Projekt (kein Blocker). Einziger Rest = On-Network-mikromcp-Smoketest (off-site nicht machbar, VLAN99:80 timeout, non-blocking) → als Merkposten nach TP30. Gitea #25 closed/`status:done`.
|
||||
### TP35 · Gitea #25 — MCP-Schichtung global/projekt/user + 3-Schicht-CLAUDE.md + Announcement-Mechanismus + Backup-Guard — 5/6 Schichten durch (MCP-Schichtung FQDN→IP, Credentials-`{env:}`-Flip angewandt+verifiziert, globale CLAUDE.md-Schicht, `/news`, Backup-Guard, `/projektstatus`-Skill). Schicht-3-**pro-Projekt**-Rollout laut Abgrenzung eigene Session je Projekt (kein Blocker). Einziger Rest = On-Network-mikromcp-Smoketest (off-site nicht machbar, VLAN99:80 timeout, non-blocking) → als Merkposten nach TP30. Gitea #25 closed/`status:done`.
|
||||
- **Auslöser:** Bestandsaufnahme Session 2026-08-28 (Handoff `docs/handoff-20260828-pre-opencode-migration.md`). Erkenntnis: MCP-Configs sind heute über `~/.config/opencode/opencode.jsonc` UND `~/.claude.json` verstreut, ohne klares Schema.
|
||||
- **Befund (geprüft):** 11/12 Backups im Verzeichnis `~/dev/.pre-opencode-migration-backups/20260828-150335/` gzip-valid; `uwe-job-bewerbung.tar.gz` korrupt (Source unverändert da). Repos und globale Configs md5-/HEAD-identisch zum Vor-Session-Stand. Synology-Drive-Sync aktiv (Anwender, manuell).
|
||||
- **Scope:**
|
||||
@@ -2034,7 +2034,7 @@ wo er ist, ohne nachzusehen.**
|
||||
|
||||
---
|
||||
|
||||
### TP36 — Index/Status als SSoT nach Gitea (Steuerung aus der branchbaren Datei herauslösen) ▸ ⏳ **CUTOVER 2026-09-07** — Index/Status = Gitea-Issues, Prosa bleibt Datei
|
||||
### TP36 · Gitea #26 — Index/Status als SSoT nach Gitea (Steuerung aus der branchbaren Datei herauslösen) — Index/Status = Gitea-Issues, Prosa bleibt Datei
|
||||
- **Auslöser:** Skill-Run 2026-08-28 (`docs/handoff-20260828-session-a-projektstatus.md`) lieferte einen überholten „Nächster Schritt"-Output; **manuell gepflegte Doku mit Live-Daten verliert gegen die Realität, sobald sie lang wird.** Verschärft 2026-09-06: `docs/teilprojekte.md` wurde in **40/40** letzten Commits angefasst — jeder TP editierte Quick-Index **und** Ist-Stand-Block → **Merge-Konflikt-Magnet**, der Branch-pro-TP verhinderte (ein Parallel-Branch hatte so die TP37-Doppelvergabe verursacht).
|
||||
- 🔄 **Reframe 2026-09-06 (Christoph):** von „SSoT via **Nautobot**" auf „SSoT via **Gitea**". Grund: Index+Status sind **kuratierte Steuerung** (Reihenfolge, Marker, Abhängigkeiten), kein Geräte-Live-Zustand — die gehören auf ein **Issue-Board**, nicht in Custom Fields. **Nautobot bleibt nur für Live-Gerätedaten** relevant (Compliance-Zahl, RouterOS-Version …) → als optionaler Rest unten, entkoppelt von diesem TP.
|
||||
- **Modell (umgesetzt):** TP = **Gitea-Issue** in [`admin/bf-infra`](https://gitea.emsenhuber.net/admin/bf-infra/issues) · Status = Label `status:*` (todo/wip/paused/idea/concept/done/dropped) · Gruppierung = Label `thema:*`. Seeder `bin/gitea-tp-sync.py` (idempotent, Dry-Run default, `--commit` schreibt; Token aus `~/.hermes/.env`, **nie ausgeben**). Erstlauf: **68 Issues (25 open/43 closed) + 15 Labels**.
|
||||
@@ -2047,7 +2047,7 @@ wo er ist, ohne nachzusehen.**
|
||||
- **Verzahnt mit:** TP35 (SSoT + Konsolidierung), TP44 (native Nautobot-Modelle), `bf-infra/CLAUDE.md`-Lessons. Plan: `~/.claude/plans/geht-das-los-auch-reflective-lark.md`.
|
||||
|
||||
<a id="tp37"></a>
|
||||
### TP38 — Out-of-Band-Management: ein untagged-VLAN99-Port je Switch ▸ 🔜 **ANGELEGT 2026-08-31**
|
||||
### TP38 · Gitea #28 — Out-of-Band-Management: ein untagged-VLAN99-Port je Switch
|
||||
|
||||
*(Nummer 2026-08-31 von 37 auf 38 korrigiert und von Christoph bestätigt: TP37 war zeitgleich in
|
||||
einem zweiten Branch für „Nautobot als Netzwerkdoku" vergeben worden.)*
|
||||
@@ -2123,7 +2123,7 @@ folgenden Absicherungen dazu, und die Entscheidung darüber in die Umsetzungs-Se
|
||||
|
||||
---
|
||||
|
||||
### TP40 — Home-Assistant-Recorder-Retention: die 41-GB-`states`-Tabelle beschneiden ▸ 🔜 **ANGELEGT 2026-09-01 (User-Okay erteilt)**
|
||||
### TP40 · Gitea #29 — Home-Assistant-Recorder-Retention: die 41-GB-`states`-Tabelle beschneiden
|
||||
|
||||
**Auslöser:** LXC 302 (MariaDB) lief am 2026-09-01 auf **100 %** voll. Sofortmassnahme war `+30G`
|
||||
(TP39 Punkt 3), aber 59 der 65 GB sind die **`homeassistant`-Datenbank**, und die wächst weiter —
|
||||
@@ -2164,7 +2164,7 @@ Der HA-Recorder schreibt **unbegrenzt** — es ist keine `purge_keep_days`-Grenz
|
||||
- 🔴 **Kein eigenmächtiger Datenlöschvorgang** — `purge` wirft echte Historie weg; die
|
||||
Aufbewahrungsdauer ist eine Nutzerentscheidung. Diese Session hat **nur** vergrössert und gemessen.
|
||||
|
||||
### TP37 — Nautobot als durchgehende Netzwerkdoku: Hosts/Container/Dienste, erster Anwendungsfall CF-Connectoren ▸ 🔜 ANGELEGT 2026-08-30 (User-Okay erteilt)
|
||||
### TP37 · Gitea #27 — Nautobot als durchgehende Netzwerkdoku: Hosts/Container/Dienste, erster Anwendungsfall CF-Connectoren
|
||||
> **Christophs Formulierung (2026-08-30):** *„können wir das setup mit den cf-connectoren dann auch in
|
||||
> nautobot abbilden. quasi eine durchgehende netzwerkdoku stück für stück. muss eh fast sein, da du auf
|
||||
> den mikrotiks ja nur via gc/nautobot deployst."*
|
||||
@@ -2226,7 +2226,7 @@ Der HA-Recorder schreibt **unbegrenzt** — es ist keine `purge_keep_days`-Grenz
|
||||
---
|
||||
|
||||
<a id="tp342"></a>
|
||||
### TP34.2 — Interne DNS-Namen als Daten (FQDN aus Nautobot) ▸ 🔜 **ANGELEGT 2026-09-22** (Gitea #73) — **gemeinsame Arbeit**
|
||||
### TP34.2 · Gitea #73 — Interne DNS-Namen als Daten (FQDN aus Nautobot) — **gemeinsame Arbeit**
|
||||
> **Auslöser:** beim Schärfen von **TP45 Schicht C (C4)** am 2026-09-22 stand die Frage, was aus dem
|
||||
> verworfenen **TP34** wird. Christoph: *„C4 unter TP45 schärfen, TP34 wird gemeinsame Arbeit. wir beide!"*
|
||||
> → **eigener Träger im TP34-Nummernkreis**. Parent **#24 (TP34) bleibt `status:dropped`** — kein Reopen:
|
||||
@@ -2254,7 +2254,7 @@ Der HA-Recorder schreibt **unbegrenzt** — es ist keine `purge_keep_days`-Grenz
|
||||
|
||||
---
|
||||
|
||||
### TP45 — VLAN20/VLAN30 ins TP32-Schema + DNS/FQDN aus Nautobot ▸ 🔜 **ANGELEGT 2026-09-21** (Gitea #71)
|
||||
### TP45 · Gitea #71 — VLAN20/VLAN30 ins TP32-Schema + DNS/FQDN aus Nautobot
|
||||
> **Auslöser (Christoph, 2026-09-21):** *„schau dir mal die fqdns von `*.emsenhuber.net` an. viele
|
||||
> verschwunden. sowohl caddy als auch cloudflare."* — und, als der Befund stand:
|
||||
> *„wenn wir schon reverse proxy & co korrigieren müssen, wäre es vl jetzt ein guter zeitpunkt,
|
||||
@@ -2479,7 +2479,7 @@ NAT/mangle/WG sind Template-Literale, der Firewall-Filter kommt als ConfigContex
|
||||
die FQDNs, die hier Daten werden). **Abgrenzung:** VMID-Umnummerierung bleibt draußen; Token-**Rotation**
|
||||
läuft in TP30; Tunnel-GC-Namensgebung hier, die **SSoT/Recovery** in TP46.
|
||||
|
||||
### TP47 — Core egress via cf-mesh und WARP-Exit-Validierung ▸ **ANGELEGT 2026-09-27**
|
||||
### TP47 · Gitea #74 — Core egress via cf-mesh und WARP-Exit-Validierung
|
||||
> **Christoph:** Validierung des Core-Egress-Weges via Cloudflare Mesh. Ausgangsprüfung gegen neutralen Host
|
||||
> und Ziel `164.90.191.7` (DigitalOcean). Korrektur früherer Behauptung: **WARP war am Mac gar nicht
|
||||
> verbunden** — `warp=off`, `ip=90.146.33.177` (Heim-IP). Die zuvor gemessene `104.28.207.39` stammte aus
|
||||
@@ -2711,7 +2711,7 @@ TP22 · TP-R · **TP3.2** (08-17) · **TP5** (08-18) · **TP7.1** (08-18) · **T
|
||||
</details>
|
||||
|
||||
|
||||
### TP43 — dw-Standort: interne BF-DNS-Namen über WG auflösbar machen ▸ ✅ **UMGESETZT 2026-09-11** — dw-FritzBox: Upstream `.36`+`.37`, DNS-Rebind-Ausnahme `bf.emsenhuber.net`, Fallback-Haken „öffentliche NS bei Unreachbarkeit" **gesetzt** (Ideal-Variante: `.37`-Redundanz bleibt, BF-down → public). (verworfene 420-Historie am Ende dieses Abschnitts)
|
||||
### TP43 · Gitea #32 — dw-Standort: interne BF-DNS-Namen über WG auflösbar machen — dw-FritzBox: Upstream `.36`+`.37`, DNS-Rebind-Ausnahme `bf.emsenhuber.net`, Fallback-Haken „öffentliche NS bei Unreachbarkeit" **gesetzt** (Ideal-Variante: `.37`-Redundanz bleibt, BF-down → public). (verworfene 420-Historie am Ende dieses Abschnitts)
|
||||
|
||||
**Live-Auslöser (2026-09-11):** Christoph am dw-Standort, WG-Tunnel zu BF up, kann `portainer.bf.emsenhuber.net`
|
||||
nicht erreichen. Direkte IP `https://10.40.20.126:9443` geht ⇒ **reines DNS-, kein Routing-Problem.** Der
|
||||
|
||||
Reference in New Issue
Block a user