Use Nix on macOS as A Homebrew User
Tags: package, nix, homebrew, macos
Published: 2020-06-12 08:26:44

Documenting my efforts following Salar Rahmanian's [Moving from Homebrew to Nix Package Manager](https://www.softinio.com/post/moving-from-homebrew-to-nix-package-manager/).

First of course is to install [`nix-darwin`](https://github.com/LnL7/nix-darwin):

```sh
nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A installer
./result/bin/darwin-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.

```nix
  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](https://github.com/LnL7/nix-darwin/issues/202) and [issue #193](https://github.com/LnL7/nix-darwin/issues/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?

    ./result/bin/darwin-installer

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
./result/bin/darwin-installer
```

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](https://www.tweag.io/blog/2018-03-15-bazel-nix/).