| Title: How to install Nix in a Qubes OS AppVM | |
| Author: Solène | |
| Date: 15 May 2023 | |
| Tags: qubes qubesos nix nixos | |
| Description: In this article, you will learn how to install the | |
| functional package manager Nix in a Qubes OS AppVM | |
| # Intro | |
| I'm still playing with Qubes OS, today I had to figure how to install | |
| Nix because I rely on it for some tasks. It turned out to be a rather | |
| difficult task for a Qubes beginner like me when not using a fully | |
| persistent VM. | |
| Here is how to install Nix in an AppVm (only /home/ is persistent) and | |
| some links to the documentation about `bind-dirs`, an important | |
| component of Qubes OS that I didn't know about. | |
| Qubes OS documentation: How to make any file persistent (bind-dirs) | |
| Nix project website | |
| # bind-dirs | |
| Behind this unfriendly name is a smart framework to customize templates | |
| or AppVM. It allows running commands upon VM start, but also make | |
| directories explicitly persistent. | |
| The configuration can be done at the local or template level, in our | |
| case, we want to create `/nix` and make it persistent in a single VM, | |
| so that when we install nix packages, they will stay after a reboot. | |
| The implementation is rather simple, the persistent directory is under | |
| the `/rw` partition in ext4, which allows mounting subdirectories. So, | |
| if the script finds `/rw/bind-dirs/nix` it will mount this directory on | |
| `/nix` on the root filesystem, making it persistent and without having | |
| to copy at start and sync on stop. | |
| # Setup | |
| A limitation for this setup is that we need to install nix in single | |
| user mode, without the daemon. I suppose it should be possible to | |
| install Nix with the daemon, but it should be done at the template | |
| level as it requires adding users, groups and systemd units (service | |
| and socket). | |
| In your AppVM, run the following commands as root: | |
| ```shell | |
| mkdir -p /rw/config/qubes-bind-dirs.d/ | |
| echo "binds+=( '/nix' )" > /rw/config/qubes-bind-dirs.d/50_user.conf | |
| install -d -o user -g user /rw/bind-dirs/nix | |
| ``` | |
| This creates an empty directory `nix` owned by the regular Qubes user | |
| named `user`, and we tell bind-dirs that this directory is persistent. | |
| /!\ It's not clear if it's a bug or a documentation issue, but the | |
| creation of `/rw/bind-dirs/nix` wasn't obvious. Someone already filled | |
| a bug about this, and funny enough, they reported it using Nix | |
| installation as an example. | |
| GitHub issue: clarify bind-dirs documentation | |
| Now, reboot your VM, you should have a `/nix` directory that is owned | |
| by your user. This mean it's persistent, and you can confirm that by | |
| looking at `mount | grep /nix` output which should have a line. | |
| Finally, install nix in single user mode, using the official method: | |
| ``` | |
| sh <(curl -L https://nixos.org/nix/install) --no-daemon | |
| ``` | |
| Now, we need to fix the bash code to load Nix into your environment. | |
| The installer modified `~/.bash_profile`, but it isn't used when you | |
| start a terminal from dom0, it's only used when using a full shell | |
| login with `bash -l`, which doesn't happen on Qubes OS. | |
| Copy the last line of `~/.bash_profile` in `~/.bashrc`, this should | |
| look like that: | |
| ``` | |
| if [ -e /home/user/.nix-profile/etc/profile.d/nix.sh ]; then . /home/user/.nix-… | |
| ``` | |
| Now, open a new shell, you have a working Nix in your environment \o/ | |
| You can try it using `nix-shell -p hello` and run `hello`. If you | |
| reboot, the same command should work immediately without need to | |
| download packages again. | |
| # Configuration | |
| In your Qube settings, you should increase the disk space for the | |
| "Private storage" which is 2 GB by default. | |
| # Conclusion | |
| Installing Nix in a Qubes OS AppVM is really easy, but you need to know | |
| about some advanced features like bind-dirs. This is a powerful | |
| feature that will allow me to make lot of fun stuff with Qubes now, and | |
| using nix is one of them! | |
| # Going further | |
| If you plan to use Nix like this in multiple AppVM, you may want to set | |
| up a local substituter cache in a dedicated VM, this will make your | |
| bandwidth usage a lot more efficient. | |
| How to make a local NixOS cache server |