Use Nix on macOS as A Homebrew User

louy2 profile image Yufan Lou ・4 min read

Documenting my efforts following Salar Rahmanian's Moving from Homebrew to Nix Package Manager.

First of course is to install nix-darwin:

nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A installer

Some interesting lines from the log:

Would you like edit the default configuration.nix before starting? [y/n] n

I haven't used nix outside of building Haskell libraries with their configuration, so I don't know anything about configuration at this point. Default it is.

warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring

This line appears in multiple locations. It is apparently related to updating nix-darwin, like so:

nix-channel --update darwin
darwin-rebuild changelog

A nix channel is like a homebrew tap I suppose.

Would you like to load darwin configuration in /etc/bashrc? [y/n] y

Upon reading this line my first reaction was to look for zsh in the nix-darwin documentation because I have changed to use zsh following macOS Catalina default. Unfortunately I cannot find much else than a passing mention in the README. I don't know at this point if the installation will work on my machine.

Would you like to create /run? [y/n] y

What the heck even is /run? The documentation of Nix stuff so far has not a bit consideration for onboarding. This front-loading of unnecessary information is very frustrating, especially compared to the simple first steps of Homebrew.

After installation, there would remain a result symlink in the current directory where the installation command was run. Nix documentation has this much to say:

nix-build registers the ./result symlink as a garbage collection root, so unless and until you delete the ./result symlink, the output of the build will be safely kept on your system. You can use nix-build’s [-o](https://nixos.org/nix/manual/#opt-out-link) switch to give the symlink another name.

There should be a nix-run-once command which automatically runs the built binary, skipping this symlink altogether.

Now that I have the nix-darwin installed, I can start install packages. I have picked aria2 to install. It is a download manager which aims to use every bit of your bandwidth. The command for looking for aria2 is

nix-env -qaP aria2

(Sigh) -q as in --query, to say we want to search. -a as in --available, to say we want to search in all available packages, as opposed to --installed which is the default. -P as in --attr-path, as for some reason Nix calls package name "attribute".

The result of the query is

nixpkgs.aria  aria2-1.35.0

I guess I put the first part in my configuration file.

  environment.systemPackages =
    [ nixpkgs.aria

Now I just need to run

darwin-rebuild switch
zsh: command not found: darwin-rebuild

(╯°□°)╯︵ ┻━┻ Of course!

Searching for "zsh" in the repo yields two useful issues: issue #202 and issue #193.

Issue #202 mentions "user shell wasn't enabled in configuration.nix". I have noticed programs.zsh.enable in configuration.nix but I don't know how to apply it without darwin-rebuild. Then it occurred to me that I could simply run the installation again. Nix is supposed to be reproducible, right?


And it worked, and as expected from issue #193, the installer does not overwrite existing etc files:

warning: not linking environment.etc."zprofile" because /etc/zprofile exists, skipping...
warning: not linking environment.etc."zshrc" because /etc/zshrc exists, skipping...

At this point I already have darwin-rebuild in PATH for some reason, but I decided to go all the way. Following issue #193, I move the original files to a .local postfix so the nix generated files would load them. I then run the installer again.

sudo mv /etc/zprofile /etc/zprofile.local
sudo mv /etc/zshrc /etc/zshrc.local

And all seems well. Just to be sure I open another new terminal, and run

 darwin-rebuild switch

Yes, I can run it! Yet what greeted me was

error: undefined variable 'nixpkgs' at /Users/ditto/.nixpkgs/darwin-configuration.nix:7:7

(╯°□°)╯︵ ┻━┻ Are you kidding me?

Fine, looking at the example, I guess I just have to use pkgs instead of nixpkgs. Why doesn't the query display pkgs already?

darwin-rebuild switch

Finally, the rebuild worked, with aria2c correctly in PATH.

In total, this took me 4 hours. This is an unacceptable onboarding experience to me, and I am not recommending Nix to anyone.

I do not think I will replace Homebrew with Nix. I do like a file which I can use to rebuild my development environment. I think I will try Homebrew Bundle for that purpose. I will probably reserve Nix for development dependencies, and towards that I am looking at Nix + Bazel = fully reproducible, incremental builds.

Posted on by:

louy2 profile

Yufan Lou


Learning Rust and Haskell, tired of JavaScript. Thinks Ruby is awesome except that it is not cross-platform enough. 日本語 / 中文 OK. He/him.


markdown guide