I think where Nix shines isn’t “one laptop every 6 years” but when your environment needs to be shared or recreated: multiple machines, a team, or a project with nasty native deps. At that point, nix-darwin + dev shells becomes infrastructure, not a hobby. You don’t have to go all-in on “my whole Mac is Nix” either: keep GUI apps and casual tools imperative, and treat Nix as the source of truth for the stuff that actually blocks you from doing work. That hybrid model matches what the article hints at and tends to give you most of the upside without turning your personal laptop into a second job.
But I think just in fairness, the comparison here for flakes should be to Homebrew bundles. My packages are managed in a bundle: https://github.com/Julian/dotfiles/blob/main/Brewfile and then locked by a lockfile: https://github.com/Julian/dotfiles/blob/main/Brewfile.lock.j... and installing is just `brew bundle install`. All native Homebrew functionality. In practice I have never had an issue with non-reproducible builds across my machines (partly because the tendency on macOS is to run the latest versions of things and stay up to date).
(But again I do find nix-darwin interesting to try for other reasons.)
> The consequence is me, spending a few hours debugging my environment instead of writing code.
But then I also see this:
> I’ve spent a lot of time recently moving my entire workflow into a declarative system using nix.
I can see how this can be beneficial for someone who switches systems very often, reinstalls their OS from scratch very often, or just derives a lot of pleasure/peace of mind knowing that their dev env is immutable.
I change computers once every 6 years or so, maybe more. To me this looks like exchanging a couple (hypothetical) hours of debugging 6 years in the future by tens of (guaranteed) hours trying to climb up the nix learning cliff.
I am happy that it works for the author though, and knowing that it's possible is good in case my particular development circumstances change.
As a bonus I was able to achieve some semblance of uniformity across Mac and my Linux desktop with home-manager.
A few of my favorite parts, which I see less represented in this thread so far:
- I simultaneously jumped into nixos on several Linux machines (starting with a few Pis for experimentation), and maintaining all of my systems with a single flake and mostly shared code is a dream come true. - no more convoluted dotfile syncing, most of my scripts and aliases and bash config and binaries all sync together - cross-building linux from Darwin -- including integration tests in a vm -- works surprisingly well, this is mostly just nix but nix-darwin has helpers that make this easier - writing system services (launchd) on my Mac then converting them to a headless Linux machine (systemd) is generally very straightforward - prefixing my path with GNU coreutils works well and saves me from many e.g. `sed` quirks, I get expected behavior across OSes - this was always a sore spot in homebrew, either dealing with the `g` prefix on everything (eg `gsed`) or dealing with intermittent breakages when stuff depends on the BSD behavior - I was also able to put nix-darwin on my wife's MacBook and greatly simplify admin / maintenance tasks I do for her - finally, the nix crew is just thirsty for help and contributions, particularly the darwin crowd; I feel like my (minor, occasional) contributions are celebrated, differences of opinion are met with an open mind, it is in general a far departure from the relative hostility of homebrew - on the down side, I have spent far more of my limited time helping contribute to nixpkgs / nix-darwin / home-manager
I would recommend it only if this type of thing naturally interests you. I can't imagine powering through the initial learning curve if it felt like a frustrating chore.
That said, if having (most of) your machine defined declaratively in a git repository sounds exciting/useful/comfy, then I would encourage you to give it a try. You can start small by just configuring a few programs or options and see how you like it.
I wrote more about my experience here where I also link to my configs: https://bryce.is/writing/code/fully-nix-pilled
I stick to nixpkgs for most of the foundational system tools, lsps, build tools - basically anything that works in the terminal and is fully open source. For everything else (zoom, slack, vscode, firefox, etc) I use homebrew packages. The combo gives you options and is a strict superset of what you can do with homebrew or nixpkgs alone. Best of both worlds really.
The article I used to help set up, in case this helps anyone: https://davi.sh/blog/2024/01/nix-darwin/
I also really wanted to like the declarative homebrew configuration but it also often didn’t work as expected for some configurations and had a lot of leaky abstractions that straight up just broke sometimes.
If I ever go back to managing my Mac with nix I would probably just do a home-manager setup and just install most of the applications imperatively.
Given this was using an intel based machine around the time when the switch to arm came so a lot of breakage also stemmed from that.
I still use nix to handle my homelab.
My setup up on my Mac is as follows:
- Orbstack
- NixOS machine run in orbstack
- My whole dev environment is run from this container and is very transportable
- GUI apps are installed on my Mac using the App Store or homebrew etc. but I try to reduce the amount of installed applications
- if I have to install something that I don’t want to install but have to, I try to do it in a UTM machine.
When i install a fresh macos i have two commands to run - install nix using the determinate systems installer, then apply my nix config.
It's not quite as streamlined as nixos but good enough.
My biggest remaining pain point is dev envs - i've been leaning into adding a flake in each project, so for example i have a single project that's written in scala 2.13, when i cd into that project dir, the correct jvm version, sbt, intellij etc are installed, some useful env vars and shell aliases etc. - that's all great (i haven't felt the need to adopt denenv.sh or flox yet) but i do find myself wanting a devcontainer sandbox workflow more often these days (blame cli coding "agents"), i lean on vscode for that rather than nix so far. In python (where i spend a lot more time) uv loses a lot of value in nix and i don't like that.
There's a lot of reasons to use Nix instead of or WITH Homebrew depending on your exact needs.
Where it’s paid off for me (and where I think it actually wins) is when the problem is recreating environments: multiple machines, teammates, CI, nasty native deps, CUDA stacks, etc. At that point you’re choosing where entropy lives: in invisible drift (brew/manual installs) or in a repo you can diff/rollback.
Also, you don’t always need to go full “immutable everything.” Really depends on your needs here. Hybrid tends to be another sane path. In certain situations this can get you 80% of the upside without having to rip it all out. So kinda the "good enough" which I've seen a lot of folks do.
We (Flox) actually worked on this with Kelsey Hightower a while back - https://bsky.app/profile/kelseyhightower.com/post/3ld2rsccls...
I still believe something like nix is the future of building software, I'm just not sure it'll be nix itself.
This is just procrastination.