Why I ditched Nix after ~4 years
After using Nix, nix-darwin, and home-manager for 4-5 years, I've finally switched back to Homebrew and bash scripts. Here's why the promise of reproducibility didn't hold up on macOS, and how freeing 80GB of disk space was the final push I needed.
Removing Nix from my system freed 80GB of disk space. That's roughly 15% of my 512GB laptop. I immediately used that space for more FFXIV patches, which tells you everything about my priorities.
After 4-5 years with Nix, nix-darwin, and home-manager, I've finally ditched the lot and gone back to Homebrew with some bash scripts. This isn't a "Nix is bad" post - it's an engineering project with ambitious goals, and I respect that. But it turns out those goals don't align with my reality on macOS, and I'm tired of paying the complexity tax for promises that never quite materialised.
#1The Complexity Tax
Let's start with the obvious: Nix is complex. Not "oh it takes a weekend to learn" complex, but "you need to learn an entirely new language to edit your package manager configuration" complex.
I write Scala for a living. I hack on Emacs Lisp and Haskell for side projects. I'm comfortable with languages that make people wince. And yet, Nix error messages still leave me staring at my terminal, wondering what I did to deserve this.
I'm not alone here. The 2022 Nix community survey showed that documentation came up "universally across almost all respondents" as the primary pain point. People on the forums talk about Nix having a steeper learning curve than vim. Someone even built an AI tool specifically for decoding cryptic NixOS error messages.
When the community response to "this is hard to learn" is "here's an AI to help you understand the error messages", maybe we've got a problem.
I tried writing my own packages a few times. It was super complex. Maybe I'm just a bad citizen of the Nix ecosystem - I never really learned the language extensively, only the basics, because frankly I didn't feel like learning it. But here's the thing: I don't think it's reasonable for a package manager to require users to learn a whole new language just to edit configuration files.
#1The Reproducibility Myth (on macOS)
The big promise of Nix is reproducibility: declare your system configuration, and it'll be the same everywhere. Brilliant idea. Doesn't work on macOS.
The problem is that Nix's reproducibility promise only truly holds on NixOS, where Nix controls everything from the kernel up. On macOS, you're layering Nix on top of a system that's fundamentally mutable by design. macOS has its own ideas about system management, application bundles, and configuration. Nix can't change that.
So you end up with partial reproducibility at best. Your packages might be the same, but your system configuration? Not really. The app bundles in /Applications? Not managed by Nix. The macOS defaults? Separate scripts. The window manager configuration? Also separate.
In the end, I still needed my eru bootstrap script to orchestrate everything, even with Nix. Because you can't escape the reality that macOS is macOS.
#1Rollbacks I Never Used
Rollbacks are one of Nix's headline features. You can always go back to a previous generation if something breaks. Sounds great in theory.
In practice, I never used it. Not once in 4-5 years.
Here's what actually happens when something breaks:
- I make a change → it breaks something → I revert that specific change in my config
- I upgrade something → something breaks → I need to fix what broke, not roll back
The second case is key: when an upgrade breaks something, rolling back doesn't help me long-term. I need to move forward, not backward. I need to understand what broke and fix it properly, because I can't stay on old versions forever.
Maybe rollbacks are useful for people running production servers. But for my personal laptops? Never needed it.
#1The Space Problem
80GB. Let that sink in.
I have a 512GB laptop. Nix was consuming 15% of my total disk space. That's space I could've used for, well, literally anything else. Like keeping FFXIV installed, which is non-negotiable.
I know there are ways to prune the Nix store more aggressively. But the fact that I have to think about it, that I have to remember to run garbage collection commands, that the default behaviour is to just accumulate generations indefinitely - it's exhausting.
When I removed Nix, I got 80GB back instantly. No configuration, no thinking, just space.
#1You Can't Escape Homebrew Anyway
Here's the killer argument: some things just don't work properly when installed via Nix on macOS.
I use yabai and skhd for window management. For some reason, they don't work reliably when installed from Nix. They work fine from Homebrew. I never fully investigated why - I just needed them to work.
So I was maintaining two package managers: Nix for most things, and Homebrew for the macOS-specific tools that didn't play nicely with Nix.
At that point, what's the benefit? If I can't escape Homebrew anyway, why am I paying the complexity cost of Nix?
#1Homebrew: Not Ideal, But Good Enough
Let me be clear: Homebrew isn't perfect. I'm quite an anti-fan, actually. It has its own quirks and issues.
But it's a well-established standard that's quite stable. It works. It doesn't require learning a new language. It doesn't consume 80GB of disk space. And crucially, it's what everyone else on macOS uses, which means packages are tested with Homebrew, documentation assumes Homebrew, and help is readily available.
Sometimes "good enough" beats "theoretically perfect".
#1The Feedback Loop Problem
One of Nix's design principles is that you declare your configuration and rebuild your environment. This is fine for static configuration, but it's painful when you're experimenting.
Want to try a new colour scheme in Alacritty? Rebuild. Want to test a different yabai layout? Rebuild. Want to tweak skhd keybindings? Rebuild.
I don't want to commit to a configuration change before I've tested it. I want instant feedback whilst I'm experimenting. The rebuild cycle kills that flow.
With plain configuration files, I just edit and reload. No rebuild, no waiting, no ceremony.
#1My Solution: Bash Scripts and Brewfiles
I replaced my entire Nix setup with bash scripts and Brewfiles. You can see it all in d12frosted/environment.
The goal is simple: keep my configurations in one place and make it easy to bootstrap any machine I'm working on. Whether I'm setting up a new laptop or keeping multiple machines in sync, I want a single command to get me there.
Of course, not all apps can be easily configured this way. Some things are still manual. But that's fine - I don't let "ideal" block "good and helpful".
The core of it is eru (named after Eru Ilúvatar from The Silmarillion, because of course it is). It's a bash script that handles:
- Homebrew installation and package management
- macOS defaults configuration
- Shell setup (fish)
- Window manager configuration (yabai + skhd)
- Development tools (git, ssh, gpg)
- Emacs configuration
- Symlink management
Is it as theoretically pure as Nix? No. Does it work reliably and let me move fast? Yes.
I'm bad at remembering complex commands, so I wrap everything in something I can mentally digest. Even with Nix, I had this orchestration layer - Nix didn't solve that problem for me.
#1Tools Exist to Solve Problems, Not as Goals
Here's the thing: I'm not an idealist. I respect that there are idealistic zealots out there building amazing things like Nix. The engineering behind it is fascinating, and the vision is compelling.
But tools exist to solve problems. Tools are not the goal themselves.
Nix doesn't solve my problems on macOS. It adds complexity, consumes space, requires learning a new language, and doesn't deliver on its core promise of reproducibility in my environment. So despite it being a very interesting project from an engineering point of view, it's not for me.
And that's fine. Not every tool is for everyone.
#1Nix as a Build Tool
One caveat: I think Nix might work well as a build tool for specific projects. The reproducible build story is genuinely compelling for continuous integration and development environments.
But in many cases, there are already specific tools for specific technologies. Maybe they're not as idealistic as Nix, but they're often good enough. And "good enough" means I can focus on my actual work instead of fighting my tools.
I have Emacs to fuck with my free time - I don't need my package manager competing for that attention.
#1Looking Forward
I'm much happier with my new setup. It's simpler, faster, takes up less space, and just works. I can experiment freely, I don't have to maintain two package managers, and I got 80GB back for important things like video game patches.
If you're using Nix on NixOS, this post probably doesn't apply to you. If you're a Nix power user who's mastered the language and built up muscle memory for the ecosystem, more power to you.
But if you're like me - someone who tried Nix for years, never quite felt comfortable with it, and kept wondering if the complexity was worth it - maybe it's okay to admit that simpler tools might serve you better.
The environment repository is public. The bash scripts are straightforward. There's no magic, just pragmatic choices. And sometimes that's exactly what you need.
Special thanks to everyone in the Nix community who's working on improving documentation and lowering the learning curve. The problems I've described aren't secrets - they're well-known challenges that people are actively trying to address. I hope they succeed, because the vision behind Nix is genuinely inspiring.