diff --git a/NixOS.md b/NixOS.md index 626ea24..d3dbf0b 100644 --- a/NixOS.md +++ b/NixOS.md @@ -22,11 +22,14 @@ This document contains general notes about NixOS that are independent of my NixO * [Nix profiles](#nix-profiles) * [Switch to previous system profile](#switch-to-previous-system-profile) * [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) * [why-depends: Why is a package installed](#why-depends-why-is-a-package-installed) * [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) * [Show Nix configuration](#show-nix-configuration) * [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 ``` -### 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 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 ``` +## 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 aren’t 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 * https://nixos.wiki/wiki/Nix_command/repl diff --git a/modules/nix-gc.nix b/modules/nix-gc.nix index 93c3454..62cf50f 100644 --- a/modules/nix-gc.nix +++ b/modules/nix-gc.nix @@ -1,54 +1,29 @@ { config, pkgs, ... }: { - # Delete all system generations except the 7 most recent ones. - # Then delete all unreachable store objects. - # - # Based on https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/modules/services/misc/nix-gc.nix + # Garbage collection: Delete generations older than 5 days and then delete unreachable store objects. - # Alternative: Delete generations older than 7 days and then delete unreachable store objects # https://nixos.wiki/wiki/Storage_optimization#Automation - #nix.gc = { - # automatic = true; - # dates = "weekly"; - # options = "--delete-older-than 7d"; - #}; - - 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"; - }; + # https://nixos.wiki/wiki/Storage_optimization#Removing_old_generations + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 5d"; }; - # View generated systemd service config with: - # cat "$(systemctl show -P FragmentPath nix-gc-7.service)" | grep ExecStart - systemd.services."nix-gc-7" = { - description = "rm old system generations and unreachable store objects"; - - conflicts = [ "shutdown.target" "sleep.target" ]; - before = [ "shutdown.target" "sleep.target" ]; - - serviceConfig = { - Type = "oneshot"; - PrivateTmp = true; - - Nice = 19; - IOSchedulingClass = "idle"; + # We need to explicitly run garbage collection for user profiles, + # this is not done by the global `nix.gc` option. + home-manager.users."yoda" = { osConfig, config, pkgs, ... }: { + nix.gc = { + automatic = true; + frequency = "weekly"; + options = "--delete-older-than 5d"; + }; + }; + home-manager.users."root" = { osConfig, config, pkgs, ... }: { + nix.gc = { + automatic = true; + frequency = "weekly"; + 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 - ''; }; }