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

151 lines
7.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.