nixos

Nix store across multiple disks


Is there configuration to make nix use additional disks for its store? Lets say I have small physical disk where nix is installed and multiple unused network ones mounted /mnt/... I would like to use to not run out of space when doing nixos-rebuild switch. Ideal situation would be to store every other generation but the current one there so the system is bootable without them.

(I am not asking how to share disk between multiple nixos machines)


Solution

  • There are a few ways to do this, depending on the constraints (local/remote, reliable/intermittent, NixOS/non-NixOS, etc.). For example, I'm currently running Nix on a non-NixOS system without much disk space; so I'm setting up two Nix stores, one local for day-to-day commands, and another on a remote disk for large build jobs.


    Putting /nix/store on a different local disk

    If our only problem is that / is too small, but we have some other large drive available, then we can use that for our Nix store by simply mounting it at /nix/store. This is easier on non-NixOS systems, since they don't rely on /nix/store during boot, but is doable on NixOS too. There are various instructions for doing this, e.g.


    Combining local disks for more space

    Others have already pointed out that LVM, ZFS, RAID, etc. can be used to combine multiple disks. These can be good solutions, but have a few caveats:


    Combine arbitrary folders with a union filesystem

    We can avoid most of the constraints imposed by LVM/ZFS/etc. by using a union filesystem (at the cost of performance). There are many union filesystems, but my preferred one is mergerfs:


    Using multiple Nix stores via different store paths

    We can use the NIX_STORE_DIR env var to tell Nix commands to use a different path for their store. This is simple, and ensures we're only running a single Nix installation.

    However, this is usually a bad idea, since that different path will be observable to all of the derivations; hence we can't use anything that's been built against the normal /nix/store location, which includes everything in pretty much all binary caches (the official Nix one, everything on Cachix, etc.)


    The following options are mostly documented on https://nixos.wiki/wiki/Nix_Installation_Guide#Installing_without_root_permissions

    Tricking Nix into seeing a different /nix/store

    Instead of asking Nix to use a different store path, we can instead run Nix in an environment where /nix/store points somewhere else. There are many ways to do this, but in all cases it's usually safest to use a whole different /nix (not just the store), and use a separate Nix installation (e.g. by running the usual Nix install script). Options to do this include:


    Use as a remote builder

    The above setup works fine for one-off builds, but requires manual use of Nix commands to copy closures back and forth to the "normal" system store. Instead, you could configure your chroot installation as a remote builder. That way, you can tell Nix to use it (either per command, or in your config file) and it will take care of copying derivations and build products back and forth. Also, this way you can garbage-collect your normal Nix store, without losing the copies that were built on the chroot store.

    This would require the chroot environment to be generally available, e.g. by logging in via SSH user, rather than just a one-off. This could be managed by a suitable SSH alias; or maybe a systemd service that sets up the chroot. At that point it may be easier to jump straight to a container/VM/etc. (since those have dedicated tooling)


    More heavyweight approaches to separate Nix installations

    If you don't mind bloat, but would like to leverage pre-existing tooling, you could upgrade the above chroot approach to a full-blown container (using systemd, nerdctl, podman, etc.) or even a virtual machine (qemu/kvm, VirtualBox, etc.) or emulator (if you want to build for a different architecture, and PRoot doesn't work for you).

    This would also let you use pre-built images, rather than running the installer yourself. One downside is the added complexity of integrating it with the host; e.g. it may require separate user accounts, full-blown networking, "secret" keys, etc.