fix: nix garbage collection

This commit is contained in:
Daniel Langbein 2025-02-09 21:05:15 +01:00
parent c745a6549a
commit e604600dbc
Signed by: langfingaz
GPG Key ID: 6C47C753F0823002
2 changed files with 121 additions and 88 deletions

144
NixOS.md
View File

@ -22,11 +22,14 @@ This document contains general notes about NixOS that are independent of my NixO
* [Nix profiles](#nix-profiles) * [Nix profiles](#nix-profiles)
* [Switch to previous system profile](#switch-to-previous-system-profile) * [Switch to previous system profile](#switch-to-previous-system-profile)
* [List system profiles](#list-system-profiles) * [List system profiles](#list-system-profiles)
* [Deleting generations - Keep most recent X system profiles](#deleting-generations---keep-most-recent-x-system-profiles)
* [Garbage collection - Delete unreachable store objects](#garbage-collection---delete-unreachable-store-objects)
* [List installed packages](#list-installed-packages) * [List installed packages](#list-installed-packages)
* [why-depends: Why is a package installed](#why-depends-why-is-a-package-installed) * [why-depends: Why is a package installed](#why-depends-why-is-a-package-installed)
* [Compare two system profiles](#compare-two-system-profiles) * [Compare two system profiles](#compare-two-system-profiles)
* [Garbage collection](#garbage-collection)
* [GC roots](#gc-roots)
* [Deleting generations - Keep most recent X system profiles](#deleting-generations---keep-most-recent-x-system-profiles)
* [Garbage collection - Delete unreachable store objects](#garbage-collection---delete-unreachable-store-objects)
* [Garbage collection - User specific generations](#garbage-collection---user-specific-generations)
* [NixOS configuration debugging](#nixos-configuration-debugging) * [NixOS configuration debugging](#nixos-configuration-debugging)
* [Show Nix configuration](#show-nix-configuration) * [Show Nix configuration](#show-nix-configuration)
* [Evaluate NixOS configuration to JSON](#evaluate-nixos-configuration-to-json) * [Evaluate NixOS configuration to JSON](#evaluate-nixos-configuration-to-json)
@ -485,47 +488,6 @@ ls -l /run/current-system
lrwxrwxrwx 1 root root 77 Nov 11 10:46 /run/current-system -> /nix/store/jf7ml8jzxrmg9djhfr8szq2f19hxysn5-nixos-system-yodaTab-24.05pre-git lrwxrwxrwx 1 root root 77 Nov 11 10:46 /run/current-system -> /nix/store/jf7ml8jzxrmg9djhfr8szq2f19hxysn5-nixos-system-yodaTab-24.05pre-git
``` ```
### Deleting generations - Keep most recent X system profiles
https://nix.dev/manual/nix/2.18/command-ref/nix-env/delete-generations
> Periodically deleting old generations is important to make garbage collection effective. The is because profiles are also garbage collection roots.
A NixOS config example is given in [nix-gc.nix](modules/nix-gc.nix).
```shell
sudo nix-env --delete-generations +7 --profile /nix/var/nix/profiles/system
```
After deleting some generations, it is still necessary to collect garbage in order to free up your system. See below.
### Garbage collection - Delete unreachable store objects
https://nix.dev/manual/nix/2.18/command-ref/nix-collect-garbage
> `nix-collect-garbage` deletes all unreachable store objects in the Nix store to clean up your system.
* https://nixos.org/manual/nix/stable/package-management/garbage-collection.html
* https://discourse.nixos.org/t/why-doesnt-nix-collect-garbage-remove-old-generations-from-efi-menu/17592/4
First delete unreachable store objects:
```shell
# Delete unreachable store objects
sudo nix-collect-garbage
# Deletes all except the currently active generation prior to deleting unreachable store objects
#sudo nix-collect-garbage --delete-old
# Deletes all generations older than 14d prior to deleting unreachable store objects
#sudo nix-collect-garbage --delete-older-than 14d
```
Then remove leftover EFI entries of deleted generations:
```shell
sudo /run/current-system/bin/switch-to-configuration boot
```
### List installed packages ### List installed packages
https://nix.dev/manual/nix/2.23/command-ref/nix-store https://nix.dev/manual/nix/2.23/command-ref/nix-store
@ -662,6 +624,102 @@ tor-browser-bundle-bin: 12.5.2 → 12.5.3, +18.1 KiB
user: +2885.0 KiB user: +2885.0 KiB
``` ```
## Garbage collection
### GC roots
https://nixos.org/guides/nix-pills/11-garbage-collector#cleanup-everything
List garbage collection roots:
```shell
find /nix/var/nix/gcroots | sort
```
```
/nix/var/nix/gcroots
/nix/var/nix/gcroots/auto
/nix/var/nix/gcroots/auto/1yr5778383bqqzc1sxv7lhj4brc42fpn
...
/nix/var/nix/gcroots/auto/z1hk2n5hbj0z6715392sc4vyjyz2b33q
/nix/var/nix/gcroots/booted-system
/nix/var/nix/gcroots/current-system
/nix/var/nix/gcroots/per-user
/nix/var/nix/gcroots/per-user/root
/nix/var/nix/gcroots/per-user/yoda
/nix/var/nix/gcroots/profiles
```
### Deleting generations - Keep most recent X system profiles
https://nix.dev/manual/nix/2.18/command-ref/nix-env/delete-generations
> Periodically deleting old generations is important to make garbage collection effective. The is because profiles are also garbage collection roots.
A NixOS config example is given in [nix-gc.nix](modules/nix-gc.nix).
```shell
sudo nix-env --delete-generations +7 --profile /nix/var/nix/profiles/system
```
After deleting some generations, it is still necessary to collect garbage in order to free up your system. See below.
**Note**: We are only cleaning up system profiles. There are still many other generations left which we didn't clean up!
### Garbage collection - Delete unreachable store objects
https://nix.dev/manual/nix/2.18/command-ref/nix-collect-garbage
> `nix-collect-garbage` deletes all unreachable store objects in the Nix store to clean up your system.
* https://nixos.org/manual/nix/stable/package-management/garbage-collection.html
* https://discourse.nixos.org/t/why-doesnt-nix-collect-garbage-remove-old-generations-from-efi-menu/17592/4
First delete unreachable store objects:
```shell
# Delete unreachable store objects
sudo nix-collect-garbage
# Deletes all except the currently active generation prior to deleting unreachable store objects
#sudo nix-collect-garbage --delete-old
# Deletes all generations older than 14d prior to deleting unreachable store objects
#sudo nix-collect-garbage --delete-older-than 14d
```
Then remove leftover EFI entries of deleted generations:
```shell
sudo /run/current-system/bin/switch-to-configuration boot
```
### Garbage collection - User specific generations
https://discourse.nixos.org/t/home-manager-and-garbage-collection/41715
> I discovered a few hundred of these home-manager generations in my gc roots, under my and several other users ~/.local/state/nix/profiles directory, going back a long way. It seems these profile generations arent considered by the nix gc service, which I invoke with a --delete-older-than 10d parameter.
https://nixos.wiki/wiki/Storage_optimization#Removing_old_generations
> There are also user-specific generations for different things (e.g. home-manager). These can be removed [by running `nix-collect-garbage -d` as user]
It is not enough to run garbage collection only for root:
```shell
sudo nix-collect-garbage --delete-older-than 3d
#=> removing old generations of profile /nix/var/nix/profiles/per-user/root/home-manager
#=> removing old generations of profile /nix/var/nix/profiles/per-user/root/channels
#=> removing old generations of profile /nix/var/nix/profiles/system
#=> removing old generations of profile /nix/var/nix/profiles/per-user/root/home-manager
#=> removing old generations of profile /nix/var/nix/profiles/per-user/root/channels
```
Instead, we also need to run it for each user:
```shell
nix-collect-garbage --delete-older-than 3d
#=> removing old generations of profile /home/yoda/.local/state/nix/profiles/home-manager
```
## NixOS configuration debugging ## NixOS configuration debugging
* https://nixos.wiki/wiki/Nix_command/repl * https://nixos.wiki/wiki/Nix_command/repl

View File

@ -1,54 +1,29 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
# Delete all system generations except the 7 most recent ones. # Garbage collection: Delete generations older than 5 days and then delete unreachable store objects.
# Then delete all unreachable store objects.
#
# Based on https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/modules/services/misc/nix-gc.nix
# Alternative: Delete generations older than 7 days and then delete unreachable store objects
# https://nixos.wiki/wiki/Storage_optimization#Automation # https://nixos.wiki/wiki/Storage_optimization#Automation
#nix.gc = { # https://nixos.wiki/wiki/Storage_optimization#Removing_old_generations
# automatic = true; nix.gc = {
# dates = "weekly"; automatic = true;
# options = "--delete-older-than 7d"; dates = "weekly";
#}; options = "--delete-older-than 5d";
assertions = [{
assertion = config.nix.enable;
message = ''nix-gc-7 requires nix.enable'';
}];
systemd.timers."nix-gc-7" = {
wantedBy = [ "timers.target" ];
partOf = [ "nix-gc-7.service" ];
timerConfig = {
OnCalendar = "weekly";
Persistent = true;
AccuracySec = "2d";
RandomizedDelaySec = "1d";
};
}; };
# View generated systemd service config with: # We need to explicitly run garbage collection for user profiles,
# cat "$(systemctl show -P FragmentPath nix-gc-7.service)" | grep ExecStart # this is not done by the global `nix.gc` option.
systemd.services."nix-gc-7" = { home-manager.users."yoda" = { osConfig, config, pkgs, ... }: {
description = "rm old system generations and unreachable store objects"; nix.gc = {
automatic = true;
conflicts = [ "shutdown.target" "sleep.target" ]; frequency = "weekly";
before = [ "shutdown.target" "sleep.target" ]; options = "--delete-older-than 5d";
};
serviceConfig = { };
Type = "oneshot"; home-manager.users."root" = { osConfig, config, pkgs, ... }: {
PrivateTmp = true; nix.gc = {
automatic = true;
Nice = 19; frequency = "weekly";
IOSchedulingClass = "idle"; options = "--delete-older-than 5d";
}; };
script = ''
${config.nix.package.out}/bin/nix-env --delete-generations +7 --profile /nix/var/nix/profiles/system
${config.nix.package.out}/bin/nix-collect-garbage
'';
}; };
} }