Aren't the majority of Homebrew users on Mac OS X? Does Nix work on Mac OS X?
Don't get me wrong: Homebrew is impressive in how many bad ideas it has implemented in a project that is so exceedingly popular; good marketing and ease of use are amazingly powerful. I thoroughly dislike Homebrew, and sincerely hope people choose not to use it, at all (but especially not on servers).
And, also don't get me wrong: I really like Nix, and I believe it has mostly right decisions across the board. If I had my druthers, Nix would be what our near-term package management future looks like.
But, if we're talking about Mac (and gods I hope there aren't a lot of people using Homebrew on other Operating Systems, particularly Linux, where we have an embarrassment of riches in terms of good, even great, package managers), I suspect recommending pkgsrc would be a better near term solution. It is more mature on OS X, and it has more packages than Nix. And, while it is not as modern as Nix, it is an acceptable package manager on most fronts, and doesn't exhibit Homebrew's alarming lack of foresight on security questions.
In short: I like Nix a lot. I dislike Homebrew a lot. So, we're agreed on those points. But, for Mac OS X users looking for a better alternative to Homebrew, pkgsrc seems to be the current best choice (Fink is poorly maintained, macports is slightly better maintained, but pkgsrc is a better package manager).
Here's why I don't like Homebrew, and why I believe Nix is (almost) strictly an improvement over it:
1. Updating packages is not safe. If I update openssl and the ABI changes, all of my currently installed packages that depend on it are now broken -- time to rebuild everything. I've burned way too many hours on ABI breakage and rebuilding everything. That problem can't happen with Nix because Nix will ensure that each library is linked precisely to the versions of the libs they need.
2. Nix has a continuous integration server (called Hydra[1]) that builds every package, and caches the binaries. Because Nix knows each packages entire dependency graph, Hydra only needs to build just the packages that have changed. When I want to update some packages, I can count on not having to rebuild everything myself. Each binary package is signed, so I know my stuff is coming from the build server, regardless of whether or not I get the files through a cache or third party. I can also run my own Hydra instance to build my OS X and Linux packages, and I can share the binaries with others should I wish.
3. The lack of determinism. With Nix on OS X, packages are built using OS X's native Sandbox APIs to ensure that the build process can only see the dependencies that were explicitly specified. This guarantees that if the build works on my machine, it will work on yours -- whereas I've seen brew formulas under-specify configure flags and such, resulting in the default of linking to non brew installed libraries, causing quite a bit of confusion when things don't work at run time, or just flat out fail to build.
4. Brew is OS X specific. Nix works on OS X, Linux, and a FreeBSD. As someone who deploys to Linux virtual servers, it's nice that I can use the same versions of packages both in development and production.
It's not all roses, though. We have a smaller community of OS X users at this point, so not everything works (thus my "almost" qualification). Regarding the underlying tech and the outlook for the future, Nix is a superior tool.
I wrote a blog post a while back about my experiments with Homebrew, which covers most of the major security concerns I have with it. I hope it's clear from the post (linked below) that I went into the process with an open mind, and even positive expectations, because so many people really like Homebrew. But, I was alarmed at the implications of some of the decisions they've made; I understand why they made the design choices they made, but I don't think the trade off is even close to worth it. It is, as noted, particularly scary for server use, but I would be hesitant to use it for any purpose.
After that post was written, I continued to tinker with Homebrew (because it is so popular, it was really hard to completely toss it aside), but found a number of other problems. While it has lots of packages and they are often very up to date, updating over time and upgrading/downgrading versions, both proved fragile.
In a world with so many really good package managers, I find it unfortunate that the one that captured so many people's imagination and enthusiasm is broken by design, and in ways that have been understood for decades (even before good package managers, it was understood that you don't run all your servers as the same user). Or, at the very least, cannot ever be a general purpose package manager for operating systems; if you understand the limitations and know you can never safely deploy to servers using Homebrew, and only ever use it on private development laptop/desktop systems, then I won't judge. I understand it is easy to use, has a lot of packages, and has a lot of good documentation. Those are good things.
Anyway, I'm a packaging nerd. It's a thing I'm weirdly passionate about (I've contributed patches to yum in the distant past, have been a maintainer of packages for all sorts of operating systems and OSS and commercial projects, and I maintain the package repositories for my company's products and projects). I have strong opinions, but they are based on much (much!) more than average experience; over the past two decades I've spent a lot of time building packages (for Linux, Windows, Mac OS X, Solaris, FreeBSD, etc.). It may even be the technical area I have spent the most time on, since it's been consistent across nearly every company and project I've ever worked for/on. Homebrew strikes me as a huge step backward.
Could you elaborate what you dislike most about home brew? I only don't like that they refuse to package old versions, although they are still supported by the author and quite popular (I'm looking at you Python).
Furthermore, it often leaves deprecated APIs on my computer without offering to upgrade them (because other packages rely on them).
> Remember when everyone switched to Homebrew because Fink/macports were "antiquated", a.k.a. not written in Ruby?
Yes, I must admit I chose the word "antiquated" quite intentionally, as Homebrew seems to get so much attention (for now) because it's written in Ruby and the website (http://brew.sh/) is shiny, rather than technical merits.
> It was nice back then. Packages didn't install themselves in /usr/local.
You might enjoy Nix, then -- for that reason, and the following:
1. Everything is stored in /nix/store -- nothing ever touches /{local,}/{bin,lib,share}
2. Profiles are symlink forests that merge multiple packages into one FSH[1]-like tree -- each link pointing into /nix/store. When you install a package, a new symlink forest is created replacing the one at ~/.nix-profile (your user profile, being the default). If you request that nix rollback to a previous "generation" of your profile, all Nix has to do is replace the ~/.nix-profile link to instead point at the previous generation's symlink forest (you can think of this as bumping HEAD in git -- it's nearly instantaneous). If upgrading a package goes wrong, just rollback.
3. Because Nix knows the entire dependency graph, its trivial to distribute a build plan across multiple machines (you can set this up to happen by default)
4. We have a continuous integration server (Hydra[2]) that builds and signs all of our packages. Of course, there's nothing stopping you from building from source (or you could run your own Hydra instance, if you so wish).
The purpose of /usr/local is for you to put stuff there, but it actually causes a lot of problems if a package manager does it.
- your work-issued laptop might have work stuff installed in there, and the package manager will overwrite it
- build-from-source package managers like fink/ports/brew are incapable of controlling themselves and always install things you didn't ask them to
Since /usr/local is in the default search path for your compiler, that last one means your personal configure script runs are not reproducible, and you'll start linking to packaged versions of libiconv or whatever without meaning to, and your code won't work on other machines or it'll crash unexpectedly.
Fink invented /sw for this, MacPorts uses /opt which I think they got from Solaris?
I think you must have ignored a substantial portion of my comment. Let's take a look at what (part of) my Nix store looks like (you'll see it fundamentally looks nothing like /usr/local):
Note that each package under /nix/store is its own prefix; that is, it contains its own bin, lib, share, etc.
/usr/local is a dumping ground "for use by the system administrator when installing software locally"[1]. If you need multiple versions of automake installed: tough luck, the paths collide. If you need multiple versions of Erlang: tough luck, the paths collide.
Would you like to be able to rollback your system by changing one symlink[2]? Too bad: when you last installed packages into /usr/local, your package manager clobbered the previous version.
Technically, we could make /usr/local a symlink forest pointing into /nix/store, but we don't: we want to make sure that only the packages we explicitly declared are picked up by build tools, rather than defaulting to searching through the currently "installed" packages.
> /nix/store? Really? You can't just make up new root level directories. That's so wrong.
Can you substantiate your claim? Note that "it doesn't feel right" doesn't count as a rational criticism.
[2]: This probably sounds like a bold claim. I tried to explain how this works above, but if you don't believe me, feel free to ask and I'll explain further. Alternatively, feel free to read the first paragraph here: http://nixos.org/nix/manual/#sec-profiles
Funny that you should mention the FHS. From that same document:
Applications must never create or require special files or subdirectories in the root directory. Other locations in the FHS hierarchy provide more than enough flexibility for any package.
They really should be using /opt:
/opt is reserved for the installation of add-on application software packages.
A package to be installed in /opt must locate its static files in a separate /opt/<package> or /opt/<provider> directory tree
That's basically the main reason why I left MacPorts. The other was the fact that they'd build their own version of already installed programs. The worst offender for a long time was tetex until they finally added support for looking at an existing tetex installation.
I also ran into a number of broken ports. I had used Fink, but I ran into issues with its packaging too. So, when I heard about Homebrew, I decided to try it. It's been pretty decent for me so I've stuck with it. The only major issue I've had has been related to Octave, but that's been a problem for MacPorts too as the OS X version isn't as up to date as the Linux version at times.
http://nixos.org/nix
https://github.com/NixOS/nixpkgs
https://blog.errright.com/switching-from-homebrew-to-nix/