feat: slice 3 - wiki, sources and AARs in their neckbeard homes

Gate 4, slice 3: verfahren/, hosts/, vision/ and shared/ moved via git
mv - six AARs to docs/aar/ (four harvested by the 2026-08-09 retro,
two open), procedures and host knowledge to docs/wiki/ (admin,
deployment, architecture, new area vision), the retro protocol and the
commit mapping table to docs/sources/ (protokolle/, migration/). New:
the wiki index linking every page, and the mirror-topology page
carrying the why-two-places reasoning verbatim from the old CLAUDE.md
(F-013 preserved). All moved-path references retargeted; the link
checker drove the sweep to zero.

pruefe_prosa.py added (pattern C+D): SHA citations resolve via repo,
mapping table, optional component clones or a curated exemption list
(documented dead Gitea-force-push commits, a vendor-repo tag, an
Authentik uid that is hex but no git SHA, the external neckbeard
reference); wiki task prose without an issue reference errors, with a
visible pragma for deliberate checklists; the dead-tracker denylist
now covers every mirrored repo's retired Gitea tracker (F-005) - two
links re-verified against live GitLab titles and retargeted, five
defused into honest historical citations.

Verified: validate 0/0, gen_status --check current, drift 0. Demo on
the pre-migration state fires 6 findings (3 orphaned SHAs, 3 task
blocks); on the current tree exactly the 3 F-004 task blocks remain -
they turn green in slice 4 when the issues exist, which is why
pruefe_prosa joins CI only then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Thore Cimbal
2026-08-11 12:00:00 +00:00
co-authored by Claude Fable 5
parent 70e81e2ff1
commit 92b448fe30
37 changed files with 424 additions and 120 deletions
+305
View File
@@ -0,0 +1,305 @@
---
type: wiki-page
area: admin
related: []
---
# CFGMON
Monitoring-Stack, Gitea und der Reverse Proxy für alles Öffentliche.
| | |
|---|---|
| **Hostname** | `CFGMON` |
| **OS** | Ubuntu 24.04.4 LTS |
| **IPv4** | `188.245.193.243` |
| **IPv6** | `2a01:4f8:c17:93eb::1` |
| **Privat** | `10.0.0.3` (`enp7s0`, Hetzner-Netz — dort liegt auch k3s auf `10.0.0.2`) |
| **DNS** | `rohana.axion1337.de` → Gitea, `selendis.axion1337.de` → Grafana |
| **Stand** | 2026-07-30 |
## Dienste
| Container | Image | Compose-Projekt | Definition |
|---|---|---|---|
| prometheus | `prom/prometheus:v3.3.1` | `monitoring` | `sorb/threadnet-operating`, `monitoring/` |
| loki | `grafana/loki:3.7.1` | `monitoring` | dito |
| grafana | `grafana/grafana:12.0.0` | `monitoring` | dito |
| alloy | `grafana/alloy:v1.16.0` | `monitoring` | dito |
| node-exporter | `prom/node-exporter:v1.9.1` | `monitoring` | dito |
| traefik | `traefik:v3.7.9` | `thread-net-git` | `sorb/thread-net-git`, seit 2026-07-30 in `main` (siehe [CFGMON-02](#cfgmon-02--traefik-gitea-cadvisor-und-runner-unter-iac-gebracht--erledigt-2026-07-30)) |
| gitea | `gitea/gitea:1.27.0` | `thread-net-git` | dito, gepinnt (war `:latest`) |
| cadvisor | `gcr.io/cadvisor/cadvisor:v0.49.1` | `thread-net-git` | dito, gepinnt (war `:latest`) |
| runner | `gitea/act_runner:0.6.1` | `thread-net-git` | dito, Container `gitea-runner`, siehe CFGMON-02 |
| portainer_agent | `portainer/agent:2.27.5` | — | standalone, kein Compose |
Prometheus-Jobs: `operating_prometheus`, `operating_node-exporter`,
`operating_cadvisor`, `operating_traefik` (alle lokal), `k3s_host_node`
(`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
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.
- [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
**Status:** erledigt (2026-07-31 spätabends) — bis auf einen kosmetischen Handgriff:
auf CFGMON `cd /opt/thread-net-git && git checkout main && git pull` (Checkout parkt
noch auf dem inhaltsgleichen, inzwischen gelöschten Fix-Branch).
**Dazu neu (2026-08-01 ~05:00):** Auch `/opt/threadnet-operating` braucht einmal
`git fetch && git reset --hard origin/main` — der State-Persistenz-Commit wurde
dort direkt nach Gitea gepusht (dfe04c4a), vom Mirror überschrieben, vom Mac aus
per Patch gerettet und kanonisch als `6ffab68` neu aufgelegt (inhaltsgleich,
anderer Hash; Autorschaft erhalten).
**Erledigt (2026-08-01, autonom):**
- Actions-Toggles deaktiviert: `ThreadNet-Web`, `threadnet-call`, `axion1337.chat-gitops`
- `ThreadNet-Web`: alle `.github/workflows/`-Dateien entfernt (Commit `a876758`)
- gitops: Verifikations-Job nach GitLab portiert + `.gitea/workflows/` entfernt
(Commit `5e46a24`, Pipeline grün, Mirror→Gitea verifiziert; `milestone-release.yml`
war toter Code, siehe #33). Flux unberührt.
- `thread-net-git`: Runner-Service/Config/`.env.example` per Commit `d904734` entfernt
(auf git.lab; Mirror trägt nach Gitea) — **noch nicht deployt**, siehe unten.
- Registry-Entscheidung npm final (Evidenz: `@sorb/threadnet-call-embedded` ist
pnpm-Dependency von `apps/web`, Lockfile pinnt Tarball-URL auf rohana): **bleibt Gitea**.
**Verbleibende manuelle Schritte (User):**
1. ~~`thread-net-git`-Stand deployen~~ **erledigt (2026-07-31 spätabends, via
CFGMON-Session)**: Runner-Container/Netz/`runner-data/`/`.env`-Zeile entfernt,
`builder-1` aus der Gitea-Admin-UI gelöscht, Actions-Registrierungstoken rotiert.
Stolperstein dabei: Rückbau-Commit `d904734` hinterließ ein verwaistes
`networks:`-Fragment (YAML invalide) — Fix nahm den kanonischen Weg
Mac→git.lab→Mirror (`15c8f2d`), Hergang in thread-net-git#1 (geschlossen).
2. ~~Token-Rotation a~~ **geklärt (2026-07-31 abends)**: der versehentlich in die VM
getippte Token (`a89bfb…`) war der Gitea-**Actions-Runner-Registrierungstoken**
(taucht nicht unter Access Tokens auf) — kein Access-Token-Risiko; wird mit
Schritt 1 obsolet. Nach dem Runner-Löschen in der Admin-UI den
Registrierungstoken dort einmal neu generieren (ein Klick), dann ist auch der
exponierte Wert wertlos.
3. ~~Token-Rotation b~~ **erledigt (2026-07-31 abends)**: Generalschlüssel
(`Projectplaning and implemantation axion`, war npm-Publish UND Issue-Verwaltung,
Klartext in `.npmrc` + Scratchpad + macOS-Schlüsselbund) gelöscht und durch drei
least-privilege-Tokens ersetzt: `gitlab-ci-npm` (write:package, als maskierte
GitLab-Gruppen-Variable `GITEA_NPM_TOKEN`), `claude-issues` (write:issue,
`~/.config/gitea-rohana/token` auf dem Mac), `claude-push` (write:repository,
`~/.config/gitea-rohana/push-token`). Erster CI-Publish `0.19.2-threadnet.6`
verifiziert → threadnet-call#1 geschlossen. Alle Klartext-Reste entfernt
(.npmrc, Skript, Schlüsselbund-Eintrag). Zusätzlich aufgeräumt: ungenutzte
Alt-Tokens `claude-push-20260730`, `claude-monitoring-rework-20260730` gelöscht.
Entscheidung vom 2026-07-30: Build-CI/CD zieht ins Homelab-GitLab
(`git.lab/axion1337.chat`, Gruppe mit importierten Projekten angelegt; die Domain ist
**nur im Homelab auflösbar** — von CFGMON/MATRIX aus nicht erreichbar, was für den
Build-Anwendungsfall in Ordnung ist: Prod läuft bei Lab-Ausfall weiter, nur neue Builds
pausieren). Der am 2026-07-30 auf Gitea-Seite aufgebaute CI-Unterbau wird damit teilweise
überflüssig. **Erst zurückbauen, wenn die GitLab-CI nachweislich läuft.**
### Sicher rückbaubar
- **Actions-Toggle** `has_actions` bei `ThreadNet-Web` (am 2026-07-30 per API aktiviert)
wieder deaktivieren, ebenso bei `threadnet-call` (stoppt die fehlschlagende
Workflow-Kaskade dort).
- **`.github/workflows/` in `ThreadNet-Web`** (der kuratierte 6-Dateien-Satz) — wird durch
`.gitlab-ci.yml` ersetzt. Die Erkenntnisse aus den Läufen vom 2026-07-30 mitnehmen:
kein `layered.sh` (würde den js-sdk-Pin mit Upstream-develop überschreiben, braucht
außerdem jq), stattdessen `pnpm install --frozen-lockfile`; webpack-Build braucht
real ~4 GB Heap; `contains(needs.*.result, ...)`-Gates sind act-spezifisch kaputt.
- **Geerbte Upstream-Workflows in `threadnet-call`** (build/publish/test/translations/
zizmor/pr-deploy) — gleiches Schicksal.
- **Runner-Identität**: wenn der Runner-Service entfällt (siehe unten), `builder-1` in
der Gitea-Admin-UI deregistrieren und `runner-data/.runner` auf dem Host entfernen.
- **Token: npm-Token in `threadnet-call`s untracked `embedded/web/.npmrc`** (Klartext im
Arbeitsverzeichnis, Fund vom 2026-07-30): revoken/rotieren. Der GitLab-CI-Publish
bekommt einen eigenen, frisch erzeugten Token als GitLab-CI-Variable — der alte
verschwindet von der Platte.
### Entscheidungsabhängig
- **Runner-Service in `thread-net-git` ganz entfernen?** Hängt daran, ob das gitops-Repo
seinen leichten `deploy-on-push.yml` (YAML-Validierung/Notification, läuft sauber)
behält — dann bleibt ein Minimal-Runner nötig. Bei Komplett-Entfernung als
Revert-Commit in `thread-net-git`: Compose-Service `runner`, `runner/config.yaml`,
`.env.example` (RUNNER_TOKEN), Cache-Port-Bindung 8088, `runner-data/`.
- **Registry-Ziel für `@sorb/threadnet-call-embedded`**: bleibt die Gitea-npm-Registry
(dann braucht GitLab-CI einen Push-Token dorthin — Neuanlage) oder wandert in die
GitLab-Package-Registry (dann läuft die Gitea-Package-Seite leer).
- **Container-Images bleiben in der rohana-Registry** (Flux/k8s pullt von dort — spricht
stark für Beibehalt). Gegenstück zur Token-Bilanz: GitLab-CI braucht dann einen
**neuen** Deploy-/Push-Token für die rohana-Registry (Neuanlage, kein Rückbau).
### Explizit nicht rückbaubar
Gitea selbst, gitops-Repo als Flux-Source, Issues/Wiki/dieses Repo, der
API-Token für Issue-Verwaltung, das Gitea-Backup-Script (CFGMON-09).
*(Stand der Analyse 2026-07-31. Issues und dieses Repo sind seitdem doch
umgezogen — [ADR-0002](../../adr/0002-issues-und-management-ins-lab.md) —,
das Repo dabei von `Backlogs` zu `management` umgewidmet
[ADR-0005](../../adr/0005-pm-framework-kanban.md). „Nicht rückbaubar" galt für
den damaligen Rückbau der Gitea-CI, nicht auf Dauer.)*
Betroffene Issues (werden bei der GitLab-Migrations-Planung umformuliert):
`ThreadNet-Web#2` (Gitea-Zählung, Tracker stillgelegt — verbindlich: Migrations-Fußtext im GitLab-Issue),
`threadnet-call#1` (Gitea-Zählung, Tracker stillgelegt).
**Nächster Schritt:** die drei manuellen Schritte oben, dann → erledigt.
## CFGMON-13 — Absender-Design für Release-/CVE-Meldungen: eigener Bot?
**Status:** entschieden (2026-08-01, sorb) — **gleicher Bot (`@alerts`), eigener Raum**
`!YRJvcEbVXtRlUIkNld:axion1337.chat`. Umsetzungsplan inkl. CVE-Metriken/Grafana/
Alertmanager-Routing: [gitops#45 auf git.lab](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/45) (ehemals Gitea-gitops#47, Tracker stillgelegt).
release-watch ist bereits auf den Raum vorbereitet (Env `MATRIX_RELEASE_ROOM_ID`,
Fallback Alerts-Raum). ⬜ Rest: `@alerts` in den Raum **einladen** (Join wurde als
restricted abgelehnt — sorb), dann Deploy.
Zwei neue Meldequellen entstehen gerade neben dem klassischen Alerting:
1. **release-watch** (gitops#22, deploybereit): Upstream-Releases/Security-Releases
→ aktuell als Notiz über den `@alerts`-Bot in den Alerts-Raum
2. **Trivy-CVE-Scans** (gitops#31, läuft wöchentlich in der Lab-CI): Funde landen
bisher NUR als Job-Artifact/-Log — keine aktive Benachrichtigung
**Frage:** Sollen diese "Informations-Meldungen" (Releases, CVE-Reports) einen
**eigenen Bot** bekommen (z. B. `@releases:axion1337.chat`, ggf. eigener Raum),
damit `@alerts` ausschließlich für echte Betriebsalarme steht und separat
scharf/stumm schaltbar bleibt? Oder bewusst alles über `@alerts` bündeln?
Bei Entscheidung "eigener Bot": Anlage per mas-cli wie gehabt, release-watch-Env
umziehen, Trivy-Anbindung (CI-Job → Matrix-Notiz bei Funden) gleich mit auf den
neuen Absender bauen.
## CFGMON-12 — Gitea-Projektmetadaten nach GitLab umziehen/integrieren
**Status:** abgelöst durch [gitops#46 auf git.lab](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/46) (ehemals Gitea-gitops#48, Tracker stillgelegt) (2026-08-01, sorb: HOHE Priorität — vollständige Issue-Migration + zentrale Gruppen-Roadmap; Plan-Skizze und die offene Erreichbarkeits-Entscheidung git.lab-only vs. extern stehen dort)
**Umgesetzt am 2026-08-01/02**: Die Migration ist durch — 62 Issues liegen auf
git.lab, die Gitea-Issues sind geschlossen und tragen einen Migrations-Fußtext.
Alles darunter ist der **Stand vor dem Umzug** und bleibt als Historie stehen;
die Aufzählung „Noch auf Gitea" gilt nicht mehr. Die zunächst verbliebene Ausnahme
für Deploy-Übergabe-Issues ist am 2026-08-02 mit LABNET-03 ebenfalls zurückgebaut.
---
Beim CI/CD-Umzug (2026-07-31) ist nur der **Code** nach git.lab gewandert; alle
Projektmetadaten liegen weiterhin auf Gitea/rohana. Verifiziert per API am
2026-07-31: alle 20 git.lab-Projekte melden `open_issues=0`.
Noch auf Gitea:
- **Issues** inkl. Kommentare/Labels: ThreadNet-Web (#2, #5, …), threadnet-call (#1),
gitops (#24, #25, #32, …)
- **Meilensteine** (u. a. die Release-Meilensteine im gitops-Repo)
- **Wiki** (gitops-Wiki mit `00-TASKS.md`-Log — bisher bewusst direkt-Gitea)
- **Releases/Packages** (npm-Registry bleibt laut Lockfile-Entscheidung in
[CFGMON-11](#cfgmon-11--gitea-ci-rückbau-nach-gitlab-umzug) auf rohana — bei
diesem Punkt prüfen, ob das so bleibt)
Vor Umsetzung zu klären:
1. **GitLab-Gitea-Importer vs. API-Skript** — der Importer verliert Autorenschaft
(alles läuft unter dem Import-User) und Issue-Nummern können sich verschieben
→ Commit-/Kommentar-Referenzen prüfen.
2. **Erreichbarkeit**: rohana ist von überall erreichbar, git.lab nur im Homelab —
das gilt dann für alle Issues und muss bewusst entschieden werden. Gleiches
Argument betrifft dieses Repo selbst (damals noch `Backlogs`, bewusst
direkt-Gitea).
3. **Flux-relevante Teile**: ob die gitops-Wiki-Konventionen mitgehen.
Nach dem Umzug gehört ein Hinweis in die Topologie-Abschnitte (gitops
README/CLAUDE.md, Fork-Docs) — dort steht aktuell „Issues/Wiki/Releases bleiben
auf Gitea" als geltende Regel.
---
## Erledigt
### CFGMON-10 — threadnet-call-CI schlägt am Artifact-Schritt fehl · verworfen 2026-07-30
Ausgelöst durch einen Push nach `threadnet-call` am 2026-07-30: der Runner (`builder-1`)
verarbeitete mehrere geerbte Upstream-Workflows, die meisten scheiterten am
Artifact-Upload/-Download-Schritt. Ursprünglich unverifizierte Hypothese: das
Job-Container-Limit (2,2 GiB / 1,5 CPU) ist zu knapp.
**Hypothese inzwischen im Kern bestätigt** — beim parallelen ThreadNet-Web-CI-Versuch
starb der webpack-Build bei 92 % mit `FATAL ERROR: ... JavaScript heap out of memory`
(Job 3442, 2026-07-30): diese Build-Klasse braucht real ~4 GB, der Host (3,7 GiB gesamt,
ohne Swap, trägt daneben Gitea/Traefik/Monitoring) kann das strukturell nicht liefern.
**Verworfen statt gefixt**: Limit-Anhebung/Swap wird bewusst nicht weiterverfolgt —
Build-CI zieht ins Homelab-GitLab um (siehe
[CFGMON-11](#cfgmon-11--gitea-ci-rückbau-nach-gitlab-umzug)), CFGMON bleibt bei leichten
Jobs. Issue-Seite: `threadnet-call#1` (Gitea-Zählung, Tracker stillgelegt).
### CFGMON-02 — Traefik, Gitea, cAdvisor und Runner unter IaC gebracht · erledigt 2026-07-30
Liefen ursprünglich im Compose-Projekt `thread-net-git` aus `/data/compose/8`, einem von
Portainer verwalteten Stack ohne Repo dazu. Jetzt in `sorb/thread-net-git`: `:latest`-Tags
gepinnt (Gitea `1.27.0`, cAdvisor `v0.49.1`), Projektname `thread-net-git` beibehalten
(Volume-Kontinuität), README mit Betriebsregeln ("nie wieder über Portainer anfassen",
Volume-Namen, Downgrade-Verbot für Gitea), nächtliches Backup-Script. Zusätzlich neu: ein
`runner`-Service (`gitea/act_runner:0.6.1`, Container `gitea-runner`, Labels
`ubuntu-latest`/`linux-build`/`win-wine` — die letzten beiden gezielt für Electron-Builds)
— ursprünglich unter [CFGMON-08](#cfgmon-08) als offene Frage gelistet, siehe dort.
Entstanden auf Branch `rework/stack`, zunächst nicht gemergt (produktiv aber schon aktiv).
**2026-07-30 nach `main` gemergt** (`origin/main` == `origin/rework/stack` auf `02b3224`,
verifiziert) — damit spiegelt die Standardansicht des Repos jetzt den Live-Stand.
Verifiziert am 2026-07-30 über die Compose-Labels der laufenden Container
(`working_dir: /opt/thread-net-git`) und `docker compose ls`. `gitea-data` ist als
external Volume deklariert — ein Deploy mit falschem Projektnamen schlägt laut fehl,
statt leise ein leeres Volume anzulegen.
Zum Bootstrapping-Problem (Definition von Gitea liegt in Gitea): mitigiert,
weil das Deploy-Verzeichnis selbst der Checkout ist — fällt Gitea aus, liegt
die Definition weiterhin lokal auf dem Host. Gegen Verlust des ganzen Hosts
hilft nur die Off-Host-Kopie, siehe
[CFGMON-09](#cfgmon-09--gitea-backups-off-host-in-die-storage-box-eigenes-borg-repo).
### CFGMON-05 — Monitoring-Stack unter IaC bringen · erledigt 2026-07-30
Der Stack lief aus `/opt/monitoring` ohne Versionierung und mit `:latest`-Tags. Jetzt
in `sorb/threadnet-operating` unter `monitoring/`, Images gepinnt,
Grafana-Datasources und 9 Dashboards provisioniert. Projektname `monitoring`
beibehalten, dadurch blieben die Volumes erhalten.
### CFGMON-06 — Grafana-Certresolver zeigte ins Leere · erledigt 2026-07-30
Das Label sagte `certresolver=le`, Traefik kennt den Resolver aber als
`letsencrypt`. Traefik protokollierte `Router uses a nonexistent certificate
resolver` und lieferte für `selendis.axion1337.de` sein Default-Self-Signed-Cert
aus. Aus dem Altbestand in `/opt/monitoring` unverändert übernommen und dort
mindestens seit dem 2026-07-27 vorhanden.
Behoben in `threadnet-operating`, Commit `a400f8a`. Cert von Let's Encrypt (YR2)
ausgestellt, gültig bis 2026-10-28 — die Nachfolge davon ist
[CFGMON-01](#cfgmon-01--zertifikatserneuerung-braucht-offene-ports-ipv4-und-ipv6).
### CFGMON-07 — Alloy verlor seine Positions-Datei bei jedem Deploy · erledigt 2026-07-30
`--storage.path=/var/lib/alloy/data` war gesetzt, aber ohne Volume: die
Positions-Datei lag im Container-Layer. Nach jedem Recreate las Alloy alle
Docker-Logdateien von vorn, worauf Loki alles älter als 7 Tage mit HTTP 400 abwies
(`timestamp too old`, `reject_old_samples`). Betroffen waren nur Alt-Logzeilen bis
zurück zu 2025, keine aktuellen Daten.
Behoben durch ein `alloy_data`-Volume, Commit `edac97e`. Verifiziert: Positions
überleben `--force-recreate`, zweiter Recreate erzeugt 0 Fehler.
### CFGMON-08 — Kein Gitea-Actions-Runner registriert, Standort noch offen · erledigt 2026-07-30
**Korrektur einer falschen Prämisse**: der Eintrag ging davon aus, dass gar kein Runner
existiert und wo einer laufen sollte, noch offen sei. Beides falsch — ein Runner
(`builder-1`) läuft bereits, auf CFGMON, als Teil von `thread-net-git`s `rework/stack`-
Branch, mit gezielt für Electron-Builds eingerichteten Labels. Details siehe
[CFGMON-02](#cfgmon-02--traefik-gitea-cadvisor-und-runner-unter-iac-gebracht--erledigt-2026-07-30) — hier
nicht dupliziert. `gitops#33` (Gitea-Zählung, Tracker stillgelegt)
(dieselbe falsche Prämisse) entsprechend korrigiert/geschlossen.
+91
View File
@@ -0,0 +1,91 @@
---
type: wiki-page
area: admin
related: []
---
# game
Pterodactyl- / Gameserver-Host.
| | |
|---|---|
| **IPv4** | `157.90.155.206` |
| **IPv6** | kein AAAA-Record |
| **DNS** | `game.axion1337.de` |
| **Privat** | `10.0.0.4` (im vSwitch seit 2026-08-02) |
| **Stand** | 2026-08-02 |
> **Teil-inventarisiert (2026-08-02).** Die Compose-Definitionen sind bekannt, der
> Host selbst wurde weiterhin nicht betreten — OS-Stand, Plattenbelegung und
> Docker-Version fehlen. Beim ersten direkten Zugriff nachtragen.
## Was darauf läuft
Zwei über **Coolify** deployte Stacks, abgebildet in
[axion1337.chat/game-operating](https://git.lab/axion1337.chat/game-operating)
(angelegt 2026-08-02).
⚠️ Das Repo ist ein **Abbild, keine Quelle**: Verwaltet wird weiter in Coolify,
Änderungen müssen dort *und* im Repo passieren. Der Umstieg auf git-basiertes
Deployment ist gewollt, aber bewusst **zurückgestellt, bis das Matrix-Projekt
abgeschlossen ist** (sorb, 2026-08-02). Bis dahin fehlen dem Abbild noch die
mitgemounteten Konfigdateien (`entrypoint.sh`, wings-Config, die drei
Monitoring-Konfigs) und die Volume-Deklarationen — **aus dem Repo allein ließe
sich der Host derzeit nicht wiederherstellen.**
**Pterodactyl** (Gameserver-Verwaltung, in Benutzung durch Bekannte des Betreibers
— Ausfälle und Datenverlust sind hier real spürbar):
| Dienst | Image |
|---|---|
| `pterodactyl` (Panel) | `ghcr.io/pterodactyl/panel:v1.12.0` |
| `wings` (Daemon, fährt die Gameserver als Docker-Container) | `ghcr.io/pterodactyl/wings:v1.12.0` |
| `mariadb` | `mariadb:11.8` |
| `redis` | `redis:alpine` |
**Eigener Monitoring-Stack** (grafana-oss, prometheus v3.0.0 mit 15 d Retention,
loki 3.1.1, promtail 3.1.1, node-exporter v1.8.1, cadvisor v0.49.2). Wird
perspektivisch von CFGMON abgelöst — siehe unten.
⚠️ **Kein einziger `ports:`-Block in beiden Stacks.** Alles hängt an Coolifys
Docker-Netz und ist nur containerintern erreichbar. Genau das war die Ursache von
GAME-01: Auf 9100/8080 des Hosts lauscht nichts, CFGMONs Scrape-Ziele auf der
öffentlichen IP konnten nie funktionieren.
## Erreichbarkeit von außen (gemessen)
Vor dem Host liegt eine **quellbewusste Firewall** — dieselben Ports verhalten sich
je nach Quelle unterschiedlich:
| Port | von CFGMON (`188.245.193.243`, 2026-08-01) | vom Hausanschluss (`178.25.213.70`, 2026-08-02) |
|---|---|---|
| 80 / 443 | offen | offen (HTTP 404 bzw. 503) |
| **22** | **Timeout** | **offen** |
| 8080 / 9100 (Exporter) | Timeout | Timeout |
| ICMP | 100 % Verlust | 100 % Verlust |
Daraus folgt zweierlei: Es gibt bereits eine **SSH-Freigabe für den Hausanschluss**,
und CFGMON ist **nicht pauschal gesperrt** (sonst wären auch 80/443 von dort tot) —
es ist eine portbezogene Regel mit Quellliste. Die Exporter-Ports 8080/9100 sind
dagegen **für niemanden** freigegeben, auch nicht für den Hausanschluss.
Es fehlte also keine Ausnahme für CFGMON. Seit 2026-08-02 liegt der Host im
vSwitch (`10.0.0.4`); die Monitoring-Anbindung läuft künftig **per Push über das
private Netz** — Alloy sammelt lokal ein und schiebt nach `10.0.0.3`, wodurch der
Host **keinen einzigen eingehenden Port** braucht. Dasselbe Muster wie beim
k3s-Cluster. Details: [GAME-01](https://git.lab/axion1337.chat/management/-/issues/2).
Die Umstellung erfolgt **additiv**: Der lokale Monitoring-Stack läuft weiter, bis
auf CFGMON über Wochen belastbar Daten liegen. Auf diesem Host wird nichts
abgeräumt, solange nicht klar ist, dass nichts fehlt.
## 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.
- [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)
+217
View File
@@ -0,0 +1,217 @@
---
type: wiki-page
area: admin
related: []
---
# matrix
Matrix-Homeserver (Element Server Suite / Synapse) + K3s-Single-Node-Cluster, GitOps-verwaltet.
| | |
|---|---|
| **Hostname** | `MATRIX` |
| **IPv4** | `49.13.132.245` |
| **IPv6** | kein AAAA-Record |
| **Privat** | `10.0.0.2` (`enp7s0`, dasselbe Hetzner-Netz wie CFGMON `10.0.0.3`) |
| **OS** | Debian 13 (trixie) |
| **DNS** | `matrix.axion1337.de` **und** `matrix.axion1337.chat` zeigen auf dieselbe IP — ebenso `axion1337.chat` (Apex) und `account.axion1337.chat` (MAS). `axion1337.de` ist die ältere/Registrar-Domain (IONOS-Mail läuft dort), `axion1337.chat` die eigentliche Matrix-Service-Domain. |
| **Stand** | 2026-07-30 |
**Inventarisiert** (direkter SSH-Zugriff, `~/.ssh/config`-Alias `axion1337`, Port 2248):
K3s + FluxCD + Element Server Suite (Synapse, MAS, Element Web, MatrixRTC), Authentik (OIDC),
Traefik, Cert-Manager, coturn, Draupnir, ClamAV, NetworkPolicies (Default-Deny). IaC-Repo:
[`sorb/axion1337.chat-gitops`](https://rohana.axion1337.de/sorb/axion1337.chat-gitops) - dieser
Host **ist** das Deployment-Ziel dieses Repos, nicht nur verwandt. Client-Forks:
`sorb/ThreadNet-Web` (Element Web), `sorb/threadnet-call` (Element Call/LiveKit-Widget).
`sorb/element-web` und `sorb/ThreadNet-Stack` sind **veraltete/abgelöste** Vorgänger-Repos
(letzte Aktivität 2026-05-11 bzw. 2025-10-24) - nicht mehr das, was hier läuft.
`ufw`: aktiv, Default Deny Incoming / Allow Outgoing, explizite Allow-Regeln für
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
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.
- [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
**Status:** erledigt (2026-08-01 ~04:10, vom Mac aus mit kubectl/SSH)
**Auflösung:** Beide Teile hatten dieselbe Wurzel — ein **doppelter node-exporter**.
Teil 1 bestätigt per Pod-Log: `listen tcp 0.0.0.0:9100: bind: address already in use`;
den Port hält der systemd-Dienst `prometheus-node-exporter` (der etablierte, den CFGMON
via `10.0.0.2:9100` scrapt). Teil 2 erklärt: der Cluster-Service "funktionierte" nur in
den Ready-Momenten des Crashloop-Pods, dessen hostNetwork-Endpoint (= Host-IP) zufällig
auf den gesunden systemd-Exporter zeigte; seit der Endpoint dauerhaft NotReady war,
setzte kube-proxy `no endpoints → REJECT`. ufw-Regeln seit April unverändert — kein
Firewall-Drift; extern war 9100 nie freigegeben (und soll es nicht sein).
**Fix (gitops `228807f`, Weg A aus gitops#45):** HelmRelease + Alloy-Scrape entfernt,
Flux hat gepruned — DaemonSet/Service/Pod sind weg, Host-Metriken kommen unverändert
vom systemd-Exporter. Volle Diagnose:
`gitops#45` (Gitea-Zählung, Tracker stillgelegt — verbindlich: Migrations-Fußtext im GitLab-Issue).
<details><summary>Ursprünglicher Befund (CFGMON-Session, vor der Host-Prüfung)</summary>
Von CFGMON aus diagnostiziert, per kube-state-metrics und den remote-geschriebenen Serien.
**Auf dem Host selbst wurde nichts geprüft** — CFGMON hat kein `kubectl`.
### Teil 1 — der Pod crasht seit Monaten (chronisch)
| Messwert | Stand 2026-08-01 |
|---|---|
| Pod `prometheus-node-exporter-4wwn7`, Restarts | **4880**, davon 1970 in 7 Tagen |
| Vorgängerpod `…-fv7hj`, Zählerstand vor 30 Tagen | 13918 |
| aktuelle Rate | ~12/h — entspricht dem CrashLoopBackOff-Deckel von 5 min |
| `last_terminated_reason` | `Error` (Exit ≠ 0, **kein** OOMKill) |
| `waiting_reason` / `ready` | `CrashLoopBackOff` / `0` |
Das besteht mindestens seit 30 Tagen, also **lange vor** dem Monitoring-Rework und vor dem
Alerting-Rollout. Neu ist nur die Sichtbarkeit: die Regel `KubePodRestartLoop` kam am
2026-08-01 dazu. Wie bei Synapse hat das Alerting einen stillen Altfehler aufgedeckt.
**Vermutete Ursache, nicht verifiziert:** Der Pod läuft mit `hostNetwork: true` und will
Port 9100 auf dem Host binden. Dort hört bereits ein **eigenständiger node-exporter**
derselbe, den CFGMON als Job `k3s_host_node` direkt auf `10.0.0.2:9100` scrapt und der
2706 Metriken sauber ausliefert. Zwei Exporter, ein Port; der Pod bekäme
`address already in use` und beendete sich sofort, was zu `reason: Error` ohne OOM passt.
Zum Bestätigen auf dem Host:
```
ss -lntp | grep :9100
kubectl -n monitoring logs prometheus-node-exporter-4wwn7 --previous | tail -20
```
### Teil 2 — der Cluster-Scrape ist am 2026-08-01 01:19 UTC ausgefallen (akut)
| Messwert | Stand |
|---|---|
| `up`-Mittel 24 h für `prometheus-node-exporter.monitoring.svc.cluster.local:9100` | 98,3 % |
| Zustandswechsel in 24 h | **1** — einmal runter, nicht zurück |
| Host-Uptime | 77,6 Tage → **kein Reboot** |
Ein Pod, der 12× pro Stunde stirbt, kann kein Target sein, das zu 98 % up ist. Geantwortet
hat also nie der Pod, sondern der eigenständige Exporter über die Host-IP. Der Pod hat
`hostNetwork`, sein Pod-IP ist die öffentliche `49.13.132.245`, dorthin zeigt der
Service-Endpoint — und dort kommt seit 01:19 nichts mehr.
Von CFGMON aus gemessen:
| Pfad | Ergebnis |
|---|---|
| `10.0.0.2:9100` (privat) | offen, 2706 Metriken |
| `49.13.132.245:9100` (öffentlich) | **keine Antwort** |
| `49.13.132.245:80` / `:443` | offen — Host lebt |
Ohne Reboot heißt das: in der Nacht wurde die Erreichbarkeit auf 9100 eingeengt. Zwei
Möglichkeiten, von hier aus nicht unterscheidbar:
1. Der Exporter bindet jetzt `10.0.0.2:9100` statt `0.0.0.0:9100`.
2. Eine `ufw`-Regel wurde geändert. Die Allow-Liste oben in dieser Datei führt 9100
ohnehin nicht auf — die private Zustellung muss also über eine Interface- oder
Subnetz-Regel laufen, an der sich etwas geändert haben kann.
Zeitlich fällt das exakt in das Fenster der Synapse-Port-Korrektur derselben Nacht. Wer
dort die Exposition aufgeräumt hat, hat den Cluster-Scrape-Pfad mitgenommen. Prüfen mit
`ss -lntp | grep :9100` und `ufw status numbered`.
### Fix — es ist ein node-exporter zu viel
**Weg B (empfohlen):** Den DaemonSet-Exporter abschalten (`nodeExporter.enabled: false` in
den kube-prometheus-stack-Values) und das Cluster-Alloy statt auf den Service-Namen direkt
auf `10.0.0.2:9100` zeigen lassen. Beendet den Crashloop und erhält die enge Bindung ans
private Netz, die in der Nacht vom 2026-08-01 gesetzt wurde.
**Weg A:** Den eigenständigen Exporter stilllegen und dem DaemonSet den Port überlassen.
Ebenfalls sauber, aber er bindet dann wieder `0.0.0.0` — also auch die öffentliche IP,
abgesichert nur noch durch `ufw` und die Cloud-Firewall. Das nähme die Einschränkung
zurück, die gerade erst gesetzt wurde.
### Nebenbefund — Job-Label kollidiert zwischen zwei Hosts
Das Label `prometheus.scrape.node_exporter` existiert zweimal, weil CFGMONs Alloy und das
Cluster-Alloy ihre Scrape-Komponente gleich benennen:
```
up=1 instance=node-exporter:9100 -> CFGMON (Kernel 6.8.0-136-generic)
up=0 instance=prometheus-node-exporter.monitoring.svc...:9100 -> MATRIX
```
Die Serien kollidieren nicht, `instance` trennt sie. Aber jede Abfrage, die nur nach `job`
filtert, mischt zwei Maschinen — und in Alarmtexten steht dann ein Job-Name, der nicht sagt,
welcher Host gemeint ist. Ein External Label auf der Remote-Write-Seite dieses Clusters
(`cluster="matrix"`) würde das sauber trennen.
---
</details>
## Erledigt
### MATRIX-01 — Klären, ob der Server Mail als `@matrix.axion1337.de` verschickt · erledigt 2026-07-30
Für `matrix.axion1337.de` existiert der komplette IONOS-Mail-Satz: `MX mx00/mx01`,
`TXT "v=spf1 include:_spf-eu.ionos.com ~all"`, `CNAME s1-ionos._domainkey` und
`CNAME autodiscover`. Bei `selendis` ist dasselbe Muster reine Altlast; hier war die Frage
offen, weil Matrix-Homeserver typischerweise Mail für Registrierung/Passwort-Reset
verschicken.
**Antwort, verifiziert per Config** (nicht nur vermutet) — direkt im IaC-Repo
`sorb/axion1337.chat-gitops`, dem tatsächlich hier deployten Stand geprüft:
- `apps/production/custom-configs/synapse-values.yaml` — kein `email:`/`smtp_host`/
`notif_from`-Block.
- `apps/production/custom-configs/mas-secret.yaml` (SOPS-entschlüsselt geprüft) — kein
`email`/`smtp`/`mailer`-Eintrag.
- `apps/production/element-server-suite.yaml` (HelmRelease values) — dito, nichts.
Weder Synapse noch MAS versenden aktuell irgendeine Mail. Registrierung/Passwort-Reset
laufen ausschließlich über Authentik (OIDC, `auth.axion1337.chat`) und Einladungslinks.
Der komplette IONOS-Mail-Satz auf `matrix.axion1337.de` ist damit **funktional unnötig**
dieselbe Härtung wie bei `selendis` anwenden (Null-MX, `v=spf1 -all`, `_dmarc p=reject`),
`autodiscover.matrix` kann ebenfalls weg. Damit ist auch
[ZONE-02](../architecture/zone-axion1337.md) an dieser Stelle entblockt.
**Separat davon** (andere Domain-Ebene, kein Widerspruch): auf diesem Host läuft seit
2026-07-30 ein eigener Mailversand für Host-Wartungsbenachrichtigungen
(`wartung@axion1337.de`, **Apex**-Postfach, nicht die `matrix.`-Subdomain) — siehe
MATRIX-04 unten. Nutzt die ohnehin am Apex laufende echte IONOS-Mail-Infrastruktur,
betrifft die `matrix.`-Subdomain-Records oben also nicht.
### MATRIX-02 — Pusht per Remote-Write auf einen offenen Prometheus · erledigt 2026-07-30
**Korrektur einer falschen Annahme im ursprünglichen Eintrag**: der Text ging von zwei
getrennten Absendern aus - "CFGMON (`10.0.0.3`) und der k3s-Host (`10.0.0.2`)" - als wären
das zwei verschiedene Maschinen. Es ist **dieselbe Maschine**: dieser Host (`matrix`) hat
selbst die private IP `10.0.0.2` (verifiziert per `ip -4 addr show` auf dem Host).
Verifiziert in `apps/monitoring/alloy-config.yaml` (diesem Cluster): Der Remote-Write-Push
geht bereits an `http://10.0.0.3:9090/api/v1/write` und Loki an `http://10.0.0.3:3100/...` -
**private IP, nicht die öffentliche** `188.245.193.243:9090`. Von dieser Seite aus ist hier
nichts mehr zu tun. Ob Prometheus/Loki auf CFGMON zusätzlich öffentlich erreichbar sind
(unabhängig davon, ob dieser Host den privaten Weg nutzt), ist
[CFGMON-03](cfgmon.md#cfgmon-03--prometheus-remote-write-und-loki-sind-öffentlich-ohne-auth)
- ein reines CFGMON-Thema, nicht mehr blockiert durch etwas auf diesem Host.
### MATRIX-04 — Host-Level Pre-Update-Benachrichtigung · erledigt 2026-07-30
Neuer, eigenständiger Mechanismus auf diesem Host, außerhalb von Flux/GitOps (Details:
`docs/deployment-guides/07-host-maintenance-notifications.md` im gitops-Repo,
`gitops#24` (Gitea-Zählung, Tracker stillgelegt)):
`unattended-upgrades` war bereits aktiv, neu ergänzt ist ein systemd-Timer
(`maintenance-notify.timer`, fest 05:00 Uhr, vor dem 06:00-07:00-Update-Fenster), der bei
anstehenden Paket-Updates per Mail **und** Matrix (Thread-Reply im `wartung`-Raum)
benachrichtigt.
Mail-Versand läuft über `msmtp`, Absender `wartung@axion1337.de` (IONOS SMTP,
`smtp.ionos.de:587`, STARTTLS - **Port 465 war ausgehend blockiert**, vermutlich
Cloud-Provider-Firewall-Regel, 587 ging durch). Relevant für die Mail-Policy-Diskussion
oben: dieses Postfach nutzt die reale, bereits am Apex laufende IONOS-Mail-Infrastruktur,
keine neue Subdomain, kein neuer Handlungsbedarf für die Zone.
+152
View File
@@ -0,0 +1,152 @@
---
type: wiki-page
area: admin
related: []
---
# Overmind
Homelab-Host: GitLab (Dokploy-verwaltet) + CI-Runner. **Nur im Lab erreichbar**
`git.lab` löst außerhalb des Homelabs nicht auf; Produktion (Flux auf CFGMON/MATRIX) hängt
nicht von diesem Host ab, nur neue Builds pausieren bei Ausfall.
| | |
|---|---|
| **Hostname** | `Overmind` |
| **DNS (Lab)** | `git.lab``10.58.73.17` (TLS via Dokploy-Proxy, Zertifikate von der aXionLabs-CA: step-ca, 24h-Leaf, Intermediate bis 2035) |
| **CPU/RAM** | 14 Kerne, 30 Gi (Stand 2026-07-31: ~11 Gi verfügbar) |
| **Disk** | 444 G NVMe (~278 G frei, Stand 2026-07-31) |
| **KVM** | `/dev/kvm` vorhanden — Basis für die Windows-Build-VM |
| **Stand** | 2026-07-31 |
## Dienste
| Dienst | Definition | Anmerkungen |
|---|---|---|
| GitLab CE 18.7.1 + Postgres 16 + Redis 7 | Dokploy-Stack `management-gitlabce` | `external_url https://git.lab`, SSH 2224; TLS terminiert der Dokploy-Proxy (GitLab-nginx lauscht nur :80) |
| gitlab-runner `lab-builder-1` (v18.7.0) | gleicher Stack, Service `gitlab-runner` | Docker-Executor + Socket, `concurrent = 1`. **Stolpersteine, live gefunden**: (1) Docker-interner DNS löst `git.lab` auf den GitLab-Container auf, wo 443 zu ist → `extra_hosts: git.lab:10.58.73.17` nötig; (2) Lab-CA muss nach `/etc/gitlab-runner/certs/git.lab.crt` (Config-Volume, übersteht Redeploys) |
| gitlab-runner `lab-windows-1` | Windows-Gast in der Build-VM | Tags `[windows]`, `run_untagged=false`, Shell-Executor PowerShell — siehe Runbook |
| Windows-Build-VM | Dokploy-Stack `windows-runner` (live seit 2026-07-31) | Image `registry.git.lab/axion1337.chat/vendor/windows:stable` (Eigenbau aus reviewtem Pin `7645a2b`, Vendor-Repo `git.lab/axion1337.chat/vendor/windows`), **on-demand** (`restart: "no"`, Start/Stop über CI-Jobs), 8G/6 Kerne/96G. Runbook: `docs/axion-runner.md` im Vendor-Repo. Gast-Uhr geht falsch (Traces stempeln ~+7h) — kosmetisch |
## Repo-Topologie (Kontext)
git.lab ist seit 2026-07-31 **kanonisch** für die gespiegelten Repos der Gruppe
`axion1337.chat` — Stand 2026-08-09 **sieben**: die sechs Produkt-Repos (ThreadNet-Web,
threadnet-call, thread-net-git, threadnet-operating, axion1337.chat-gitops, seit heute auch
`game-operating`) **und `management`, also dieses Repo**. Push-Mirrors nach rohana/Gitea,
direkte Gitea-Pushes tabu.
⚠️ `gameserver` (achtes Projekt der Gruppe) hat **keinen** Mirror — offen in
[management#32](https://git.lab/axion1337.chat/management/-/issues/32), dort liegt auf Gitea
ein gleichnamiges Repo mit anderem Stand.
Gitea bleibt: Flux-Source (via Mirror beliefert), Registry, Packages.
**Issues nicht mehr** — die sind am 2026-08-01/02 nach git.lab gewandert
([ADR-0002](../../adr/0002-issues-und-management-ins-lab.md)). Die letzte Ausnahme,
die Deploy-Übergabe-Issues auf dem Gitea-Tracker `sorb/management`, ist am 2026-08-02
mit LABNET-03 zurückgebaut: beide umgezogen (#25, #26), der Tracker ist leer.
**Ohne Ausnahme: Issues leben auf git.lab.**
*(Bis 2026-08-01 stand hier „Backlogs (dieses Repo, ungespiegelt)" — das Repo heißt
seit der Umwidmung zum Management-Repo `management` und wird seither gespiegelt,
[ADR-0005](../../adr/0005-pm-framework-kanban.md).)*
## OVERMIND-01 — GitLab-Container-Registry aktivieren, Images nach Konsument sortieren
**Status:** erledigt (2026-08-01)
**Abschluss-Verifikation**: `desktop_image` baut und pusht per `CI_JOB_TOKEN` nach
`registry.git.lab/axion1337.chat/threadnet-web/desktop-build:bullseye` (Job 386 grün,
Tag per API bestätigt); `desktop_linux` nutzt dieses Image als Job-Container und lief
damit grün durch (Job 398 - beweist auch den anonymen Pull des public Projekts durch
den Runner-Daemon). Die rohana-`REGISTRY_*`-Variablen bleiben nur noch für den
App-Image-Push (`docker_web`) in Gebrauch - genau die Ziel-Sortierung nach Konsument.
Die eingebaute GitLab-Registry ist aus (kein `registry_external_url` im Omnibus-Config).
Folge: lab-interne Build-Images (`windows-vm`, `element-desktop-build`) machen den Umweg
Lab-CI → rohana (Prod, Internet) → zurück ins Lab — koppelt Lab-Infrastruktur unnötig an
die Verfügbarkeit des Prod-Hosts.
**Ziel-Sortierung nach Konsument:**
- **rohana (Gitea) behält**: `sorb/threadnet-web` (App-Image — Flux/Prod pullt es),
npm-Packages
- **Lab-Registry (`registry.git.lab`) bekommt**: `windows-vm`,
`element-desktop-build` — beides konsumiert nur das Lab selbst
**Umsetzung** (TLS terminiert wie bei `git.lab` der Dokploy-Proxy):
1. Omnibus-Config: `registry_external_url 'https://registry.git.lab'`,
`registry_nginx['listen_port'] = 5050`, `registry_nginx['listen_https'] = false`;
Port 5050 in der Compose exposen
2. Lab-DNS: `registry.git.lab``10.58.73.17`
3. Dokploy: Domain `registry.git.lab` → GitLab-Service Port 5050 (Zertifikat von der
aXionLabs-CA wie gehabt)
4. Docker-Daemon-Trust auf Overmind: CA-Kette nach
`/etc/docker/certs.d/registry.git.lab/ca.crt` (Datei liegt schon als
`/tmp/git.lab.crt` vom Runner-Setup — kopieren reicht; kein Daemon-Restart nötig)
5. CI-Umstellung: `vendor/windows` pusht nach `registry.git.lab` (Bonus: GitLabs
eingebaute `$CI_REGISTRY`/`$CI_JOB_TOKEN`-Auth statt Gruppen-Secrets),
`desktop_image`/`desktop_linux` in ThreadNet-Web folgen; Registry-Speicher liegt im
`gitlab_data`-Volume (278 G frei)
**Fortschritt 2026-07-31**: Punkte 14 umgesetzt (Registry live auf
`registry.git.lab`, 401/Bearer-Auth korrekt, CA-Trust auf dem Host); `vendor/windows`
pusht per `CI_JOB_TOKEN` in die Lab-Registry — verifiziert, Tags `5bc25447` + `stable`
vorhanden, Runbook referenziert `stable`.
**Nächster Schritt:** `element-desktop-build` von rohana in die Lab-Registry umziehen
(ThreadNet-Web-CI: `desktop_image`-Push-Ziel + `desktop_linux`-Image-Referenz) — bewusst
zurückgestellt, bis kein Auto-Job das alte Image parallel referenziert (Reihenfolge:
erst neues Image bauen, dann Referenz umstellen).
## OVERMIND-02 — Host-Ausfall 2026-07-31 ~19:15 lokal (NIC-Hang, Fix aktiv)
**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
(bekanntes e1000e-Problem in Kombination mit EEE/Energiesparen), der Host lief weiter,
war aber netzwerktot. Kein OOM, kein Bezug zur Windows-VM/CI. Passt zu allen Symptomen:
Ping tot, aber der Windows-Runner erreichte GitLab host-intern noch (Job 413 wurde
aufgegriffen) und scheiterte erst an der DNS-Auflösung übers tote Interface.
**Fix (2026-07-31, Overmind-Session):** `ethtool --set-eee eno1 eee off` live gesetzt
+ persistente udev-Regel `/etc/udev/rules.d/71-disable-eee-eno1.rules` (greift bei
jedem Boot). Temporäre sudoers-Freigabe danach wieder entfernt.
**Offen:**
- ~~NIC-/BIOS-Firmware-Update 2.4.0.0 → 2.5.2.0~~ **erledigt** (Wartungsfenster
2026-08-01, durch sorb)
- Falls der Hang trotz EEE-off + neuer Firmware wiederkehrt: gezielter ASPM-Fix
statt globalem Kernel-Parameter
**Zeitleiste (lokal, UTC+2):**
- 18:58 — Windows-VM nach händischem Container-Stop+Start zurück, Runner online
- 19:00 — desktop_windows Job 399 (Versuch 5): läuft bis `build:native`, scheitert an
fehlendem rustc (kein Host-Problem)
- 19:0519:12 — Provision-Job 409 grün (Rust 1.97.1 maschinenweit, Strawberry Perl,
Python 3.14, NASM-PATH), Dienst-Neustart via Scheduled Task funktionierte
- 19:13/19:14 — letzte saubere Runner-Herzschläge
- **zwischen 19:14 und 19:21 — Host fällt aus**: Ping 100 % Verlust, git.lab-API tot
- 19:21 — Job 413 (Versuch 6) wird noch aufgegriffen, Git-Fetch scheitert nach 8 s mit
`Could not resolve host: git.lab` → Host-Netz/DNS zu dem Zeitpunkt bereits kaputt;
danach Funkstille
- ~20:15 — Host pingt wieder (Reboot durch sorb), 20:21 GitLab-API zurück,
lab-builder-1 online; windows-runner-Container down (`restart: "no"` — korrekt)
**Wichtig:** Der Windows-Build war NICHT die Ursache — Job 413 hat nie Quellcode
geholt, die VM lief nur idle (frisch provisioniert; denkbare Gast-Hintergrundlast:
Windows Update/Defender nach den choco-Installs). Die 8-G-Zuteilung der VM plus
GitLab-Stack blieb aber auch nach dem Puma-Fix ein enges Budget auf 30 Gi.
**Konsequenz für die Build-Kette:** RAM-Budget war nicht das Problem — VM bleibt bei
8G. Nach dem NIC-Fix lief die Kette durch: **desktop_windows Job 438 grün**
(2026-07-31 ~21:50 lokal, `Element Setup 1.12.17.exe`, 141 MB, unsigniert) —
ThreadNet-Web#5 geschlossen, Folgethemen (Signing/Branding) in ThreadNet-Web#6.
Auf dem Weg dahin zusätzlich gefixt: GitHub-CDN-Abrisse bei app-builder-Downloads
(resumefähiges Prefetch-Skript im ThreadNet-Web-Repo, Jobs 415/416/424/431).
---
Weitere CI-Betriebsthemen laufen über die Projekt-Issues (ThreadNet-Web#5
Windows-Strecke, threadnet-call#1 npm-Ziel) und CFGMON-11 (Gitea-CI-Rückbau).
+100
View File
@@ -0,0 +1,100 @@
---
type: wiki-page
area: admin
related: []
---
# Refinement und Retro — die Termine des Frameworks
Kanban braucht wenige, aber verlässliche Termine, sonst verkommt das Board zur
Ablage. Festgelegt in [ADR-0005](../../adr/0005-pm-framework-kanban.md); hier
steht, wie sie ablaufen.
## Termine (festgelegt im Struktur-Workshop, 2026-08-06)
| Termin | Wann |
|---|---|
| **Refinement** | **sonntagabends**, wöchentlich, 3045 min |
| **Retro light** | im **ersten Refinement des Monats**, +2030 min |
Sonntag, weil die GitLab-Backups dort ohnehin laufen (00:00) — die Woche hat an
dieser Stelle eine Kante, und die Abendblöcke, in denen real gearbeitet wird,
liegen meist am Wochenende.
Die Retro bekommt **keinen eigenen Termin**: Ein monatlicher Extra-Termin im
Solo-Betrieb ist ein Termin, der ausfällt. Sie hängt sich an das erste Refinement
des Monats an — dann ist die Vorbereitung (die AARs des Monats) ohnehin offen.
## Refinement (≈ wöchentlich, 3045 min)
Der eine Termin, der das System am Leben hält. Immer dieselbe Reihenfolge:
1. **Board von rechts nach links lesen** — zuerst `status:doing`: Läuft es noch,
oder ist es in Wahrheit blockiert? Dann `status:wartet`: Wartet es noch auf das,
was im Issue steht? Erst zuletzt `status:next`.
2. **WIP-Limit prüfen** — höchstens zwei Issues in `doing`. Ist es voll, wird nichts
Neues gezogen; stattdessen wird gefragt, was das Laufende blockiert.
3. **Nachziehen** — freie Plätze aus `next` füllen, `next` aus dem Backlog auffüllen.
Auswahlkriterium ist nicht Priorität allein, sondern **was still kaputtgeht**
(Fristen, abgeschaltete Schutzmechanismen) vor **was nervt** vor **was Spaß macht**.
4. **Entscheidungsvorlagen** — offene Fragen, die eine Entscheidung von sorb brauchen,
werden als Optionen mit Empfehlung vorgelegt, nicht als offene Fragen geparkt.
Dauerhafte Ausnahmen von Regeln werden hier zu ADRs.
5. **Datumspflicht prüfen** — jedes zeitkritische Issue trägt ein Datum, kein „bald".
## Retro light (≈ monatlich, 2030 min)
Drei Fragen, mehr nicht:
- Welche **Verfahren** haben diesen Monat getragen, welche haben gestört?
- Welche **ADRs** sind durch die Realität überholt (→ neues ADR, altes auf
„abgelöst durch")?
- **Fasert etwas aus?** Gibt es wieder Arbeit, die nur in Chatverläufen lebt?
Grundlage sind die AARs des Monats — sie sind die Retro-Vorbereitung, nicht ihr
Ersatz.
Ergebnisse werden unter [`docs/sources/protokolle/`](../../sources/protokolle/retro-2026-08-09.md) abgelegt, eine Datei je Termin. Die
erste: [2026-08-09](../../sources/protokolle/retro-2026-08-09.md).
## AAR (anlassbezogen)
Nach jedem Deploy mit Übergabe und nach jedem Incident, Vorlage in
[docs/aar/template.md](../../aar/template.md). Ein AAR ist keine Chronik, sondern ein
Wissensspeicher: Was war das Ergebnis, welche Befunde, was hat die Eingrenzung
ermöglicht, welche Lehren, was bleibt offen. **Offene Punkte aus einem AAR werden
im selben Zug zu Issues** — sonst versacken sie in der Prosa (real passiert am
2026-08-01, nachgezogen als #14#16).
## Board-Pflege, wenn sorb länger nicht dazukommt
Festgelegt 2026-08-06. Eine Session darf das Board **abbilden**, aber nichts
**zusagen**:
| erlaubt | nicht erlaubt |
|---|---|
| `status:wartet` setzen (mit benanntem Grund) | nach `status:doing` ziehen |
| Erledigtes schließen, mit Begründung im Issue | `status:next` vergeben |
| Fristen ins `due_date`-Feld nachtragen | Prioritäten umsortieren |
| Befunde als neues Issue anlegen | Milestones neu zuordnen |
Die Trennlinie ist nicht Vorsicht, sondern Bedeutung: `doing` und `next` sind die
**Zusage-Spalten** — sie sagen, was als Nächstes wirklich passiert. Das entscheidet
sorb. Alles links davon bildet nur ab, was ohnehin schon der Fall ist.
**Jede Änderung wird im Issue begründet**, nicht still vorgenommen. Ein Board, dem
man nicht ansieht, wer warum etwas verschoben hat, ist beim nächsten Refinement
wertlos.
## Zusammenspiel mit den Sessions
Mehrere Claude-Sessions arbeiten parallel (Mac-Session, Host-Sessions auf CFGMON
und Overmind). Für sie gilt:
- Die **kanonischen Arbeitskonventionen** stehen in [`CLAUDE.md`](../../../AGENTS.md) und
sind über den Gitea-Mirror von überall lesbar.
- Arbeit zwischen Sessions läuft über das
[Deploy-Übergabe-Verfahren](../deployment/deploy-uebergabe.md) — Auftrag, Meldung, Protokoll
im Issue, nicht im Chat.
- Was eine Session lernt, gehört ins Repo (AAR/ADR/Doku), nicht nur in ihr
Gedächtnis — Sessions gehen verloren, Repos nicht.
+77
View File
@@ -0,0 +1,77 @@
---
type: wiki-page
area: admin
related: []
---
# Stillstandsprüfung
Sucht Dinge, die **leise aufgehört haben zu funktionieren**. Beschlossen in der
[Retro 2026-08-09](../../sources/protokolle/retro-2026-08-09.md).
## Warum es sie gibt
In neun Augusttagen sind sechs Fehler aufgefallen, die alle dasselbe Merkmal
hatten: Sie sahen erfolgreich aus, ohne es zu sein — eine grüne Pipeline, die nie
ein Artefakt hochlud; ein veröffentlichtes npm-Paket ohne Inhalt; ein Blueprint,
der bei jedem Lauf verworfen wurde, während Flux grün meldete.
**Keiner davon wurde durch eine Überwachung gefunden.** Vier durch Zufall beim
Suchen nach etwas anderem. Genau diese Lücke schließt das Skript.
## Was geprüft wird
Jede Prüfung bildet einen **real passierten** Fall ab. Nichts steht hier auf
Vorrat.
| Prüfung | Der Fall dahinter |
|---|---|
| Repo ohne aktiven Push-Mirror | `game-operating` wurde angelegt und nie gespiegelt — auf Gitea existierte es nicht |
| Mirror-Drift | MIRROR-01 (management#28): fällt der Mirror aus, liefert Flux still den letzten Stand weiter |
| Pipeline mit null Jobs | ThreadNet-Web 203/204, threadnet-call 187 — rot, ohne dass etwas kaputt war |
| Erfolgreicher Job ohne Artefakt | `build_embedded` lief seit jeher grün und lud **nichts** hoch |
| npm-Paket zu klein | `0.19.2-threadnet.6`: 12,5 KB statt 12,8 MB, ohne `dist/` |
| Authentik-Blueprint ≠ successful | `matrix-recovery-flow` wurde tagelang bei jedem Lauf verworfen |
Die Projektliste wird **zur Laufzeit aus der Gruppe gelesen**, nicht im Code
gepflegt — eine Liste im Quelltext wäre genau die Stelle, an der ein neues Repo
jahrelang durchrutscht. (Beim ersten Lauf kamen so zwei Projekte zum Vorschein,
die niemand auf dem Schirm hatte.)
## Wie sie läuft
Geplanter CI-Job im management-Repo, zusätzlich von Hand über *Run pipeline*
auslösbar. Befunde färben die Pipeline **rot** — das ist bei uns die Alarmanlage,
nicht ein zusätzlicher Meldeweg (siehe `gitops/CLAUDE.md` zur TURN-Rotation).
Lokal:
```bash
export GITLAB_TOKEN=$(cat ~/.config/gitlab-lab/token)
export GITEA_TOKEN=$(cat ~/.config/gitea-rohana/push-token) # fuer private Spiegel
export LAB_CA=.../ci/lab-ca-chain.crt
python3 scripts/stillstandspruefung.py
```
## Zwei Regeln für diese Prüfung
**Ein „kann nicht geprüft werden" ist ein Befund, kein Übersprungen.** Real
aufgefallen am 2026-08-09: `game-operating` wurde auf Gitea privat gestellt, und
die Prüfung übersprang den Mirror-Abgleich klaglos. Ein Repo, das gespiegelt wird,
dessen Gegenseite aber unlesbar ist, ist **ungeprüft** — und das darf nicht wie
„in Ordnung" aussehen.
**Ein Befund wird zum Issue, nicht weggeklickt.** Sonst wird die Prüfung zu dem,
was sie sucht: etwas, das läuft, ohne dass jemand hinsieht.
⚠️ **Fehlt ein Zugang, bricht sie ab — sie überspringt sich nicht still.** Eine
Prüfung, die sich bei fehlendem Token selbst deaktiviert, ist wertlos: Sie meldet
dann jahrelang nichts, und niemand merkt den Unterschied zu „alles in Ordnung".
Ausnahme sind die klar benannten optionalen Teile (Authentik), die ihr Fehlen im
Ergebnis ausweisen.
## Erweitern
Neue Prüfungen kommen dazu, **wenn wieder etwas still ausgefallen ist** — mit einem
Docstring, der den konkreten Fall nennt. Prüfungen auf Verdacht erzeugen Rauschen
und kosten die Glaubwürdigkeit, die diese hier braucht.
+122
View File
@@ -0,0 +1,122 @@
---
type: wiki-page
area: admin
related: []
---
# Textbausteine für Sessions
Kurze, kopierbare Blöcke, die man einer Claude-/Agenten-Session voranstellt.
Die Konventionen stehen kanonisch in [`CLAUDE.md`](../../../AGENTS.md) — aber eine
Session liest sie nur, wenn sie dazu aufgefordert wird. Diese Bausteine sind die
Aufforderung.
## Zwei Regeln für diese Datei
**Die Bausteine verweisen auf die Regeln, sie wiederholen sie nicht.** Stünden die
Regeln hier ausgeschrieben, gäbe es eine zweite Fassung, die driftet — real
passiert am 2026-08-02, als `gitops/CLAUDE.md` „keine Gitea-Ausnahme mehr" behauptete,
während die `management/CLAUDE.md` zwei nannte.
**Höchstens acht Zeilen je Baustein.** Der Test ist banal: Wer zum Kopieren scrollen
muss, benutzt es nicht. Was länger wäre, gehört in die CLAUDE.md — nicht hierher.
---
## 1 · Session-Start (Mac, mit Lab-Zugang)
```
Lies zuerst CLAUDE.md im management-Repo auf git.lab und halte dich daran.
Kanonisch ist git.lab; nie direkt nach Gitea pushen.
Alles Offene wird zum Issue, nicht zur Chat-Notiz — auch Nebenbefunde.
Bevor du ein Issue schließt oder darüber urteilst: vollständig lesen, inklusive
Kommentare.
Bevor du aus einer Vorlage/Spezifikation ableitest: die Quelle öffnen, nicht raten.
Verifiziert und vermutet klar trennen; fremde Messungen als fremde kennzeichnen.
```
> Die letzten drei Zeilen stehen hier, weil genau das dreimal an einem Tag
> schiefging: erfundene Theme-Paletten statt gelesener Skill-Quelle; ein Sweep nach
> dem Pfad `sorb/Backlogs` statt nach dem Namen `Backlogs`; und ein Issue, von dem
> 750 von 1237 Zeichen gelesen wurden — samt übersehenem Korrekturkommentar, der
> seit 16 Stunden darunterstand.
## 2 · Host-Session (CFGMON, MATRIX — ohne Lab-Zugang)
```
Du arbeitest auf einem Hetzner-Host ohne direkte Lab-Route.
Konventionen: CLAUDE.md im management-Repo — von hier lesbar über den Gitea-Mirror
rohana.axion1337.de/sorb/management. Dort NUR lesen, niemals hinpushen.
Für git.lab (Issues, Pushes) muss sorb erst den Site-to-Site-Tunnel einschalten.
git.lab-API: PRIVATE-TOKEN-Header — .netrc gilt nur für clone/push (sonst 401,
bei privaten Projekten irreführend 404, sieht aus wie "Projekt gibt es nicht").
Ping auf 10.58.73.17 schlägt IMMER fehl (nur 443 + DNS offen), das ist kein
Tunnelproblem — prüfen mit: curl https://git.lab/users/sign_in
```
> Soll in dieser Session etwas ausgerollt werden, kommt **Baustein 3** dazu — der
> Deploy-Weg samt AAR-Pflicht steht dort, nicht hier, damit dieser Block kurz bleibt.
## 3 · Deploy-Übergabe
```
Öffne auf git.lab ein Issue aus der Vorlage "Deploy-Übergabe"
(Feld "Description template") und fülle ALLE Felder — Verfahren und Begründung
je Feld: verfahren/deploy-uebergabe.md.
Pflicht: Stand (Repo/Branch/Commit) · Testtiefe (ehrlich, "ungetestet" ist gültig)
· Mengengerüst (geschätzt oder gemessen, dazuschreiben welches) · vollständiges
Deploy-Kommando inkl. Reload/Recreate · Verifikation DORT WO DER DIENST LIEST
· Außenwirkung und Not-Aus · Rollback · bewusst offen Gelassenes.
Wo nichts zutrifft: "-" eintragen, nicht das Feld löschen.
```
## 4 · Abschluss einer Session
> **Dieser Baustein ist zugleich unsere Definition of Done für Änderungen ohne
> Deploy** (festgelegt 2026-08-06). Für Deployments gilt weiterhin das
> [Übergabe-Verfahren](../deployment/deploy-uebergabe.md) — das ist die längere DoD.
>
> Bewusst kein eigenes DoD-Dokument: Es wäre die dritte Fassung derselben Regeln
> und damit die dritte, die driften kann.
```
Vor dem Ende prüfen und benennen:
- Alle Commits über git.lab gepusht, kein Rest im Arbeitsverzeichnis, Mirror grün.
- Jeder offene Punkt und Nebenbefund ist ein Issue — nichts bleibt nur im Chat.
- Zeitkritisches trägt ein Datum im due_date-Feld, nicht nur im Fließtext.
- Genau ein status:*-Label je angefasstem Issue; status:wartet nur mit Grund.
- Gedächtnis aktualisiert: nur was kein Repo festhält.
- Wiederaufsetzpunkt in einem Satz: Was ist als Nächstes dran, und wer ist dran?
```
## 5 · Entscheidungsvorlage
```
Leg mir das als Entscheidung vor, nicht als offene Frage:
24 Optionen, je eine Zeile Konsequenz, und deine Empfehlung zuerst mit Begründung.
Sag dazu, was du gemessen und was du angenommen hast.
Wenn die Entscheidung eine dauerhafte Ausnahme von einer Regel schafft, ist sie
ADR-pflichtig (decisions/, siehe CLAUDE.md) — dann leg die ADR gleich mit vor.
```
---
## Wann welcher
| Situation | Baustein |
|---|---|
| Neue Session auf dem Mac | 1 |
| Session auf CFGMON/MATRIX/game | 2 |
| Etwas gebautes soll ausgerollt werden | 3 |
| Session neigt sich dem Ende | 4 |
| Eine Frage braucht sorbs Entscheidung | 5 |
Bausteine 1 und 2 schließen sich aus; 35 kommen anlassbezogen dazu.
## Pflege
Ein Baustein wird ergänzt, wenn **derselbe Fehler zweimal** passiert ist — nicht
vorsorglich. Sonst wachsen sie, bis sie niemand mehr kopiert, und dann wirken sie
gar nicht mehr. Wächst einer über acht Zeilen, gehört der Inhalt in die CLAUDE.md
und hier bleibt der Verweis.