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>
218 lines
11 KiB
Markdown
218 lines
11 KiB
Markdown
---
|
||
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.
|