How to get rid of unused home manager packages?

I have around 10 generations wort of home-manager data lying around on my system and I have no idea how to get rid of it.
I have deleted all old home manager and system generations, ran nix-collect-garbage -d several times and ran rm /nix/var/nix/gcroots/auto/* and so on.

I tried following one of the seemingly duplicate packages all the way down using nix-store --query --referrers and while one of them is being used by my current home manager generation, the other one is not.
But how come that it is not being garbage collected?

I could just remove it manually, but I do not want to do that for several hundred packages.

This is what my storage looks like. Several packages are even duplicated more that two times.

I ran nix optimize-store and that freed about 20GB, but now I also have 20GB of symlinks.
My best bet is that something is so fundamentally broken that I should just boot a live-stick and delete and reinstall the whole store.

you may also want to look into /nix/var/nix/gcroots/per-user/$USER, as that also may be containing stale references.

You could also try to slim down your profile closure by removing some of the larger packages. nerdfonts for example is close to 2GB

$ nix path-info -Sh /nix/store/agdms5d2lkdmn9hg57h54z66mgk1nijf-nerdfonts-2.1.0
/nix/store/agdms5d2lkdmn9hg57h54z66mgk1nijf-nerdfonts-2.1.0	   1.9G

Can I just safely remove the user gcroots directory?

I do have some large packages, kicad for example is one offender, but that is only present twice for some reason. Still, even with all the larger packages my whole system plus user software shouldn’t be any larger than 20GB, which is definitely not the case.
Some packages are even present several dozen times. I counted over 30 instances of the same nvidia driver package in my store, all with different hashes.

While it is hard to really break a Nix installation, I would be careful with that. At least build a new generation before running garbage collection.

With that said, it can easily happen that there are stray gcroots hidden in unexpected places (from building envs from shell.nix files, for example).

I usually use this snippet to find them:

sudo -i nix-store --gc --print-roots | egrep -v '^(/nix/var|/run/current-system|/run/booted-system|/proc|{memory|{censored)'
4 Likes

Thanks for your reply.
Turns out I was using nixos-rebuild wrong. I read somewhere that the -p parameter could be used to set custom names for grub entries which I set to the commit messages of the changes I made to my system, resulting in a bunch of gc-roots that could not be garbage collected.

I have since deleted those, but there are still lots of packages left over that cannot be garbage collected and I do not know how to get to those.
I guess doing a full reinstall of my system is in order.

The command above should you list all gcroots blocking GC that are not part of your current system.
If something not in your configs is left: Did you install packages with nix-env?
‘nix-env -e ’ should autocomplete if there is anything installed.
You need to check that for every user account, of course.

For me /nix/var/nix/gcroots/per-user/$USER doesn’t even exist btw. That may mean that it’s unnecessary.