For my first few years of NixOS I didn't understand the point of the NixOS stable releases, since even on "nixos-unstable" I found that if my nix config evaluates, then it'll work. And in the very rare case things broke, I could easily rollback.
NixOS stable, for me, provides API stability. I can leave a machine auto-updating, and be confident that my nix config will continue to be compatible, and thus build.
Thanks to the release managers for the work that goes into this!
As soon as lanzaboote works with stable, I'll go back to stable (but I think that is not the case yet, sadly).
Lowkey plug for lanzaboote though. Getting secure boot working went pretty well for me thanks to it.
I suppose in combination with LUKS you could at least prevent evil maid attacks, to the extent that your machine's firmware is actually secure, but it seems like a lot of work for just that...
I'm keen for secure boot and TPM FDE, and would like to see lanzaboote in nixpkgs.
“ Speedify, a proprietary VPN which allows combining multiple internet connections (Wi-Fi, 4G, 5G, Ethernet, Starlink, Satellite, and more) to improve the stability, speed, and security of online experiences. Available as services.speedify.”
Consistently through the 25.05 period nix-darwin and nixpkgs would fall out of sync. I learned not to `nix flake update` too often as a result. It’s amazing that rolling back is as easy as it is, and that’s huge, but if you squint and reason that mise and nix solve the same issue, why not use the less opinionated, easier to reason about mise?
As time has gone on, more and more of my system is managed via nix-homebrew … effectively producing a Brewfile for the vast majority of my package needs. Why not just use Brewfile directly?
I really want to advocate for nix, but it feels like I lose the “why not x?” conversations with myself, I can’t fathom winning them against a less invested peer.
Most tutorial out there encourage you to download someone else's configuration to get going. I don't want to do that. I want to understand at its core how this thing works.
I've read the official nix language documentation, watched YouTube tutorials, read 3rd party tutorials, and still couldn't get going with a simple configuration that would install a few packages.
The nix language is also really unpalatable to me. But I could deal with that if the examples out there showed a consistent way of doing things – that's not the case. It seems one same thing can be done many different ways – but I want to know and do it the right way. I would generally turn myself to the official best practices documentation, except nix' is very short and doesn't help much.
I really want to use nix. There's no question about its advantages. But nix just won't let me (or maybe I'm too old to learn new things).
That being said, I'll probably give it another try this month...
yeah, I wish I could give you some "it gets better" good news, but...
I've used NixOS as my daily driver for ~10 years, including the laptop I'm typing this on.
I love NixOS-the-OS, I love nixpkgs-the-ecosystem. but I still hate Nix-the-language.
it's like Perl and Haskell had a drunken hookup that produced a child. and then abandoned that child in the forest where it was raised by wolves and didn't have contact with another human until it was fully grown.
(to answer the inevitable replies, yes I understand functional programming in general, and yes I am aware that Guix exists)
for simple NixOS administration, you can get pretty far with treating configuration.nix as "just" a config file, rather than a program written in a Turing-complete functional language.
writing your own modules or flakes, or re-using flakes published by other people, is strictly optional. make friends with The Big Options Page [0] - anything you find there can be dropped into your configuration.nix without really needing to understand Nix-the-language.
I actually find the language simple and easy to learn: It's just untyped lambda calculus with dicts and lists.
(I, too, would like static types though.)
It may not really help the case, but I firmly believe that it is not the language, but the ecosystem, and is more of a fundamental issue. But maybe putting the blame elsewhere could help accept the situation.
So anyways, the language is pretty much a lazily evaluated JSON. But even if it were something else (insert your favourite language), the problem ultimately is that packaging software is complex especially in a non-standard way, with endless edge cases, requires whole libraries and conventions and this is simply not a well-trodden path. Most programs simply hard-code "traditional" Linux file system conventions and those have to be patched in some way.
So the hard thing is not "is this really a function application here", when writing new Nix code the hard thing is simply knowing that for python there already exist this abstraction in nixpkgs, but to use it you need this folder structure and this build tool, etc. Especially when there are multiple abstractions for the same thing because it's an absolutely huge repository with countless packages.
But the benefits absolutely make up for it big time - there is simply no going back from Nix imo. I would honestly feel constantly "dirty" with any other traditional package manager, it's like file "versioning" before version control.
(PS: just grep for use cases of a function you are looking for. Also, find a "blueprint" package and start from there, e.g. another program written in python with a few native deps)
These two design warts also interact with each other really badly: If you try to put a function application into a list and forget to enclose it in parentheses, you instead insert the function as one element in the list and its arguments as successive elements. The usual result is "expected an X but got a function" error in some completely unrelated part of the code.
Maybe lazy evaluated attrsets can help make a dent, but still the lack of static types for module code is beyond painful. It's hostile.
I believe Nix is worth it in spite of this, and I'll advise anyone to learn it, it truly is the way forward, but by god do I hope it's not the last step on this journey. Please, Lord, please don't let nixlang be the final iteration XD
I switched a couple devices to Guix and was at first encouraged by their much better docs, but the lack of features and battle testing has been a problem with longer use.
I've mostly been happy to go back to NixOS thanks to LLMs. Even a year ago, AI was very good at updating Nix configs and fixing any errors. Ideally Nix would have better docs and a more intuitive unified config system, but LLMs have made it usable and the best solution for now.
Sorry for adding to your frustration of "just follow what someone else did" but I recently went all-in on managing my Mac (programs, dotfiles, configs, etc) via Nix* when setting up a new machine recently. https://github.com/landaire/config/tree/main/modules
*Nix + homebrew, mostly because Homebrew packages more macOS applications.
I similarly found `nix flake update` frustrating for a while, especially when using unstable Nixpkgs. I wrote a tool called `npc` that basically solved the problem for me by letting me bisect whatever Nixpkgs channel(s) I have in my flake inputs: https://github.com/samestep/npc
> Consistently through the 25.05 period nix-darwin and nixpkgs would fall out of sync. I learned not to `nix flake update` too often as a result.
I find using a singular nixpkgs version is almost always a recipe for things breaking if you are on unstable. I usually end up juggling multiple nixpkg versions, for example you might want to pin the input to nix-darwin separately.
This is squarely a nixpkgs problem. It's the largest most active package repository known to man. I am pretty sure GitHub has special-cased infrastructure just for it to even function. Things are much more stable in release branches. If that causes you pain because you want the latest and greatest, it's worth considering that you'd experience the same problem with other package repositories (e.g. Debian), and then asking yourself what it is you are actually trying to accomplish. There's a reason they call it unstable.
> but if you squint and reason that mise and nix solve the same issue, why not use the less opinionated, easier to reason about mise?
If mise works for you then great, use it. When I squint and reason, they do not solve the same issue. I don't know how you come to the same conclusion either. Why are you using nix-darwin at all? What is the overlap between nix-darwin and mise? I don't see it.
If all you want is dev environments, I recommend flox.
At the end of the day I'll continue using nix, and especially nix-darwin, _solely_ because it let me set up a new machine in under 5 minutes and hit the ground running. Nothing else compares.
I got here through devenv, I was fully bought in on its proposal and once I found its edges I started peeking under the covers to understand how it worked.
At that point I was pretty deep in mise for everything that wasn’t using devenv. This perhaps help frame why I see them solving the same problem.
I definitely had my “aha!” and ditched mise because nix seemed it had solved my problems. But now, in a new gig, I’m running into lots of edge cases that mise could solve at the drop of a hat and nix (/ my poor understanding of the fundamentals) struggles with.
So, with that all said, I suppose my point is that you get a lot of overlap between the two, and mise is easier to use and get buy-in on. There are certainly elements I find appealing about nix which mise doesn’t touch (promise of repeatable builds, the entire package ecosystem, etc), however.
Especially because installing Nix is still a pain for most users.
What do you mean? Those should be fairly independent in practice.
Here are the links from my journal:
This went into nixpkgs: https://github.com/NixOS/nixpkgs/pull/376988
Which then changed the api between and broke this: https://github.com/LnL7/nix-darwin/blob/master/modules/nix/n...
The fix took a few hours, I happened to be one of the first folks bit by it: https://github.com/LnL7/nix-darwin/pull/1318
I also have in my notes that Emilazy is a super star: https://github.com/emilazy
Notes on how I worked around it for the time it was broken:
> To work around it on myside I tried various things. Fundamentally I rolled back to nixpkgs-24.11-darwin which needed corresponding changes to nix-darwin (nix-darwin-24.11) and home-manager (release-24.11) to get everything working.
I do very much recommend home-manager, which will manage your dot-files and cli packages, and is portable between macOS and Linux.
Along the way I acquired enough talent that use at work seemed reasonable.
As time has gone on, however, I have found things like the stringent need for everything to be built results in archaic packages versions in nixpkgs, etc., while core waits to bump the rustc version. Thus my return to using brew for almost everything albeit managed via nix-homebrew.
Case in point: I use zed, which relies on cutting edge rust features, which nix cannot deploy because of stability concerns. Everyone is right in this situation, but that left me with an archaic version of zed until I moved to the homebrew version.
https://github.com/zed-industries/zed/issues/26277
About 4mos ago I moved to using brew for zed because at the time there was some hard block on updating rustc in nixpkgs-stable to a version which included some feature that zed relied upon.
It's certainly not for everyone, but for anyone who's full time job involves managing runtime environments it is second to none.
Unfortunately, without a base level understanding of the entire ecosystem, I stay lost.
I keep checking back every year or so secretly hoping they'll have upgraded the language. It's fascinating how successful Nix is given how utterly opaque the language is.
my recommendation (as I said elsewhere in this thread, I'm a 10+ year NixOS user) would be to install NixOS on a VM or spare laptop and tinker with configuring it. you can follow the breadcrumbs, for example enabling sshd [0] has a "declared in" link to [1] where you can read the Nix source code of what that NixOS option actually does on your system.
flakes, modules, and overlays are all relatively "advanced" parts of the ecosystem, you don't need to know them as a new user. in particular, you will find many blog posts telling you to use flakes right from the beginning. that's an option, but not at all required.
0: https://search.nixos.org/options?channel=25.11&show=services...
1: https://github.com/NixOS/nixpkgs/blob/nixos-25.11/nixos/modu...
Regarding features: so far for my home setup (few vms on proxmox) I only needed flakes. They age good at organizing multihost config.
But besides it it works smoothly. And I constantly have thought “wait, why we didn’t always do it this way?”
https://shopify.engineering/shipit-presents-how-shopify-uses...
https://www.youtube.com/watch?v=6iVXaqUfHi4
Flakes are a dependency-pinning and hermetic evaluation feature baked into the Nix tool itself.
Overlays are an idiom that uses lazy evaluation to build up larger attribute sets in a modular and composable way (e.g., package collections for a particular programming language).
The arguments probably come from the fact that flakes are 'experimental', but de facto widely used.
I use nix via flakes on my own machines (via NixOS), in my projects (with direnv), on my infrastructure/servers (NixOS deploying with colmena) and at work (nix-darwin and projects). So far the upgrade have gone painlessly, the only change I needed to make is how git is configured in home manager. I continue to be amazed how well NixOS works.
Edit: The only place I still struggle in adopting nix is on my phone. Last time I tried nix-on-droid it didn't even run, but I plan to try that again. Still new to Android (and GrapheneOS)
What, one month to upgrade to keep receiving security updates? How can you force 1-month upgrade windows every 6 months and who would go for that?
Contrary to the name, even the stable branch of NixOS can have problems while installing routine updates with `nixos-rebuild switch --upgrade`. In fairness, at least with NixOS you can normally roll back to a previous working configuration where you can try to fix or work around the problem if that does happen. It’s still painful if you have to do that, though.
Even if your routine updates all go smoothly, as you mentioned, each stable release is only supported for a very limited time window after the next one is out. NixOS doesn’t have any long-term support branch in the sense that some distros do. Again, you can overcome this to a degree by customising your configuration if you need specific versions of certain packages, but in doing so you’re moving back towards manually setting things up and resolving your own compatibility issues rather than having a distro with compatible packages you can install in whatever combination you want, which reduces the value of using a distro with a package repository in the first place.
To be clear, I’m a big fan of NixOS. I run it as my daily driver on a workstation where I do a lot of work on different projects for different clients. Its ability to have a clean, declarative description of what’s currently installed globally or for any given user or even when working in any given project directory for any given user is extremely valuable to me.
But it’s also fair to say that NixOS is not for everyone. It has been by far the least stable Linux distro I have ever used, in the sense of “If I turn my computer on and install the latest updates from the stable branch, will my computer still work afterwards?”. If you’re looking for a distro you can deploy and then maintain with little more than semi-automatic routine updates for a period of years then, at least for now, it is not the distro for you.
Rust is such a heavy dependency though, is it not? Is it worth it? Additionally, what does it add as a new project / software (disregard Rust here)? What was wrong with the previous one and/or what does this fix or add that justifies adding a heavy dependency? Seems like most of these projects are written in Rust though.
You can read about the project here: https://github.com/NixOS/nixpkgs/issues/428908
As the project doc notes:
> This radical solution is only really feasible and/or interesting for appliances (i.e. non-interactive) systems.
https://pad.lassul.us/nixos-perlless-activation
> stops almost all attack vectors
Can you explain a bit more about this? Is the idea that verity protects the integrity of the nix store, and then the boot process only runs binaries that don't expose any sort of arbitrary code functionality?
I agree with https://github.com/NixOS/nixpkgs/issues/267982#issuecomment-... that the MITRE attack vector link doesn't help understanding much. Is the right idea: removing attack vectors is useful? (I agree.)