diff --git a/README.md b/README.md index 7ca4e9b..bef3d1a 100644 --- a/README.md +++ b/README.md @@ -1,131 +1,75 @@ -# Backlogs +# management -Zentrale Sammlung offener Punkte über alle Hosts und Dienste hinweg. Ein Eintrag -landet hier, wenn er bewusst nicht sofort erledigt wurde — damit er nicht in einer -Chat-Historie oder einem Kopf verschwindet. +Steuerungs-Repo für alles über den einzelnen Projekten: Visionen, Roadmap, +Entscheidungen (ADR), Arbeitsverfahren, AARs — und der Bestand der Hosts. +Framework: **Kanban-Rückgrat mit leichten Scrum-Elementen**, begründet und +im Detail festgelegt in [ADR-0005](decisions/0005-pm-framework-kanban.md). + +*(Bis 2026-08-01 hieß dieses Repo `Backlogs` und führte offene Punkte als +Markdown — die leben jetzt als Issues, siehe unten.)* ## Repo-Topologie (seit 2026-08-01) -**Kanonisch lebt dieses Repo auf `git.lab`** (`axion1337.chat/Backlogs`, nur im -Lab bzw. via VPN erreichbar — das Lab ist die Quelle der Wahrheit). -`rohana.axion1337.de/sorb/Backlogs` ist ein **Push-Mirror**: git.lab überschreibt -ihn bei jedem Push per Force. Deshalb **nie direkt zu Gitea pushen** — solche -Commits gehen beim nächsten Mirror-Lauf verloren (Rettung: `.patch` von Gitea -ziehen + `git am`, siehe [Kanonisierung](verfahren/deploy-uebergabe.md)). +**Kanonisch lebt dieses Repo auf `git.lab`** (`axion1337.chat/management`, nur im +Lab bzw. via VPN erreichbar — das Lab ist die Quelle der Wahrheit, +[ADR-0002](decisions/0002-issues-und-management-ins-lab.md)). +`rohana.axion1337.de/sorb/management` ist ein **Push-Mirror**: git.lab +überschreibt ihn bei jedem Push per Force. Deshalb **nie direkt zu Gitea +pushen** — solche Commits gehen beim nächsten Mirror-Lauf verloren (Rettung: +`.patch` von Gitea ziehen + `git am`, siehe +[Kanonisierung](verfahren/deploy-uebergabe.md)). -**Eine bewusste Ausnahme:** Die **Deploy-Übergabe-Issues** laufen weiter auf dem -Gitea-Mirror (dortiger Issue-Tracker), weil CFGMON und andere Hosts außerhalb -des Labs `git.lab` nicht erreichen — eine Übergabe muss aber von beiden Seiten -lesbar/kommentierbar sein. +**Eine befristete Ausnahme:** Die **Deploy-Übergabe-Issues** laufen auf dem +Gitea-Mirror-Tracker, weil CFGMON und andere Hosts außerhalb des Labs `git.lab` +noch nicht erreichen. Abgelöst wird das durch das Site-to-Site-VPN +([ADR-0004](decisions/0004-site-to-site-vpn-hetzner-lab.md), +[Issue #12](https://git.lab/axion1337.chat/management/-/issues/12)). -## Aufbau +## Struktur -``` -hosts/ ein File pro Host, benannt nach dem Hostnamen -shared/ Themen, die mehrere Hosts betreffen (DNS-Zone, Mail-Policy) -verfahren/ wiederkehrende Abläufe zwischen Personen und Hosts, plus AARs -``` - -Faustregel für die Einordnung: **Der Eintrag gehört dorthin, wo die Arbeit -stattfindet, nicht dorthin, wo das Symptom auftritt.** Ein down-Target in Prometheus -auf CFGMON, dessen Ursache ein blockierter Port auf dem Gameserver ist, gehört nach -`hosts/game.md` — mit Querverweis von CFGMON. - -## Hosts - -| Host | Adressen | Rolle | Backlog | -|---|---|---|---| -| **CFGMON** | `188.245.193.243`, `2a01:4f8:c17:93eb::1`, privat `10.0.0.3` | Monitoring-Stack, Gitea, Traefik | [hosts/cfgmon.md](hosts/cfgmon.md) | -| **game** | `157.90.155.206` (`game.axion1337.de`) | Pterodactyl / Gameserver | [hosts/game.md](hosts/game.md) | -| **matrix** | `49.13.132.245` (`matrix.axion1337.de`) | Matrix-Homeserver | [hosts/matrix.md](hosts/matrix.md) | -| **Overmind** | `10.58.73.17` (`git.lab`, **nur im Homelab auflösbar**) | GitLab + CI-Runner (Lab) | [hosts/overmind.md](hosts/overmind.md) | - -## Übergreifend - -| Thema | Backlog | +| Pfad | Artefakt | |---|---| -| DNS-Zone `axion1337.de` und Mail-Policy (IONOS) | [shared/zone-axion1337.md](shared/zone-axion1337.md) | +| `vision/` | Eine Vision je Linie: Community (axion1337.chat), Tool (ThreadNet), Plattform (Homelab) | +| `roadmap.md` | Linien, Meilenstein-Kandidaten, Kadenz — GitLab-Milestones halten den Stand | +| `decisions/` | ADRs — Pflicht bei Architekturentscheidungen **und dauerhaften Ausnahmen** | +| `verfahren/` | Wie wir arbeiten: [Deploy-Übergabe/DoD](verfahren/deploy-uebergabe.md), [AARs](verfahren/aar/), Werkzeuge | +| `hosts/`, `shared/` | **Bestand + Historie** je Host/Thema — offene Punkte sind Issues | -## Verfahren +## Das Backlog: Issues + Board -`hosts/` und `shared/` halten **offene Punkte**, [verfahren/](verfahren/) hält -**wie wir arbeiten** — Abläufe, die zwischen Personen oder über mehrere Hosts -hinweg gelten und deshalb an kein einzelnes Projekt-Repo gehören. +Alle offenen Punkte sind **Issues in diesem Projekt** (host-/infra-Scope, mit +`host:`-Labels; die alten IDs wie `CFGMON-01` bleiben im Titel) bzw. in den +Produkt-Projekten der Gruppe (Projekt-Scope). Das +**[Gruppen-Board](https://git.lab/groups/axion1337.chat/-/boards)** zeigt alles +über die `status:`-Labels: -| Verfahren | Inhalt | -|---|---| -| [Deploy-Übergabe](verfahren/deploy-uebergabe.md) | „einer baut, ein anderer rollt aus": Issue-Vorlage, Prüfliste, AAR | +| Label | Bedeutung | Policy | +|---|---|---| +| *(keins)* | Backlog | wird im Refinement gesichtet | +| `status:next` | als Nächstes gezogen | die einzige „Zusage" (Pull nach Kapazität) | +| `status:doing` | in Arbeit | **WIP-Limit: max. 2** | +| `status:wartet` | blockiert | nur mit benanntem Grund im Issue | -Zur Deploy-Übergabe gehört die Issue-Vorlage -`.gitea/ISSUE_TEMPLATE/deploy-uebergabe.yaml` — sie erscheint beim Anlegen eines -Issues in diesem Repo als **Deploy-Übergabe**. Die Übergabe-Issues laufen auf dem -**Gitea-Mirror** (siehe Repo-Topologie oben: CFGMON erreicht git.lab nicht), weil -das Verfahren repo-übergreifend gilt; der fachliche Inhalt bleibt im jeweiligen -Projekt-Repo. +Genau **ein** `status:`-Label pro Issue. Prioritäten weiter über `priority:*`. -## Konventionen +## Konventionen (unverändert gültig) -**IDs** sind pro Datei fortlaufend mit einem Präfix, das den Ort benennt: -`CFGMON-01`, `GAME-01`, `MATRIX-01`, `ZONE-01` — ein Präfix pro Datei in `hosts/` -bzw. `shared/`, keine Liste losgelöst vom tatsächlichen Datei-Bestand. IDs werden -**nicht wiederverwendet** — ein erledigter Punkt behält seine Nummer, damit -Querverweise und Commit-Messages dauerhaft stimmen. Auch wenn eine ganze Datei -entfällt (siehe `hosts/k3s.md`, entfernt 2026-07-30), wird ihr Präfix nicht für -etwas anderes wiederverwendet. +**IDs** (`CFGMON-01`, `ZONE-01`, …) werden **nie wiederverwendet**; sie leben in +Issue-Titeln weiter. Neue host-/infra-Punkte bekommen die nächste freie Nummer +ihres Präfixes als Issue. -Das Präfix für DNS-Themen ist bewusst `ZONE-` und nicht `DNS-`: `DNS-01` ist der -Name eines ACME-Challenge-Typs und käme in genau diesen Backlogs ständig als -Fachbegriff vor. +**Jeder Punkt braucht** eine Beschreibung des tatsächlichen Zustands und einen +konkreten nächsten Schritt; nicht selbst Verifiziertes wird als solches markiert +(woher stammt die Aussage?). **Zeitkritisches** bekommt ein Datum, nicht „bald". -**Status:** - -| Wert | Bedeutung | -|---|---| -| `offen` | noch nicht angefasst | -| `in Arbeit` | läuft gerade | -| `wartet auf …` | blockiert, mit Angabe worauf | -| `erledigt` | fertig, mit Datum — Eintrag bleibt stehen, siehe unten | -| `verworfen` | bewusst **nicht** umgesetzt, mit Datum und Begründung — nicht dasselbe wie `erledigt`: es ist nichts passiert, sondern es wurde entschieden, es zu lassen | - -Erledigte **und** verworfene Punkte werden **nicht gelöscht**, sondern nach unten -in den Abschnitt „Erledigt" verschoben (verworfene Punkte darin klar als solche -kennzeichnen). Der Grund: bei mehreren Hosts ist die Frage „haben wir das damals -eigentlich gemacht, und warum so — oder haben wir es bewusst gelassen?" häufiger -als die Frage „was ist noch offen". - -**Jeder Eintrag braucht** einen Status, eine Beschreibung des tatsächlichen -Zustands, und einen konkreten nächsten Schritt. Wenn eine Aussage nicht direkt -verifiziert ist (aus einer Konsole, einer Doku, einer Ableitung statt einer -Messung von dem betroffenen System selbst), wird kurz dazugeschrieben, woher sie -stammt — eine unbestätigte Vermutung, die wie ein Befund aussieht, kostet beim -nächsten Mal mehr Zeit als sie spart. - -**Zeitkritisches** bekommt ein Datum in der Statuszeile, nicht nur „bald". - -**Gegenstücke in anderen Host-Dateien** (z. B. ein Punkt, der von zwei Seiten -beschrieben wird, wie ein Push von `matrix` auf einen offenen Port bei `CFGMON`) -werden beim Schließen einer Seite **auf der anderen Seite mitaktualisiert**, nicht -nur verlinkt und stehen gelassen — sonst bleibt eine Seite unbemerkt veraltet. +**Erledigtes und Verworfenes** bleibt sichtbar: Issues werden geschlossen (nicht +gelöscht), `verworfen` wird im Schlusskommentar begründet — der Unterschied +zwischen „gemacht" und „bewusst gelassen" ist die häufigste Rückfrage. ## Verhältnis zu den Projekt-Repos -Dieses Repo hält die offenen Punkte. Die **Konfiguration** liegt weiter in den -jeweiligen Projekt-Repos, z. B. `sorb/threadnet-operating` für den -Monitoring-Stack auf CFGMON. Damit nichts doppelt geführt wird, verweisen die -Projekt-Repos hierher statt eigene Backlog-Dateien zu pflegen. - -## Verhältnis zu Projekt-Issues - -Die Projekt-Repos führen ihren eigenen Feature-/Fix-Backlog als Issues — **seit -2026-08-01 auf git.lab** (Migration per gitops#48, alte Gitea-Issues tragen einen -Verweis auf ihr GitLab-Gegenstück). Das bleibt dort, wird hier **nicht** -dupliziert. Faustregel für die Abgrenzung: - -- **Reiner Projekt-Scope** (eine Funktion in einem Repo, ein Bug in einem Service): - Issue im jeweiligen Projekt auf git.lab, kein Eintrag hier. -- **Host-/Infrastruktur-Scope** (betrifft einen Host direkt, oder eine Entscheidung - über mehrere Hosts/Repos hinweg, z. B. wo ein CI-Runner laufen soll): Eintrag - hier, mit Verweis auf betroffene Issues statt deren Inhalt zu wiederholen. -- **Beides zugleich** (ein Host-Thema hat ein konkretes Gegenstück als Issue, z. B. - ein fehlender Gitea-Runner blockiert CI in mehreren Repos): kurzer Eintrag hier - mit Link zum führenden Issue, statt den Issue-Inhalt hierher zu kopieren. +Konfiguration lebt in den Projekt-Repos (z. B. `threadnet-operating` für den +CFGMON-Stack), reine Projekt-Bugs/-Features in deren Issues auf git.lab. +Hierher gehört, was mehrere Hosts/Repos betrifft oder eine Entscheidung ist. +Ein Punkt, der von zwei Seiten beschrieben wird, verlinkt die andere Seite und +wird beim Schließen **dort mitaktualisiert**. diff --git a/decisions/0001-gitlab-kanonisch-push-mirror.md b/decisions/0001-gitlab-kanonisch-push-mirror.md new file mode 100644 index 0000000..249dd3a --- /dev/null +++ b/decisions/0001-gitlab-kanonisch-push-mirror.md @@ -0,0 +1,30 @@ +# 0001 — git.lab ist kanonisch, Gitea wird per Push-Mirror beliefert + +**Status:** akzeptiert · **Datum:** 2026-07-31 (rückwirkend dokumentiert 2026-08-01) · **Entscheider:** sorb + +## Kontext + +Build-CI brauchte mehr Ressourcen als CFGMON hat (webpack ~4 GB Heap auf einem +3,7-GiB-Host) und Gitea Actions zeigte mehrere echte Bugs. Das Homelab-GitLab +(`git.lab`, nur im Lab/VPN auflösbar) hat die Kapazität; Produktion (Flux) darf +aber nicht von der Lab-Verfügbarkeit abhängen. + +## Entscheidung + +`git.lab/axion1337.chat/*` ist die kanonische Heimat aller Repos; Gitea/rohana +wird über Push-Mirrors beliefert und bleibt Flux-Source, Container-Registry, +npm-Registry und Release-Download. **Direkte Pushes zu Gitea sind für gespiegelte +Repos verboten** — der Mirror überschreibt divergenten Stand per Force. + +## Konsequenzen + +- Bei Lab-Ausfall läuft Prod weiter; nur neue Builds pausieren. +- Commits, die doch auf Gitea landen (z. B. Cluster-CronJobs ohne Lab-Route), + brauchen das Kanonisierungs-Verfahren (`verfahren/deploy-uebergabe.md`): + `.patch` ziehen, `git am`, Push über git.lab. Zweimal live gebraucht. +- Arbeiten an den Repos setzt Lab-Zugang voraus (vor Ort oder VPN). + +## Verworfene Alternativen + +- CFGMON-CI aufrüsten (Swap/Limits): strukturell zu klein, verworfen mit CFGMON-10. +- git.lab öffentlich exponieren: Angriffsfläche fürs Lab, stattdessen VPN (→ 0004). diff --git a/decisions/0002-issues-und-management-ins-lab.md b/decisions/0002-issues-und-management-ins-lab.md new file mode 100644 index 0000000..0a9d2b3 --- /dev/null +++ b/decisions/0002-issues-und-management-ins-lab.md @@ -0,0 +1,30 @@ +# 0002 — Issues und Management-Repo ziehen ins Lab („das Lab ist die Quelle der Wahrheit") + +**Status:** akzeptiert · **Datum:** 2026-08-01 · **Entscheider:** sorb + +## Kontext + +Nach dem Code-Umzug (ADR-0001) lagen Projektmetadaten (Issues, Backlogs-Repo) +weiter auf Gitea — zwei Wahrheiten, driftgefährdet. Erreichbarkeits-Blocker +LABNET-01 (WireGuard-Roadwarrior) wurde am 2026-08-01 gelöst. + +## Entscheidung + +Alle Projekt-Issues leben auf git.lab (62 migriert, Gitea-Issues geschlossen mit +Verweis); das Backlogs-Repo zieht als `axion1337.chat/management` ins Lab +(Push-Mirror → `sorb/management` auf Gitea). Das Lab ist die Quelle der Wahrheit. + +## Konsequenzen + +- ⚠️ gitops-Issue-Nummern haben sich verschoben (Gitea zählte PRs mit); die + verbindliche Zuordnung steht im Migrations-Fußtext jedes GitLab-Issues. +- **Befristete Ausnahme:** Deploy-Übergabe-Issues laufen auf dem Gitea-Tracker + von `sorb/management`, weil CFGMON git.lab (noch) nicht erreicht. Diese + Ausnahme wird durch das Site-to-Site-VPN (ADR-0004) abgelöst — sie war der + Auslöser für die ADR-Pflicht bei Ausnahmen (siehe `decisions/README.md`). +- Releases bleiben auf Gitea (öffentlicher Download-Pfad), ebenso das gitops-Wiki. + +## Verworfene Alternativen + +- Issues auf Gitea belassen: dauerhafte Doppelführung, Roadmap/Boards unmöglich. +- git.lab exponieren statt VPN: siehe ADR-0001/0004. diff --git a/decisions/0003-cve-meldeweg-aggregiert.md b/decisions/0003-cve-meldeweg-aggregiert.md new file mode 100644 index 0000000..fbe504c --- /dev/null +++ b/decisions/0003-cve-meldeweg-aggregiert.md @@ -0,0 +1,30 @@ +# 0003 — CVE-Meldeweg: aggregierte Alarme, eigener Security-Raum, gleicher Bot + +**Status:** akzeptiert · **Datum:** 2026-08-01 · **Entscheider:** sorb + +## Kontext + +Der erste CVE-Alarmweg (eine Matrix-Nachricht pro CVE) flutete den Raum mit 126 +Nachrichten und musste stummgeschaltet werden (gitops#51, AAR in `verfahren/aar/`). +Gleichzeitig war entschieden (CFGMON-13), Release-/Security-Meldungen von +Betriebsalarmen zu trennen. + +## Entscheidung + +CVE-Alarme werden **pro Scan-Ziel aggregiert** (`count by (target, target_type, +host)`, CRITICAL sofort / HIGH nach 24 h) und in den **Security-Raum** +(`!YRJvcEbVXtRlUIkNld`) geroutet; Details liegen im Grafana-CVE-Dashboard, die +Nachricht verlinkt nur dorthin. Absender bleibt der bestehende `@alerts`-Bot +(ein Bot, Trennung über Räume). + +## Konsequenzen + +- Raum bleibt lesbar; Einzel-CVE-Detail wandert in Dashboard/Metriken + (`trivy_vuln_info{...}` mit CVE-ID, Severity, fixed_version, first_seen). +- Pflichtfelder je Meldung: CVE-ID, Mitigation/Fix-Version, Zeitstrahl, Ort, Typ. +- Follow-up-Idee (sorb): Grafana-Dashboard als Widget direkt im Matrix-Raum. + +## Verworfene Alternativen + +- Eine Nachricht pro CVE: real erlebter Flood, Raum unbrauchbar. +- Eigener Bot je Meldungsklasse: mehr Betrieb ohne Erkenntnisgewinn, Räume trennen genügt. diff --git a/decisions/0004-site-to-site-vpn-hetzner-lab.md b/decisions/0004-site-to-site-vpn-hetzner-lab.md new file mode 100644 index 0000000..cc90f73 --- /dev/null +++ b/decisions/0004-site-to-site-vpn-hetzner-lab.md @@ -0,0 +1,40 @@ +# 0004 — Site-to-Site-VPN Hetzner-Projektnetz ↔ Lab, schaltbar über die UDM + +**Status:** vorgeschlagen (Design abgestimmt, Umsetzung offen → [Issue #12](https://git.lab/axion1337.chat/management/-/issues/12)) · **Datum:** 2026-08-01 · **Entscheider:** sorb + +## Kontext + +Das Lab ist die Quelle der Wahrheit (ADR-0002), aber die Hetzner-Hosts erreichen +`git.lab` nicht — das erzwang beim Cutover die Übergabe-Issue-Ausnahme. Ein +dauerhafter Zugang von exponierten Servern ins Heimnetz soll es trotzdem nicht sein. + +## Entscheidung + +Ein **eigener WireGuard-Site-to-Site-Tunnel** (getrennt vom Roadwarrior) verbindet +das Hetzner-Projektnetz `10.0.0.0/24` mit dem Lab — **die UDM initiiert**, der +An/Aus-Schalter liegt in der UniFi-UI (Bedarfsfall-Prinzip, Kontrolle im Lab): + +- Endpunkt = CFGMON (WG-Listener UDP 51821, ufw nur für `178.25.213.70/32`); + keine neue Portfreigabe am Heimanschluss. +- Transfernetz `10.58.75.0/24`; CFGMON ist Hetzner-seitiges Gateway + (Forwarding + Hetzner-Cloud-Netzwerk-Route `10.58.73.0/24 → 10.0.0.3`). +- Split-Tunnel strikt (AllowedIPs nur `10.58.73.0/24`), Split-DNS nur `~lab` + → `10.58.73.1` (kein `lab.de`, kein `axion1337.de`). +- Eigene UDM-Firewall-Zone: nur → Overmind:443 + DNS `10.58.73.1:53`. + +## Konsequenzen + +- Übergabe-Issues können nach Umsetzung auf git.lab umziehen; die Ausnahme aus + ADR-0002 entfällt. +- Ein kompromittierter Hetzner-Host kann den Tunnel nicht öffnen (Initiative + liegt bei der UDM) und sieht bei offenem Tunnel nur git.lab:443. +- Der TURN-Rotations-CronJob trifft nur bei eingeschaltetem Tunnel auf git.lab — + seine Gitea-PR-Ausnahme bleibt, bewusst. +- game.axion1337.de profitiert erst nach Aufnahme in den vSwitch (GAME-01). + +## Verworfene Alternativen + +- Einzelne Roadwarrior-Profile pro Server: Schalter läge auf den exponierten + Hosts, Key-Streuung, kein Site-Routing. +- Tunnel dauerhaft an: widerspricht dem Bedarfsfall-Prinzip ohne echten Gewinn. +- git.lab öffentlich exponieren: größte Angriffsfläche, klar verworfen. diff --git a/decisions/0005-pm-framework-kanban.md b/decisions/0005-pm-framework-kanban.md new file mode 100644 index 0000000..9af5f00 --- /dev/null +++ b/decisions/0005-pm-framework-kanban.md @@ -0,0 +1,44 @@ +# 0005 — Projektmanagement: Kanban-Rückgrat mit leichten Scrum-Elementen + +**Status:** akzeptiert · **Datum:** 2026-08-01 · **Entscheider:** sorb + +## Kontext + +Die Arbeit (Solo-Betrieb plus Claude-Sessions, unregelmäßige Abendblöcke, +incident-getrieben) fasert ohne Struktur aus. Artefakte existierten verstreut +(Markdown-Backlogs, Issues, AARs) ohne verbindenden Rahmen. sorb ist +zertifizierter Scrum Master (ohne Praxis in der Rolle). + +## Entscheidung + +**Kanban als Betriebssystem**, ergänzt um die Scrum-Artefakte, die solo tragen: + +| Element | Umsetzung | +|---|---| +| Board | GitLab-Gruppen-Board (Gruppe `axion1337.chat`), Spalten über `status:`-Labels | +| Pull statt Commitment | `status:next` ist die einzige Zusage; gezogen wird nach Kapazität | +| WIP-Limit | **max. 2 × `status:doing`** (Konvention — CE hat keine Board-Limits) | +| Explizite Policies | ein `status:`-Label pro Issue; blockiert = `status:wartet` mit benanntem Grund | +| Product Goal / Vision | `vision/` (eine Datei je Linie) | +| Refinement | die etablierten Entscheidungsrunden (Vorlagen mit Optionen) | +| Review/Retro | AARs (`verfahren/aar/`) nach Deploys/Incidents | +| Definition of Done | Deploy-Übergabe-Verfahren (`verfahren/deploy-uebergabe.md`) | +| Roadmap/Meilensteine | Gruppen-Milestones + `roadmap.md` (CE: keine Epics/Roadmap-View) | +| Entscheidungen | ADRs in `decisions/` | +| Experimente | Lean-Startup-Muster (Hypothese → kleinstes Experiment → messen) für Produktideen wie Raidplaner/Invite-Workflow | + +## Konsequenzen + +- Das Backlogs-Repo wird zum Management-Repo `axion1337.chat/management`; + offene Punkte aus `hosts/`/`shared/` sind Issues mit `host:`-Labels, + die Markdown-Dateien halten Bestand und Historie. +- Ein Backlog-System statt zwei; das Gruppen-Board zeigt alles Offene. +- Disziplin-Pflichten: Status-Labels pflegen, WIP-Limit respektieren, + ADR bei Architekturentscheidungen und dauerhaften Ausnahmen. + +## Verworfene Alternativen + +- Scrum/Nexus: Sprints und Commitment brauchen planbare Team-Kapazität — + bei Solo-Betrieb mit unregelmäßigen Blöcken Theater; Nexus ist Multi-Team. +- Lean Startup / Design Thinking als Rahmen: Produktentdeckungs-Werkzeuge, + kein Betriebs-Framework — bleiben als Werkzeug im Einsatz. diff --git a/decisions/README.md b/decisions/README.md new file mode 100644 index 0000000..84fd211 --- /dev/null +++ b/decisions/README.md @@ -0,0 +1,19 @@ +# Architecture Decision Records (ADR) + +Eine Datei pro Entscheidung, fortlaufend nummeriert, Format siehe +[template.md](template.md) (MADR-light). ADRs werden **nie umgeschrieben** — +eine revidierte Entscheidung bekommt ein neues ADR, das alte wird im Status +auf `abgelöst durch NNNN` gesetzt. + +**Wann ist ein ADR Pflicht:** + +- Architektur- oder Prozessentscheidungen, die mehrere Repos/Hosts betreffen +- **Jede dauerhafte Ausnahme von einer bestehenden Regel** — eine Ausnahme, die + nur dokumentiert, aber nicht entschieden wurde, ist ein Fehler (gelernt beim + git.lab-Cutover 2026-08-01: die „Übergabe-Issues bleiben auf Gitea"-Ausnahme + hätte als Entscheidungsvorlage kommen müssen, nicht als Fußnote) +- Verworfene Wege, deren erneute Prüfung Zeit kosten würde („warum haben wir + das damals nicht gemacht?") + +Kleine, repo-lokale Entscheidungen bleiben im jeweiligen Projekt (Commit-Message +oder Issue) — nicht jede Abwägung braucht ein ADR. diff --git a/decisions/template.md b/decisions/template.md new file mode 100644 index 0000000..20fe0c4 --- /dev/null +++ b/decisions/template.md @@ -0,0 +1,19 @@ +# NNNN — Titel (Aussagesatz der Entscheidung) + +**Status:** vorgeschlagen | akzeptiert | abgelöst durch NNNN · **Datum:** JJJJ-MM-TT · **Entscheider:** sorb + +## Kontext + +Was ist das Problem, was zwingt zur Entscheidung? (2–5 Sätze) + +## Entscheidung + +Was wurde entschieden — als klare Aussage, umsetzbar ohne den Kontext zu lesen. + +## Konsequenzen + +Was wird dadurch besser, was nehmen wir bewusst in Kauf, was ist jetzt Pflicht. + +## Verworfene Alternativen + +Je Alternative ein Satz, warum nicht. diff --git a/hosts/cfgmon.md b/hosts/cfgmon.md index e6e5b04..6279388 100644 --- a/hosts/cfgmon.md +++ b/hosts/cfgmon.md @@ -32,183 +32,16 @@ Prometheus-Jobs: `operating_prometheus`, `operating_node-exporter`, (`10.0.0.2:9100`), `pterodactyl_host_node` und `gameserver_cadvisor` (beide `157.90.155.206`, siehe [game](game.md)). ---- +## Offene Punkte → git.lab-Issues -## CFGMON-01 — Zertifikatserneuerung braucht offene Ports (IPv4 **und** IPv6) +Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im +[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten. +Dieses File hält nur noch Bestand und Historie. -**Status:** offen — zeitkritisch ab **2026-09-28** - -Das Cert für `selendis.axion1337.de` wurde am 2026-07-30 ausgestellt und läuft am -**2026-10-28** ab. Traefik erneuert ca. 30 Tage vorher, also ab Ende September. -Gitea (`rohana.axion1337.de`) hängt am selben Resolver und ist damit genauso -betroffen — inklusive der Erreichbarkeit dieses Repos per HTTPS. - -Traefik nutzt TLS-ALPN-01 -(`--certificatesresolvers.letsencrypt.acme.tlschallenge=true`). Die Challenge läuft -ausschließlich über **Port 443, erreichbar aus dem offenen Internet**. Bei -gesperrtem Port scheitert sie mit: - -``` -urn:ietf:params:acme:error:connection :: Timeout during connect (likely firewall problem) -``` - -Traefik liefert dann sein Default-Self-Signed-Cert aus. Das fällt niemandem auf, bis -jemand die Seite aufruft — genau so ist es am 2026-07-30 passiert. - -Eine IP-Allowlist ist **keine** Option: Let's Encrypt veröffentlicht seine -Validierungs-IPs nicht und prüft seit Einführung der Multi-Perspective Validation -aus mehreren Regionen gleichzeitig. - -**IPv6 war der vermutete Fallstrick — geprüft und in Ordnung.** `rohana`, `selendis` -(und noch `www.*`, siehe [ZONE-01](../shared/zone-axion1337.md)) haben AAAA-Records -auf `2a01:4f8:c17:93eb::1`. Damit validiert LE **bevorzugt über IPv6**. Die -Hetzner-Cloud-Firewall kennt kein familienübergreifendes „any": das Feld *Source IPs* -ist eine Liste, `0.0.0.0/0` deckt IPv6 **nicht** mit ab, `::/0` muss separat drinstehen. - -Stand 2026-07-30 enthält die Inbound-Regel für TCP 443 **beide** Einträge — vom User -in der Hetzner-Console nachgesehen. Damit ist der IPv6-Pfad frei. - -Diese Angabe stammt **nicht** aus einer Messung von diesem Host aus, sondern aus der -Console. Vom Host ist es nicht verifizierbar: die Cloud-Firewall liegt außerhalb des -Systems, `iptables` und `ufw` sagen nichts darüber (und Root gibt es hier nicht), eine -Verbindung auf die eigene öffentliche Adresse läuft lokal, es gibt keinen zweiten Host -für eine Rückverbindung, und Traefik läuft ohne Access-Log — es existieren also auch -keine historischen Client-IPs. Für eine Prüfung von hier aus wäre ein -Hetzner-API-Token mit Read-Berechtigung nötig. - -Auch die erfolgreiche Ausstellung vom 2026-07-30 um 12:00 UTC belegt IPv6 **nicht**: -zu dem Zeitpunkt existierte für `selendis` noch kein AAAA-Record, LE hat also über -IPv4 validiert. Die Erneuerung Ende September ist der erste Lauf, der IPv6 überhaupt -versucht. - -**Damit bleibt als Risiko nur, ob die Ports offen bleiben.** Sie wurden am -2026-07-30 für die Ausstellung geöffnet; der Normalzustand dieser Umgebung ist, 80 -und 443 aus Sicherheitsvorsicht auf die eigene IP zu beschränken. Werden sie wieder -zugezogen, scheitert die Erneuerung Ende September genau wie heute Mittag — und zwar -still. - -**Nächster Schritt:** Entscheidung zwischen - -- **A — Ports offen lassen** bzw. zur Erneuerung wieder öffnen. Nichts umzubauen, - aber alle ~60 Tage daran zu denken, und ein Fehlschlag fällt erst auf, wenn jemand - die Seite aufruft. Wenn A, dann mit einem Kalendereintrag auf **Mitte September**, - nicht auf das Ablaufdatum. -- **B — auf DNS-01 umstellen** (empfohlen). Validierung über einen TXT-Record, - **kein offener Port nötig**, läuft bei dichter Firewall durch. Braucht ein - API-Token für die Zone bei IONOS, als Secret für Traefik hinterlegt. Ermöglicht - zusätzlich Wildcard-Certs (`*.axion1337.de`), also künftige Subdomains ohne - Portöffnung. Die frühere Voraussetzung — ein anfassbarer, versionierter - Traefik-Stack — ist seit dem 2026-07-30 erfüllt (CFGMON-02, siehe „Erledigt"). - ---- - -## CFGMON-03 — Prometheus-Remote-Write und Loki sind öffentlich ohne Auth - -**Status:** Weg A beschlossen (sorb 2026-08-01) — **Betrachtung nachgelagert**: -Beim Baseline-Check vom Mac aus waren 9090/3100 bereits zu (Timeout), OHNE dass der -Console-Klick gemacht war — die reale Hetzner-Firewall-Lage weicht offenbar vom -Backlog-Bild ab. Vor dem Abhaken einmal gemeinsam in die Console schauen: welche -Regeln existieren wirklich, und läuft der GAME-Push (nach GAME-01) noch durch? - -**Vorbereitung/Empfehlung:** Absender-Inventur ergab: Der k3s/Matrix-Host pusht -längst übers private Netz (10.0.0.3, verifiziert) — öffentlich brauchen 9090/3100 -nur noch Absender **außerhalb** des vSwitch, praktisch also der GAME-Host -(157.90.155.206, siehe GAME-01). - -- **Weg A (empfohlen, 5 Minuten):** Hetzner-Cloud-Firewall auf CFGMON — eingehend - 9090/tcp + 3100/tcp nur von `157.90.155.206` (+ ggf. weitere bekannte Absender) - erlauben; privater vSwitch-Verkehr ist davon unberührt. Sofort wirksam, kein - Config-Umbau. -- **Weg B (sauberer, später):** GAME-Host in den vSwitch aufnehmen (deckt sich mit - gitops#41 „privates Netz statt Internet" und der GAME-01-Firewall-Arbeit) — - danach beide `ports:`-Blöcke aus der Compose entfernen, nichts mehr öffentlich. -- **Weg C (verworfen):** BasicAuth via Traefik — 9090/3100 sind direkte - Port-Mappings, kein Traefik-Routing; der Umbau (Router+Middleware+htpasswd auf - CFGMON, `basic_auth`-Block im GAME-Alloy) wäre deutlich mehr Bewegung als A/B - für denselben Effekt. - -Prometheus läuft mit `--web.enable-remote-write-receiver` und Port `9090` ist -veröffentlicht, weil der k3s-Cluster und der Matrix-Server dorthin pushen. Loki ist -auf `3100` ebenfalls veröffentlicht. - -Ein offener Remote-Write-Receiver ohne Auth erlaubt Fremden, **beliebige Metriken -einzuspeisen** — damit lassen sich Dashboards und Alerts unbrauchbar machen — und -über die Query-API alle Daten auszulesen. Bei Loki auf `3100` gilt dasselbe für -Logs, die typischerweise mehr Interna enthalten als Metriken. - -In `monitoring/docker-compose.yml` steht dazu bereits ein Warnhinweis als Kommentar, -umgesetzt ist er nicht. - -**Nächster Schritt:** Beide Ports per Hetzner-Cloud-Firewall auf die Absender -einschränken. Sauberer wäre, sie gar nicht öffentlich zu binden: k3s liegt mit -`10.0.0.2` im selben privaten Netz wie CFGMON (`10.0.0.3`), der Push könnte also -über das private Netz laufen. - -**Update 2026-07-30**: der k3s/Matrix-Host (`49.13.132.245`, privat `10.0.0.2` — ist -derselbe Host, siehe [MATRIX-02](matrix.md#matrix-02--pusht-per-remote-write-auf-einen-offenen-prometheus--erledigt-2026-07-30)) -nutzt für seinen eigenen Remote-Write/Loki-Push bereits die private IP -(`http://10.0.0.3:9090`/`:3100`, verifiziert in `apps/monitoring/alloy-config.yaml`), nicht -`188.245.193.243`. Der öffentlich erreichbare, unauthentifizierte Port bleibt trotzdem ein -CFGMON-seitiges Risiko (jeder im Internet könnte ihn ansprechen, nicht nur der k3s-Host) - -dieser Teil des Punkts ist also weiterhin offen, nur nicht mehr durch fehlende -Netz-Erreichbarkeit des Matrix-Hosts blockiert. - ---- - -## CFGMON-04 — Grafana-Admin-Credentials aus `.env` gelten nicht für die HTTP-API - -**Status:** offen, geringe Priorität - -`GF_SECURITY_ADMIN_USER` und `GF_SECURITY_ADMIN_PASSWORD` greifen nur beim -allerersten Start mit leerem Volume. Der Live-Admin wurde offenbar später in der UI -geändert, die Werte aus der `.env` sind damit funktionslos. Verifikation von -Datasources und Dashboards läuft deshalb über `grafana.db` statt über die API. - -Kein Defekt, aber eine Falle: die `.env` sieht aus, als wäre sie die Quelle der -Wahrheit, ist es aber nicht. - -**Nächster Schritt:** entweder das echte Admin-Passwort in die `.env` nachziehen und -dokumentieren, dass es nur den Ersteinrichtungsfall abdeckt, oder einen -Service-Account mit API-Token für Verifikationszwecke anlegen. Letzteres ist -sauberer, weil dafür kein Admin-Passwort nötig ist. - ---- - -## CFGMON-09 — Gitea-Backups off-host in die Storage Box (eigenes Borg-Repo) - -**Status:** offen — bewusst zurückgestellt am 2026-07-30 - -**Achtung: Der nächtliche Backup-Cron ist seit dem 2026-07-30 deaktiviert** -(auskommentiert in der Crontab von `rantanplan`). Bis zur Umsetzung dieses Punkts -laufen **keine Gitea-Backups** — der letzte Stand ist -`/opt/backup/gitea-dump-2026-07-30.tar.gz`. Beim Erledigen (oder Verwerfen) dieses -Punkts den Cron wieder aktivieren. - -Ausgangslage: Die Platte (38G) ist zu 73 % voll, der einzelne lokale Dump belegt -4,3 GB (beides `df`/`du` vom 2026-07-30). Das Backup-Script -(`/opt/thread-net-git/backup/gitea-backup.sh`) rotiert deshalb auf genau einen -Stand; Historie existiert nur, wenn jemand manuell per scp abzieht. -Off-host-Kopien fehlen komplett. - -Plan: **Eigenes Borg-Repo auf der Hetzner Storage Box.** Die Storage Box spricht -Borg nativ über SSH (Port 23, laut Hetzner-Doku — nicht von hier verifiziert, -es existiert noch keine Storage Box dafür), z. B. -`ssh://uXXXXXX@uXXXXXX.your-storagebox.de:23/./backups/gitea`. - -- **Dedup:** Die nächtlichen Dumps sind fast identisch — Borg überträgt nur - geänderte Blöcke. Dafür den Dump **unkomprimiert** an Borg geben (das `gzip` im - Script entfällt, Borg komprimiert selbst), sonst greift die Deduplizierung nicht. -- **Retention** über `borg prune` (z. B. 7 täglich, 4 wöchentlich, 6 monatlich) - statt nur eines Standes. -- Optional ein **Sub-Account** der Storage Box mit eigenem Verzeichnis, damit das - Gitea-Repo von anderen Backups getrennt bleibt. - -Voraussetzungen, beide beim User: - -1. Storage-Box-Username (`uXXXXXX`) bzw. Sub-Account (im Hetzner-Robot anlegen). -2. Der Host hat **keinen SSH-Key** (`~/.ssh/` enthält nur `authorized_keys`, - geprüft 2026-07-30) — Key generieren und den Public Key in der Storage Box - hinterlegen (Robot-Webinterface oder einmalig per Passwort-Login). +- [CFGMON-01 — Zertifikatserneuerung braucht offene Ports (zeitkritisch ab 2026-09-28)](https://git.lab/axion1337.chat/management/-/issues/7) +- [CFGMON-03 — Prometheus-Remote-Write/Loki öffentlich ohne Auth (Weg A, nachgelagerte Prüfung)](https://git.lab/axion1337.chat/management/-/issues/8) +- [CFGMON-04 — Grafana-Admin-Credentials aus `.env` gelten nicht für die API](https://git.lab/axion1337.chat/management/-/issues/9) +- [CFGMON-09 — Gitea-Backups off-host (⚠️ Backup-Cron deaktiviert)](https://git.lab/axion1337.chat/management/-/issues/10) ## CFGMON-11 — Gitea-CI-Rückbau nach GitLab-Umzug diff --git a/hosts/game.md b/hosts/game.md index 48cb58b..151e493 100644 --- a/hosts/game.md +++ b/hosts/game.md @@ -14,95 +14,12 @@ Pterodactyl- / Gameserver-Host. > aus. Auf dem Host selbst wurde nichts geprüft. Beim ersten direkten Zugriff > sollten OS, Dienste und Compose-Projekte hier nachgetragen werden. ---- +## Offene Punkte → git.lab-Issues -## GAME-01 — Host von CFGMON aus nicht erreichbar, 2 Prometheus-Targets down +Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im +[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten. +Dieses File hält nur noch Bestand und Historie. -**Status:** offen — Ursache liegt auf diesem Host oder in dessen Firewall +- [GAME-01 — Host von CFGMON aus nicht erreichbar, 2 Targets down (⚠️ Silences bis 2026-08-04)](https://git.lab/axion1337.chat/management/-/issues/2) +- [GAME-02 — `www.game.axion1337.de` ist überflüssig](https://git.lab/axion1337.chat/management/-/issues/3) -Zwei Scrape-Targets sind down. Das bestand **schon vor** dem Monitoring-Rework vom -2026-07-30, ist also kein Regressionsschaden aus der Umstellung. - -| Job | Target | Fehler | -|---|---|---| -| `gameserver_cadvisor` | `157.90.155.206:8080` | `context deadline exceeded` | -| `pterodactyl_host_node` | `157.90.155.206:9100` | `context deadline exceeded` | - -Von CFGMON aus geprüft: der Host antwortet **nicht auf Ping** (100 % packet loss) und -auf keinem der beiden Ports. Das Problem ist also nicht die Prometheus-Konfiguration, -sondern die Erreichbarkeit. Mögliche Ursachen, von wahrscheinlich nach unwahrscheinlich: - -1. Die Hetzner-Cloud-Firewall dieses Hosts lässt `188.245.193.243` nicht auf - 8080/9100 — passend zum restriktiven Firewall-Setup der Umgebung. -2. cAdvisor und node-exporter laufen nicht (mehr) oder binden nur auf `127.0.0.1`. -3. Der Host ist abgeschaltet oder umgezogen und die IP ist veraltet. Dagegen spricht, - dass `game.axion1337.de` weiter auf sie zeigt. - -### Nachtrag 2026-08-01 — Ursache eingegrenzt - -Erneut von CFGMON aus geprüft. Die Befunde streichen die Liste oben zusammen: - -| Prüfung | Ergebnis | -|---|---| -| Port 80 / 443 | **offen, antworten sofort** | -| Port 22 / 8080 / 9100 | keine Antwort, Timeout | -| ICMP | 100 % Verlust | -| `10.0.0.0/24`, Ports 9100+8080 | nur `10.0.0.2` (k3s) und `10.0.0.3` (CFGMON) — dieser Host ist **nicht** im vSwitch | -| `up == 1` in den letzten 45 Tagen | **nie** — beide Targets waren im gesamten Retention-Fenster nie erreichbar | - -Damit ist **Ursache 3 ausgeschlossen**: der Host lebt und bedient 80/443. Und -**Ursache 1 ist die wahrscheinliche**: die Ports laufen ins *Timeout* statt -`connection refused` zu liefern. Ein nicht laufender oder auf `127.0.0.1` gebundener -Exporter würde die Verbindung aktiv ablehnen — stilles Verwerfen ist die Signatur -eines Paketfilters davor. Ursache 2 bleibt als Zusatzbedingung möglich: selbst bei -offener Firewall muss cAdvisor drüben seinen Port auch veröffentlichen (auf CFGMON -läuft er bewusst ohne `-p`, nur containerintern). - -**Nächster Schritt:** in der Hetzner-Cloud-Firewall dieses Hosts inbound TCP 8080 und -9100 für `188.245.193.243/32` freigeben — oder besser den Weg unten gehen. Danach auf -dem Host prüfen, ob beide Exporter laufen und worauf sie binden. - -**Empfehlung: nicht über die öffentliche IP.** CFGMON scrapt den k3s-Host bereits -über das private Netz (`10.0.0.2:9100`) und der ist up — das ist das Modell, das -hier funktioniert. Wenn dieser Host in denselben Hetzner-vSwitch aufgenommen wird -(CFGMON hat `10.0.0.3`), braucht es für das Monitoring **gar keine im Internet -offenen Ports**. Zwei Exporter öffentlich erreichbar zu machen wäre der schlechtere -Weg: node-exporter gibt detaillierte Host-Interna preis, cAdvisor die komplette -Container-Landschaft. - -Danach in `threadnet-operating` die Targets in `monitoring/prometheus/prometheus.yml` -von der rohen IP auf die private Adresse bzw. den DNS-Namen umstellen — aktuell -stehen dort öffentliche IPs, obwohl mit `game.axion1337.de` ein Name existiert. - -**Solange offen — Alerting stummgeschaltet.** Seit dem Alerting-Rollout (gitops#32, -2026-08-01) erzeugen beide Targets echte `TargetDown`-Alarme im Matrix-Alerts-Raum, -mit `repeat_interval: 4h` also alle vier Stunden erneut. Dafür sind auf CFGMON zwei -Alertmanager-Silences gesetzt: - -| Silence-ID | Matcher | -|---|---| -| `abedb8a2-6969-41d0-aa94-20c1f575fe61` | `alertname="TargetDown" instance="pterodactyl"` | -| `0f64aa3c-67a0-45c5-a9d9-a30ce64e8113` | `alertname="TargetDown" instance="157.90.155.206:8080"` | - -**Sie laufen am 2026-08-04 01:30 UTC ab.** Ist der Host bis dahin nicht gefixt, meldet -sich das Alerting von selbst zurück — bewusst so gewählt, damit der Punkt nicht still -liegen bleibt. Verlängern oder aufheben mit `docker compose exec alertmanager amtool -silence expire --alertmanager.url=http://localhost:9093` aus -`/opt/threadnet-operating/monitoring`. - ---- - -## GAME-02 — `www.game.axion1337.de` ist überflüssig - -**Status:** offen, geringe Priorität - -Es existiert ein A-Record `www.game.axion1337.de` → `157.90.155.206`, angelegt nach -IONOS-Default-Muster. Bei einer Subdomain ist ein `www.`-Präfix überflüssig, siehe -die Begründung in [ZONE-01](../shared/zone-axion1337.md). - -**Nicht verifiziert**, ob auf diesem Host etwas auf den Namen hört — von CFGMON aus -ist er nicht erreichbar. Bei `rohana` und `selendis` liefert das äquivalente -Konstrukt einen Zertifikatsfehler. - -**Nächster Schritt:** prüfen, ob der Name irgendwo verlinkt oder konfiguriert ist, -sonst A-Record löschen. diff --git a/hosts/matrix.md b/hosts/matrix.md index 21ac2eb..7c9534e 100644 --- a/hosts/matrix.md +++ b/hosts/matrix.md @@ -25,19 +25,13 @@ Host **ist** das Deployment-Ziel dieses Repos, nicht nur verwandt. Client-Forks: 2248/tcp (SSH), 80/443, TURN/RTC-Ports. `unattended-upgrades` aktiv (Debian-Security + Debian-Origin), siehe [MATRIX-04](#matrix-04--host-level-pre-update-benachrichtigung-erledigt). ---- +## Offene Punkte → git.lab-Issues -## MATRIX-03 — `www.matrix.axion1337.de` ist überflüssig +Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im +[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten. +Dieses File hält nur noch Bestand und Historie. -**Status:** offen, geringe Priorität - -A-Record `www.matrix.axion1337.de` → `49.13.132.245`, nach IONOS-Default-Muster -angelegt. Begründung siehe [ZONE-01](../shared/zone-axion1337.md). **Nicht -verifiziert**, ob auf dem Host etwas auf den Namen hört. - -**Nächster Schritt:** prüfen und sonst löschen. - ---- +- [MATRIX-03 — `www.matrix.axion1337.de` ist überflüssig](https://git.lab/axion1337.chat/management/-/issues/1) ## MATRIX-05 — node-exporter-DaemonSet in CrashLoopBackOff, Cluster-Scrape seit 2026-08-01 tot diff --git a/hosts/overmind.md b/hosts/overmind.md index ed307c2..686e72e 100644 --- a/hosts/overmind.md +++ b/hosts/overmind.md @@ -78,7 +78,8 @@ erst neues Image bauen, dann Referenz umstellen). ## OVERMIND-02 — Host-Ausfall 2026-07-31 ~19:15 lokal (NIC-Hang, Fix aktiv) -**Status:** Fix aktiv, Beobachtung +**Status:** Fix aktiv — die Beobachtung läuft als [Issue #4](https://git.lab/axion1337.chat/management/-/issues/4) +(Framework-Umbau 2026-08-01); dieser Abschnitt ist Bestand/Historie. **Ursache (Journal des Vor-Boots, via Claude-Session auf Overmind):** `e1000e` `Detected Hardware Unit Hang` auf `eno1` in Endlosschleife — die Intel-NIC hing diff --git a/roadmap.md b/roadmap.md new file mode 100644 index 0000000..6efb833 --- /dev/null +++ b/roadmap.md @@ -0,0 +1,50 @@ +# Roadmap + +> Stand 2026-08-01, Erstfassung aus dem Framework-Umbau (ADR-0005). Milestones +> werden im ersten gemeinsamen Refinement in GitLab (Gruppen-Milestones) +> angelegt und Issues zugeordnet — diese Datei hält die Linien und die +> Reihenfolge, GitLab hält den Stand. + +## Linien und nächste Meilenstein-Kandidaten + +### Betrieb & Sicherheit (axion1337.chat-Stack) + +1. **CVE-Meldeweg v2 live** — aggregierte Alarme deployen (Übergabe-Issue auf + dem Gitea-management-Tracker), Grafana-CVE-Dashboard, Security-Raum-Widget + (Follow-up-Wunsch sorb). [gitops#45](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/45), + [#49](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/49) +2. **Zertifikats-Risiko entschärfen** vor Ende September — + [CFGMON-01 (#7)](https://git.lab/axion1337.chat/management/-/issues/7) ⏰ +3. **Backups wiederherstellen** — [CFGMON-09 (#10)](https://git.lab/axion1337.chat/management/-/issues/10) + (Cron ist AUS!) +4. K3s-API-Härtung (gitops#25, gemeinsame Session), CFGMON-03-Konsolen-Klärung. + +### Infrastruktur (Lab & Netz) + +1. **Site-to-Site-VPN** Hetzner ↔ Lab — + [LABNET-02 (#12)](https://git.lab/axion1337.chat/management/-/issues/12), + ADR-0004; danach Übergabe-Issues ins Lab, Ausnahme-Rückbau. +2. GAME-01-Erreichbarkeit + vSwitch-Aufnahme — + [#2](https://git.lab/axion1337.chat/management/-/issues/2) (Silences bis 2026-08-04!) +3. Roadmap-/Board-Ausbau in GitLab (Rest von gitops#46: Milestones, Boards). + +### Produkte (ThreadNet) + +1. Windows-Installer: Signing + Branding (ThreadNet-Web#6) — hängt mit der + vertagten Rebranding-Runde zusammen (→ `vision/threadnet.md`). +2. **Raidplaner** (gitops#47) — Lean-Experiment: HumHub-Kandidat evaluieren. +3. **Gäste-Invite-Workflow** (gitops#48) — Design steht (@concierge, + Freischaltung im Matrix-Raum), Umsetzung gemeinsam. +4. Zammad-artiges Feedback-Tool als spätere Ergänzung (ThreadNet-Web#9). + +### Community (axion1337.chat) + +- Rebranding-Runde (bewusst vertagt; Leitplanke in `vision/axion1337-chat.md`). +- Vision-Verfeinerung im ersten Refinement. + +## Kadenz + +- **Refinement** (gemeinsame Session, ~wöchentlich): Board pflegen, + `status:next` füllen, Entscheidungsvorlagen durchgehen. +- **AAR** nach jedem Deploy mit Übergabe und nach Incidents (bestehendes Verfahren). +- **Retro light** (~monatlich): Verfahren/ADRs prüfen — fasert etwas aus? diff --git a/shared/lab-netzwerk.md b/shared/lab-netzwerk.md index abfdd51..3d61dde 100644 --- a/shared/lab-netzwerk.md +++ b/shared/lab-netzwerk.md @@ -26,8 +26,7 @@ Damit ist die Cutover-Voraussetzung für gitops#48 erfüllt. fremde Hosts funktionierten) → Fix: **VPN-Subnetz auf 10.58.74.0/24** (Docker fasst 10.x nie an). -**Restarbeiten:** MacBook-WG-Profil auf neue Adresse (10.58.74.2/32) und Endpunkt -`178.25.213.70:51840` nachziehen (sorb, 2 min). ⚠️ Latente Wiederholungsgefahr +**Restarbeiten:** MacBook-WG-Profil → [Issue #11](https://git.lab/axion1337.chat/management/-/issues/11). ⚠️ Latente Wiederholungsgefahr notiert: Overminds Docker-Pool deckt auch `192.168.176.0/20` ab = kollidiert mit dem Fritzbox-Netz 192.168.178.x — aktuell folgenlos, aber bei künftigen Subnetz- Entscheidungen 192.168.x auf Overmind grundsätzlich meiden (oder Docker @@ -72,3 +71,13 @@ für das VLAN. **Verwandt:** gitops#48 (Cutover erst nach Lösung), perspektivisch ersetzt ein funktionierender Roadwarrior auch Ad-hoc-Wünsche wie „GitLab exponieren". + +## Offene Punkte → git.lab-Issues + +Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im +[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten. +Dieses File hält nur noch Bestand und Historie. + +- [LABNET-01-Rest — MacBook-WireGuard-Profil nachziehen](https://git.lab/axion1337.chat/management/-/issues/11) +- [LABNET-02 — Site-to-Site-VPN Hetzner-Projektnetz ↔ Lab (Design: ADR-0004)](https://git.lab/axion1337.chat/management/-/issues/12) + diff --git a/shared/zone-axion1337.md b/shared/zone-axion1337.md index 35ab610..b623426 100644 --- a/shared/zone-axion1337.md +++ b/shared/zone-axion1337.md @@ -32,139 +32,12 @@ Host trennen lässt. Mail-Records existieren auf `selendis` und `matrix` (MX ×2, SPF, DKIM-CNAMEs, `autodiscover`), auf `rohana` und `game` nicht. ---- +## Offene Punkte → git.lab-Issues -## ZONE-01 — IONOS-Default-Records bereinigen +Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im +[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten. +Dieses File hält nur noch Bestand und Historie. -**Status:** `rohana` und `selendis` in Arbeit (User setzt direkt um, 2026-07-30); -`game`, `matrix`, `ftp` offen +- [ZONE-01 — IONOS-Default-Records bereinigen (Rezepte im Issue; rohana/selendis in Arbeit)](https://git.lab/axion1337.chat/management/-/issues/5) +- [ZONE-02 — Apex-DMARC ist `p=none` und schützt nichts](https://git.lab/axion1337.chat/management/-/issues/6) -IONOS legt beim Anlegen einer Subdomain automatisch einen kompletten Mail-Satz mit an -— MX, SPF, DKIM-CNAMEs, `autodiscover` — und ein `www.`-Paar. Auch für Hosts, auf -denen nie Mail läuft. - -### Warum `www.` bei einer Subdomain überflüssig ist - -Das Muster stammt aus der Zeit, als der Webserver einer Domain der Host `www` war, -und hält sich für **Apex-Domains**: `axion1337.de` und `www.axion1337.de` sollen -dasselbe liefern, weil Leute beides tippen. Beim Apex ist das also richtig und bleibt. - -Auf eine Subdomain überträgt es sich nicht. `rohana.axion1337.de` **ist** schon der -Hostname des Dienstes; `www.rohana.axion1337.de` heißt wörtlich „der Webserver des -Webservers". Das tippt und verlinkt niemand. - -Verifiziert für `www.rohana` und `www.selendis`: kein Traefik-Router matcht die Namen, -Traefik liefert sein `TRAEFIK DEFAULT CERT` aus, TLS bricht mit Zertifikatsfehler ab. -Die Namen funktionieren also ohnehin nicht — wer dort landet, sieht etwas Kaputtes. -Sie zum Funktionieren zu bringen hieße Router plus Cert-SAN, also mehr Teile, die bei -jeder Erneuerung mitvalidieren müssen, für null Nutzen. - -### Warum die Mail-Records nicht ersatzlos gelöscht werden - -Zwei Fallstricke, die Löschen zur schlechteren Variante machen: - -- Ohne SPF existiert **keine Aussage** darüber, wer als dieser Name senden darf. Das - bestehende `~all` ist nur Softfail und wird von vielen Empfängern akzeptiert — eine - ungenutzte Subdomain mit gültigen MX und Softfail-SPF ist ein brauchbarer - Spoofing-Vektor. -- **Fehlt ein MX-Record, weichen Absender per RFC 5321 auf A/AAAA aus.** Mail an - `@rohana.axion1337.de` würde also Port 25 auf `188.245.193.243` ansprechen. - -Richtig ist, „hier gibt es keine Mail" explizit zu erklären: Null-MX (RFC 7505), SPF -`-all`, DMARC `p=reject`. - -### rohana.axion1337.de - -**Löschen:** `A www.rohana`, `AAAA www.rohana` - -**Anlegen:** - -| Typ | Name | Wert | -|---|---|---| -| MX | `rohana` | `.` (Priorität 0) | -| TXT | `rohana` | `v=spf1 -all` | -| TXT | `_dmarc.rohana` | `v=DMARC1; p=reject;` | - -**Nicht anfassen:** `A rohana`, `AAAA rohana` — daran hängen Gitea und das Zertifikat. - -### selendis.axion1337.de - -**Löschen:** `MX mx00.ionos.de`, `MX mx01.ionos.de`, -`CNAME s1-ionos._domainkey.selendis`, `CNAME s2-ionos._domainkey.selendis`, -`CNAME s42582890._domainkey.selendis`, `CNAME autodiscover.selendis`, -`A www.selendis`, `AAAA www.selendis` - -**Ändern** — den bestehenden TXT editieren, **nicht** einen zweiten anlegen: zwei -SPF-Records auf einem Namen ergeben einen PermError, die Prüfung fällt dann komplett -aus. - -| Typ | Name | von | auf | -|---|---|---|---| -| TXT | `selendis` | `v=spf1 include:_spf-eu.ionos.com ~all` | `v=spf1 -all` | - -**Anlegen:** `MX selendis` = `.` (Priorität 0), `TXT _dmarc.selendis` = -`v=DMARC1; p=reject;` - -**Nicht anfassen:** `A selendis`, `AAAA selendis`. - -**Vorab prüfen:** ob im IONOS-Mail-Bereich ein Postfach oder eine Weiterleitung für -`selendis.axion1337.de` existiert. Wenn ja, entfallen die MX-Änderungen. - -**Falls IONOS `.` als MX-Ziel ablehnt** — kommt vor: MX löschen und nur die -TXT-Records setzen. `-all` und `p=reject;` greifen trotzdem, es fehlt nur die -explizite „nimmt keine Mail an"-Aussage. - -### Noch offen - -- **`game`** und **`matrix`**: `www.`-Records, siehe - [GAME-02](../hosts/game.md#game-02--wwwgameaxion1337de-ist-überflüssig) und - [MATRIX-03](../hosts/matrix.md#matrix-03--wwwmatrixaxion1337de-ist-überflüssig). -- **`ftp.axion1337.de`** → `217.160.233.227`: IONOS-Default aus dem Hosting-Paket, - zeigt auf IONOS und nicht auf eigene Infrastruktur — also keine zusätzliche - Angriffsfläche, aber Ballast. Löschen, falls dort kein FTP genutzt wird. - -### Geklärt: Mail-Records auf `matrix` - -[MATRIX-01](../hosts/matrix.md#matrix-01--klären-ob-der-server-mail-als-matrixaxion1337de-verschickt--erledigt-2026-07-30) -ist erledigt (2026-07-30): weder Synapse noch MAS versenden Mail (per Config verifiziert, -nicht nur vermutet — Registrierung/Reset laufen über Authentik). Der komplette Mail-Satz -auf `matrix.axion1337.de` kann damit genauso gehärtet werden wie bei `selendis` -(Null-MX, `v=spf1 -all`, `_dmarc p=reject`), siehe ZONE-01 oben. Separat davon läuft seit -2026-07-30 echter, unabhängiger Mailversand über das **Apex**-Postfach -`wartung@axion1337.de` (Host-Wartungsbenachrichtigungen) - betrifft die -`matrix.`-Subdomain-Records nicht, bestätigt aber, dass am Apex weiterhin reale -IONOS-Mail-Infrastruktur aktiv genutzt wird. - -**Nach der Umsetzung von hier aus verifizieren:** dass `www.rohana` und -`www.selendis` nicht mehr auflösen; dass MX, SPF und DMARC greifen und **nur ein** -SPF-Record pro Name existiert; und dass `A`/`AAAA` von `rohana` und `selendis` -unverändert sind und Gitea sowie Grafana weiter über HTTPS antworten. Der letzte -Punkt ist der, bei dem ein Verklicker in der IONOS-Oberfläche wehtun würde. - ---- - -## ZONE-02 — Apex-DMARC ist `p=none` und schützt nichts - -**Status:** offen — nicht mehr blockiert, [MATRIX-01](../hosts/matrix.md#matrix-01--klären-ob-der-server-mail-als-matrixaxion1337de-verschickt--erledigt-2026-07-30) ist seit 2026-07-30 erledigt - -`_dmarc.axion1337.de` enthält `v=DMARC1; p=none;` (via `dmarc.ionos.de`). Das ist -reines Monitoring: Empfänger melden Verstöße, verwerfen aber nichts. Für gefälschte -Mail in deinem Namen ist das kein Hindernis. - -Zusätzlich fehlt eine `sp=`-Angabe. Ohne sie **erben alle Subdomains dieses -`p=none`** — auch solche, die nie Mail senden, und auch künftige. - -`sp=reject` am Apex wäre daher der effiziente Hebel: deckt alle Subdomains auf einmal -ab, inklusive der noch nicht angelegten, und macht die einzelnen `_dmarc`-Records aus -ZONE-01 auf Dauer entbehrlich. - -**Reihenfolge ist hier wichtig.** Zuerst [MATRIX-01](../hosts/matrix.md) klären, dann -für jeden Namen, der tatsächlich Mail versendet, SPF und DKIM korrekt setzen — erst -danach `sp=reject`. Umgekehrt zerlegt es den Mailversand der betroffenen Dienste, und -zwar unbemerkt, weil verworfene Mail beim Absender keinen Fehler produziert. - -Für den Apex selbst (dort läuft echte Mail über IONOS) wäre der übliche Weg, `p=none` -erst auf `p=quarantine` zu ziehen, die DMARC-Reports eine Weile zu beobachten und dann -auf `p=reject` zu gehen. Auffällig: unter `s1._domainkey.axion1337.de` war kein -DKIM-Record auffindbar, obwohl die Subdomains DKIM-CNAMEs von IONOS haben — das wäre -beim Härten mitzuprüfen. diff --git a/vision/axion1337-chat.md b/vision/axion1337-chat.md new file mode 100644 index 0000000..b2ba952 --- /dev/null +++ b/vision/axion1337-chat.md @@ -0,0 +1,24 @@ +# Vision: aXion1337.chat — die Community + +> **Entwurf** (2026-08-01, aus bisherigen Entscheidungen destilliert) — wird im +> ersten gemeinsamen Refinement geschärft. Leitplanke von sorb: +> **„axion1337.chat ist die Community, ThreadNet ist das Tool."** + +## Kern + +Eine selbst betriebene, souveräne Kommunikationsplattform für die eigene +Community: Matrix-Homeserver mit eigenem Client, eigener Identität (Authentik), +eigenen Regeln — unabhängig von Discord & Co. + +## Was dazugehört (Stand heute) + +- Matrix/ESS-Stack mit Voice/Video (Element Call, 1440p-Defaults) +- Gäste sollen unkompliziert, aber kontrolliert reinkommen + (Invite-Workflow gitops-Issue, Freischaltung im Matrix-Raum, `@concierge`) +- Community-Funktionen über Chat hinaus: Raidplaner mit Fotoalbum (HumHub-Kandidat) +- Sicherheit als Feature: ClamAV beidseitig, CVE-Transparenz im Security-Raum + +## Offene Vision-Fragen + +- Zielgruppe/Größe: geschlossener Kreis oder wachsende Community? +- Verhältnis zu ThreadNet-Branding (→ vertagte Rebranding-Runde) diff --git a/vision/homelab.md b/vision/homelab.md new file mode 100644 index 0000000..fdb04da --- /dev/null +++ b/vision/homelab.md @@ -0,0 +1,23 @@ +# Vision: Homelab — die Plattform + +> **Entwurf** (2026-08-01) — wird im ersten Refinement geschärft. + +## Kern + +Das Lab (MorninglightMountain, Overmind, das Netz dazwischen) ist die +**Quelle der Wahrheit** und die Werkbank: kanonische Repos, Build-CI, +Verwaltung — alles, was nicht öffentlich erreichbar sein muss, lebt hier +(ADR-0001/0002). + +## Prinzipien + +- Prod hängt nie vom Lab ab: Hetzner-Hosts laufen bei Lab-Ausfall weiter, + nur Neues pausiert. +- Verbindungen ins Lab sind schaltbar und minimal (Roadwarrior für Menschen, + Site-to-Site für Server — ADR-0004), nie dauerhaft exponiert. +- Bestand wird dokumentiert, wo er lebt: [homelab/docs](https://git.lab/homelab/docs) + für Netz/Geräte, Betriebs-Repos je Host. + +## Offene Vision-Fragen + +- Ausbaustufen (weitere Hosts/Dienste im Lab?) — bisher nicht diskutiert. diff --git a/vision/threadnet.md b/vision/threadnet.md new file mode 100644 index 0000000..21165eb --- /dev/null +++ b/vision/threadnet.md @@ -0,0 +1,26 @@ +# Vision: ThreadNet — das Tool + +> **Entwurf** (2026-08-01) — wird im ersten Refinement geschärft. +> Leitplanke: ThreadNet ist die Produkt-/Tool-Linie, axion1337.chat der Betrieb. + +## Kern + +Die Software-Artefakte, die die Community tragen — als eigenständige, +wiederverwendbare Produkte gedacht: ThreadNet-Web (Element-Web-Fork mit +Discord-artiger Raumliste), threadnet-call (Call-Fork), thread-net-git, +threadnet-operating. + +## Prinzipien + +- **Reproduzierbar für Dritte:** Deployment-Arbeit so bauen, dass eine andere + Community den Stack forken kann (stehendes Ziel von sorb, 2026-07-30) — + Instanzwerte getrennt von generischer Struktur. +- Fork-Pflege mit kleinem Delta: Upstream-Merges müssen billig bleiben, + chirurgische Patches statt Umbauten. +- CI beweist Releases: Tag → Pipeline → Artefakt, keine Handbuilds. + +## Offene Vision-Fragen + +- Rebranding (Element-Namen in Installer/Client vs. ThreadNet-Identität) — + bewusst vertagt, Issue ThreadNet-Web#6 hält den Installer-Teil. +- Veröffentlichungsgrad: bleiben die Forks privat oder irgendwann public?