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/intent/nix-gc-plattform.md
2026-09-05 16:34:53 +02:00

7.4 KiB
Raw Permalink Blame History

Intent: Automatische Nix-Garbage-Collection und Generationslimit auf blunix/pinix

Status: Phase 1 (Preflight) abgeschlossen; Phase 2 auf blunix umgesetzt, verifiziert und deployed (2026-09-05, Commit 5cd83cf). Für pinix bleibt Phase 2 im Repo (deklarativ, ungetestet vor Ort) vorerst undeployed — der pinix-Dry-Run deckte einen davon unabhängigen, großen Rückstand gegenüber dev auf (praktisch der gesamte Dienstkatalog würde neu starten), der erst separat geklärt werden soll, bevor dort überhaupt geswitcht wird. Phase 3 weiterhin offen. Datum: 2026-09-02 (Preflight-Ergebnisse ergänzt, Phase 2 deployed 2026-09-05)

Ziel

Automatische, wiederkehrende Nix-Garbage-Collection und eine Begrenzung der Boot-Menü-Generationen auf blunix und pinix einführen, damit alte Store-Generationen und Boot-Einträge nicht mehr unbegrenzt wachsen. Beobachtung, die diesen Auftrag ausgelöst hat: Am 2026-09-02 wurden auf blunix 45 alte Systemgenerationen sowie 100% Diskauslastung und ein gescheiterter nix flake check/Build festgestellt; der genaue ursächliche Zusammenhang zwischen Generationenzahl und Vollauslastung ist nicht im Detail (Store-Belegung, größte GC-Roots) dokumentiert und wird in Phase 1 nachgeholt. Zusätzlich die aktuelle Diskvoll-Situation auf blunix beheben — aber als eigener, separat freizugebender operativer Schritt, nicht als Nebeneffekt der deklarativen Änderung.

Umfang

Dreiphasiger Ablauf, jede Phase mit eigenem Abschluss:

Phase 1 — Preflight (read-only, beide Hosts):

  • df -B1 / und df -B1 /boot auf blunix und pinix.
  • Auflistung vorhandener Systemgenerationen und GC-Roots (nix-env --list-generations -p /nix/var/nix/profiles/system, nix-store --gc --print-roots o. ä.).
  • Store-Belegung und größte GC-Roots dokumentieren, um die eingangs genannte Beobachtung zu erhärten oder zu widerlegen.
  • Anhand der gemessenen Werte konkrete min-free/max-free-Schwellen je Host festlegen (siehe Annahmen).

Phase 2 — Deklarative Konfiguration (blunix, pinix):

  • nix.gc.automatic mit wöchentlicher GC, --delete-older-than 30d.
  • nix.settings.min-free/max-free, Werte pro Host konfigurierbar (nicht zwingend identisch — pinix' SD-Karte hat andere Kennzahlen als blunix' VPS-Platte); konkrete Bytes aus Phase 1.
  • boot.loader.<bootloader>.configurationLimit = 10 auf beiden Hosts (blunix: grub, pinix: generic-extlinux-compatible).
  • Gemeinsame Werte über ein eigenständiges Modul, das nur in hosts/blunix/localServices/default.nix und hosts/pinix/localServices/default.nix importiert wird — ausdrücklich nicht über hosts/globalServices/default.nix, da dieses auch von tnix importiert wird und tnix von diesem Auftrag ausgeschlossen bleibt.
  • Build und nix flake check für beide Hostkonfigurationen als Abschluss dieser Phase.

Phase 3 — Cleanup auf blunix (destruktiv, eigene Freigabe erforderlich):

  • Erst nach Phase 1 und 2 sowie einer gesonderten, ausdrücklichen Ausführungsfreigabe durch den Nutzer.
  • Altersbegrenzter Cleanup (--delete-older-than 30d, dieselbe Frist wie in Phase 2), ausdrücklich nicht nix-collect-garbage -d ohne Altersgrenze.
  • Vorher: bekannte gute Generation identifizieren und bestätigen, dass sie die 30-Tage-Frist übersteht.
  • Nachher: Diskbelegung und verbliebene Generationen erneut prüfen.

Phase-1-Ergebnisse (Preflight, 2026-09-05)

blunix:

  • /: 39,5 GB gesamt, ~184–192 MB frei (100%); /boot (eigene Partition, 524 MB) unkritisch (12% belegt).
  • Nur noch 4 Systemgenerationen (364–367, alle vom 04./05.09.) — nicht die 45 vom 02.09., offenbar zwischenzeitlich schon aufgeräumt.
  • Die drei alten Generationen zu löschen würde nur ~22 MB freigeben (fast identischer Closure wie die aktuelle).
  • Reines nix-collect-garbage (ohne Generationen zu löschen): ~810 MB reclaimable (26.074 tote Pfade, überwiegend klein).
  • Store insgesamt: 29 GB, kein einzelner Ausreißer (breite Masse an Paketen: Codex 539 MB, MariaDB 272 MB, Claude Code 215 MB, WordPress-HdM 196 MB, Traefik 185 MB, drawio 146 MB, …). /var zusätzlich 4,4 GB (davon 424 MB WordPress-Backup, 527 MB Logs).
  • Die eingangs vermutete Kausalität (viele alte Generationen → Vollauslastung) ist für den aktuellen Zustand widerlegt: es sind kaum noch alte Generationen da, und selbst volles GC bringt nur ~800 MB. Der Store ist schlicht legitim groß (29 GB) für eine 37-GB-Platte — automatische GC/Boot-Limits bremsen das Nachwachsen, lösen aber die strukturelle Platzknappheit allein nicht.

pinix:

  • /: 118 GB gesamt, 49 GB frei (57%) — unkritisch, wie in den Annahmen vermutet.
  • 227 Systemgenerationen, älteste vom 06.07.2025 — hier liegt die eigentliche Altlast. 21 Boot-Menüeinträge (extlinux).
  • Reines GC: ~873 MB reclaimable (12.184 tote Pfade). Store: 38 GB.
  • Hier umgekehrtes Bild: kein akuter Platzdruck, aber reale Generationen-Anhäufung, die ohne configurationLimit/GC nur weiterwächst.

Daraus abgeleitete Schwellen (ersetzen die vorherige offene Annahme unten):

  • blunix: min-free 1 GB, max-free 3 GB — realistisch angesichts der knappen Reserven; löst die 100%-Auslastung selbst nicht, das braucht eher Phase 3 plus ggf. eine separate, spätere Entscheidung (Disk vergrößern? /var/backups aufräumen?) außerhalb dieses Auftrags.
  • pinix: min-free 2 GB, max-free 6 GB — bewusst zurückhaltender wegen SD-Karten-Schreibverschleiß bei nur wöchentlichem GC.

Explizit ausgeschlossen

  • tnix bleibt außen vor (Laptop, manuell verwaltet, kann ausgeschaltet bleiben) — auch nicht indirekt über ein gemeinsames Modul in globalServices/.
  • Phase 3 (Cleanup) läuft nicht automatisch im selben Zug wie Phase 2; keine implizite Freigabe durch dieses Dokument.

Annahmen

  • Pinix hat aktuell kein akut geprüftes Diskproblem; Phase 1 klärt das für beide Hosts gleichermaßen, statt es zu unterstellen oder auszuschließen.
  • Rückhaltedauer (30 Tage) und Boot-Generationenlimit (10) sind bewusst jetzt schon fest gewählt, weil sie unabhängig von der absoluten Plattengröße sinnvolle Standardwerte sind (Rollback-Fenster vs. Store-Wachstum).
  • Die konkreten min-free/max-free-Bytes-Schwellen sind jetzt anhand der Phase-1-Messung festgelegt, siehe „Phase-1-Ergebnisse" oben: blunix 1 GB/3 GB, pinix 2 GB/6 GB.

Offene Risiken

  • Laut Phase-1-Messung reicht 30 Tage Rückhaltedauer auf blunix allein nicht, um die 100%-Auslastung zu beheben (reines GC bringt dort nur ~800 MB) — das ist kein Bug in der Konfiguration, sondern eine Grenze dieses Auftrags: Phase 2 bremst weiteres Wachstum, löst aber nicht die bestehende Knappheit. Auf pinix ist 30 Tage bei 49 GB frei unkritisch.
  • Falls pinix' SD-Karte empfindlich auf häufige Schreibzugriffe reagiert, kann ein für blunix passender GC-Zeitplan für pinix zu aggressiv sein — in Phase 1 gegenprüfen.

Erfolgskriterien

  • Phase 1: Preflight-Werte für beide Hosts dokumentiert, min-free/ max-free-Schwellen je Host festgelegt.
  • Phase 2: nix flake check und Build beider Hostkonfigurationen erfolgreich; nach Aktivierung: nix-gc-Timer läuft, effektive min-free/max-free-Werte stimmen mit der Konfiguration überein, Anzahl Boot-Menüeinträge ≤ 10.
  • Phase 3: Diskauslastung auf blunix nach Cleanup deutlich unter 100%; die zuvor bestätigte gute Generation ist weiterhin vorhanden; ein erneuter Build/nix flake check scheitert nicht mehr an Diskplatzmangel.