I have the automatic nix store gc service running, nightly.
Every day when I cd somewhere with dotenv and flake devshells, a bunch of stuff gets re-downloaded, because it’s not linked via any of the profiles gc sees.
I could think of a few hacks:
- run the gc service much less often, or not at all
- add the packages to a profile, just because
- add something to the direnv hook that somehow adds all the packages to a dummy profile, and then add another layer of gc logic to that
Are there any better suggestions / options / patterns / existing solutions?
nix-direnv plugin for
direnv and it manages GC roots for the shells entered through it.
About once a month though I have to go through GC roots and delete the shell profiles I won’t need in the near future.
Oh, that looks like pretty much exactly the thing. Awesome.
/nix/var/nix/gcroots/auto/ or similar?
nix-store --gc --print-roots.
You can use
nix develop --profile ./profile. This makes it save the devshell as a version of a profile, which prevents it from being garbage-collected. You can enter any version of the profile by doing
nix develop ./profile-<version>-link.
This isn’t quite working.
I have some projects. I ran
nix develop --profile ./profile, and profile links were created. They show up in
nix-store --gc --print-roots, and seemingly all is good.
Some time passes. Some project aren’t touched for a while. Eventually when I get back to them, starting a devshell (via
direnv, but I assume that doesn’t matter) ends up re-downloading a bunch of dependencies again, that I would not have expected to get gc’d.
Looking again at the roots, those profile links are no longer listed (even if they point to valid store locations). They reappear in the gc roots when I update the project deps (e.g.
nix flake update) and recreate a new profile version in the workspace.
I’m not yet sure when they disappear:
after a reboot? once they’re older than the auto-gc threshold? some other expiry? I will have to keep an eye on this and try to work out what’s going on - but it’s not what I expected to happen and may be a bug?
I usually have this:
# reload when these files change
# shell gc root dir
mkdir -p "$(direnv_layout_dir)"
eval "$(nix print-dev-env --profile $(direnv_layout_dir)/flake-profile)"
} || use nix
Well it’s not as simple as them just going away after a reboot. I was wondering if the state was stored somewhere on a tmpfs or similarly obvious problem.
I went looking. It seems they get registered in
/nix/var/nix/gcroots/auto, which has a set of hash/key files as links to the profile links. This looks like something maintained by the nix daemon.
Hypothesis: could the contents of this be getting validated on nix daemon startup, perhaps (sometimes) too early before the filesystems they’re pointing to are mounted, and thus there’s a race where they sometimes get removed incorrectly?