"Guix drops" part 2: garbage collection

by Marius Bakke — Mon 28 November 2022

This is the second post in a series showcasing advanced features of Guix. You can read the first part here.

As you may know, Guix upgrades are transactional: the new state is computed up-front and "switched to" in one atomic operation. Unlike some other package managers (and real life for that matter!), it is not possible to get into a partially completed upgrade situation.

Also unlike real life, a bad transaction can always be rolled back. If you messed up your system somehow, the resolution is a simple guix system roll-back away. No need to say "I'm sorry, we need to start over" to your mom who just wanted to install that totally legitimate looking casino game.

Naturally this luxury uses more disk space than a traditional happy-go-lucky operating system. That's where guix gc comes in. When called without any arguments, guix gc will delete all store items (i.e. packages) that are not in use by active system generations (or user profiles).

However that alone won't free up disk space from old generations that are no longer useful. To do that you first need to run guix system delete-generations to make those eligible for garbage collection:

$ sudo guix system delete-generations 3m
deleting /var/guix/profiles/system-122-link
deleting /var/guix/profiles/system-123-link
deleting /var/guix/profiles/system-124-link
building /gnu/store/r8g38hm98wcz5vn46ifv1ylrs525rvqp-grub-locales.drv...
building /gnu/store/0764m04djxrn0b85nzdmp8chfrci0jdj-grub.cfg.drv...
building /gnu/store/pgrr3q31z4wq3bwrc715aaynglrq7zmh-install-bootloader.scm.drv...

This deleted all generations older than three months and also removed the entries from the bootloader menu. All gone, just like that! If you don't pass a date argument, everything except the current generation will be deleted. Better make sure you won't regret that later (like I have!).

To clear old generations from your user profile, use guix package --delete-generations:

$ guix package --delete-generations=3m
deleting /var/guix/profiles/per-user/marius/guix-profile-35-link
deleting /var/guix/profiles/per-user/marius/guix-profile-36-link
deleting /var/guix/profiles/per-user/marius/guix-profile-37-link
deleting /var/guix/profiles/per-user/marius/guix-profile-38-link

Notice that it only deletes links, not actual packages. If we now run guix gc, the packages inside those profile generations will be deleted (as long as they are not referenced by other generations).

Conveniently guix gc can delete old generations and clear up disk space in one go. This also includes generations from guix pull and guix home:

$ guix gc --delete-generations=3m
deleting /var/guix/profiles/per-user/marius/current-guix-14-link
deleting /var/guix/profiles/per-user/marius/current-guix-15-link
deleting /var/guix/profiles/per-user/marius/current-guix-16-link
deleting /var/guix/profiles/per-user/marius/guix-home-52-link
deleting /var/guix/profiles/per-user/marius/guix-home-53-link
deleting /var/guix/profiles/per-user/marius/guix-home-54-link
finding garbage collector roots...
[... lots of output about deleted packages ...]
deleting `/gnu/store/trash'
deleting unused links...
note: currently hard linking saves 627740.99 MiB
guix gc: freed 80,173.42858 MiBs

If you run this command as root or with sudo, it will clear old generations from all users which is useful on a multi-user system.

For developers who just want to free up some space, but not necessarily delete everything (because they will inevitably need some of the unreferenced packages later), there are handy flags to only control how much to delete.

For example, to clear up 40GiB for that other operating system you want to try in a VM:

guix gc -C 40G

Or if you want to make 100GiB available on the system:

guix gc -F 100G

This differs from -C in that it will stop once the free disk space reaches 100GiB. If you already have 100GiB available space, the command does nothing.

The latter is useful as a cron job to make sure the store does not take up the whole disk, while not deleting all those builds you worked so hard for (but did not install to a profile).