We recently completed two days of Nixcademy training. Due to time constraints, we had to skip a few topics, but since we’ve been using Nix and NixOS for around five years, we felt comfortable doing so.
Let’s start with some fun facts. I knew that nixpkgs boasts the largest collection of packages among repositories, but I didn’t fully grasp just how huge the gap actually is. You can see a clear comparison here. Additionally, nixpkgs is among the top 10 GitHub projects by contributions, standing right alongside heavyweights like Microsoft VSCode, TypeScript, and TensorFlow. I can only imagine the confusion at the Gituniverse conference when attendees saw this list, since many hadn’t even heard of Nix or NixOS. But awareness is changing quickly. Looking at the project’s star history, growth has clearly become exponential.
Of course, while there are many fantastic things about Nix and NixOS, there must be some downsides, right? The most significant challenge is undoubtedly complexity. The Nix ecosystem itself is intricate, and as you delve deeper, it only becomes more complicated. You can achieve incredibly powerful things that other systems simply can’t do—but these tasks are rarely trivial (I’m looking at you, fixed-point recursion).
This complexity likely explains why larger companies struggle to adopt Nix. Developers often prefer not to invest the time required to learn it. I’ve tackled many technologies in my career, but none have ever made me feel as frustrated or as “stupid” during the learning process as Nix. Thankfully, once you experience your “aha” moment, the feeling of empowerment is incredible, at least until the next tricky Nix concept comes along.
On Monday, we began with an introduction to Nix and NixOS. It was a gentle start. For me, Monday felt like a breeze compared to Tuesday, mainly because I was already familiar with most of the topics we covered.
I was already comfortable with installing (or infecting) NixOS, but I’d never heard of nixos-anywhere before. It’s something I’d like to try next time I install NixOS. Until now, I’ve always created a virtual server with the latest Ubuntu and then run the infect script. This method has been reliable across the more than 20 providers I’ve worked with. Interestingly, nixos-anywhere operates similarly to how we deploy changes to our own NixOS fleet: we use GitHub Actions to perform remote builds and push activation scripts to the target servers.
The second major topic was Nix tests. Testing is one of the standout features Nix offers. It’s extremely powerful. The nixpkgs repository itself hosts the largest collection of Nix tests. If you’re ever unsure whether a certain test is possible, the nixpkgs repository probably contains a similar example to guide you.
Tuesday was more of a rollercoaster. We started by exploring derivations: what they are, how they work, and why they’re important. Jacek explained these complex concepts brilliantly. Afterwards, we dove into more challenging topics: Nix overrides
, overrideAttrs
, and overlays
. Again, the explanations were excellent, but these are inherently complex topics, difficult to fully grasp in just a few hours. To be honest, until this session, I’d never completely understood the difference between these three, but now I finally do. I’ll definitely need more practice with overlays, as they seem like one of the most powerful tools for package management.
To really grasp overlays, you must understand fixed-point recursion. In short, overlays allow you to modify a package deep in your dependency tree without needing to override every dependent package individually. With simple overrides, you must explicitly override all dependencies, but overlays handle this elegantly through fixed-point recursion.
Think of fixed-point recursion as repeatedly applying a function until the result stabilizes (no further changes occur). In Nix, overlays leverage this concept, enabling you to define or modify packages by referencing the entire package set—including your own changes.
For example:
final: prev: {
myHello = final.hello.overrideAttrs (oldAttrs: {
version = "2.10"; # Change the version of hello
});
}
* final
is the complete package set, including your overlay (the fixed point).
* prev
is the original package set, prior to applying your overlay.
By using final.hello
, you can reference the potentially modified hello
package, allowing your overlay to self-reference effectively.
In short:
* Overrides directly modify a single package.
* Overlays (with fixed-point recursion) allow you to redefine or add multiple packages simultaneously, each potentially referencing others as they’re modified.
We wrapped up the training by spending additional time practicing overrides through various examples.
I highly recommend the full Nixcademy course to anyone working with—or considering working with—Nix or NixOS. The knowledge you’ll gain is invaluable and could easily save you 6 to 12 months of frustration and head-scratching.
Are you a Linux or Mac user that works remotely and/or on your private device? Check out Pareto Security, a privacy-first alternative to MDMs for teams that require security compliance, with first-class support for NixOS!