Framework-Umbau: Backlogs wird management-Repo (ADR-0005, Kanban + Scrum-Elemente)

- decisions/: ADR-Verzeichnis mit Template + 0001-0005 (git.lab-Kanonik,
  Lab-Cutover, CVE-Meldeweg, Site-to-Site-VPN-Design, Framework-Wahl)
- vision/: je eine Vision fuer Community/Tool/Plattform (Entwuerfe)
- roadmap.md: Linien, Meilenstein-Kandidaten, Kadenz
- hosts/+shared/: offene Punkte -> Issues #1-#12 im management-Projekt
  (IDs bleiben in den Titeln), Dateien halten Bestand + Historie
- README: Framework, Board/status-Labels (WIP-Limit 2), Topologie

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
This commit is contained in:
Thore Cimbal
2026-08-01 12:00:00 +00:00
co-authored by Claude Fable 5
parent 0f3f155bc5
commit fdf30d42e1
18 changed files with 429 additions and 523 deletions
+56 -112
View File
@@ -1,131 +1,75 @@
# Backlogs # management
Zentrale Sammlung offener Punkte über alle Hosts und Dienste hinweg. Ein Eintrag Steuerungs-Repo für alles über den einzelnen Projekten: Visionen, Roadmap,
landet hier, wenn er bewusst nicht sofort erledigt wurde — damit er nicht in einer Entscheidungen (ADR), Arbeitsverfahren, AARs — und der Bestand der Hosts.
Chat-Historie oder einem Kopf verschwindet. 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) ## Repo-Topologie (seit 2026-08-01)
**Kanonisch lebt dieses Repo auf `git.lab`** (`axion1337.chat/Backlogs`, nur im **Kanonisch lebt dieses Repo auf `git.lab`** (`axion1337.chat/management`, nur im
Lab bzw. via VPN erreichbar — das Lab ist die Quelle der Wahrheit). Lab bzw. via VPN erreichbar — das Lab ist die Quelle der Wahrheit,
`rohana.axion1337.de/sorb/Backlogs` ist ein **Push-Mirror**: git.lab überschreibt [ADR-0002](decisions/0002-issues-und-management-ins-lab.md)).
ihn bei jedem Push per Force. Deshalb **nie direkt zu Gitea pushen** — solche `rohana.axion1337.de/sorb/management` ist ein **Push-Mirror**: git.lab
Commits gehen beim nächsten Mirror-Lauf verloren (Rettung: `.patch` von Gitea überschreibt ihn bei jedem Push per Force. Deshalb **nie direkt zu Gitea
ziehen + `git am`, siehe [Kanonisierung](verfahren/deploy-uebergabe.md)). 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 **Eine befristete Ausnahme:** Die **Deploy-Übergabe-Issues** laufen auf dem
Gitea-Mirror (dortiger Issue-Tracker), weil CFGMON und andere Hosts außerhalb Gitea-Mirror-Tracker, weil CFGMON und andere Hosts außerhalb des Labs `git.lab`
des Labs `git.lab` nicht erreichen — eine Übergabe muss aber von beiden Seiten noch nicht erreichen. Abgelöst wird das durch das Site-to-Site-VPN
lesbar/kommentierbar sein. ([ADR-0004](decisions/0004-site-to-site-vpn-hetzner-lab.md),
[Issue #12](https://git.lab/axion1337.chat/management/-/issues/12)).
## Aufbau ## Struktur
``` | Pfad | Artefakt |
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 |
|---|---| |---|---|
| 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 Alle offenen Punkte sind **Issues in diesem Projekt** (host-/infra-Scope, mit
**wie wir arbeiten** — Abläufe, die zwischen Personen oder über mehrere Hosts `host:`-Labels; die alten IDs wie `CFGMON-01` bleiben im Titel) bzw. in den
hinweg gelten und deshalb an kein einzelnes Projekt-Repo gehören. Produkt-Projekten der Gruppe (Projekt-Scope). Das
**[Gruppen-Board](https://git.lab/groups/axion1337.chat/-/boards)** zeigt alles
über die `status:`-Labels:
| Verfahren | Inhalt | | Label | Bedeutung | Policy |
|---|---| |---|---|---|
| [Deploy-Übergabe](verfahren/deploy-uebergabe.md) | „einer baut, ein anderer rollt aus": Issue-Vorlage, Prüfliste, AAR | | *(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 Genau **ein** `status:`-Label pro Issue. Prioritäten weiter über `priority:*`.
`.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.
## Konventionen ## Konventionen (unverändert gültig)
**IDs** sind pro Datei fortlaufend mit einem Präfix, das den Ort benennt: **IDs** (`CFGMON-01`, `ZONE-01`, …) werden **nie wiederverwendet**; sie leben in
`CFGMON-01`, `GAME-01`, `MATRIX-01`, `ZONE-01` — ein Präfix pro Datei in `hosts/` Issue-Titeln weiter. Neue host-/infra-Punkte bekommen die nächste freie Nummer
bzw. `shared/`, keine Liste losgelöst vom tatsächlichen Datei-Bestand. IDs werden ihres Präfixes als Issue.
**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.
Das Präfix für DNS-Themen ist bewusst `ZONE-` und nicht `DNS-`: `DNS-01` ist der **Jeder Punkt braucht** eine Beschreibung des tatsächlichen Zustands und einen
Name eines ACME-Challenge-Typs und käme in genau diesen Backlogs ständig als konkreten nächsten Schritt; nicht selbst Verifiziertes wird als solches markiert
Fachbegriff vor. (woher stammt die Aussage?). **Zeitkritisches** bekommt ein Datum, nicht „bald".
**Status:** **Erledigtes und Verworfenes** bleibt sichtbar: Issues werden geschlossen (nicht
gelöscht), `verworfen` wird im Schlusskommentar begründet — der Unterschied
| Wert | Bedeutung | zwischen „gemacht" und „bewusst gelassen" ist die häufigste Rückfrage.
|---|---|
| `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.
## Verhältnis zu den Projekt-Repos ## Verhältnis zu den Projekt-Repos
Dieses Repo hält die offenen Punkte. Die **Konfiguration** liegt weiter in den Konfiguration lebt in den Projekt-Repos (z. B. `threadnet-operating` für den
jeweiligen Projekt-Repos, z. B. `sorb/threadnet-operating` für den CFGMON-Stack), reine Projekt-Bugs/-Features in deren Issues auf git.lab.
Monitoring-Stack auf CFGMON. Damit nichts doppelt geführt wird, verweisen die Hierher gehört, was mehrere Hosts/Repos betrifft oder eine Entscheidung ist.
Projekt-Repos hierher statt eigene Backlog-Dateien zu pflegen. Ein Punkt, der von zwei Seiten beschrieben wird, verlinkt die andere Seite und
wird beim Schließen **dort mitaktualisiert**.
## 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.
@@ -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).
@@ -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.
+30
View File
@@ -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.
@@ -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.
+44
View File
@@ -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.
+19
View File
@@ -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.
+19
View File
@@ -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? (25 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.
+8 -175
View File
@@ -32,183 +32,16 @@ Prometheus-Jobs: `operating_prometheus`, `operating_node-exporter`,
(`10.0.0.2:9100`), `pterodactyl_host_node` und `gameserver_cadvisor` (`10.0.0.2:9100`), `pterodactyl_host_node` und `gameserver_cadvisor`
(beide `157.90.155.206`, siehe [game](game.md)). (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** - [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)
Das Cert für `selendis.axion1337.de` wurde am 2026-07-30 ausgestellt und läuft am - [CFGMON-04 — Grafana-Admin-Credentials aus `.env` gelten nicht für die API](https://git.lab/axion1337.chat/management/-/issues/9)
**2026-10-28** ab. Traefik erneuert ca. 30 Tage vorher, also ab Ende September. - [CFGMON-09 — Gitea-Backups off-host (⚠️ Backup-Cron deaktiviert)](https://git.lab/axion1337.chat/management/-/issues/10)
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-11 — Gitea-CI-Rückbau nach GitLab-Umzug ## CFGMON-11 — Gitea-CI-Rückbau nach GitLab-Umzug
+6 -89
View File
@@ -14,95 +14,12 @@ Pterodactyl- / Gameserver-Host.
> aus. Auf dem Host selbst wurde nichts geprüft. Beim ersten direkten Zugriff > aus. Auf dem Host selbst wurde nichts geprüft. Beim ersten direkten Zugriff
> sollten OS, Dienste und Compose-Projekte hier nachgetragen werden. > 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 <id> --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.
+5 -11
View File
@@ -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 + 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). 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 - [MATRIX-03 — `www.matrix.axion1337.de` ist überflüssig](https://git.lab/axion1337.chat/management/-/issues/1)
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-05 — node-exporter-DaemonSet in CrashLoopBackOff, Cluster-Scrape seit 2026-08-01 tot ## MATRIX-05 — node-exporter-DaemonSet in CrashLoopBackOff, Cluster-Scrape seit 2026-08-01 tot
+2 -1
View File
@@ -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) ## 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` **Ursache (Journal des Vor-Boots, via Claude-Session auf Overmind):** `e1000e`
`Detected Hardware Unit Hang` auf `eno1` in Endlosschleife — die Intel-NIC hing `Detected Hardware Unit Hang` auf `eno1` in Endlosschleife — die Intel-NIC hing
+50
View File
@@ -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?
+11 -2
View File
@@ -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 fremde Hosts funktionierten) → Fix: **VPN-Subnetz auf 10.58.74.0/24** (Docker
fasst 10.x nie an). fasst 10.x nie an).
**Restarbeiten:** MacBook-WG-Profil auf neue Adresse (10.58.74.2/32) und Endpunkt **Restarbeiten:** MacBook-WG-Profil → [Issue #11](https://git.lab/axion1337.chat/management/-/issues/11). ⚠️ Latente Wiederholungsgefahr
`178.25.213.70:51840` nachziehen (sorb, 2 min). ⚠️ Latente Wiederholungsgefahr
notiert: Overminds Docker-Pool deckt auch `192.168.176.0/20` ab = kollidiert mit 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- 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 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 **Verwandt:** gitops#48 (Cutover erst nach Lösung), perspektivisch ersetzt ein
funktionierender Roadwarrior auch Ad-hoc-Wünsche wie „GitLab exponieren". 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)
+6 -133
View File
@@ -32,139 +32,12 @@ Host trennen lässt.
Mail-Records existieren auf `selendis` und `matrix` (MX ×2, SPF, DKIM-CNAMEs, Mail-Records existieren auf `selendis` und `matrix` (MX ×2, SPF, DKIM-CNAMEs,
`autodiscover`), auf `rohana` und `game` nicht. `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); - [ZONE-01 — IONOS-Default-Records bereinigen (Rezepte im Issue; rohana/selendis in Arbeit)](https://git.lab/axion1337.chat/management/-/issues/5)
`game`, `matrix`, `ftp` offen - [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.
+24
View File
@@ -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)
+23
View File
@@ -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.
+26
View File
@@ -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?