I finally had some time to play around with Nix - the immutable package manager and build system. This was on my agenda since a long time, but I finally took the plunge on my M1 OSX system. I by no means understand Nix fully yet, but making progress and it is usable to me already.
Getting Started
I started by reading all of zero-to-nix.com - a great website which explains the first baby steps. For installing, I used the unofficial installer DeterminateSystems/nix-installer for reasons explained on the website, which ran through smoothly.
After doing the tutorials at zero-to-nix.com, I wondered how to continue. After all, I had two main goals:
- have a reproducible global dev tool setup (basically a replacement for Homebrew)
- have reproducible dev environments (basically replacing docker)
For the second use case, reproducible dev environments, I quickly settled on cachix/devenv. I also checked out jetpack-io/devbox which does fundamentally the same thing; but which hides the Nix files completely underneath - so that was too restrictive for my tastes.
When reading about the ecosystem, I saw there are lots of patterns how one could use Nix; and this is in flux right now, as the community irons out flakes (which many people seem to be using already though). So I for now decided on the following:
- Embrace Nix Flakes: I'll only use nix flakes, especially after reading this blog post.
- Only use the nix tool, instead of the older nix-env etc tools. It seems the new world and the old world sometimes are incompatible, and you need to decide which way to go consistently.
- Only go declarative: I will never install a package by typing a CLI command, but always editing some configfile and running a "converge" script.
I have read that flakes and nix are still considered alpha; but from my perspective right now it feels 95% done - and maybe other projects would have called this a finished product by now. So I feel good about using this.
Global Dev Setup
For installing tools globally, I've read about nix profiles, but I was unsure about how to use them with Flakes. I then stumbled over this forum post, which is the way I am doing it now:
- I created a folder in ~/nix-sebastian (does not matter) containing my global Nix configuration.
- In this folder, I placed a flake.nix (content see below), effectively making this folder a flake.
- Then, for initial installation, I ran nix profile install . (inside the folder). This registered the flake.nix as part of the global nix profile. You can see that nix profile list shows the profile.
- To update, you need to run nix profile upgrade 0 (assuming you only have this single profile installed) - if you have multiple profiles installed, you need to use the number displayed at the front of the listing.
Pitfall: you are not allowed to re-run nix profile install ., as this will install the profile a second time - and this will lead to conflicts. This is what I stumbled over at first :)
flake.nix skeleton
The following is the skeleton file I am using for global installation. To understand the syntax, this post about language basics and this post about functions have been helpful for me.