Nix-sweep: Clean up old Nix profile generations and left-over garbage collection roots

Hi everyone,

One of my greatest annoyances with NixOS the last few years was how untransparent store usage is. There were a few questions that seemed hard to answer easily with nix itself/standard Nix tooling. How much space does one of my system generations take? What generations do I have? How old are they? What gc roots do I have lingering around from things like nix build .? It was possible to answer some of these questions with a little bit of tooling and nix-tree was of great help as well, but what I really wanted is a cli utility to cover all these problems without much scripting required.

I was also annoyed with the gc mechanisms Nix brings out of the box. All you can specify is --delete-older-than. No possibility to specify “delete older 7 days, but keep at least 3 generations” or “delete all but the 5 newest generations”.

nix-sweep aims to help with both of these shortcomings. For example you can interactively delete user and home-manager generations older than 7 days, but keep at least 3 generations each:

$ nix-sweep cleanout --remove-older 7 --keep-min 3 user home

Or you can list all your lingering gc roots (including their age and size):

$ nix-sweep gc-roots

To get a summary for your system you can use:

$ nix-sweep analyze

This has improved my NixOS experience quite a bit: I can now use nix build without having to worry about gc roots wasting gigabytes of store space. I can remove generations based on their age on one day and based on a keep-max value on the next day. I can schedule a systemd service that removes old generations daily, while performing true garbage collections when necessary.

I hope this little program can be of help to some of you as well. I think especially newer and non-frequent users could benefit from a utility like this. If you have any feedback feel free to open an issue.

26 Likes

Thanks. Gave it a try. Seems that it is aiming to be more comprehensive than nh with regards to analysis and cleanup. So I turned release notifications on. Keep it up.

1 Like

Here’s what I currently have in my flake for garbage collection. How do I replace this with nix-sweep?


  nix.gc = {
    automatic = true;
    dates = "daily";
    options = "--delete-older-than 7d";
  };

I would suggest you first try it out manually (nix shell github:jzbor/nix-sweep to get it into your environment) . You can get a quick overview of your Nix store usage with nix-sweep analyze and try out playing with the options nix-sweep cleanout --help.

If you want to replace your nix.gc option you can use the nixosModule in the flake, but note that it should be considered “experimental” right now and its interface may change in the future.

These options would give you the exact same behavior as above (provided you imported nix-sweep into your flake):

imports = [
  inputs.nix-sweep.nixosModules.default
];

services.nix-sweep = {
  enable = true;
  interval = "daily";
  removeOlder = "7d";
  gc = true;
  gcInterval = "daily";
};

nix-sweep has quite some more options than nix.gc and only really makes sense if you want to use these options. What settings you use/want to use depends a lot on your personal preference. Also atm it is only packaged for Flakes, so if you manage your system differently you will have to figure out how.

Thank you! I want to use this setting:

Basically I want to combine remove-older + keep-min. I’ll definitely test it out before putting it into my flake!

If you want to replace your nix.gc option you can use the nixosModule in the flake, but note that it should be considered “experimental” right now and its interface may change in the future.

Can I do something like: inputs.nix-sweep.url = "github:jzbor/nix-sweep";

This would probably look something like:

services.nix-sweep = {
  enable = true;
  interval = "daily";
  removeOlder = "7d";
  keepMin = 10;
  gc = true;
  gcInterval = "daily";
};

Note that you can also just keep the regular Nix gc service instead of using the nix-sweep one:

services.nix-sweep = {
  enable = true;
  interval = "daily";
  removeOlder = "7d";
  keepMin = 10;
};

nix.gc = {
  automatic = true;
  dates = "daily";
};

Yes that should work. You might also have to add/update the specialArgs field for your configuration. You can refer to Flakes - NixOS Wiki for detailed instructions.

1 Like