Apprehensive NixOS Newbie: Questions Before Daily Driving

Hi all. I’ve been using the Nix package manager and some of its associated tools (particularly home-manager, Flakes, and devenv.sh) for a while now, but I haven’t fully committed to daily-driving NixOS yet. I have some reservations about making the switch, mainly because I feel like I still don’t have a solid grasp of the language, tooling, and ecosystem, despite having used these for more than 2 years. Recently, I’ve been considering installing and using NixOS daily, as the declarative and reproducible nature of the distro greatly appeals to me, but before I take the plunge, I have some fundamental questions I’d like the community’s input on:

From my understanding, NixOS is a rolling-release distro. I’ve been using rolling-release distros (Arch a while back and Void as of late) for the past couple of years. While I appreciate not having to reinstall my OS every few years (something I had to do in my Lubuntu and Mint days), the rolling nature of updates means my configuration files can become outdated and contain deprecated settings. Void addresses this by allowing you to install newer default configuration files alongside your current ones, which you can then manually compare. This seems like a reasonable compromise. Since NixOS is also rolling-release, I’m curious:

  • How does NixOS handle out-of-date configuration files/settings during updates?
  • Is there a process to ensure configuration files/settings are kept up to date during updates?

I have experience with home-manager, which I understand is based on NixOS configuration. One thing I dislike about home-manager is the inconvenience of changing a program’s configuration. If you have many programs installed and configured with home-manager, changing one program’s configuration means rebuilding the configuration for all programs, which becomes slow with more programs installed. This is not conducive to quick feedback loops and makes it difficult to experiment with settings, especially for learning through discovery. Similarly, updating a few programs also means rebuilding the whole home-manager derivation, which I find slow. So, my questions are:

  • Does configuring one program in NixOS also mean rebuilding the whole system, like in home-manager?
  • Is there a way in NixOS to make quick, temporary configuration changes without rebuilding the entire environment (or at least, without it taking a long time)?

One thing holding me back from fully embracing Nix and installing NixOS is the unintuitive nature of the expression language and tooling. There are many language constructs in Nix and many tools and libraries (e.g., flake-parts, flake-utils) in the ecosystem, and the documentation for these are vast and hard to navigate due to their verbosity and poor organisation. The lack of examples doesn’t help either. I especially dislike how unhelpful the errors are when building derivations, especially after being spoiled by Rust’s precise error messages. Nix errors usually just tell me that some derivation has failed to build, without clearly explaining why or how to fix it. Running its suggested command to get a stack trace results in an incomprehensible trace 100s of levels deep, making it hard to pinpoint the issue. So, I’d like to know:

  • How can I get better at debugging Nix issues? What processes-to-follow, tools, tips, and tricks are available for debugging? I want to learn how to interpret and act on Nix errors, but I’m not sure how to go about this.
  • Is there a particular way to tackle the documentation, as much of it seems irrelevant if I just want to do everyday developer/Linux user tasks?
  • How do I determine which parts of the documentation are most relevant to whatever I want to accomplish with the system?
  • Is there something like “blessed.rs” for Nix/NixOS, which lists community-preferred tools and methods, acting as a quick overview of the ecosystem?

I am planning on installing NixOS onto my Framework 16 laptop. Does anyone have experience using NixOS on this hardware? How well does it work and have you experienced any issues with your set up?

Other than that, what other potential issues/gripes that NixOS users frequently encounter with the distro should I be aware of? Do you have any other suggestions, articles, documentation, tools, or insights for someone apprehensive about NixOS before fully committing to it?

That is not entirely correct. There are both “point” releases every 6 months that are supported for roughly 7 months, the current one being 24.11, and “rolling release” branches like nixos-unstable. Point releases work as in any other distro: maintainers take care to not introduce breaking changes, software usually stays on the same major version for the duration of that release.

In the usual case, breaking changes to NixOS options will have some kind of transitionary period. E.g. if a configuration option is being removed in 25.05, when you upgrade to 24.11 you’ll start getting a warning about it, but everything will still work. Such changes will also be documented in the release notes.

In the worst case, you will suddenly get a more generic error telling you that e.g. an option or a package does not exist.

NixOS does not do any automated changes / “fixes” to your config to bring it up to compatibility.

When making changes in the NixOS configuration, you will need to rebuild the entire configuration, that is not different from building the entire Home Manager configuration. In my experience, the baseline time to evaluate one of my NixOS configurations is about a dozen seconds, which is not too bad.

In some cases, it is possible to configure stuff by customizing the derivation itself, rather than via NixOS configuration options. See e.g. the section about Vim in the Nixpkgs manual. Such customized derivation can be built in isolation via nix-build, which is quicker than rebuilding the NixOS configuration.

What about the language is unintuitive? I am curious because I often hear about how bad the Nix language is, but really most of people’s issues are with something else than the language itself.

<opinion>

My suggestion is to avoid maximalism of “let’s use ALL the 3rd party abstractions”. If you don’t know how flake-parts, flake-utils, or even flakes themselves are useful to you and solve your problems, do not use them.

Please take this suggestion charitably, I don’t mean it in a “haha you are a noob, this is too advanced for you for now” way. I don’t use any of those either, not even flakes themselves, and I’ve been using NixOS wherever possible for years now.

I see many people plopping massive opinionated flake.nix templates into their repos without understanding even 20% of what’s happening there, and then complaining how hard and complicated Nix is. They do not form a conceptual model of where the Nix language, Nix derivations, NixOS, Flakes, etc. begin and end, and get lost in the jumbled mess where all of these interact in advanced ways.

Instead, start as minimal as possible, and add stuff when you know that you need it. Add a 3rd-party abstraction when you know what it abstracts for you, ideally when you already know how to achieve the same thing without the abstraction, and are using it to not-repeat-yourself, rather than “I don’t know what is happening here, so I’ll just use some utility library and hope it works out”.

</opinion>

Well, other people complain that too little is documented :slightly_smiling_face: I really like the NixOS manual for starting out with using NixOS, starting with the “Installation” and “Configuration” sections. The latter then branches out into a lot of docs for individual software, most of which you will not use so you can just skip these sections they’re not relevant for you. The remaining sections “Administration” and “Development” are good as well.

Nix / Nixpkgs manuals are great when you begin to do some more custom stuff, or want to write your own packages, etc. nix.dev is great as well, and I would recommend it as the first place if you want to learn how to package things, rather than just use what’s already in Nixpkgs / NixOS.

The official wiki is okay as a secondary resource to fill in the gaps. It is not as rigorously vetted, that has both pros and cons: you may find documentation about niche stuff you won’t find in the official manuals, but you may also run into some bad / outdated examples.

You may find nixos-hardware useful. It has modules with configuration for your laptop model.


I might address some of your other questions later, for now I’ve addressed questions that stood out and where I have something to say :slightly_smiling_face:

7 Likes

Note that this is not the nature of rolling distros but rather the nature of changes in software itself.

The same problem exists to the same extent in stable distros. The only difference with stable distros is that you have to deal with those changes at discrete coordinated points in time rather than continuously as they are introduced upstream.

NixOS side-steps this problem entirely by use of an abstraction layer.

In imperative configuration management, it’s typical to copy paste a sample config file with all default values and modify it.

In properly abstracted declarative configuration management such as NixOS, you (ideally) never declare direct contents of a config file where you are also required to declare all default configuration. Instead, there exists an abstraction layer which sets the appropriate defaults and you merely layer your desired changes on top.
When the defaults change, you don’t need to change your configuration because you only declare additional configuration to the default. If you only use the default config, you don’t need to change anything at all because the defaults will be changed for you.

This is much more elegant than any config text file comparison tool for imperative config management could ever be IMHO.

@Nebucatnetzer already covered this but I want to add that this is counter-acted by the fact that NixOS options are abstract.

It’s a bit like rust or Haskell vs. C. Whereas in C after you’ve compiled your code, you know you’ll spend just as much or more time debugging it to actually make it do what you intended to, in Rust and Haskell allow you to declare your intention precisely enough that, once it compiles, you can be reasonably sure that it works as intended; requiring fewer debugging cycles or none.

In order to configure the foobar service on e.g. Arch, you’d need to read the foobar arch wiki page (if it exists) and then manually do a bunch of steps. If you don’t read carefully enough or do it slightly wrong, you’ll need to do a bunch more work to figure out what went wrong.

With NixOS, you’d have an abstract services.foobar.enable option that, when enabled, either provides you with a minimally-viable instance of that service with sensible defaults or explicitly asks you to clarify your intention by way of an assertion causing an eval error.
If your intended use-case is covered by an abstract NixOS option, you usually barely need any troubleshooting cycles at all because the abstraction takes care of setting things up as they should be to realise the intention.

This depends on what kind of error it is.

If it’s a build error (derivation failed to build), there isn’t a generic way to tell you what’s wrong or how to fix it because it’s just running arbitrary processes inside of a sandbox.

For eval errors, Nix mostly cannot tell what’s actually going wrong because the language itself isn’t very expressive in its features. It’s mostly just declaring data and without further knowledge about said data, it’s not possible to say whether it’s correct or not.

Read and understand the source. That’s the best tip I can give you. Once you learn the basic concepts of how the stdenv or module system work, it’s usually quite easy to tell what’s going on.

If you only care about “Linux user tasks”, you mostly shouldn’t need to look at the manuals but only the NixOS option descriptions.

With experience sadly. Some guidelines:

  • The Nixpkgs manual contains information about packaging software in or outside Nixpkgs
  • The NixOS manual contains general high-level NixOS administration information, information about the NixOS module system and also a few module-specific documentation
  • The Nix manual contains information about the Nix package manager itself; its executables, implementation details aswell as the language features
  • nix.dev contains documentation to “bootstrap” your Nix knowledge; what the basic concepts are and how they generally function in practice

Uhhh, typing this from one right now actually ^^’

As far as laptops go, it’s really quite good.

Here’s my FW16-hardware-specific config. It’s quite minimal with mostly just customisations for how I personally like things to behave.

Of course, it’s still the Linux desktop, so expect jank and fundamentally broken implementations for basic hardware support such as touch pad scroll. That’s a general Linux issue and has nothing to do with NixOS or the FW16.

I’d prefer it to be more power efficient though. It idles with like 10-15W which is insanely wasteful. Perhaps I’m just a little spoiled by using an aarch64 MBP for a while which draws like 5-10W at idle or “basically idle” (playing back video, network transfers, light CPU util, etc.) which you could never hope to achieve with inefficient x86 chips such as the AMD one in the FW16. You’re lucky to get it below 10W even with minium display brightness, much less any “basically idle” load.

Everything works via Nix and mostly cannot work without. If something isn’t managed by Nix, you usually must make it managed by Nix or else it won’t work at all.

This is both a curse and a blessing though; depending on how you look at it.

Build out the config to your liking in a VM first. This will take a good afternoon worth of time.

The cool thing is of course that none of that work will have gone to waste because you can simply apply the configuration to your bare-metal installation and it will all work the same.

Otherwise I want to mirror what @Nebucatnetzer said: Stay minimal and only use external projects if you exactly know what they do for you. I’ve been using NixOS for many many years and have been contributing for just as long and to this day still don’t have a single outside dependency other than Nixpkgs and don’t use flakes. You absolutely don’t need any of that, especially not in the beginning.

Oh and the very first thing you should do if you’ve never used NixOS before is to git init and version control your configuration. NixOS can roll back your system configuration state but it cannot roll back a broken/lost configuration.nix; that’s the one thing that you must be careful with w.r.t. configuration state.

3 Likes

Module system yes. stdenv I think like 5 people in the world know what’s going on there :grin:

@nicoty You can also throw in manual lib.trace* statements to help with debugging values at given points. And reading stacktraces gets easier with experience when you know what to look for. But yes they are terrible in comparison to rustc’s.

Also, second the git init recommendation. You’re writing code, so do what you need to do to be effective in that way. And no need to rush into using hundreds of libs before learning hello world, so to speak. Add one thing at a time, debug, and ask if you’re stuck.

The details aren’t that complicated but I didn’t meant he internal implementation but rather how to work with it; how to use stdenv.mkDerivation etc.

You probably wanted to tag @justinas however I agree with everything you two wrote :smiley:

Two things I would add are:

  • Use the GitHub search when you’re looking for inspiration.
    As with an LLM be aware that the code you’re looking at might be outdated or wrong but sometimes it helps to see how other people solved a problem.
    I explicitly exclude the nixpkgs repo because I don’t want to see how the code was written but how people are using it.
    Code search results · GitHub
  • You don’t have to use Nix for everything when configuring software. E.g. for my Emacs config I only symlink to my configuration (which lives in the same repo as my NixOS config).
    This way, most of the time, I don’t have to rebuild my system just to change a setting for Emacs.
    However, I would only do this for very special cases as you usually gain more when you use the options provided by NixOS and home-manager.
    nixos/default.nix at 0d5e346c6836c03dbd7c47cf0ce0ca2119d66b11 - nixos - Gitea: Git with a cup of tea
1 Like

How embarrassing; I confused the Androids :'D