I just reached the same breaking point -- and normally I am pretty sympathetic to software jank, but the maintainer of homebrew is so actively hostile and rude that my degree of empathy is significantly less -- and switched to Nix, which is quite good, conditional on three gotchas:
1. Nix has very limited support for GUI applications of the kind that you'd find in `brew cask`. Not no support, some of them are there, but limited support compared to brew. If you use brew as an out-of-the-box install-everything setup like me, you'll not be able to replicate that easily with Nix.
2. Nix can't currently build Swift applications because of some Xcode something I didn't fully understand.
3. I found a small number of packages that are broken on Nix on my aarch64 / M1 MacBook Air (and marked broken, so when you try to install it complains) and a small number that are broken without being marked broken. In specific, I think R was one that surprised me -- this is a major programming language and although the build requirements are onerous (it's a mix of C and Fortran), I would think it would work.
That being said the actual process of installing, updating, and upgrading seems much faster and dramatically less shitty than homebrew, and so I recommend migrating stuff off of brew anyway.
I find Mike McQuaid pretty reasonable and forthright whenever I have ever messaged him. Also, he is hardly responsible for every formula out there.
For anyone who remembers the year 2000 and having to compile everything from scratch, Homebrew is brilliant - but there are complexities and quirks. For Python I’d go with pyenv. Postgres - well, watch your step and maybe use Docker instead.
For PostgreSQL on macOS I use and suggest https://postgresapp.com/ which is free and able to manage multiple Postgres major versions. It's also self-contained in a folder in /Applications. Also, version 14 of Postgres in the app has m1 native support.
For “infrastructure” apps like databases, caches, etc, I’ve been using Docker containers. Very easy to setup and tear down in a repeatable way. Unless I’m modifying the app itself, of course.
For me it’s the only sane way to manage multiple small projects. A few lines in a docker compose file and I’m done, no matter the Postgres/Python/Ruby/Lib or framework version, everything is isolated and reproductible. Downside is gigabytes of RAM wasted.
Exactly. I have a few build tools on my machine but any service installed locally has been long gone. Even the apps I work on - I just have the code locally and compile/package it up for testing within a container, which resembles the actual production landing spot. No more "it works on my machine".
When I choose tools I like to ask "Who has the hardest version of this problem? What are they using?"
I'm reaching the tipping point to adopt Nix, after seeing Nix as an alternative for supporting project after project. The unstated subtext always seems to be "Nix is what the smart kids are using, but it's harder to learn."
Haskell? Same religion. But the joke is that one needs a PhD in category theory to use Haskell at all, and package management has long been a Haskell sore point, yet Nix hasn't taken over.
A century ago, Hilbert's program to formalize and automate mathematics was stopped in its tracks by developments in logic such as Gödel's incompleteness theorems. There is a new push involving many leading mathematicians, using the Lean theorem prover. While some imagine computers replacing people, a better model is how a chess grandmaster checks their analysis using computers. Even as the experience of observing computer Go games leads to moments of amazement, as if observing an alien tournament, the role of a human to appreciate and generalize is preserved. Primates have long used tools; our future is to coevolve with machines.
Dependency hell and Gödel's incompleteness are cut of the same fabric. This is where I first read about Nix flakes.
I also tried Nix (as well as NixOS) but it's obviously difficult to use and has a very steep learning curve. But actually it might be the most flexible and stable package manager out there. So probably the problems mentioned can be fixed by custom configuration but that might require deep-diving into Nix and using Functional Programming for package configs... For some time I also used to just ./configure && make && make install (sometimes combined with stow) to my home dir, that worked also well but makes installing and upgrading tedious.
That said, I'm sticking to Homebrew. Not really sure about this auto-upgrading, maybe it can be deactivated, on the other hand probably it's a good way to keep packages updated.
I think the problem with Nix is that it is actually not a package manager but a build tool (that provides some package management utilities). People try Nix with the assumption that it should be as easy as apt-get (for example), but found tutorials with a block of code in a weird language...
Sure, you will eventually need to use the Nix language if you want to have complex and reusable configurations, but this is actually not needed for beginners! To install packages, you need the Nix package manager (with channels already setup) and use `nix-env` to install for the current user. You can just search for the package in https://search.nixos.org/packages and use the command directly.
If you want to have user configurations, use home-manager, just modify the example to add other options, you seldom need complicated Nix expressions unless you need to build a package by yourself.
When you really need to do so, you may want to have a look at other's build script, and make sure you understand everything in the build process, including compile dependencies and runtime dependencies, environment variables, etc. You may want to read Nix Pills at some point, but maybe you can get away with reading just the relevant section (incomplete knowledge, but usually enough to get the work done).
> I think the problem with Nix is that it is actually not a package manager but a build tool (that provides some package management utilities). People try Nix with the assumption that it should be as easy as apt-get (for example), but found tutorials with a block of code in a weird language...
Indeed, I've been using Nix for many years (on Ubuntu, NixOS and macOS), and I now find the apt-get style 'considered harmful'.
Instead, I define a single Nix derivation ("package") which provides everything I want in its 'bin/' directory, e.g.
with nixpkgs;
buildEnv {
name = "my-macbook-programs";
paths = [ bash gimp /* etc */ ];
}
The nix-build command creates a symlink called `result`, so I put `/path/to/my/git/repo/result/bin` in my $PATH.
Just wondering, what is the benefit of doing this over nix-env for system-wide applications?
For project specific environments, I usually use `shell.nix` (maybe I should switch to flakes now) together with direnv that runs nix-shell automatically when you enter the directory.
For beginners to Nix, I think they should do the transition gradually, there are so many concepts in Nix that may be unfamiliar to them. I think getting a system to work quickly (maybe in a not so idiomatic way) is more encouraging than asking them to read Nix Pills and understand how packaging works in Nix :)
You could use nix-env to install the file with `nix-env --install --file default.nix` rather than using nix-build + symlinking the result.
What are the advantages of just nix-build, and adding the result/bin/ to path? Arguably, `nix-env --install` modifies the underlying profiles which manage symlinks. (nix-build + add to PATH is imperative invocation; but `nix-env --install` is and imperative invocation with a stateful effect).
e.g. of "how could that be bad?". I'd managed to get myself into a confusing state with `nix-env --install`. When setting up NixOS, I'd installed firefox as the root user. Months later, in my normal user account, I was confused why such an old firefox was installed (since my profile didn't install firefox). I can't remember exactly, but this also somehow caused problems with fontconfig. -- Probably easily avoidable; but if you don't know what you were doing, you might also try all sorts of install commands and forget.
`which -a` and `realpath` are your best friend when you're dealing with a multiuser package manager! Together, they make it easy to figure out if a package comes from your user profile, the default imperative profile, the system profile, or a transient shell profile
I also use Nix, and agree with these caveats. My personal experience is that it can be hard to initially set up Nix, but once you do, it's rock solid. It's particularly great for sharing config across machines. Here's config for my personal dev environment for instance: https://github.com/mjhoy/dotfiles/blob/main/nix/nixpkgs/conf...
I tried Nix while ago when NixOS made news in HN. You are right, it is difficult to set it up. Eventually I give up on it and tried to remove Nix from my macOS, let say it is difficult to remove Nix as well. I tried their command line to remove Nix and it didn't remove it even with sudo. Nix been sitting on my macOS for a month since it couldn't remove it completely. I realized I just have to go to Disk Utility to dismount/remove the Nix VHD and then ran the command line again which finally got it removed from my OS.
Removing Nix is easier on operating systems where root is root (normal Unix-likes without a lot of filesystem-related security policies enabled). Nix only uses a separate APFS volume on macOS because Apple disabled writing to /.
The way that affects the uninstall process should be documented.
I spotted some people who've recently worked on Nix's install scripts and uninstall procedure elsewhere on the thread. You can file an issue if you think they'll miss your comment :)
I've just gone through the process of configuring a new MBP with nix-darwin and home-manager, and I'm sold. Keeping my MacOS and my NixOS environments in sync has been a nice bonus.
I still run Homebrew for a couple of services and casks, but I'm down to less than 20 packages still installed that way.
There have been a few points of friction (which I'm used to as a polyglot with lots of active projects), but the community has been very helpful with ironing those out.
Nix-Darwin is great! I wish the Nix installer on macOS were (a) always multi-user and (b) came with Nix-Darwin, so it could be a more NixOS-like experience out of the box.
This is neat! I wonder if there would be value in having a repo for only GUI applications, equivalent to casks. I suppose it works best when the application doesn’t also auto-update, which many do.
I had R working with Nix on my work Macbook, but this was on a version of Nixpkgs from several months ago. Of course, one of the upsides with Nix is that I can look up the exact version of Nixpkgs that was working for me because it's in a git repo with the rest of my dotfiles :).
Thanks for the summary, it is very helpful! I love Haskell and its philosophy and I'm intrigued to find that there can be some of it in a package manager as well.
One question: How do you properly install things like R on the M1 Macs, then? Do you use a 'backup' package manager?
> Homebrew is old and it needs to be replaced. It has served its time.
You are more than welcome to build your own alternative. Homebrew is open source and volunteer run. I'm sure there is a very valid reason requests like this get shot down.
No wonder open source maintainers hate dealing with people like you.
I don't hate it, I just think there is room to improve. Also, no need to accuse me of not understanding open source development. I am thankful to you and others, at the same time it is I think OK to say it needs to improve. Although, I believe like a lot of technology pieces that sometimes it is not worth improving - just start from scratch. There is a lot of baggage with Homebrew.
The maintainer did close they issue but they didn't lock the thread. If there was a very valid reason the request got shot down, it went unstated afaict. (Fair enough if they just don't allow feature requests on the issue tracker, I guess)
> Homebrew is old and it needs to be replaced. It has served its time.
Counterpoint: I've spent serious time (years) with, oh, six or seven package managers, in a couple decades of using package managers. More if you count Flatpack and stuff like that.
Brew is my favorite, all-around. Package selection is incredible. Stability is excellent. It's a little slow and I think defaulting to updating the package list damn near every time one invokes the command is a really weird choice, but that's configurable.
My second favorite? Docker :-)
Third would probably be portage (from Gentoo), I guess. Then apt/dpkg.
Worst I've used is easily Macports, and it's not even close—however, I switched years ago because it broke constantly under normal usage, on my machine, so for all I know it's great now—and I've never forgiven RPM-based distros for all the time I lost to RPM hell over the years, and for going so long with worse CLI tools than apt.
Void's seems very nice, but I've not spent enough time with it to feel the rough edges.
Some of its advantages are, in a sense, unfair, because it doesn't manage my OS or its most vital pieces, which is part of why it's never, in nearly a decade, broken my system the way any others have. Homebrew's never made my system unbootable. Homebrew's never broken my GUI. Homebrew's never fucked up some driver that had been working totally fine.
In another sense, that's totally fair if you consider the platform as a whole. It's really hard for Linux overall to separate user packages from system packages, mostly because it's all mixed up together in a way that it's not on MacOS or Windows—but a distro could take that approach, if they wanted.
So, that'd be one thing. #1: Separation of a very complete and capable base GUI OS from the rest of my packages, with the base OS upgrading in lock-step and very reliably, and everything else totally disconnected from that.
#2 would be the package selection. The number of times I've found some lowish-star-count project on Github, blindly done "brew install [guess at package name]" and had it work, is crazy. Non-free stuff? It's there too. AFAIK Gentoo and Arch are the only ones that even come close—but then you're stuck either hoping rolling-everything doesn't break your system, or trying to maintain a jenga tower of pinned packages and still risking breaking your system when you eventually do update them. I'm actually not sure there's a single piece of software on any of my Mac hardware, for work or play, that's not either, 1) from Apple, or 2) installed via Homebrew. And I've never added any kind of 3rd-party repo to it.
(a minor point: it's also nice that I can guess the correct package name more often with Homebrew than on Debian and Ubuntu)
#3 is that it has never, ever broken for me, under normal operation. An "install" or "update" or "upgrade" or "remove" has never broken my package manager itself, or its package database, or left its installed dependency tree so deeply fucked that I lose an hour or five un-fucking it (in fact, I've never seen that happen at all with Homebrew). OS upgrades have occasionally made me run a one-time fix to its directory permissions. Maybe that's happened twice in a decade of use? AFAI can recall, that's it. Macports borked itself badly under normal operation every 3-4 months while I was using it, while having a smaller package selection and compiling (=taking way longer) more often—this was, IIRC, like 2011, though, so again, it may be better now. Every other package manager I've used for any serious length of time, I've repeatedly seen get in weird states that required substantial fiddling before I could use them for anything again, after what should have been boring and normal usage.
(see point #1 for why it would also be a lot more tolerable if it did have that trouble, than it is when that happens on, say, Linux, and indeed, that's the only reason I was able to struggle along with Macports for a little over a year before switching—I could just rm its directory and start over, after the second time from a script that did it for me, without causing any harm whatsoever to my OS itself)
> Some of its advantages are, in a sense, unfair, because it doesn't manage my OS or its most vital pieces[.] [...] [T]hat's totally fair if you consider the platform as a whole. It's really hard for Linux overall to separate user packages from system packages, mostly because it's all mixed up together in a way that it's not on MacOS or Windows—but a distro could take that approach, if they wanted.
Yeah, this is a valid insight! It's essentially the approach that contemporary free BSDs take, and it's a direction popular distros are gradually trying to move in by shifting end-user applications to containerized package managers like Flatpak, AppImage, and Snappy. Fedora Silverblue is an example of an extreme case, where the base system is read-only.
> #1: Separation of a very complete and capable base GUI OS […]
I suppose the BSDs fall down here, since their base system doesn't include a GUI.
> Every other package manager I've used for any serious length of time, I've repeatedly seen get in weird states that required substantial fiddling before I could use them for anything again, after what should have been boring and normal usage.
I've only really seen this happen when using distro package managers to perform several years worth of release upgrades or convert between distributions.
I like the uniformity of Linux's package management tools (i.e., the ability to use the same tools to manage OS components as end-user software), but I can see how using one thing for OS components, especially if it's reliable and mostly hands-off, but then using something else for end-user software can be appealing.
Yeah, I think these days I'd find FreeBSD a better fit than Linux. I'm... increasingly kinda over Linux. Red Hat's continuing political success in pushing projects it (more or less) steers toward de facto standard status, while having (in my opinion) god-awful taste in project architecture and goals, has the whole ecosystem going a direction I don't like.
Nonetheless, it'd be nice to have the GUI included in the "this doesn't break" part of the OS. It'd be pretty unlikely that Homebrew could screw up an entire day for me, because the scope of things it's likely to even be able to mess up is limited. A package upgrade breaks X or Wayland, though? Ugh, there goes the day. Increasingly, I think stronger guarantees that the GUI layer does not break, or become unstable (god, I've seen so many X crashes in my life) except under very unusual circumstances, would be table-stakes in my switching full time to another workstation OS. Which leaves me options of... MacOS or Windows. Win10/11's telemetry and adware crap is unacceptable, and I like unixy tools, so that leaves me one option. :-(
Then again, ZFS with snapshotting can paper over a lot of packaging & system-update problems, which is part of why I'm thinking there may be a lot more FreeBSD in my future (yeah, yeah, I know, Linux has it too, but I've developed—like scar tissue—a healthy mistrust of Linux distros' ability to deal with "non-standard" file systems, when it comes to the root filesystem)
Homebrew is still here to stay. If Apple provide a package manager, then it likely that people will swarm to that but again it depends on how much capabilities and feature parity it have over other package managers. Microsoft is working on this with their Winget. Homebrew is great for casual and daily users since we don't have to keep hunting for software updates.
And Homebrew does have a progress bar for each app. The bar is for the downloading but other than that, I don't think it need a progress bar for installtion since they are quick to install than using the GUI installation.
Winget isn't really a package manager so much as an installer wrangler and frontend for the Microsoft App store. Of the nearly 30,000 manifest files inside the winget repo, fewer than 150 of them define a single dependency. The rest run executable installers that can do basically anything, or just grab an app from the Microsoft Store. It doesn't do anything to eliminate the chaos of every program doing whatever the fuck it wants to get itself installed or create a common ecosystem of integrated packages, which are the main points of package management.
Winget also lacks most of the core functionality of a package manager, including knowing how to uninstall anything at all. But uninstallation will never work reliably on winget anyway, as long as winget an installer wrangler, because installer wranglers inherit unreliable and bespoke per-package installation/uninstallation procedures from existing Windows apps. After a year and a half in public, Winget is still just Chocolatey but faster and much worse in every other respect.
There's basically nothing on offer on Windows if you want a package manager instead of just some automation wrapping executable installers.
(Scoop is the closest thing, and it's sort of just now swinging back from the verge of death after months in limbo.) The fact that Microsoft announced a project and called it a package manager has done more or less nothing to change that.
I know that there are usually workarounds to these problems, but they tend to be obscure, and change frequently, and are not simple to look up.
Pacman, apt, portage, etc have much more stable interfaces. But the workarounds for my edge cases in Homebrew from a year ago don't work anymore. Even knowing what is an edgecase or not is a problem.
Most of these issues would be fine if the interface changed as slowly and consistently as Linux package managers.
It’d be nice if it asked if it’s ok to remove old versions of dependencies when installing a new package. It’d also be nice for it to not upgrade, say, wireshark and nginx when installing, say, ffmpeg, without asking first.
`HOMEBREW_NO_INSTALL_CLEANUP` used to be the default. Many users complained about how much space Homebrew used, and were shocked by how much they saved by doing `brew cleanup`, so now it’s done by default.
1. Nix has very limited support for GUI applications of the kind that you'd find in `brew cask`. Not no support, some of them are there, but limited support compared to brew. If you use brew as an out-of-the-box install-everything setup like me, you'll not be able to replicate that easily with Nix.
2. Nix can't currently build Swift applications because of some Xcode something I didn't fully understand.
3. I found a small number of packages that are broken on Nix on my aarch64 / M1 MacBook Air (and marked broken, so when you try to install it complains) and a small number that are broken without being marked broken. In specific, I think R was one that surprised me -- this is a major programming language and although the build requirements are onerous (it's a mix of C and Fortran), I would think it would work.
That being said the actual process of installing, updating, and upgrading seems much faster and dramatically less shitty than homebrew, and so I recommend migrating stuff off of brew anyway.