This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/docs/research/full-system-aufit.md
pijukka 314f56b956 docs: recategorize full-system audit as a research intent
Was created under docs/intent/, which only ever reaches the Operator
(direct_builder/split/needs_human -- no "send to Researcher" option
exists there at all). The Operator picked direct_builder for a
read-only audit needing systemd/journal/network access; Builder
correctly refused (scoped git-only Bash, no shell/journal/network
access) and recommended the Researcher role by name. Moved to
docs/research-intent/, re-ran through Request Research, and committing
its now-completed docs/research/full-system-aufit.md alongside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016w25covboHfcYuLXBAvX3g
2026-09-11 17:32:07 +02:00

24 KiB
Raw Permalink Blame History

Full-System-Audit: NixOS-Plattform (blunix / pinix / tnix)

Datum: 2026-09-11 Scope: Read-only Audit von Repository (/home/drone/nixos-config, Branch dev, HEAD detached), Runtime-Zustand auf blunix (lokale Shell, systemd, Journal, Netzwerk, HTTP), sowie extern erreichbare Endpunkte unter *.0ff.space. Methode: Repository-Lektüre (Nix-Konfiguration, Git-Historie), lokale Diagnosebefehle auf blunix (systemctl, journalctl, ss, df/du, tailscale status), sowie HTTP-Prüfungen gegen öffentlich exponierte Endpunkte über einen bereits im Nix-Store vorhandenen curl-Build (kein neuer Build/keine Zustandsänderung). Kein SSH auf pinix/tnix, kein nixos-rebuild, keine schreibenden Aktionen.

Executive Summary

  1. Kritischer Vorfall bestätigt: blunix ist mit 96 % Diskbelegung (1,5 GB frei von 37 GB) faktisch am Limit. Am 10.09. führte das tatsächlich zu Ausfällen (Forgejo-Dump, Prosody Push-Notifications, DHCP-Lease-Schreibvorgang schlugen mit „No space left on device" fehl). Ursache: ~208 nixos-rebuild switch-Läufe und 34 System-Generationen in weniger als 48 Stunden (automatisierte Builder-Pipeline), während GC nur wöchentlich mit 30-Tage-Retention läuft.
  2. pinix ist seit ca. 1 Tag über Tailscale nicht erreichbar (tailscale status: „offline, last seen 1d ago"). Das erklärt gleichzeitig mehrere scheinbar unabhängige Symptome: Timeouts auf board.0ff.space, social.0ff.space, phanpy.0ff.space, sound.0ff.space, calendar.0ff.space sowie wiederkehrende Forgejo-Webhook-Fehler gegen 100.64.0.3:9000 (pinix' Tailnet-IP).
  3. Der Codeberg-Push-Mirror schlägt seit Tagen zyklisch alle paar Stunden fehl, weil der Mirror versucht, den Branch master auf Codeberg zu löschen (lokal existiert kein master mehr, nur dev/production), Codeberg das aber als aktuellen Default-Branch ablehnt.
  4. Auf blunix liegt ein verwaistes 117 MB großes /var/lib/gotosocial-Verzeichnis, obwohl GoToSocial laut Repo ausschließlich auf pinix läuft — vermutlich Rückstand einer Host-Migration, verschärft den Diskdruck unnötig.
  5. LLDAP (Admin-Verzeichnisdienst) ist öffentlich unter lldap.0ff.space ohne zusätzliche Traefik-Middleware (kein basicAuth, anders als z. B. das Traefik-Dashboard) erreichbar (HTTP 200 auf Login-Seite) — vergrößert die Angriffsfläche für den zentralen Auth-Verzeichnisdienst.

Audit Coverage

Untersucht:

  • Repository-Struktur, flake.nix, Host-Configs (hosts/blunix, hosts/pinix, hosts/tnix, hosts/globalServices), Firewall-/Traefik-/GC-Konfiguration
  • Git-Historie (letzte ~30 Commits), Branch-/Remote-Zustand
  • systemd: alle Units, Failed-Units (keine), Restart-Zähler, laufende vs. nicht-laufende Services, Timer (restic, forgejo-dump, nix-gc)
  • Journal: journalctl -p err über die letzten Tage, gezielte Suche nach wiederkehrenden Mustern (Forgejo, Prosody, SSH, dhcpcd)
  • Disk-/Speicherzustand (df -h, du auf /var/lib/*, /nix/store, /home, journal disk usage), Nix-Generationenverlauf
  • Netzwerk: offene Ports (ss -tlnp), Firewall-Regeln aus dem Repo (allowedTCPPorts, trustedInterfaces), Tailscale-Peer-Status
  • HTTP: Live-Check mehrerer extern gerouteter Endpunkte (git, lldap, traefik, board, social, phanpy, sound, data, hdm, head, calendar) via bereits gebautem curl
  • Backup-Kette: restic-Timer und letzte drei Läufe, Forgejo-Dump-Timer und letzter Lauf

Nicht untersucht / eingeschränkt:

  • Kein Zugriff auf pinix oder tnix (weder SSH noch Shell) — alle Aussagen zu diesen Hosts stammen ausschließlich aus Repo-Konfiguration und indirekten Beobachtungen von blunix aus (Traefik-Timeouts, Tailscale-Status, Webhook-Fehler). Der tatsächliche Zustand von pinix (läuft es noch? Netzwerkproblem oder Host down?) bleibt ungeklärt.
  • Keine Web-UI-Funktionsprüfung mit echtem Login (Board, Kanboard, Mastodon-Frontend etc.), da das die Sandbox-Vorgabe „keine Formulareingaben/Aktionen" verletzen würde und ohnehin die Backends über pinix nicht erreichbar waren.
  • Detailinhalt von /var/lib/forgejo, /var/lib/mysql/*, /var/log/fail2ban, /var/lib/tailscale etc. war aus Permission-Gründen (kein sudo im Runtime-Pfad dieser Rolle) nicht lesbar; Aussagen zu diesen Komponenten stützen sich auf öffentlich lesbare Metadaten (Verzeichnisgröße von außen, systemctl-Status).
  • Kein nix flake check / nix eval durchgeführt (für diesen Auftrag nicht notwendig gewesen); keine Bewertung der Nix-Ausdrucks-Korrektheit über die gelesenen Dateien hinaus.
  • Keine tiefere Analyse von agents/ (Board-Automatisierung, Codex/Claude-Runner) über das hier relevante Maß hinaus — der Job, der diesen Audit ausführt, läuft selbst als board-agent-worker.service-Kindprozess; das wurde nur am Rande beobachtet, nicht separat auditiert.
  • Die genannten 5 SSH-kex_exchange_identification-Fehler/Tag wurden nicht tiefer untersucht (typisches Internet-Hintergrundrauschen von Portscannern); fail2ban-Jail-Details konnten mangels fail2ban-client im PATH nicht abgefragt werden, nur systemctl is-active fail2ban (aktiv).

Findings

F1 — Disk-Auslastung auf blunix kritisch, bereits mit realem Ausfall (Critical)

Komponenten: blunix Root-Filesystem, Nix-Store, nix.gc (hosts/nix-gc.nix), automatisierte Rebuild-Pipeline (agent-codex/deploy_runner.py), Forgejo, Prosody, dhcpcd Beobachtung: df -h zeigt 96 % Belegung (34G/37G, 1,5G frei). /nix/store allein belegt 25G. Zwischen dem 09.09. 22:49 und dem 11.09. 16:40 wurden 34 System-Generationen erzeugt (system-471-link … system-504-link), journalctl zählt 208 Aktivierungen von nixos-rebuild-switch-to-configuration.service in 3 Tagen. Evidenz:

Filesystem             Size  Used Avail Use% Mounted on
/dev/mapper/pool-root   37G   34G  1.5G  96% /
Sep 10 04:31:02 blunix forgejo[1636407]: Failed to create temporary directory: ... no space left on device
Sep 10 04:31:02 blunix systemd[1]: Failed to start forgejo dump.
Sep 10 00:59:42 blunix prosody[683999]: datamanager: Unable to write to cloud_notify storage ('No space left on device')
Sep 10 05:00:07 blunix dhcpcd[450984]: dhcp_writefile: ... No space left on device

Erwarteter Zustand: Ausreichend Puffer entsprechend der in hosts/nix-gc.nix dokumentierten Analyse (docs/intent/nix-gc-plattform.md, min-free 1GiB/max-free 3GiB), keine anwendungsseitigen Fehler durch Plattenmangel. Tatsächlicher Zustand: Trotz aktivierter min-free/max-free-Settings (verifiziert in /etc/nix/nix.conf) reicht die inkrementelle Garbage Collection nicht aus, weil nix.gc nur wöchentlich mit --delete-older-than 30d läuft — bei 200+ Rebuilds/3 Tage bleiben praktisch alle Generationen (und ihre GC-Roots) für Wochen erhalten. Vermutete Ursache: Hohe Rebuild-Kadenz der Board-/Builder-Automatisierung kombiniert mit einer GC-Policy, die auf gelegentliche manuelle Rebuilds ausgelegt war, nicht auf mehrfach-stündliche automatisierte Deploys. Mögliche Auswirkungen: Wiederkehrende Datenverlust-nahe Situationen (fehlgeschlagene Backups/Dumps), Instabilität weiterer schreibender Dienste, im Extremfall Root-FS voll → Totalausfall. Empfohlene nächste Schritte: GC-Strategie an tatsächliche Rebuild-Frequenz anpassen (z. B. nix.gc.dates täglich statt wöchentlich, --delete-older-than deutlich verkürzen, oder Generationen explizit auf eine kleine Anzahl begrenzen statt nur Boot-Menu-Einträge via configurationLimit); alternativ Rebuild-Frequenz der Automatisierung selbst hinterfragen (muss jeder einzelne Board-Job sofort switch auslösen?). Konfidenz: Hoch (direkt aus df, journalctl, Generationenliste und Rebuild-Zähler belegt).

F2 — pinix seit ~1 Tag über Tailscale nicht erreichbar, mehrere Public-Routes tot (Critical)

Komponenten: pinix (Tailnet-Konnektivität), Traefik-Routing (routes-external.nix), Forgejo-Webhooks, Kanboard/„board", GoToSocial/„social", „phanpy", „sound", Radicale/„calendar" Beobachtung: tailscale status zeigt pinix als „offline, last seen 1d ago" (tx>0/rx=0 — einseitig tot). Live-Checks gegen alle Traefik-Routen, die auf tailnetIPs.pinix zeigen, laufen in einen TLS-Handshake-Erfolg gefolgt von vollständigem Timeout; rein lokale Routen (data, hdm, head, alle 127.0.0.1) liefern HTTP 200. Evidenz:

100.64.0.3  pinix  worker@  linux  active; relay "fra"; offline, last seen 1d ago, tx 6240 rx 0
board.0ff.space  -> Operation timed out after 15002 milliseconds
social/phanpy/sound/calendar.0ff.space -> http_code 000 (Timeout)
data/hdm/head.0ff.space -> http_code 200
Sep 11 16:33:16 blunix forgejo[...]: Unable to deliver webhook task[1374] ... http://100.64.0.3:9000/hooks/wiki-update ... context deadline exceeded

Erwarteter Zustand: pinix als Tailnet-Peer aktiv, alle darüber gerouteten Public-Services erreichbar. Tatsächlicher Zustand: pinix vom Tailnet aus nicht erreichbar; dadurch mindestens 5 nach außen beworbene Dienste (Board/Kanboard, Mastodon-Frontend, Phanpy, Sound, Calendar) faktisch down, plus tägliche Webhook-Fehlversuche gegen pinix. Vermutete Ursache: Entweder pinix selbst ist down/hängt, oder ein Tailscale-/Netzwerkproblem auf pinix-Seite (z. B. IP-Wechsel, Stromausfall, Kernel-Update-Hänger). Ohne Zugriff auf pinix nicht abschließend klärbar. Mögliche Auswirkungen: Nutzer-sichtbarer Totalausfall mehrerer Dienste seit ~24h, ohne dass dies (soweit im Audit sichtbar) bereits gemeldet/alarmiert wurde — deutet auf eine Observability-Lücke hin (kein Alerting für Tailnet-Peer-Verfügbarkeit oder Backend-Health der Traefik-Routen). Empfohlene nächste Schritte: Sofortige manuelle Prüfung von pinix (Konsolen-/Out-of-Band-Zugriff, da SSH über Tailnet ja gerade das Problem sein könnte); danach Monitoring/Alerting für Tailnet-Peer-Status und Traefik-Backend-Health ergänzen. Konfidenz: Hoch für „pinix nicht erreichbar" und „dadurch Route-Timeouts" (direkt gemessen); die eigentliche Ursache auf pinix selbst ist unbelegte Vermutung.

F3 — Codeberg-Push-Mirror scheitert zyklisch seit Tagen (Medium)

Komponenten: Forgejo Push-Mirror (lukas/nixos-config → codeberg.org/pijukka/nixos-config) Beobachtung: Wiederkehrender Fehler alle paar Stunden über mehrere Tage hinweg. Evidenz:

Sep 11 13:54:49 blunix forgejo[608639]: Error pushing .../lukas/nixos-config.git mirror[2] ...: PushRejected
Sep 11 13:54:49 blunix forgejo[608639]: remote: Forgejo: branch master is the default branch and cannot be deleted

Lokal existiert kein master-Branch mehr (git branch -a zeigt nur dev/production), origin/HEAD zeigt aber noch auf refs/remotes/origin/master. Erwarteter Zustand: Push-Mirror synchronisiert erfolgreich, kein wiederkehrender Fehler im Journal. Tatsächlicher Zustand: Jeder Sync-Versuch versucht, den auf Codeberg als Default gesetzten master-Branch zu löschen, was Codeberg ablehnt — seit Tagen ununterbrochen wiederholt. Vermutete Ursache: master wurde im Quell-Repo entfernt/umbenannt (vermutlich im Zuge der dev/production-Umstellung), ohne den Default-Branch auf dem Mirror-Ziel entsprechend nachzuziehen. Mögliche Auswirkungen: Kein Datenverlust, aber dauerhaftes Fehlerrauschen im Journal, unnötige Last, und ein nicht mehr aktueller Codeberg-Mirror (bleibt vermutlich auf dem Stand vor der Branch-Umstellung). Empfohlene nächste Schritte: Default-Branch auf Codeberg-Seite auf production oder dev umstellen (oder Mirror-Konfiguration entsprechend anpassen), danach Journal auf Wiederholung prüfen. Konfidenz: Hoch (Fehlermeldung ist eindeutig, lokale Branch-Situation bestätigt die Diskrepanz).

F4 — Verwaistes GoToSocial-Datenverzeichnis auf blunix (Low, Cleanup)

Komponenten: /var/lib/gotosocial auf blunix, GoToSocial-Service (laut Repo nur auf pinix definiert) Beobachtung: du -sh /var/lib/gotosocial liefert 117M auf blunix, obwohl hosts/pinix/localServices/gotosocial.nix der einzige Ort im Repo ist, der den Service definiert; systemctl status gotosocial auf blunix meldet „could not be found". Erwarteter Zustand: Keine GoToSocial-Daten auf einem Host, der den Service gar nicht betreibt. Tatsächlicher Zustand: 117 MB toter Daten-Altlast auf einer Platte, die gerade bei 96 % liegt (F1). Vermutete Ursache: Migration von GoToSocial von blunix nach pinix, Altdaten wurden nicht bereinigt. Mögliche Auswirkungen: Unnötiger Verbrauch von knappem Speicherplatz; potenzielle Verwechslungsgefahr bei zukünftigen Debugging-Sessions. Empfohlene nächste Schritte: Verifizieren, dass die Daten wirklich nicht mehr gebraucht werden (z. B. Vergleich mit dem aktiven Datenstand auf pinix, sobald erreichbar), dann manuell entfernen. Konfidenz: Mittel — Verzeichnisinhalt selbst war wegen fehlender Leserechte nicht einsehbar, nur die Größe und der Servicename sind belegt.

F5 — LLDAP-Admin-UI öffentlich ohne zusätzliche Auth-Schicht exponiert (Medium, Security)

Komponenten: hosts/blunix/localServices/lldap.nix, hosts/blunix/localServices/traefik/routes-external.nix (Route „lldap") Beobachtung: https://lldap.0ff.space/ liefert HTTP 200 (Login-Seite) ohne Traefik-basicAuth-Middleware, im Unterschied zur Traefik-API-Route, die per middlewares = ["auth"] geschützt ist (HTTP 401 bestätigt). Erwarteter Zustand / Vergleich: Andere sensible interne Tools (intent-board) sind bewusst mit middlewares = ["auth"] versehen; LLDAP als zentraler Identitäts-/Admin-Dienst hat dieses zusätzliche Netzwerk-Gate nicht. Vermutete Ursache: LLDAP verlässt sich allein auf sein eigenes Login (Passwort-Auth), vergleichbar mit der bewussten Design-Entscheidung bei „calendar" (Kommentar: „Radicale's own per-request LDAP auth is the real security boundary"). Bei LLDAP ist das aber der Verzeichnisdienst selbst, dessen Kompromittierung (z. B. Brute-Force, ungepatchte CVE) alle nachgelagerten Auth-Flows (Dex, oauth2-proxy) betrifft. Mögliche Auswirkungen: Größere Angriffsfläche für den zentralen Identity-Provider als nötig; kein Brute-Force-Schutz auf HTTP-Ebene sichtbar (nur generisches fail2ban, Jail-Details nicht einsehbar). Empfohlene nächste Schritte: Prüfen, ob basicAuth- oder IP-/Tailnet-Beschränkung für die LLDAP-Web-UI sinnvoll ergänzt werden kann, ohne den beabsichtigten Nicht-Tailnet-Zugriff (falls gewollt) zu brechen; alternativ gezielte fail2ban-Jail für LLDAP-Login-Fehlversuche verifizieren/ergänzen. Konfidenz: Mittel — die Exposition ist belegt, ob das eine bewusste Design-Entscheidung war (wie bei „calendar" dokumentiert) oder ein Versehen, ist aus dem Repo nicht eindeutig ersichtlich (kein entsprechender Kommentar wie bei anderen Routen).

F6 — Wiederkehrende Forgejo „bad object"-Fehler bei PR-Diff-Stats (Low)

Komponenten: Forgejo, GetPullDiffStats Beobachtung: Drei distincte Objekt-Hashes (059210b7…, 13f74c33…, 45db7d4d…) tauchen über mehrere Tage hinweg wiederholt als „fatal: bad object" auf. Erwarteter Zustand: Diff-Stats-Berechnung für alle offenen PRs funktioniert fehlerfrei. Tatsächlicher Zustand: Für (vermutlich) einzelne PRs mit inzwischen nicht mehr existenten Commits (z. B. nach Force-Push/Rebase eines Fork-Branches) schlägt die Berechnung dauerhaft fehl und wird periodisch erneut versucht. Vermutete Ursache: Stale PR-Referenz auf gelöschten/umgeschriebenen Branch-Kopf, kein Repo-Korruptionsproblem des Hauptrepos. Mögliche Auswirkungen: Kosmetisch (fehlende Diff-Stats-Anzeige für betroffene PR(s)), plus unnötige wiederkehrende Last/Log-Rauschen. Empfohlene nächste Schritte: Betroffene(n) PR(s) identifizieren (über Forgejo-UI/DB) und schließen oder neu synchronisieren. Konfidenz: Mittel (Fehlermuster eindeutig, genaue betroffene PR nicht identifiziert).

F7 — MySQL/MariaDB lauscht auf 0.0.0.0:3306 statt 127.0.0.1 (Informational)

Komponenten: MySQL/MariaDB (WordPress-Backend), Firewall Beobachtung: ss -tlnp zeigt 0.0.0.0:3306 und [::]:3306; die Firewall-Konfiguration (allowedTCPPorts = [22 80 443 5222 5269], keine trustedInterfaces, kein tailscale0-Sonderfall für 3306) lässt aber keinen externen oder Tailnet-Zugriff zu. Erwarteter/tatsächlicher Zustand: Kein akutes Risiko, da die OS-Firewall den Port blockt; sauberer wäre dennoch ein bind-address = 127.0.0.1, um Defense-in-Depth nicht allein von der Firewall-Regel abhängig zu machen. Mögliche Auswirkungen: Gering, solange Firewall-Konfiguration unverändert bleibt; Risiko steigt bei künftigen Firewall-Änderungen (z. B. neuer trustedInterfaces-Eintrag). Empfohlene nächste Schritte: bind-address/http_host-Äquivalent für MySQL auf 127.0.0.1 setzen, falls kein externer DB-Zugriff je benötigt wird. Konfidenz: Hoch für die Beobachtung, mittel für die Risikoeinschätzung (abhängig von künftigen Konfigurationsänderungen).

Positive Findings

  • Backups laufen zuverlässig: restic-backups-vpsBackup hat an allen drei geprüften Tagen (09.–11.09.) erfolgreich Snapshots erzeugt, auch am Tag des Disk-Vorfalls — die Backup-Kette selbst war nicht betroffen.
  • Selbstheilung des Forgejo-Dumps: Nach dem akuten Space-Vorfall am 10.09. lief der Forgejo-Dump am 11.09. wieder sauber durch (Finished dumping in file forgejo-dump-…), sobald wieder Platz frei war — kein manuelles Eingreifen nötig.
  • Durchdachte, dokumentierte GC-Tuning-Historie: hosts/nix-gc.nix zeigt bereits eine bewusste, aus einem Preflight abgeleitete Anpassung (docs/intent/nix-gc-plattform.md, 2026-09-05) mit klar begründeten Host-spezifischen Schwellenwerten — das Problem in F1 ist also bereits erkannt und teilweise adressiert worden, reicht aber (siehe F1) angesichts der Rebuild-Frequenz nicht aus.
  • Saubere Trennung von Auth-Boundaries dort, wo dokumentiert: Die calendar-Route hat eine explizit begründete Design-Entscheidung („Radicale's own per-request LDAP auth is the real security boundary"), die intent-board-Route bekam bewusst basicAuth ergänzt, nachdem ein Review das als Lücke markiert hatte — die Codebase zeigt an mehreren Stellen nachvollziehbare, kommentierte Sicherheitsentscheidungen statt Zufall.
  • Firewall-Policy minimal und explizit: Nur 5 TCP-Ports global offen, alle weiteren Dienste laufen entweder rein lokal oder über gezielte tailscale0-Ausnahmen — kein Anzeichen einer „alles offen"-Konfiguration.
  • Keine failed systemd-Units zum Prüfzeitpunkt, kein Service mit auffälliger Restart-Historie außer dem hier selbst laufenden Board-Worker-Job.

Cross-System Observations

  • F1 (Disk voll) und die 34 Generationen/208 Rebuilds sind direkt kausal verknüpft: Die hohe Automatisierungs-Kadenz der Board-/Builder-Pipeline (jeder abgeschlossene Job löst offenbar einen nixos-rebuild switch aus) unterläuft die am 2026-09-05 bewusst eingeführte GC-Politik. Das ist kein Konfigurationsfehler in nix-gc.nix selbst, sondern ein Mismatch zwischen einer für gelegentliche Rebuilds ausgelegten Politik und einer inzwischen viel höherfrequenten Realität.
  • F2 ist die gemeinsame Ursache für mindestens 5 scheinbar unabhängige Symptome: Timeout auf board.0ff.space, social.0ff.space, phanpy.0ff.space, sound.0ff.space, calendar.0ff.space sowie die tagelang wiederkehrenden Forgejo-Webhook-Fehler gegen 100.64.0.3:9000 — alle laufen über denselben Tailnet-Pfad zu pinix. Ohne Korrelation hätte man das leicht als 6 getrennte Bugs behandelt.
  • Dokumentation vs. Runtime: docs/intent/nix-gc-plattform.md beschreibt einen Zustand („blunix hat kaum Reserve, 29G Store auf 37G-Platte"), der sich seit dem 2026-09-05 durch die gestiegene Rebuild-Frequenz weiter verschärft hat (Store jetzt 25G, Gesamtbelegung 34G/37G) — die Doku ist also nicht falsch, aber die zugrunde liegende Annahme (Rebuild-Häufigkeit) hat sich seither verändert, ohne dass die Gegenmaßnahme nachgezogen wurde.
  • Kein sichtbares Alerting für beide Critical-Findings: Weder der Disk-Vorfall vom 10.09. noch der seit ~24h laufende pinix-Ausfall scheinen ein aktives Monitoring/Alerting ausgelöst zu haben (soweit aus Journal/Config ersichtlich) — beides wäre ohne diesen Audit vermutlich erst durch Nutzerbeschwerden aufgefallen.

Empfohlene Folge-Intents (priorisiert)

  1. [Reliability/Bugfix] GC-Policy an tatsächliche Rebuild-Frequenz von blunix anpassen. Ziel: nix.gc täglich statt wöchentlich, kürzere Retention und/oder Begrenzung der Anzahl gehaltener System-Generationen, damit die min-free/max-free-Schwellen nicht durch Dutzende frischer Generationen unterlaufen werden. Bezug: F1, hosts/nix-gc.nix.
  2. [Reliability] pinix-Erreichbarkeit klären und wiederherstellen. Ziel: Root Cause des Tailnet-Ausfalls seit ca. 24h ermitteln (Host down? Tailscale-Client hängt? Netzwerkproblem?) und Board/Social/Phanpy/Sound/Calendar wieder erreichbar machen. Bezug: F2. Höchste Nutzerrelevanz.
  3. [Observability] Alerting für Tailnet-Peer-Status und Disk-Füllstand ergänzen. Ziel: Beide Critical-Vorfälle (F1, F2) hätten proaktiv erkannt werden können; ein einfacher Schwellenwert-Check (Diskbelegung, tailscale status Peer-Offline-Dauer) mit Benachrichtigung wäre risikoarm und hochwirksam.
  4. [Bugfix] Codeberg-Push-Mirror-Konfiguration an aktuellen Default-Branch (production/dev) anpassen. Bezug: F3. Geringer Aufwand, beseitigt tagelanges Fehlerrauschen.
  5. [Cleanup] Verwaiste GoToSocial-Altdaten auf blunix identifizieren und entfernen, nachdem pinix wieder erreichbar ist und der aktive Datenstand verifiziert werden kann. Bezug: F4.
  6. [Security] LLDAP-Web-UI-Exposition bewerten und ggf. zusätzliche Schutzschicht (Middleware/IP-Beschränkung/Rate-Limiting) ergänzen. Bezug: F5.
  7. [Cleanup] Betroffene PR(s) mit „bad object"-Referenzen in Forgejo identifizieren und bereinigen. Bezug: F6.
  8. [Security/Cleanup] MySQL bind-address auf 127.0.0.1 setzen als Defense-in-Depth, unabhängig von der Firewall-Regel. Bezug: F7.
  9. [Architecture] Grundsätzliche Diskussion, ob jeder einzelne Board-/Builder-Job wirklich einen sofortigen nixos-rebuild switch auslösen muss, oder ob Batching/Throttling der Deploys (z. B. max. 1 Switch pro X Minuten) die Systembelastung strukturell reduzieren würde — würde F1 nicht nur symptomatisch (GC), sondern ursächlich adressieren.

Unsicherheiten / offene Punkte

  • Die tatsächliche Ursache der pinix-Nichterreichbarkeit (F2) ist von blunix aus nicht abschließend diagnostizierbar (Host down vs. reines Netzwerkproblem).
  • Ob die fehlende Middleware bei LLDAP (F5) eine bewusste Entscheidung oder ein Versehen war, ist aus dem Repo nicht mit Sicherheit ablesbar.
  • Genaue Größe/Inhalt von /var/lib/forgejo, /var/lib/mysql/*, /var/lib/traefik, /var/lib/postgresql etc. blieb wegen fehlender Leserechte im Runtime-Pfad dieser Rolle unzugänglich; die Diskbilanz aus F1 könnte daher noch weitere, hier nicht sichtbare Verbraucher enthalten.
  • Fail2ban-Jail-Konfiguration/-Wirksamkeit im Detail nicht prüfbar (fail2ban-client nicht im PATH der Sandbox).

Fazit

Die Plattform ist grundsätzlich solide und mit erkennbarer Sorgfalt gepflegt (dokumentierte Design-Entscheidungen, funktionierende Backups, minimale Firewall-Policy). Der Audit deckt jedoch zwei bereits real eingetretene bzw. laufende Incidents auf, die ohne diesen Blick von außen leicht als mehrere unabhängige Kleinprobleme behandelt worden wären: ein selbstverschärfender Diskplatz-Engpass durch die hohe Automatisierungs-Kadenz der Deploy-Pipeline (F1), und ein seit rund einem Tag bestehender Totalausfall mehrerer öffentlicher Dienste durch einen nicht erreichbaren pinix-Host (F2). Beide sollten vorrangig behandelt werden; die übrigen Findings sind überwiegend kostengünstig zu beheben und primär Hygiene-/Cleanup-Charakter.