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:
co-authored by
Claude Fable 5
parent
70e81e2ff1
commit
92b448fe30
@@ -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.
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
@@ -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 1–4 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:05–19: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).
|
||||
@@ -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, 30–45 min |
|
||||
| **Retro light** | im **ersten Refinement des Monats**, +20–30 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, 30–45 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, 20–30 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.
|
||||
@@ -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.
|
||||
@@ -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:
|
||||
2–4 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; 3–5 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.
|
||||
@@ -0,0 +1,220 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: architecture
|
||||
related: []
|
||||
---
|
||||
|
||||
# Branding: Marke, Farben, Bildsprache
|
||||
|
||||
Übergreifend, weil dieselben Farben in mehreren Oberflächen eingestellt werden
|
||||
(Chat-Clients, Wikis, künftige Dienste) und sich das nicht pro Host oder Linie
|
||||
trennen lässt: **Bestand** (welche Farbe wo eingetragen ist) und **Historie**
|
||||
(was wann warum geändert wurde).
|
||||
|
||||
Hier im `management`-Repo, weil es als einziges der beteiligten Repos
|
||||
**gespiegelt** ist und jede Werkzeugentscheidung überlebt: Wird das
|
||||
BookStack-Experiment nach [ADR-0007](../../adr/0007-wiki-oberflaeche-docusaurus-vs-bookstack.md)
|
||||
abgeräumt oder ein Client ersetzt, bleiben Marke und Paletten bestehen.
|
||||
|
||||
## Bildmarke
|
||||
|
||||
`threadnet-mark.png` (Bildmarke) und `threadnet-logo-wortmarke.png` (mit
|
||||
Schriftzug), erstellt von sorb. Sie liegen im Wiki-Repo unter `static/img/` und
|
||||
sind die Quelle für alle abgeleiteten Formate — Favicon, App-Icons für macOS,
|
||||
Windows und Linux, Web-Icons.
|
||||
|
||||
⚠️ Beim Ableiten den **transparenten Rand wegschneiden** und mit `resize()`
|
||||
skalieren, nicht mit `thumbnail()` — Letzteres verkleinert nur und lässt das Motiv
|
||||
in großen Icons als Briefmarke zurück (real passiert, siehe
|
||||
[AAR 2026-08-02](../../aar/2026-08-02-wiki-und-desktop-clients.md)).
|
||||
|
||||
⚠️ **Und danach mittig setzen — das ist ein zweiter, eigener Schritt.** Beim ersten
|
||||
Anlauf wurde nur beschnitten und skaliert: Das Motiv füllte 81 % der Breite, saß
|
||||
aber mit 3 % Rand oben und 40 % unten an der Oberkante. In runden und quadratischen
|
||||
Icon-Slots fällt das sofort auf. Korrigiert am 2026-08-06 auf 21 % oben wie unten.
|
||||
|
||||
**Das Rezept, das jetzt gilt:** Bounding-Box des Motivs ermitteln, darauf
|
||||
beschneiden, auf ~81 % der Kantenlänge skalieren, auf einer quadratischen,
|
||||
transparenten Fläche **mittig einsetzen**. Alle Größen aus *derselben* Quelldatei
|
||||
ableiten — dann können sie nicht auseinanderlaufen.
|
||||
|
||||
### Wo überall Icons liegen
|
||||
|
||||
Elf Artefakte, alle aus einer Quelle (Stand 2026-08-06, `v0.4.0`):
|
||||
|
||||
| Ort | Was |
|
||||
|---|---|
|
||||
| `apps/web/res/vector-icons/` | 1024, 512, 180, 152, 144, 120, 24 px |
|
||||
| `apps/desktop/build/icon.png` | App-/Installer-Icon |
|
||||
| `apps/desktop/build/icon.ico` | Windows, 7 Größen von 16 bis 256 |
|
||||
| `apps/desktop/build/icon.icns` | macOS, via `iconutil` aus einem `.iconset` |
|
||||
| `apps/desktop/build/icon.icon/Assets/element.png` | Layer des macOS-Icon-Composers |
|
||||
|
||||
Prüfen lässt sich die Gleichheit über die Prüfsumme von `vector-icons/1024.png`
|
||||
gegen `build/icon.png` — weichen sie ab, ist eine Seite nachgezogen worden und die
|
||||
andere nicht.
|
||||
|
||||
## Paletten
|
||||
|
||||
### aXion1337 Dark — das Stammschema
|
||||
|
||||
Gruvbox Dark. Grundtöne `#282828` / `#1d2021`, Text `#ebdbb2`, Akzent `#bd93f9`,
|
||||
Sekundär `#fe8019`. Die acht Username-Farben sind der Gruvbox-Satz.
|
||||
**`aXion1337 Light` ist das exakte helle Gegenstück** (Gruvbox Light) — gleiche
|
||||
Rollenverteilung, gespiegelte Helligkeitsachse. Wer eines ändert, zieht das andere
|
||||
mit.
|
||||
|
||||
### Terrakotta-Beige — sorbs BookStack-Schema
|
||||
|
||||
Am 2026-08-02 in der BookStack-Oberfläche eingestellt und von dort extrahiert
|
||||
(die Werte stehen als CSS-Variablen im ausgelieferten HTML). Fünf der sieben sind
|
||||
der Coolors-Satz `#264653 · #2A9D8F · #E9C46A · #F4A261 · #E76F51`:
|
||||
|
||||
| Rolle in BookStack | Wert | Ton |
|
||||
|---|---|---|
|
||||
| Primäre Farbe | `#264653` | Charcoal |
|
||||
| Standard-Linkfarbe | `#5f757b` | gedämpftes Blaugrau |
|
||||
| Regalfarbe | `#e76e51` | Burnt Sienna |
|
||||
| Buchfarbe | `#e9c46a` | Saffron |
|
||||
| Kapitelfarbe | `#f3a261` | Sandy Brown |
|
||||
| Seitenfarbe | `#77bb41` | Grün |
|
||||
| Seitenentwurfsfarbe | `#e32400` | Rot |
|
||||
|
||||
Bemerkenswert: **dieses von Hand eingestellte Schema ist bis auf zwei Ziffern die
|
||||
offizielle Sunset-Boulevard-Palette** (siehe nächster Abschnitt) — `#e76e51` statt
|
||||
`#e76f51`, `#f3a261` statt `#f4a261`. Beide Wege sind unabhängig voneinander auf
|
||||
demselben Coolors-Satz gelandet. Die Irritation an der ersten Theme-Fassung war
|
||||
also berechtigt und ließ sich an der Originalquelle belegen.
|
||||
|
||||
### theme-factory — die zehn benannten Themes
|
||||
|
||||
Quelle ist Anthropics [theme-factory-Skill](https://github.com/anthropics/skills/tree/main/skills/theme-factory):
|
||||
je Theme vier Farben plus ein Schriftpaar. Sie sind seit 2026-08-02 **wörtlich
|
||||
übernommen** (gitops `b10b607`), nachdem eine erste Fassung die Namen frei
|
||||
interpretiert hatte.
|
||||
|
||||
| Theme | Hintergrund | hell/dunkel | Akzent · Sekundär · Highlight |
|
||||
|---|---|---|---|
|
||||
| Ocean Depths | `#f1faee` | hell | `#2d8b8b` · `#a8dadc` · `#457b9d` |
|
||||
| Sunset Boulevard | `#264653` | dunkel | `#e76f51` · `#f4a261` · `#e9c46a` |
|
||||
| Forest Canopy | `#faf9f6` | hell | `#2d4a2b` · `#7d8471` · `#a4ac86` |
|
||||
| Modern Minimalist | `#ffffff` | hell | `#36454f` · `#708090` · `#d3d3d3` |
|
||||
| Golden Hour | `#4a403a` | dunkel | `#f4a900` · `#c1666b` · `#d4b896` |
|
||||
| Arctic Frost | `#fafafa` | hell | `#4a6fa5` · `#d4e4f7` · `#c0c0c0` |
|
||||
| Desert Rose | `#5d2e46` | dunkel | `#d4a5a5` · `#b87d6d` · `#e8d5c4` |
|
||||
| Tech Innovation | `#ffffff` | hell | `#0066ff` · `#00ffff` · `#1e1e1e` |
|
||||
| Botanical Garden | `#f5f3ed` | hell | `#4a7c59` · `#f9a620` · `#b7472a` |
|
||||
| Midnight Galaxy | `#e6e6fa` | hell | `#2b1e3e` · `#4a4e8f` · `#a490c2` |
|
||||
|
||||
⚠️ **Ob ein Theme hell oder dunkel gemeint ist, steht nicht verlässlich in den
|
||||
Beschreibungen** — „Warm Sand · backgrounds" findet sich bei einem Theme, dessen
|
||||
Showcase-Seite dunkel ist. Maßgeblich ist `theme-showcase.pdf` im Skill: sieben der
|
||||
zehn sind hell, nur Sunset Boulevard, Golden Hour und Desert Rose dunkel.
|
||||
„Midnight" Galaxy ist trotz des Namens ein helles Theme mit dunkelviolettem Akzent.
|
||||
Wer die Werte prüfen will, rendert die PDF-Seiten und misst die Hintergrundfarbe,
|
||||
statt der Prosa zu glauben.
|
||||
|
||||
Die übrigen Rollen (Flächenabstufungen, Username-Farben) sind aus diesen vier
|
||||
Farben gemischt — so bleibt jedes Theme in sich stimmig, ohne dass Werte
|
||||
dazuerfunden werden.
|
||||
|
||||
## Namensgebung: ThreadNet oder aXion1337.Chat?
|
||||
|
||||
**Beides, auf verschiedenen Ebenen — und das ist Absicht, kein Versehen.**
|
||||
|
||||
| Ebene | Name | Wo gesetzt |
|
||||
|---|---|---|
|
||||
| Betriebssystem, Startmenü, Installer, PWA | **ThreadNet** | `productName` in `apps/desktop/axion1337/build.json`, `name` in `apps/web/res/manifest.json` |
|
||||
| in der Anwendung | **aXion1337.Chat** | `brand` in `element-values.yaml` (Prod) und `apps/desktop/axion1337/config.json` |
|
||||
| eingebettetes Call-Widget | **aXion1337.Chat** | `VITE_PRODUCT_NAME` in `.env.production` (threadnet-call) |
|
||||
| Anmeldeseite (Authentik) | **ThreadNet** | `branding_title` im Brand-Blueprint (gitops, `apps/authentik/authentik-blueprints.yaml`) |
|
||||
|
||||
Das Call-Widget folgt der Zeile darüber: Es läuft *in* der Anwendung, also heißt es
|
||||
dort auch so. Die Anmeldeseite dagegen kommt **vor** der Anwendung — dort meldet man
|
||||
sich am Werkzeug an, nicht in der Gemeinschaft. Deshalb ThreadNet.
|
||||
|
||||
Die Leitplanke dahinter steht in [`vision/threadnet.md`](../vision/threadnet.md):
|
||||
*ThreadNet ist das Tool, axion1337.chat die Community.* Das Programm heißt
|
||||
ThreadNet — auch wenn es jemand für eine andere Instanz nutzt; die Gemeinschaft
|
||||
darin heißt aXion1337.Chat.
|
||||
|
||||
⚠️ **Nicht „geradeziehen".** Wer nur eine der beiden Stellen sieht, hält es für
|
||||
eine Inkonsistenz. Ist es nicht.
|
||||
|
||||
**Attribution:** „ThreadNet — powered by Element" steht seit `v0.4.0` in
|
||||
*Einstellungen → Hilfe & Info*, direkt unter der Client-Version, verlinkt auf
|
||||
element.io. Element Web steht unter der AGPL; ein Fork unter eigenem Namen ist
|
||||
erlaubt, die Nennung ist die faire Form davon. Bewusst **nicht** im Kopiertext der
|
||||
Versionsangabe — der landet in Fehlerberichten, dort ist die Fork-Herkunft nur
|
||||
Rauschen.
|
||||
|
||||
## Wo was eingestellt ist
|
||||
|
||||
| Oberfläche | Ort | Anmerkung |
|
||||
|---|---|---|
|
||||
| Element/ThreadNet-Web | `apps/production/custom-configs/element-values.yaml` (gitops), `setting_defaults.custom_themes` | 17 Themes; Änderungen chirurgisch, **nie die YAML neu serialisieren** |
|
||||
| Web-Icons + PWA | `apps/web/res/vector-icons/`, `apps/web/res/manifest.json` (ThreadNet-Web) | `theme_color` = `#ed4f4c`, die Markenfarbe — nicht Elements `#76CFA6` |
|
||||
| Desktop-Icons | `apps/desktop/build/` (ThreadNet-Web) | `.png`, `.ico`, `.icns`, Layer-Asset — alle aus derselben Quelle |
|
||||
| ThreadNet Desktop | `apps/desktop/axion1337/config.json` (ThreadNet-Web) | eigene Kopie derselben Themes — beim Ändern beide mitziehen |
|
||||
| BookStack | *Settings → Customization*, getrennt für hell und dunkel | liegt in der Datenbank, **nicht im Repo** — schriftlich hier und in `theme/sorbs-palette.md` |
|
||||
| BookStack (Feinschliff) | `theme/*.css` im Wiki-BookStack-Repo | nur Flächen, Text, Ränder — die sieben Farben oben gehören in die Oberfläche |
|
||||
| Docusaurus-Wiki | `src/css/custom.css` (homelab/wiki) | bislang nur Akzentfarbe |
|
||||
| Titelbild Login | `apps/web/res/themes/element/img/backgrounds/alpenglow.jpg` (ThreadNet-Web), gesetzt in `SdkConfig.ts` | siehe unten — Bilddatei kommt nur über einen Build in den Container |
|
||||
| Anmeldeseite Authentik | Brand-Blueprint in `apps/authentik/authentik-blueprints.yaml` (gitops) | Favicon und Hintergrund werden **von axion1337.chat referenziert**, nicht hochgeladen. **Logo ist noch Authentiks eigenes** → gitops#55 |
|
||||
|
||||
### Titelbild
|
||||
|
||||
Seit 2026-08-06 zeigt die Login-Seite ein Alpenglühen über einer Bergkette statt
|
||||
Elements See: **John Towner** ([@heytowner](https://unsplash.com/@heytowner)),
|
||||
[Unsplash](https://unsplash.com/photos/JgOeRuGD_Y4), *Unsplash License*.
|
||||
|
||||
Die Lizenz erlaubt kommerzielle Nutzung und Bearbeitung ohne Genehmigung und
|
||||
**verlangt keine Namensnennung**. Genannt wird er trotzdem — in *Einstellungen →
|
||||
Hilfe & Info* unter „Danksagungen". Verboten wäre nur der Weiterverkauf
|
||||
unbearbeiteter Bilder und das Nachbauen eines konkurrierenden Bilddienstes; beides
|
||||
trifft uns nicht.
|
||||
|
||||
⚠️ **Die Danksagung ist bewusst nicht übersetzt.** Elements Schlüssel
|
||||
`credits|default_cover_photo` liegt in 32 Sprachdateien, 31 davon nennen deren
|
||||
Fotografen namentlich. Nur `en`/`de` anzupassen hätte in 29 Sprachen eine **falsche
|
||||
Attribution** stehen lassen — und diese 29 pflegen wir nicht, sie kommen aus Elements
|
||||
Übersetzungsdienst. Deshalb steht die Zeile als fester Text im TSX, wie schon die
|
||||
„powered by Element"-Attribution.
|
||||
|
||||
⚠️ **Authentik hängt an dieser Datei.** Der Flow-Hintergrund dort zeigt auf
|
||||
`https://axion1337.chat/themes/element/img/backgrounds/alpenglow.jpg`. Wer das Bild im
|
||||
Client umbenennt oder entfernt, macht die Anmeldeseite grau — und merkt es nicht,
|
||||
weil im Client alles stimmt.
|
||||
|
||||
### Warum in Authentik kein PNG-Logo funktioniert
|
||||
|
||||
Der erste Versuch setzte `branding_logo` auf `vector-icons/512.png`. Ergebnis: das
|
||||
Logo rendert in der Anmeldemaske in **Naturgröße**. Authentiks Default ist ein SVG,
|
||||
das sich seiner Box anpasst — ein PNG tut das nicht, und der Slot begrenzt die Höhe
|
||||
nicht.
|
||||
|
||||
Zurückgesetzt am 2026-08-06 auf Authentiks eigenes Logo. Ein Ersatz braucht eine
|
||||
**Wortmarke im Querformat, am besten als SVG**; alles Vorhandene ist quadratisch,
|
||||
auch `threadnet-logo-wortmarke.png` (Bildmarke *über* Schriftzug). Offen in
|
||||
gitops#55.
|
||||
|
||||
⚠️ **Nicht über Authentiks Oberfläche einstellen.** Solange `branding_logo` im
|
||||
Blueprint steht, gewinnt der Blueprint: eine Auswahl in der UI hält bis zur nächsten
|
||||
Reconciliation und ist dann wieder weg.
|
||||
|
||||
⚠️ **Das BookStack-Schema lebt nur in der Datenbank.** Bei einem Volume-Verlust
|
||||
ist es weg — deshalb steht es oben in dieser Tabelle. Wiederherstellen heißt:
|
||||
sieben Felder in der Oberfläche neu eintragen.
|
||||
|
||||
Es steht bewusst an **zwei** Stellen schriftlich, und die Rollen sind verschieden:
|
||||
`theme/sorbs-palette.md` im BookStack-Repo ist die betriebsnahe Kopie mit den
|
||||
DB-Schlüsseln, liegt aber in der Gruppe `homelab` — die hat **keine Mirrors** und
|
||||
ist von außerhalb des Labs nicht lesbar. Diese Datei hier ist die gespiegelte
|
||||
und damit maßgebliche Fassung. Wer die Farben ändert, zieht beide mit; im
|
||||
Zweifel gilt, was in der laufenden Instanz eingestellt ist.
|
||||
|
||||
## Offen
|
||||
|
||||
Ob die Terrakotta-Richtung das Stammschema ablösen oder eine Alternative neben
|
||||
Gruvbox bleiben soll, ist nicht entschieden — das gehört in die Rebranding-Runde
|
||||
(→ [`vision/threadnet.md`](../vision/threadnet.md), ThreadNet-Web#10).
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: architecture
|
||||
related: []
|
||||
---
|
||||
|
||||
# Lab-Netzwerk (Heimnetz: Fritzbox + UDM Pro)
|
||||
|
||||
Themen rund um das Homelab-Netz selbst — Router-Kaskade, VLANs, VPN-Zugänge.
|
||||
Hosts im Lab: Overmind (git.lab, [hosts/overmind.md](../admin/overmind.md)),
|
||||
der Mac. Kaskade: **Fritzbox (WAN) → UDM Pro**, kein Doppel-NAT, statische
|
||||
Route in der Fritzbox für das Lab-VLAN.
|
||||
|
||||
> ✅ **Das VPN-Thema ist abgeschlossen und validiert** (sorb, 2026-08-02).
|
||||
> Beide Zugänge laufen und sind abgenommen, ADR-0004 steht auf *akzeptiert*
|
||||
> (Testreihe 1–7 in [#12](https://git.lab/axion1337.chat/management/-/issues/12)).
|
||||
> Es gibt dazu **keine offenen Issues mehr** — auch die Restpunkte #11
|
||||
> (MacBook-Profil) und #16 (LABNET-04, Feinschliff an den UniFi-Regeln) sind
|
||||
> geschlossen. Alles Folgende ist **Bestand und Historie**, keine offene Arbeit.
|
||||
|
||||
**Zwei WireGuard-Zugänge (Stand 2026-08-01, beide gelöst/abgenommen):**
|
||||
|
||||
| Zugang | Server | Port | Tunnelnetz | Zweck |
|
||||
|---|---|---|---|---|
|
||||
| Roadwarrior „Thore" | UDM | 51840 | 10.58.74.0/24 | Handy/MacBook ins Lab (LABNET-01) |
|
||||
| Site-to-Site „Matrix" | UDM | 51841 | 10.58.75.0/24 | Hetzner-Netz 10.0.0.0/24 ↔ Lab (LABNET-02, [ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md)) |
|
||||
|
||||
### Verhältnis zu `homelab/docs`
|
||||
|
||||
Die Tabelle oben steht **absichtlich doppelt**. Maßgeblich für die
|
||||
Soll-Konfiguration ist
|
||||
[homelab/docs → MorninglightMountain](https://git.lab/homelab/docs/-/blob/main/netz/morninglightmountain.md)
|
||||
(dort auch Portfreigaben, Firewall-Zonen, Diagnose-Merksätze) — dieses Repo
|
||||
führt die **Historie**: was wann warum geändert wurde und mit welchem Issue.
|
||||
|
||||
Der Grund für die Doppelung ist der Mirror-Geltungsbereich aus der
|
||||
[CLAUDE.md](../../../AGENTS.md): Die Gruppe `homelab` hat bewusst **keine Mirrors** und
|
||||
ist von außerhalb des Labs nicht lesbar. Wer ohne Tunnel nachsehen muss, welcher
|
||||
Tunnel überhaupt auf welchem Port liegt, findet es nur hier. Deshalb hält dieses
|
||||
Dokument einen Kurzüberblick vor — Ports, Tunnelnetze, Zweck — und nichts
|
||||
darüber hinaus. **Bei Widerspruch gilt `homelab/docs`.**
|
||||
|
||||
---
|
||||
|
||||
## LABNET-01 — WireGuard-Roadwarrior ins Lab kaputt (seit einigen Monaten)
|
||||
|
||||
**Status:** GELÖST 2026-08-01 ~15:20 — `git.lab` lädt vom Handy über 5G/VPN. ✅
|
||||
Damit ist die Cutover-Voraussetzung für gitops#48 erfüllt.
|
||||
|
||||
**Drei gestapelte Ursachen (jede verdeckte die nächste):**
|
||||
1. **Privater Endpunkt** in jeder UDM-generierten Client-Config (UDM kennt hinter
|
||||
der Fritzbox ihre öffentliche IP nicht) → Fix: Endpunkt `178.25.213.70`;
|
||||
dauerhaft gelöst über UniFi-Option **„Alternate Address for Clients"**.
|
||||
2. **FritzOS reserviert UDP 51820 für seinen eigenen WireGuard-Stack** — die
|
||||
Portfreigabe 51820→UDM lief ins Leere (erklärt die „invalid response"-Stürme
|
||||
im Juli: zwei WG-Stacks auf einem Port) → Fix: UDM-WG auf **51840**.
|
||||
3. **Docker-Routen-Kollision auf Overmind**: Dokploys Bridge-Netze belegen zehn
|
||||
/20-Blöcke in 192.168.0.0/16; `192.168.0.0/20` verschluckte das VPN-Subnetz
|
||||
192.168.5.0/24 → Antworten an VPN-Clients endeten in der Bridge (SYN kam an,
|
||||
SYN-ACK verschwand — exakt der Chrome-Connection-Timeout, während Ping/DNS/
|
||||
fremde Hosts funktionierten) → Fix: **VPN-Subnetz auf 10.58.74.0/24** (Docker
|
||||
fasst 10.x nie an).
|
||||
|
||||
**Restarbeiten:** MacBook-WG-Profil → [Issue #11](https://git.lab/axion1337.chat/management/-/issues/11). ⚠️ Latente Wiederholungsgefahr
|
||||
notiert: Overminds Docker-Pool deckt auch `192.168.176.0/20` ab = kollidiert mit
|
||||
dem Fritzbox-Netz 192.168.178.x — aktuell folgenlos, aber bei künftigen Subnetz-
|
||||
Entscheidungen 192.168.x auf Overmind grundsätzlich meiden (oder Docker
|
||||
default-address-pools begrenzen).
|
||||
|
||||
**Bestätigte Ursachenkette (Diagnose-Session 2026-08-01):**
|
||||
1. Handy-Profil „@home" hatte seit 07.07. die **private** UDM-WAN-IP
|
||||
(192.168.178.20) als Endpunkt — die UDM kennt hinter der Fritzbox ihre
|
||||
öffentliche IP nicht und schreibt sie in jede generierte Config
|
||||
(⚠️ gilt für ALLE künftig exportierten Profile: Endpunkt manuell auf
|
||||
178.25.213.70 ändern!).
|
||||
2. Nach Endpunkt-Fix weiter tot: **FritzOS reserviert UDP 51820 für seinen
|
||||
EIGENEN WireGuard-Stack** — die alte Portfreigabe 51820→UDM lief ins Leere
|
||||
(erklärt auch die „invalid response"-Stürme im Juli: zwei WG-Stacks auf
|
||||
einem Port). Fix: UDM-WG auf **51840** umgezogen + Freigabe angepasst.
|
||||
3. Server + Schlüssel waren nie das Problem (WLAN-Handshake bewies beides).
|
||||
|
||||
Danach nur noch der ursprüngliche Blocker-Vermerk:
|
||||
blockierte gitops#48 (Erreichbarkeits-Entscheidung „WireGuard statt exponieren")
|
||||
|
||||
sorb hatte einen funktionierenden VPN-Zugang fürs Handy ins Lab; seit einigen
|
||||
Monaten „funktioniert das nicht mehr sauber" (Symptome noch zu präzisieren:
|
||||
Handshake? Routing nur teilweise? DNS?). Setup-Rahmen laut sorb (2026-08-01):
|
||||
UDM Pro hinter Fritzbox, ohne doppeltes NAT, statische Route in der Fritzbox
|
||||
für das VLAN.
|
||||
|
||||
**Diagnose-Plan von VOR der Lösung** — ⚠️ abgearbeitet und überholt, steht hier
|
||||
nur als Beleg, wie die Ursachen eingekreist wurden. Nichts davon ist zu tun:
|
||||
1. Symptom präzisieren: Handshake kommt zustande? (`wg show` auf der UDM /
|
||||
Client-Log) — trennt Portweiterleitungs- von Routing-Problemen
|
||||
2. Fritzbox: Portfreigabe UDP (WireGuard-Port) → UDM noch vorhanden/korrekt?
|
||||
(FritzOS-Updates werfen gern Freigaben/Exposed-Host-Einstellungen um)
|
||||
3. ~~DS-Lite~~ **ausgeschlossen** (sorb 2026-08-01: Dualstack + feste IPs) —
|
||||
damit auch kein DynDNS-Drift möglich. Verdacht konzentriert sich auf:
|
||||
FritzOS-Update warf die UDP-Portfreigabe um, UniFi-OS-Update veränderte
|
||||
WG-Server/Firewall, oder die statische Route griff nach Änderung nicht mehr.
|
||||
4. (entfällt — feste IP)
|
||||
5. UDM-Seite: WireGuard-Server-Config/Firewall-Regeln nach UniFi-OS-Updates
|
||||
prüfen; statische Route Fritzbox → VLAN gegenchecken
|
||||
6. Erst wenn 1–5 sauber: Client-Profil fürs Handy neu ausstellen, git.lab-DNS
|
||||
(Lab-Resolver) in die AllowedIPs/DNS-Konfig aufnehmen — Erfolgsbeweis =
|
||||
Issue-Board vom Handy über VPN erreichbar
|
||||
|
||||
**Verwandt:** gitops#48 (Cutover erst nach Lösung), perspektivisch ersetzt ein
|
||||
funktionierender Roadwarrior auch Ad-hoc-Wünsche wie „GitLab exponieren".
|
||||
|
||||
## Zugehörige Issues — alle geschlossen
|
||||
|
||||
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.
|
||||
|
||||
Zum Netz/VPN ist **nichts mehr offen** (Stand 2026-08-02):
|
||||
|
||||
| Issue | Thema | Stand |
|
||||
|---|---|---|
|
||||
| [#11](https://git.lab/axion1337.chat/management/-/issues/11) | LABNET-01-Rest — MacBook-WireGuard-Profil | geschlossen |
|
||||
| [#12](https://git.lab/axion1337.chat/management/-/issues/12) | LABNET-02 — Site-to-Site-VPN (Design: [ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md)) | geschlossen, Testreihe 1–7 protokolliert |
|
||||
| [#16](https://git.lab/axion1337.chat/management/-/issues/16) | LABNET-04 — Feinschliff UniFi-Regeln | geschlossen |
|
||||
|
||||
Zwei Punkte tragen zwar LABNET im Text, gehören aber **nicht** zum VPN-Thema und
|
||||
bleiben offen: [#13](https://git.lab/axion1337.chat/management/-/issues/13)
|
||||
(LABNET-03, Rückbau der Gitea-Ausnahme für Übergabe-Issues — durch den Tunnel
|
||||
erst möglich geworden, aber eine Repo-Frage) und
|
||||
[#15](https://git.lab/axion1337.chat/management/-/issues/15) (CFGMON-15,
|
||||
Widerruf der Einmal-Tokens aus der LABNET-02-Nacht — Credential-Hygiene, und der
|
||||
Widerruf kann still einen Push-Mirror brechen, solange dessen hinterlegtes Token
|
||||
unbekannt ist).
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: architecture
|
||||
related:
|
||||
- "docs/adr/0001-gitlab-kanonisch-push-mirror.md"
|
||||
- "docs/adr/0002-issues-und-management-ins-lab.md"
|
||||
- "docs/adr/0004-site-to-site-vpn-hetzner-lab.md"
|
||||
- "docs/adr/0006-wikis-konsolidieren-docusaurus.md"
|
||||
---
|
||||
|
||||
# Mirror-Topologie: Das Lab ist die Quelle der Wahrheit
|
||||
|
||||
Begründungsprosa übernommen aus der alten `CLAUDE.md` (Abschnitt
|
||||
„Projektrealitäten", Wortlaut in der git-Historie vor der
|
||||
neckbeard-Migration); die verbindlichen Regeln stehen in `AGENTS.md` §6
|
||||
und den verlinkten ADRs. Erhalten per Feldtest-Befund F-013: Diese
|
||||
Begründung samt Gegenargument und Rettungspfad ist der Wert — sie
|
||||
erklärt, warum die Topologie so aussieht und so bleiben soll.
|
||||
|
||||
- Kanonische Repos liegen auf `git.lab/axion1337.chat/*` (nur im
|
||||
Lab/VPN auflösbar). Gitea/rohana wird per **Push-Mirror** beliefert
|
||||
und bleibt Flux-Source, Container-/npm-Registry und Release-Download
|
||||
([ADR-0001](../../adr/0001-gitlab-kanonisch-push-mirror.md)).
|
||||
- **Warum überhaupt zwei Orte — und warum das kein Altbestand ist:**
|
||||
Auf git.lab liegen die *Baupläne*, auf Gitea eine Kopie, die der
|
||||
Cluster **ohne verfügbares Lab** erreicht. Der Hetzner-Cluster muss
|
||||
sich bauen und neu ausrollen lassen, wenn das Homelab aus ist, im
|
||||
Umbau steckt oder niemand zu Hause ist — er darf deshalb nicht von
|
||||
einem Host abhängen, der nur im Lab antwortet.
|
||||
⚠️ **Die Flux-Quelle nicht „geradeziehen"** auf git.lab: Das sähe
|
||||
aufgeräumter aus und würde die Verfügbarkeit der Produktion an das
|
||||
Lab koppeln — genau das, was die Trennung verhindert.
|
||||
- **Gespiegelt wird nur die Gruppe `axion1337.chat`** (die Produkt-Repos
|
||||
und `management`). Die Gruppe **`homelab`** (`docs`, `wiki`,
|
||||
`wiki-bookstack`) hat bewusst **keine Mirrors**: Sie beschreibt und
|
||||
konfiguriert ausschließlich Lab-Infrastruktur, und seit dem
|
||||
Site-to-Site-VPN ([ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md))
|
||||
erreichen auch Host-Sessions git.lab direkt — Tunnel einschalten
|
||||
genügt. Betriebslehren, die von außen lesbar sein müssen, gehören
|
||||
deshalb in die **AARs** unter `docs/aar/` (dieses Repo ist
|
||||
gespiegelt), nicht nur in die READMEs der Lab-Repos.
|
||||
- Landet doch ein Commit auf Gitea (z. B. aus einer Host-Session ohne
|
||||
Lab-Route): **Kanonisierungs-Verfahren** in
|
||||
[deploy-uebergabe](../deployment/deploy-uebergabe.md) — `.patch` von
|
||||
Gitea ziehen, `git am` (erhält Autorschaft), Push über git.lab.
|
||||
- ⚠️ gitops-Issue-Nummern haben sich beim Gitea-Umzug verschoben (Gitea
|
||||
zählte PRs mit; z. B. Gitea#48 → GitLab#46) — alte „gitops#N"-Verweise
|
||||
meinen die Gitea-Nummer; verbindlich ist der Migrations-Fußtext im
|
||||
Issue ([ADR-0002](../../adr/0002-issues-und-management-ins-lab.md)).
|
||||
- **Ausnahme** (bewusst entschieden, nur noch eine): der
|
||||
TURN-Rotations-CronJob schreibt weiter nach Gitea, weil er im Cluster
|
||||
läuft und git.lab nicht erreicht. **Die Rotation nicht von Hand
|
||||
nachziehen und den PR nie auf Gitea mergen** — das erledigt seit
|
||||
2026-08-02 der geplante CI-Job `canonize_rotation` im gitops-Repo
|
||||
täglich von git.lab aus. Scheitert er, bleibt die Pipeline rot; diese
|
||||
rote Pipeline **ist** der Alarm, einen zusätzlichen Termin gibt es
|
||||
bewusst nicht.
|
||||
- **Dokumentation** ([ADR-0006](../../adr/0006-wikis-konsolidieren-docusaurus.md)):
|
||||
Das gitops-Wiki liegt seit 2026-08-02 auf git.lab (*Wiki*-Reiter im
|
||||
Projekt); ⚠️ der `wiki`-**Branch** im gitops-Repo ist ein überholter
|
||||
Mai-Abzug von `docs/` und nicht die gepflegte Fassung. Alle Quellen
|
||||
zusammen erscheinen unter **axionwiki.lab**
|
||||
([`homelab/wiki`](https://git.lab/homelab/wiki), Docusaurus) —
|
||||
Inhalte werden beim Bau geholt, **Änderungen gehören ins Quell-Repo**.
|
||||
@@ -0,0 +1,148 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: architecture
|
||||
related: []
|
||||
---
|
||||
|
||||
# DNS-Zone `axion1337.de` und Mail-Policy
|
||||
|
||||
Übergreifend, weil die Zone alle Hosts abdeckt und die Mail-Policy sich nicht pro
|
||||
Host trennen lässt.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Registrar / DNS** | IONOS (`ns1098.ui-dns.biz`, `ns1022.ui-dns.com`, `ns1070.ui-dns.org`, `ns1059.ui-dns.de`) |
|
||||
| **Apex** | `217.160.0.140` / `2001:8d8:100f:f000::2e9` — IONOS-Hosting, nicht eigene Infrastruktur |
|
||||
| **Mail** | IONOS (`mx00.ionos.de`, `mx01.ionos.de`) |
|
||||
| **Stand** | 2026-08-06 (Mail-Records gemessen) |
|
||||
|
||||
**Ist-Stand der Mail-Härtung** (gemessen 2026-08-06 über DoH, um den Lab-Resolver
|
||||
zu umgehen):
|
||||
|
||||
| Name | `www` | MX | SPF | `_dmarc` | Bewertung |
|
||||
|---|---|---|---|---|---|
|
||||
| `rohana` | löst auf ❌ | gelöscht | **gelöscht** ⚠️ | fehlt | ⚠️ schwächer als vorher |
|
||||
| `selendis` | weg ✅ | IONOS ❌ | `~all` ❌ | fehlt | unangetastet |
|
||||
| `matrix` | löst auf ❌ | IONOS ❌ | `~all` ❌ | fehlt | offen |
|
||||
| `game` | löst auf ❌ | — | — | fehlt | teilweise |
|
||||
| **Apex** | legitim ✅ | IONOS (genutzt) | `~all` | **`p=none`** ⚠️ | siehe ZONE-02 |
|
||||
|
||||
Kein einziger Name trägt bisher `_dmarc`, alle erben damit `p=none` vom Apex.
|
||||
|
||||
> **Die Aufstellung ist nicht garantiert vollständig.** Zonentransfer ist verweigert,
|
||||
> DNS erlaubt kein Enumerieren. Die Records unten stammen aus gezielten Abfragen und
|
||||
> der IONOS-Oberfläche. Für eine vollständige Prüfung entweder die ungefilterte
|
||||
> IONOS-Liste durchgehen oder die Certificate-Transparency-Logs abfragen (zeigt alle
|
||||
> Namen, für die je ein Cert ausgestellt wurde).
|
||||
|
||||
## Bekannter Bestand
|
||||
|
||||
| Name | A | AAAA | Ziel |
|
||||
|---|---|---|---|
|
||||
| `axion1337.de` | `217.160.0.140` | `2001:8d8:100f:f000::2e9` | IONOS-Hosting |
|
||||
| `www` | `217.160.0.140` | dito | IONOS-Hosting — hier ist `www` **legitim** |
|
||||
| `rohana` | `188.245.193.243` | `2a01:4f8:c17:93eb::1` | CFGMON, Gitea |
|
||||
| `selendis` | `188.245.193.243` | `2a01:4f8:c17:93eb::1` | CFGMON, Grafana |
|
||||
| `game` | `157.90.155.206` | — | Pterodactyl |
|
||||
| `matrix` | `49.13.132.245` | — | Matrix-Homeserver |
|
||||
| `ftp` | `217.160.233.227` | `2001:8d8:1000:30f5:…` | IONOS-Default |
|
||||
| `www.rohana`, `www.selendis`, `www.game`, `www.matrix` | wie ohne `www` | teils | überflüssig, siehe ZONE-01 |
|
||||
|
||||
Mail-Records existieren auf `selendis` und `matrix` (MX ×2, SPF, DKIM-CNAMEs,
|
||||
`autodiscover`), auf `rohana` und `game` nicht.
|
||||
|
||||
## Was die Mail-Records eigentlich tun
|
||||
|
||||
Damit die Rezepte in [ZONE-01](https://git.lab/axion1337.chat/management/-/issues/5)
|
||||
nicht als Zahlensalat dastehen: Vier Mechanismen, die zusammenspielen. **Keiner
|
||||
schützt allein.**
|
||||
|
||||
### Das Grundproblem
|
||||
|
||||
Der Absender einer Mail (`From:`) ist frei wählbar — SMTP prüft ihn nicht. Jeder
|
||||
kann `rechnung@rohana.axion1337.de` in den Umschlag schreiben. Die folgenden
|
||||
Records sind die Möglichkeit, dem widersprechen, **bevor** jemand darauf hereinfällt.
|
||||
|
||||
### SPF — „diese Server dürfen für mich senden"
|
||||
|
||||
TXT-Record am Namen selbst. Listet die berechtigten Absender-IPs.
|
||||
|
||||
Entscheidend ist das **Ende** des Eintrags:
|
||||
|
||||
| Endung | Bedeutung | Wirkung beim Empfänger |
|
||||
|---|---|---|
|
||||
| `~all` | Softfail | „war nicht auf der Liste" → wird meist **trotzdem zugestellt**, evtl. markiert |
|
||||
| `-all` | Hardfail | „war nicht auf der Liste" → **ablehnen** |
|
||||
|
||||
`v=spf1 -all` ohne jeden Server davor heißt: *Für diesen Namen sendet niemand.*
|
||||
Genau die richtige Aussage für `rohana`, `selendis`, `matrix` — die verschicken keine
|
||||
Mail (für `matrix` verifiziert in MATRIX-01: weder Synapse noch MAS senden).
|
||||
|
||||
⚠️ **Es darf nur EIN SPF-Record je Name existieren.** Ein zweiter erzeugt
|
||||
`PermError`, und dann prüfen viele Empfänger **gar nicht mehr** — die Härtung
|
||||
schlägt ins Gegenteil um. Deshalb: bestehenden TXT **editieren**, nie einen zweiten
|
||||
anlegen.
|
||||
|
||||
### DKIM — „diese Mail wurde unterwegs nicht verändert"
|
||||
|
||||
Signatur mit einem privaten Schlüssel, öffentlicher Teil als CNAME/TXT im DNS
|
||||
(`s1-ionos._domainkey…`). Beweist Unversehrtheit und Herkunft.
|
||||
|
||||
Für Namen, die nicht senden, sind die DKIM-Einträge schlicht **Ballast** — sie
|
||||
signieren nichts. Sie können weg.
|
||||
|
||||
### DMARC — „und das tust du, wenn SPF oder DKIM nicht passen"
|
||||
|
||||
TXT unter `_dmarc.<name>`. SPF und DKIM stellen nur **fest**; DMARC sagt, welche
|
||||
**Konsequenz** das hat:
|
||||
|
||||
| Policy | Wirkung |
|
||||
|---|---|
|
||||
| `p=none` | nur beobachten — **kein Schutz**, Mail wird zugestellt |
|
||||
| `p=quarantine` | in den Spam-Ordner |
|
||||
| `p=reject` | ablehnen |
|
||||
|
||||
⚠️ **DMARC wird vererbt.** Fehlt `_dmarc.rohana`, gilt die Policy des
|
||||
organisatorischen Namens `axion1337.de`. Die steht heute auf **`p=none`**
|
||||
([ZONE-02](https://git.lab/axion1337.chat/management/-/issues/6)) — **damit erben
|
||||
alle Subdomains „kein Schutz"**, egal wie sauber ihr SPF ist.
|
||||
|
||||
Das ist der wichtigste Hebel der ganzen Zone: **Der Apex wirkt auf alle Namen
|
||||
gleichzeitig.** Mit `sp=` lässt sich für Subdomains sogar eine strengere Policy
|
||||
setzen als für den Apex selbst.
|
||||
|
||||
### Null-MX — „hier nimmt niemand Mail an" (RFC 7505)
|
||||
|
||||
Ein MX-Record mit dem Ziel `.` (Punkt) und Priorität 0.
|
||||
|
||||
Der Grund, warum **Löschen nicht reicht**: Findet ein Absender **keinen** MX,
|
||||
weicht er per RFC 5321 auf den **A/AAAA-Record** aus und versucht, direkt an den
|
||||
Webserver zuzustellen. Der Name sieht dann nach „nimmt vielleicht Mail an" aus.
|
||||
Null-MX sagt stattdessen ausdrücklich *nein* — Absender brechen sofort ab.
|
||||
|
||||
### Warum die Kombination
|
||||
|
||||
| Record | Beantwortet die Frage |
|
||||
|---|---|
|
||||
| **Null-MX** | Nimmt dieser Name Mail **an**? → nein |
|
||||
| **SPF `-all`** | Darf jemand für diesen Namen **senden**? → niemand |
|
||||
| **DMARC `p=reject`** | Was tun, wenn doch jemand behauptet, es zu dürfen? → ablehnen |
|
||||
|
||||
Erst zusammen ergeben sie eine Aussage, auf die sich ein Empfänger verlassen kann.
|
||||
Einzeln bleibt jeweils eine Lücke — und **ersatzloses Löschen** hinterlässt die
|
||||
größte: keine Aussage ist schwächer als eine schlechte Aussage.
|
||||
|
||||
**Real eingetreten:** Bei `rohana` sind MX und SPF gelöscht, die Ersatz-Records
|
||||
fehlen (gemessen 2026-08-06). Vorher gab es wenigstens ein Softfail-SPF, jetzt gar
|
||||
keine Aussage mehr — dazu die geerbte `p=none` vom Apex. Der Halbfertig-Zustand ist
|
||||
schwächer als der Ausgangszustand.
|
||||
|
||||
## 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.
|
||||
|
||||
- [ZONE-01 — IONOS-Default-Records bereinigen (Rezepte im Issue; rohana/selendis in Arbeit)](https://git.lab/axion1337.chat/management/-/issues/5)
|
||||
- [ZONE-02 — Apex-DMARC ist `p=none` und schützt nichts](https://git.lab/axion1337.chat/management/-/issues/6)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: deployment
|
||||
related: []
|
||||
---
|
||||
|
||||
# Verfahren: Deploy-Übergabe
|
||||
|
||||
Für die Konstellation „einer baut, ein anderer rollt aus". Zweck ist nicht mehr
|
||||
Prozess, sondern **weniger Rückfragen und weniger stille Fehlschläge**.
|
||||
|
||||
Eingeführt am 2026-08-01 nach dem Deploy der CVE-Pipeline (`gitops#47`), siehe
|
||||
[aar/2026-08-01-cve-pipeline-gitops47.md](../../aar/2026-08-01-cve-pipeline-gitops47.md).
|
||||
|
||||
## Ablauf
|
||||
|
||||
1. Wer baut, öffnet **auf git.lab** ein Issue aus der Vorlage **Deploy-Übergabe**
|
||||
(`.gitlab/issue_templates/Deploy-Übergabe.md`, im Feld *Description template*).
|
||||
2. Wer ausrollt, arbeitet die Prüfliste unten ab und deployt.
|
||||
3. Wer ausrollt, hängt den **AAR** als Kommentar an dasselbe Issue
|
||||
(Vorlage: [docs/aar/template.md](../../aar/template.md)). Bei Befunden ab MEDIUM
|
||||
zusätzlich als Datei unter `docs/aar/`.
|
||||
|
||||
## Die vier Punkte, die den Unterschied machen
|
||||
|
||||
### 1. Mengengerüst vor dem Deploy
|
||||
|
||||
Bei allem, was etwas erzeugt — Nachrichten, Alarme, Zeitreihen, Requests —
|
||||
gehört die erwartete Anzahl beim **ersten** Lauf in die Übergabe. Geschätzt ist
|
||||
in Ordnung, gemessen ist besser; welches von beidem, muss dabeistehen.
|
||||
|
||||
Der Grund: „ein Alarm pro Fund" ist eine völlig unauffällige Zeile im Code und
|
||||
harmlos bei 5 Funden. Bei 126 ist es ein Ausfall. Der Unterschied steht nirgends
|
||||
im Diff — er ergibt sich erst aus den Daten, gegen die das Ding läuft.
|
||||
|
||||
Eine Stichprobe reicht: drei repräsentative Elemente von 29 messen und
|
||||
hochrechnen kostet Minuten und liefert die Größenordnung.
|
||||
|
||||
### 2. Verifikation dort, wo der Dienst liest
|
||||
|
||||
Ein grüner Linter belegt, dass eine Datei **gültig** ist — nicht, dass sie
|
||||
**geladen** wurde. Diese beiden Aussagen sind bei Bind-Mounts, Caches und
|
||||
Reload-Semantiken regelmäßig verschieden.
|
||||
|
||||
Also im Container prüfen, in der laufenden API, im tatsächlich geladenen
|
||||
Regelwerk. Ein Blick auf die Platte beweist nichts über den Prozess.
|
||||
|
||||
### 3. Deploy-Kommando vollständig übergeben
|
||||
|
||||
Inklusive Reload-, Restart- und Recreate-Schritten. Ein `docker compose up -d`,
|
||||
das `Running` meldet und dabei nichts aktiviert, ist der häufigste stille
|
||||
Fehlschlag: kein Fehler, kein Log, falscher Zustand.
|
||||
|
||||
Konkret auf dem Monitoring-Stack (CFGMON): Einzeldatei-Mounts hängen am Inode,
|
||||
`git pull` benennt beim Schreiben um und erzeugt damit einen neuen — der
|
||||
Container zeigt danach weiter auf die alte Datei. Es braucht
|
||||
`--force-recreate`. Details: `gitops#52`.
|
||||
|
||||
### 4. Zustellwege stumm schalten statt Deploy verschieben
|
||||
|
||||
Datensammlung und Außenwirkung lassen sich fast immer getrennt scharf schalten.
|
||||
Wenn der Zustellweg das Risiko ist, wird **er** abgeklemmt — nicht der ganze
|
||||
Deploy verschoben.
|
||||
|
||||
So läuft die Datensammlung ab sofort, das Dashboard steht, echte Zahlen
|
||||
ersetzen die Schätzung, und die Entscheidung über die Zustellung fällt auf
|
||||
Basis von Messwerten statt Vermutungen. Wichtig: die Stummschaltung gehört
|
||||
committet und dokumentiert, sonst ist sie in zwei Wochen ein Rätsel.
|
||||
|
||||
## Prüfliste für den Ausrollenden
|
||||
|
||||
<!-- pruefe-prosa:ok (Checkliste des Verfahrens, keine offene Aufgabe) -->
|
||||
- [ ] Diff gelesen, nicht nur die Beschreibung
|
||||
- [ ] Mengengerüst plausibel? Bei Zweifel an einer Stichprobe selbst messen
|
||||
- [ ] Configs mit den jeweiligen Werkzeugen validiert (`promtool`, `amtool`,
|
||||
`compose config`, `py_compile` …)
|
||||
- [ ] Außenwirkung identifiziert — was verlässt beim ersten Lauf das System?
|
||||
- [ ] Nach dem Deploy **im Container** verifiziert, dass die neue Config aktiv ist
|
||||
- [ ] Geprüft, ob vorher gesunde Dinge noch gesund sind (keine stille Regression)
|
||||
- [ ] AAR geschrieben, Folge-Issues angelegt, Stummschaltungen dokumentiert
|
||||
|
||||
## Abgrenzung
|
||||
|
||||
Das Verfahren gilt für Übergaben zwischen Personen. Wer baut **und** ausrollt,
|
||||
braucht kein Issue — der AAR lohnt trotzdem, sobald es Befunde ab MEDIUM gab.
|
||||
|
||||
## Kanonisierung nach CFGMON-Deploys (Topologie-Pflichtschritt)
|
||||
|
||||
CFGMON erreicht git.lab nicht — Commits aus Deploy-Sessions landen zwangsläufig
|
||||
direkt auf dem Gitea-Mirror und werden vom nächsten Mirror-Lauf **kommentarlos
|
||||
überschrieben** (zweimal passiert: dfe04c4→6ffab68 am 01.08. nachts,
|
||||
2b715ca→0bd77e2 am 01.08. nachmittags). Deshalb gehört zu jeder Übergabe:
|
||||
|
||||
1. **CFGMON-Seite** vermerkt den Commit-Hash im Übergabe-Issue (Feld „Stand").
|
||||
2. **Mac-Seite** kanonisiert zeitnah: Patch per
|
||||
`https://rohana.axion1337.de/sorb/<repo>/commit/<sha>.patch` ziehen
|
||||
(verwaiste Objekte bleiben eine Weile abrufbar), `git am`, Push nach git.lab.
|
||||
Der Hash ändert sich dabei — **Autorschaft und Inhalt bleiben erhalten**.
|
||||
3. **CFGMON** vor dem nächsten Pull: `git fetch && git reset --hard origin/main`
|
||||
(inhaltsgleich, nur neuer Hash).
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: index
|
||||
related: []
|
||||
---
|
||||
|
||||
# Wiki-Index
|
||||
|
||||
Areas sind Ordner; leere Ordner werden nie angelegt — Struktur entsteht
|
||||
mit Inhalt. Projektfassung des neckbeard-Index (Original:
|
||||
`docs/sources/upstream/neckbeard-v0.1.1/`), erweitert um die Area
|
||||
`vision` (Alt-Wert „eine Datei je Linie", ADR-0005).
|
||||
|
||||
## Areas
|
||||
|
||||
| Area | Enthält | Stand |
|
||||
|---|---|---|
|
||||
| `admin/` | Betrieb: [cfgmon](admin/cfgmon.md) · [game](admin/game.md) · [matrix](admin/matrix.md) · [overmind](admin/overmind.md) · [Refinement & Retro](admin/refinement.md) · [Stillstandsprüfung](admin/stillstandspruefung.md) · [Textbausteine](admin/textbloecke.md) | belegt |
|
||||
| `deployment/` | [Deploy-Übergabe](deployment/deploy-uebergabe.md) (Definition of Done, Kanonisierungs-Verfahren) | belegt |
|
||||
| `architecture/` | [Mirror-Topologie](architecture/mirror-topologie.md) · [Lab-Netz](architecture/lab-netzwerk.md) · [DNS-Zone](architecture/zone-axion1337.md) · [Branding](architecture/branding.md) | belegt |
|
||||
| `vision/` | Eine Datei je Linie: [axion1337.chat](vision/axion1337-chat.md) · [Homelab](vision/homelab.md) · [ThreadNet](vision/threadnet.md) | belegt |
|
||||
| `user-guide/` | Für Nicht-Owner | entfällt — Gate 0: Publikum ist Owner + Sessions |
|
||||
| `requirements/` | Eigenständige Anforderungssicht | nur bei echtem Bedarf |
|
||||
| `faq/`, `stolpersteine/` | Nur aus AARs und geschlossenen Issues geerntet — nie auf Vorrat | leer, entsteht im Refinement |
|
||||
|
||||
## Seitenregeln
|
||||
|
||||
- Jede Seite trägt Frontmatter per `schema.yaml` (`type: wiki-page`,
|
||||
`area`, `related`, ggf. `sources`).
|
||||
- `sources` zitiert, worauf die Seite fußt — Dateien unter
|
||||
`docs/sources/` (unveränderlich, agentenschreibgeschützt) oder
|
||||
externe URLs.
|
||||
- Nur Standard-Markdown-Links, Diagramme als Mermaid (ADR-0003
|
||||
upstream); keine Wikilinks.
|
||||
- **Aufgaben gehören nicht ins Wiki:** offene Arbeitspunkte sind Issues
|
||||
(`docs/issues/`), Wiki-Seiten verweisen höchstens darauf
|
||||
(Lehre F-004; Prüfung: `scripts/pruefe_prosa.py`).
|
||||
- Widersprüche werden aufgelöst oder ausdrücklich als Konflikt markiert
|
||||
— nie stillschweigend nebeneinander stehen gelassen.
|
||||
- Kein „Stand:"-Etikett in Seitenkörpern — `git log` beantwortet das
|
||||
(Lehre F-010).
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: vision
|
||||
related: []
|
||||
---
|
||||
|
||||
# Vision: aXion1337.chat — die Community
|
||||
|
||||
> **Getragene Fassung** — geschärft im Struktur-Workshop am 2026-08-06 (#17).
|
||||
> 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
|
||||
|
||||
## Zielgruppe und Größe
|
||||
|
||||
**Kontrolliert wachsend** (entschieden 2026-08-06). Offen für Neue, aber **jeder
|
||||
Eintritt wird freigegeben** — genau das, was der Invite-Workflow mit `@concierge`
|
||||
und befristeten Gast-Accounts baut. Wachstum ist erwünscht, aber gedeckelt durch
|
||||
das, was eine Person moderieren kann; der Ein-Node-Stack setzt denselben Rahmen.
|
||||
|
||||
Verworfen: **geschlossener Kreis** (dann wäre der Invite-Workflow überdimensioniert)
|
||||
und **offene Registrierung** (verlangt Moderationsteam und Kapazität, die es nicht
|
||||
gibt).
|
||||
|
||||
Was daraus folgt: Der Invite-Workflow ist kein Nice-to-have, sondern das Mittel,
|
||||
mit dem diese Entscheidung durchgesetzt wird. Freie Registrierung bleibt aus.
|
||||
|
||||
## Verhältnis zum ThreadNet-Branding
|
||||
|
||||
Nicht mehr offen: Das Rebranding wird in **M4 zu Ende gebracht**, nicht separat
|
||||
terminiert — siehe [`threadnet.md`](threadnet.md).
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: vision
|
||||
related: []
|
||||
---
|
||||
|
||||
# Vision: Homelab — die Plattform
|
||||
|
||||
> **Getragene Fassung** — geschärft im Struktur-Workshop am 2026-08-06 (#17).
|
||||
|
||||
## 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.
|
||||
|
||||
## Ausbaustufen
|
||||
|
||||
**Konsolidieren vor Ausbauen** (entschieden 2026-08-06). Kein neuer Dienst und
|
||||
kein weiterer Host, solange die Absicherung des Bestehenden nicht steht.
|
||||
|
||||
Der Maßstab ist nicht „läuft es", sondern „überlebt es den Verlust der Maschine,
|
||||
auf der es läuft". Ein Lab, das Quelle der Wahrheit ist, hat diese Frage zuerst zu
|
||||
beantworten — jeder zusätzliche Dienst vergrößert sonst die Angriffsfläche
|
||||
schneller als die Kontrolle.
|
||||
|
||||
**Nachtrag sorb (2026-08-06):** Die Git-Daten werden bereits in einen S3-Bucket
|
||||
auf sein NAS gesichert. Das entschärft den ursprünglichen Befund aus
|
||||
[#10](https://git.lab/axion1337.chat/management/-/issues/10) — offen bleibt
|
||||
jedoch, was diese Sicherung **nicht** umfasst (Registry-Blobs, npm-Pakete,
|
||||
Gitea-Datenbank). Siehe dort.
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
type: wiki-page
|
||||
area: vision
|
||||
related: []
|
||||
---
|
||||
|
||||
# Vision: ThreadNet — das Tool
|
||||
|
||||
> **Getragene Fassung** — geschärft im Struktur-Workshop am 2026-08-06 (#17).
|
||||
> 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.
|
||||
|
||||
## Veröffentlichungsgrad
|
||||
|
||||
**Die Forks werden öffentlich** (entschieden 2026-08-06) — aber erst nach einem
|
||||
**History-Audit**, und in dieser Reihenfolge: zuerst gitops und Doku, die Clients
|
||||
später.
|
||||
|
||||
Der Grund für die Entscheidung steckt im Prinzip oben: „reproduzierbar für Dritte"
|
||||
zahlt sich nur öffentlich aus. Bliebe alles privat, würde dauerhaft für einen Zweck
|
||||
gebaut, den es nicht gibt — dann hätte das Prinzip gestrichen gehört.
|
||||
|
||||
⚠️ **Der Audit ist Bedingung, nicht Formsache.** In der Historie des gitops-Repos
|
||||
steht Commit `51ea513` — *„remove plaintext TURN shared secret, rotate leaked
|
||||
value"*. Der Wert ist rotiert und damit wertlos, aber er steht weiterhin in der
|
||||
Historie, und er ist vermutlich nicht der einzige Fund. Vor dem Umschalten auf
|
||||
public: Historie aller zu veröffentlichenden Repos auf Klartext-Geheimnisse prüfen
|
||||
und entscheiden, ob bereinigt (History-Rewrite) oder bewusst akzeptiert wird.
|
||||
|
||||
## Rebranding
|
||||
|
||||
**Wird in M4 zu Ende gebracht** (entschieden 2026-08-06), ohne eigenen Termin.
|
||||
|
||||
Begründung: Halbfertig ist der schlechteste Zustand — der Desktop-Client heißt
|
||||
seit `6b0261d` ThreadNet und trägt die eigene Marke, der Web-Client zeigt weiter
|
||||
Element. Der Rest gehört zusammen mit Signing und Installer-Branding in
|
||||
„Produktreife ThreadNet" (ThreadNet-Web#6, #7, #10).
|
||||
Reference in New Issue
Block a user