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.
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 :)
Development Environments with devenv
I cannot say much about devenv.sh, except that it works as intended :) The docs are a bit sparse, but I found the devenv.nix file reference to be extremely helpful. It shows what you can all install and how you can customize the environment - I especially like the customizability of languages, and that the system supports services and scripts. As an example, for a Neos/Flow PHP application, I am using the following devenv.nix. It does not yet install all optimal PHP extensions, but it already sets up a database with permissions :)
In case you wonder, I used the "Advanced (declaratively with flakes)" installation method of devenv.sh described here.
Bonus and Closing Thoughts
So far I like what I saw :) I only played around with this for a few hours, but I was already able to remove most of my homebrew packages and convert them to Nix. I am curious where I will end up :)
In case you are interested, below is my current global flake.nix file, with the following specials:
- install devenv
- install diverse language toolchains (Rust, php, deno, node, JDK, go)
- install PHP with extensions
- custom-compile a PHP extension