NixOS Automatic GC and Generation Retention: Bootloader Limit Behavior Needs Diagnosis
0 reputation · 20 Nov 2023, 12:51 UTC
0 reputation · 20 Nov 2023, 12:51 UTC
NixOS derives system state from a declarative configuration and keeps prior generations in the Nix store so rollbacks remain possible. Garbage collection is not automatic unless a systemd timer or manual invocation triggers it, while the bootloader's configurationLimit controls how many generations appear in the boot menu.
The unresolved point is the boundary between these two mechanisms. A boot menu limit may only affect which entries are displayed, leaving older store paths intact until GC runs; alternatively, it may act as a retention floor that GC respects. The distinction matters on small root partitions, where automatic GC is often enabled to avoid disk exhaustion but where removing too many generations reduces recovery options.
Behavior may vary by NixOS release, so any conclusion should be checked against the specific version in use and the actual generation list.
Does boot.loader.grub.configurationLimit or boot.loader.systemd-boot.configurationLimit constrain what garbage collection may delete, or only what the boot menu shows? When automatic GC is enabled, what determines the minimum number of generations retained?
31775 reputation · 20 Nov 2023, 14:12 UTC
The configurationLimit settings for GRUB or systemd-boot do not constrain what the Nix garbage collector (GC) may delete. They only control how many entries are written to the bootloader's configuration file and displayed in the boot menu.
In NixOS, the bootloader and the Nix store operate as two separate layers of abstraction. The bootloader limit is a display and configuration filter, whereas the GC is a storage manager.
nixos-rebuild switch, the system updates the boot menu. If a limit is set, the bootloader configuration is pruned to show only the most recent N entries. This does not delete the underlying store paths.When nix.gc.automatic is enabled, the minimum number of generations retained is determined by the system profiles located in /nix/var/nix/profiles/. The GC will not delete any generation that is still linked as a valid profile.
If you use nix.gc.automatic without manually pruning profiles, the store will continue to grow because the profiles act as "roots" that protect the data. To actually reclaim space, you must remove the profile links (e.g., via nix-collect-garbage -d), which then makes those paths eligible for deletion during the next GC cycle.
To diagnose the current state of your retention boundaries, use the following commands:
ls /nix/var/nix/profiles/system-*
/nix/var/nix/profiles/ is higher than the boot menu entries, your configurationLimit is working as a display filter only.sudo nix-collect-garbage
Diagnostic Detail Needed: Are you using a custom script or a specific nix.gc.dates configuration to prune profiles? If you are not explicitly deleting profiles, nix.gc.automatic will not reduce the number of generations over time.
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 20 Nov 2023, 18:14 UTC
To clarify the mechanism: the Nix garbage collector does not look at the bootloader configuration to determine what to keep. Instead, it identifies "roots"—paths that are explicitly referenced. The system profiles located in /nix/var/nix/profiles/system act as these roots.
You can verify the discrepancy between the boot menu and the actual store retention by comparing these two outputs:
nix-env --list-generations: Shows all generations currently acting as roots (and thus protected from GC).configurationLimit.If the first list is significantly longer than the boot menu, your disk space is being consumed by "invisible" generations. To align these, you must prune the profiles themselves, as nix.gc.automatic will not delete a generation that is still linked as a profile root.