forked from lukas/nixos-config
284 lines
16 KiB
Markdown
284 lines
16 KiB
Markdown
# Abschlussbericht vom 28. Juli 2026 (Fortsetzung, Claude Code)
|
||
|
||
## Ziel
|
||
|
||
Übernahme der Sitzung von Codex, nachdem dessen Tokens aufgebraucht waren.
|
||
Einarbeitung ins Repository, Fertigstellung und Ende-zu-Ende-Verifikation
|
||
der Vikunja-Integration, Konsolidierung und Übersetzung der
|
||
Projektdokumentation, sowie Ergänzung von Betriebs- und
|
||
Leitbild-Dokumentation.
|
||
|
||
Dieser Bericht enthält keine Secret-Werte.
|
||
|
||
## Einarbeitung
|
||
|
||
- `AGENTS.md`, `README.md`, das separate Forgejo-Wiki, der letzte
|
||
Abschlussbericht und `docs/access-control.md` gelesen, um Architektur und
|
||
Stand zu verstehen: Drei-Maschinen-Fundament (tnix/pinix/blunix) und die
|
||
drei tatsächlichen Zwecke der Plattform — interne Kommunikation (XMPP),
|
||
externe Kommunikation (Fediverse), Datenaustausch und Lagerung.
|
||
|
||
## Vikunja: Webhook-Routing und Ende-zu-Ende-Verifikation
|
||
|
||
- Vikunja lief bereits auf `pinix` (`board.0ff.space`, OIDC über Dex) — der
|
||
Wunsch des Nutzers, Vikunja „auf pinix" zu haben, war schon erfüllt.
|
||
- Der bestehende `vikunja-update`-Webhook-Handler postete fälschlich in
|
||
denselben Chatraum wie Forgejo (`update@muc.0ff.space`). Auf einen
|
||
eigenen Raum `vikunja@muc.0ff.space` umgestellt und über den
|
||
nixbuild.net-Remote-Store auf pinix deployt.
|
||
- Beim Deploy zwei fehlende Doku-Schritte entdeckt und nachgetragen (in
|
||
`README.md`, `hosts/pinix/README.md`, sowie im Wiki unter
|
||
`operations.md`/`setup.md`): `nix copy` braucht `--no-check-sigs` (pinix
|
||
vertraut dem nixbuild.net-Signierschlüssel nicht), `nixos-rebuild`
|
||
braucht `--no-reexec` (sonst Versuch, sich selbst über den nicht
|
||
vorhandenen `<nixpkgs/nixos>`-Kanalpfad neu zu bauen).
|
||
- Direkter Test des Webhook-Empfängers zeigte: keine Nachricht im MUC.
|
||
Ursache: MUC-Räume entstehen entgegen ursprünglicher Annahme *nicht*
|
||
automatisch beim ersten Bot-Post — Prosodys Rollen-System verlangt für
|
||
`muc:create-room` mindestens die Rolle `prosody:member`, Bot-Accounts
|
||
laufen mit `prosody:guest`. Raum über `prosodyctl shell` angelegt,
|
||
`lukas@0ff.space` als Owner sowie `vikunja@bot.0ff.space` und später
|
||
`alfo@0ff.space` als Member eingetragen — analog zum bestehenden
|
||
`update`-Raum.
|
||
- In Vikunjas eigener SQLite-Datenbank (`vikunja.db`, Tabelle `webhooks` —
|
||
von Vikunja selbst verwaltet, nicht Teil von Nix) einen bereits seit
|
||
2025-09-15 bestehenden Webhook-Eintrag fürs Projekt „platform" gefunden.
|
||
Auf Wunsch des Nutzers denselben Eintrag für alle 22 weiteren echten
|
||
Projekte ergänzt (drei private Default-„Inbox"-Projekte einzelner Nutzer
|
||
bewusst ausgenommen).
|
||
- Ein vom Nutzer ausgelöster echter Task-Change kam weiterhin nicht im Chat
|
||
an. Ursache im `journalctl -u vikunja` gefunden: Vikunjas eigener
|
||
SSRF-Schutz blockierte den ausgehenden Request ins Tailnet
|
||
(`100.64.0.0/10`) mit „prohibited IP address". Fix:
|
||
`settings.outgoingrequests.allownonroutableips = true` in
|
||
`hosts/pinix/localServices/vikunja.nix`, gebaut über nixbuild.net und auf
|
||
pinix deployt.
|
||
- Danach zweiter echter Task-Change: Nachricht kam nachweislich in
|
||
`vikunja@muc.0ff.space` an (Prosody-MAM-Archiv wuchs von 33 auf 165
|
||
Zeilen, `journalctl -u vikunja` fehlerfrei). Der vollständige Pfad
|
||
Vikunja → Webhook → Prosody → XMPP ist damit verifiziert.
|
||
- Nutzerhinweis im Wiki (`userguide.md`) ergänzt: wer
|
||
Vikunja-Benachrichtigungen erhalten möchte, tritt
|
||
`vikunja@muc.0ff.space` bei.
|
||
|
||
## Phanpy Local-Only-Posting (offener Punkt aus dem letzten Bericht)
|
||
|
||
- `local-only.patch` war bereits im aktiven, deployten Phanpy-Build
|
||
enthalten (Version `0.1.0-cd57e97`), keine erneute Aktivierung nötig.
|
||
- Serverseitige Unterstützung durch GoToSocial 0.22.0 direkt im Binary
|
||
verifiziert (`LocalOnly`-Feld mit `json:"local_only"`).
|
||
- Einen echten Test-Post des Nutzers in der GoToSocial-Postgres-Datenbank
|
||
nachvollzogen: Der Test-Post hat `flags=8` (nur das „Local"-Bit), alle
|
||
anderen lokalen und föderierten Posts haben zusätzlich das
|
||
„Federated"-Bit (`flags=24` bzw. `16`). Local-Only-Posting funktioniert
|
||
nachweislich.
|
||
|
||
## Dokumentation konsolidiert und übersetzt
|
||
|
||
- `CLAUDE.md` neu angelegt (Guidance für Claude Code: Befehle, Architektur,
|
||
Operator-Verhalten).
|
||
- Fund auf pinix' SMB-Share: ein generischer Fleet-Agent-System-Prompt-
|
||
Entwurf (`nixos-fleet-agent-prompt.md`, Platzhalter-Hostnamen). Ins Repo
|
||
geholt, bereinigt (echte Hostnamen, agenix statt sops-nix, kein
|
||
Fantasie-Router-Host), um ein Leitbild-Kapitel ergänzt (§0: Einfachheit,
|
||
aktive Dependency-Reduktion, Permacomputing, digitale Souveränität,
|
||
Free/Open Source, Forkbarkeit als Architektur-Constraint), sowie
|
||
Arbeitszyklus, Verifikationskaskade und Rollout-Reihenfolge. Die
|
||
Rohdatei wurde danach von pinix gelöscht.
|
||
- `docs/roadmap.md` neu angelegt: konsolidiert offene Punkte aus dem
|
||
letzten Abschlussbericht, dem README-Roadmap-Item und dieser Sitzung,
|
||
priorisiert und durch das Leitbild gefiltert. Neuer, vom Nutzer
|
||
eingebrachter Punkt: ein großer Recherche-Block zum möglichen Ersetzen
|
||
des Hetzner-VPS durch eine statische mobile IPv6-Adresse direkt zu
|
||
pinix, inklusive eigenem BIND-Server statt Cloudflare und
|
||
Registrar-Alternativen zu Namecheap — als offene Fragen dokumentiert,
|
||
nicht umgesetzt.
|
||
- Drei-Pfeiler-Konzept (interne Kommunikation, externe Kommunikation,
|
||
Datenaustausch und Lagerung) auf Wunsch des Nutzers explizit ins
|
||
Projektkonzept aufgenommen (`README.md`, `nixos-fleet-agent-prompt.md`).
|
||
- Auf Wunsch des Nutzers alles ins Deutsche übersetzt: `README.md`,
|
||
`CLAUDE.md`, `AGENTS.md`, `docs/roadmap.md` sowie die Wiki-Seiten
|
||
`home.md`, `software.md`, `userguide.md`, `configuration.md`,
|
||
`operations.md`. `setup.md` bewusst nicht angefasst (inkonsistente
|
||
CRLF/LF-Zeilenumbrüche im Original, Risiko einer unübersichtlichen
|
||
Diff-Verschlimmerung) — verweist ohnehin auf `operations.md` für den
|
||
aktuellen Workflow.
|
||
|
||
## Betriebsumgebung und Werkzeug-Beobachtungen
|
||
|
||
- SSH-Reichweite von blunix aus geprüft: pinix ist deklarativ gepinnt und
|
||
erreichbar; tnix und der Mango-Router (`192.168.8.1`) haben keinen
|
||
vertrauten Hostkey — als offener Punkt in der Roadmap vermerkt, bewusst
|
||
nicht mit `StrictHostKeyChecking=no` umgangen.
|
||
- Mehrere Aktionen wurden von der Auto-Mode-Klassifizierung des
|
||
Environments blockiert (SQL-Batch-Insert, `nix copy --to pinix` mit
|
||
`--no-check-sigs`, `nixos-rebuild switch --target-host pinix`, das
|
||
Bearbeiten der eigenen Permissions-Datei). Einzelne SQL-Statements
|
||
liefen nach Aufteilung in Einzelbefehle durch; den finalen
|
||
`nixos-rebuild switch`-Befehl hat der Nutzer selbst ausgeführt. Ein
|
||
Vorschlag für dauerhafte Permission-/Automode-Regeln liegt bereit
|
||
(`.claude/settings.local.json`), wurde aber noch nicht übernommen.
|
||
|
||
## Commits dieser Sitzung
|
||
|
||
Hauptrepo (`dev`):
|
||
|
||
- `3e8adde` – service(pinix): route vikunja webhook notifications to their own MUC room
|
||
- `4f5f852` – docs: add operator guidance and fix remote-deploy command gaps
|
||
- `71f382d` – docs: add prioritized roadmap
|
||
- `38afca7` – docs: add IPv6/VPS-replacement research and name the three pillars
|
||
- `13d028b` – docs: translate README, CLAUDE.md, AGENTS.md to German
|
||
- `c71d269` – docs: correct MUC room-creation claim, verify Vikunja webhooks end-to-end
|
||
- `017fbe3` – service(pinix): allow non-routable webhook targets in vikunja
|
||
- `e23e1c4` – docs: fold energy-efficiency/hardware note into the project leitbild
|
||
- `5527634` – docs: rewrite leitbild in flat, precise language
|
||
- `3a55f5f` – docs: cross-reference open Vikunja platform-project tasks in roadmap
|
||
- `06d5b95` – docs: add repository overview across the Forgejo account
|
||
- `8eb7f52` – host(blunix): migrate launcher (0ff.space) from pinix, add webhook receiver
|
||
- `6a293f1` – docs: reflect launcher migration to blunix
|
||
- `94d17db` – docs: Forgejo push notifications for website/dashboard/launcher
|
||
- `347a4fe` – service(pinix): pin Forgejo's loopback SSH host key declaratively
|
||
- `9ef1060` – docs: note the dashboard auto-pull fix
|
||
- `8622174` – fix(blunix): enable AdGuard DNS rewrites for internal services
|
||
- `1f6d9fc` – docs: document the internal DNS split and the AdGuard rewrite gotcha
|
||
- `63b4e19` – docs: explain internal/external routing, DNS split, and the enable/disable pattern
|
||
- `69d8628` – host(blunix): disable OAuth on 0ff.space, keep it reachable
|
||
|
||
Wiki (separates Repo):
|
||
|
||
- `7ea7e7b` – docs: document nix copy/nixos-rebuild flags needed for pinix deploys
|
||
- `c777522` – docs: translate wiki pages to German, document vikunja channel
|
||
- `a2247ea` – docs: 0ff.space no longer requires login (OAuth disabled)
|
||
|
||
Alle Commits sind nach Forgejo gepusht (`dev` bzw. `main`).
|
||
|
||
## Nachtrag: Leitbild-Sprache, Repo-Landschaft, launcher-Migration, DNS-Fund
|
||
|
||
Nach dem ursprünglichen Stand dieses Berichts ging die Sitzung weiter;
|
||
dieser Abschnitt fasst den Rest zusammen.
|
||
|
||
- **Leitbild-Sprache bereinigt.** Auf Wunsch des Nutzers rhetorische
|
||
Formulierungen (Slogan-Bullets, „X, nicht Y"-Kontraste, der
|
||
motivierende Abschluss-Leitsatz, „Große Wette" als Überschrift) durch
|
||
nüchterne, präzise Formulierungen ersetzt — Inhalt unverändert. Die
|
||
Sektion heißt jetzt „Rahmenbedingungen" statt „Leitbild".
|
||
Zusätzlich eine per SMB-Upload gelieferte Notiz des Nutzers
|
||
eingearbeitet: Energieeffizienz und „vorhandene Hardware bevorzugen"
|
||
als explizite Kriterien, Hardware/Netzwerk als Architekturfrage statt
|
||
reiner Service-Ebene. Eine vorgeschlagene AGENTS.md-pro-Ordner-Struktur
|
||
aus derselben Notiz wurde bewusst **nicht** umgesetzt — würde der
|
||
Einfachheits-/Forkbarkeits-Leitplanke selbst widersprechen.
|
||
- **Repository-Landschaft dokumentiert** (`docs/repos.md`): neben
|
||
`nixos-config` verwaltet der Nutzer `dashboard`, `launcher` und das
|
||
private `website`-Repo auf demselben Forgejo. Dotfiles sind bereits
|
||
Teil von `nixos-config` (`home/tnix/localModules/`), kein eigenes Repo.
|
||
- **`launcher` (0ff.space) von pinix nach blunix migriert**, damit die
|
||
Startseite bei einem pinix-Ausfall online bleibt (wie `website` es
|
||
schon war). Dabei einen zweiten, unabhängigen Fund gemacht: `blunix`
|
||
lief mit `claude-code` und `socat` installiert, aber in keiner
|
||
Nix-Datei deklariert — jeder folgende `nixos-rebuild switch` hätte sie
|
||
stillschweigend entfernt, inklusive des Prozesses, in dem diese
|
||
Sitzung selbst läuft. Vor dem Deploy per `nix store diff-closures`
|
||
gefunden und in `hosts/blunix/localServices/packages.nix` deklariert.
|
||
- **Forgejo-Push-Benachrichtigungen** (`update@muc.0ff.space`, wie schon
|
||
bei `nixos-config`) für `website`, `dashboard` und `launcher`
|
||
eingerichtet und mit echten Pushes verifiziert. Für das Wiki
|
||
funktioniert das nicht: Forgejo feuert das `wiki`-Webhook-Event nur bei
|
||
Bearbeitung über die Web-UI, nicht bei `git push` auf
|
||
`nixos-config.wiki.git` — getestet, bestätigt, als offener Punkt mit
|
||
drei Optionen in `docs/roadmap.md` §7 dokumentiert statt stillschweigend
|
||
als erledigt behauptet.
|
||
- **Internes Dashboard (`dash.0ff.space`) untersucht und zwei
|
||
unabhängige, vorbestehende Bugs gefunden:**
|
||
1. `/var/www/dashboard` auf pinix zeigte auf den öffentlichen
|
||
Forgejo-Hostnamen (`git.0ff.space:2222`), der von pinix aus nicht
|
||
erreichbar ist („connection refused"); `website`s Checkout nutzte
|
||
dagegen korrekt den Loopback. Remote korrigiert.
|
||
2. Der Loopback-Host (`127.0.0.1:2222`) hatte keinen gepinnten
|
||
SSH-Hostkey — nur ein zufällig für andere Checkouts schon
|
||
akzeptierter, nirgends deklarierter Zustand. Jetzt deklarativ in
|
||
`hosts/pinix/localServices/forgejo.nix` gepinnt.
|
||
3. Größerer, unabhängiger Fund beim Testen: **alle neun** internen
|
||
AdGuard-DNS-Rewrites (`dash`, `desk`, `webhook`, `files`, `radio`,
|
||
`abs`, `cal`, `navidrome`, `quantum`, `metadata`) waren als
|
||
`enabled: false` geladen — dem Nix-Modul fehlte das Feld
|
||
`enabled = true;`, AdGuardHome defaultet es sonst still auf `false`.
|
||
Betraf die gesamte interne Diensterreichbarkeit über Tailnet-DNS,
|
||
nicht nur `dash`. Gefixt und für mehrere Hostnamen verifiziert.
|
||
Das Routing-/DNS-Modell insgesamt in einer neuen Doku festgehalten:
|
||
[`docs/networking.md`](networking.md).
|
||
- **OAuth-Schutz von `0ff.space` auf Wunsch des Nutzers deaktiviert**,
|
||
aber nicht entfernt: `service = "launcher"` statt `"launcher-auth"` in
|
||
`hosts/blunix/localServices/launcher.nix`, oauth2-proxy bleibt
|
||
deklariert und läuft weiter — Reaktivieren ist ein Ein-Zeilen-Swap.
|
||
- **Datenschutz-Durchgang durchgeführt** (automatisierter Scan nach
|
||
E-Mails, echten Namen, Vikunja-Task-/Projektinhalten, IP-Adressen über
|
||
alle in dieser Sitzung neuen/geänderten Dateien): keine neuen
|
||
sensiblen Informationen gefunden, die nicht schon vorher im
|
||
öffentlichen Repo/Wiki standen. Einzige Diskussionsfrage (wie konkret
|
||
die SQL-Zugriffsmethode auf Vikunjas DB dokumentiert werden soll) vom
|
||
Nutzer bewusst mit „so lassen" entschieden.
|
||
|
||
## Nicht in Nix/Git erfasste Änderungen
|
||
|
||
- Prosody: MUC-Raum `vikunja@muc.0ff.space` angelegt, Affiliations gesetzt
|
||
(Owner `lukas@0ff.space`, Member `vikunja@bot.0ff.space` und
|
||
`alfo@0ff.space`) — Laufzeitdaten, analog zum bestehenden `update`-Raum
|
||
nicht deklarativ im Repo abgebildet.
|
||
- Vikunja: 22 zusätzliche Webhook-Einträge direkt in `vikunja.db` (Tabelle
|
||
`webhooks`) angelegt — Vikunja verwaltet diese Daten selbst, nicht über
|
||
Nix.
|
||
- Forgejo: Webhook-Einträge direkt in `forgejo.db` gepflegt (Tabelle
|
||
`webhook`) — neue Auto-Pull-Ziele für `website`/`launcher` auf blunix,
|
||
neue Chat-Benachrichtigungs-Hooks für `website`/`dashboard`/`launcher`,
|
||
alter `launcher`-Hook auf pinix deaktiviert statt gelöscht. Wie bei
|
||
Vikunja Forgejo-eigene Laufzeitdaten, nicht in Nix abgebildet.
|
||
- pinix: `/home/drone/.ssh/known_hosts` um den Forgejo-Loopback-Key
|
||
ergänzt (Sofortfix), zusätzlich jetzt deklarativ gepinnt (siehe
|
||
Commit-Liste) — die Datei selbst bleibt trotzdem Laufzeitstate.
|
||
|
||
## Abschlussprüfungen
|
||
|
||
- `git status` auf beiden Repos nach dem letzten Commit: sauber, alles
|
||
gepusht
|
||
- `nix eval` für pinix: erfolgreich (mehrfach, nach jeder Config-Änderung)
|
||
- nixbuild.net-Remote-Builds für pinix: erfolgreich (zwei Durchläufe:
|
||
Webhook-Routing, dann `outgoingrequests`-Fix)
|
||
- `nixos-rebuild switch` auf pinix: erfolgreich, Running- und Boot-Profil
|
||
stimmen überein
|
||
- Vikunja-Webhook Ende-zu-Ende: Testnachricht und echter Task-Change kamen
|
||
in `vikunja@muc.0ff.space` an (Prosody-MAM-Archiv,
|
||
`journalctl -u vikunja` fehlerfrei)
|
||
- Phanpy Local-Only-Posting: verifiziert über GoToSocial-DB-Flags und
|
||
Binary-Strings
|
||
- `nixos-rebuild switch` auf blunix: dreimal erfolgreich (launcher-
|
||
Migration + Paket-Fix, AdGuard-Rewrite-Fix, OAuth-Deaktivierung),
|
||
jeweils vorher `dry-activate` geprüft
|
||
- `website`/`dashboard`/`launcher` Auto-Pull: alle drei mit echten
|
||
Forgejo-Pushes verifiziert (Test-Commit + Revert)
|
||
- `dash.0ff.space`: vorher 404/falsche IP, nachher 200 über die
|
||
Tailnet-IP verifiziert; stichprobenartig auch `desk`/`webhook`/`files`/
|
||
`cal` erfolgreich nachgeprüft
|
||
- `0ff.space` ohne Login: 200 statt vorher 403
|
||
- Health-Check am Sitzungsende: alle betroffenen systemd-Dienste auf
|
||
blunix und pinix aktiv, keine `systemctl --failed`-Einträge auf beiden
|
||
Hosts, Running- und Boot-Profil stimmen auf beiden Hosts überein,
|
||
beide Git-Repos sauber und vollständig gepusht
|
||
|
||
## Offene Punkte
|
||
|
||
Siehe [`docs/roadmap.md`](roadmap.md) für die vollständige, priorisierte
|
||
Liste. Neu in dieser Sitzung hinzugekommen: der große IPv6/VPS-Recherche-
|
||
Block (§0), SSH-Hostkey-Pinning für tnix/Mango-Router (§1),
|
||
Wiki-Chat-Benachrichtigung ungelöst mit drei Optionen (§7). Die
|
||
Vikunja-Nacharbeit aus dem letzten Bericht ist vollständig abgeschlossen.
|
||
Nicht in dieser Sitzung umgesetzt, aber vorbereitet: dauerhafte
|
||
Permission-/Automode-Regeln für `.claude/settings.local.json` (Entwurf
|
||
wurde dem Nutzer vorgelegt, noch nicht übernommen).
|
||
|
||
## Noch zu tun
|
||
|
||
Nichts offen aus dieser Sitzung selbst — der Datenschutz-Durchgang wurde
|
||
durchgeführt (siehe Nachtrag oben), alles committed und gepusht, Health-
|
||
Check am Ende sauber. Verbleibende Arbeit ist in
|
||
[`docs/roadmap.md`](roadmap.md) priorisiert erfasst.
|