Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

To others who might be interested in trying Nix instead of Homebrew:

There is a `brew install` equivalent in vanilla Nix -- `nix-env` provides an imperative interface pretty similiar to `brew`.

`nix-darwin` is a third-party thing that tries to give you a NixOS-like experience on macOS. It's not necessary if you're only interested in replacing Homebrew. You can have `shell.nix` files and ad-hoc environments without replacing your entire system configuration.

Vanilla Nix is very well isolated, and you can try it side by side with Homebrew to see how you like it -- one of the nice side effects of Nix-installed software being independent from the rest of your system is that, well, you can install whatever you want without breaking the Homebrew equivalents. For example instead of putting binaries in `/usr/local/bin`, Nix creates a directory of symlinks to files in `/nix/store`, and you can add that directory to your `PATH` if you wish.

I switched to Nix a few months ago and have found it... fun. It's not something I would recommend if you want things to just work, but if you're curious about Nix, you can learn quite a lot about it from the comfort of your MacBook.

I wrote a little about this experience here, including how to map common `brew` commands into their `nix-env` equivalents: https://ianthehenry.com/posts/how-to-learn-nix/switching-fro...

(Warning: it's more of a rambling diary entry than a blog post.)



view as:

Thanks for posting this, it’s very helpful.

Very helpful. Unfortunately Nix doesn't support aarch64 yet, only x86_64...

It seems to be coming though: https://github.com/NixOS/nixpkgs/issues/95903


Yeah, it, like, mostly works? But maybe only in multi-user mode? I don't know; I didn't read the whole thread. I don't have an M1 machine, but it seems like there are binaries cached for the arch in the official cache:

    $ nix-env -qasA nixpkgs.git --argstr system 'aarch64-darwin'
    --S  git-2.31.1
Which implies that it's supported in some capacity.

(The "S" means "there's a substitute available;" i.e. git at least is cached for aarch64. Yeah, Nix's CLI... needs work.)

I don't know exactly what the state of it is -- i.e how many packages can build natively on M1 -- but I know that the Nixpkgs community has done a lot of work in the last year to support M1 nicely, and I thought that it was fully usable at this point. But there's a big difference between "Nix works on M1" and "every package in Nixpkgs works on M1."


A better future is on the horizon (or here, today, if you're willing to install a 2.4 pre-release): Flakes make it trivial to fall back to x86_64 when aarch64 fails, and the CLI experience is dramatically improved.

Alas, that path is probably not yet suitable for folks without prior Nix experience, given how new everything is.


Are flakes necessary for that? I would think you could install x86_64 binaries manually by setting `system`, even on the 2.3 branch. It seems I can do the reverse thing:

    $ nix-env -iA nixpkgs.hello --argstr system aarch64-darwin
    $ file $(which hello)
    /Users/ian/.nix-profile/bin/hello: Mach-O 64-bit executable arm64
But maybe you just mean that it does this automatically? That's neat, if so. And I would expect this to be a lot more annoying within a default.nix file, having to keep track of two different nixpkgs imports.

Not automatic, but as a replacement for nix-env and nix-shell, it's great. When I need an x86_64 package, I find `nix shell nixpkgs#legacyPackages.x86_64-darwin.neovim` easier to recall and reason about.

(Or `nix profile install nixpkgs#...` for a persistent version of the same)


Where would I look to get started with that?

I do have preexisting Nix experience, as well as with flakes, but I don't know how it applies to my M1.


What I did on my M1 was:

1. Grab a pre-release of Nix 2.4 from the `binaryTarball.aarch64-darwin` job on Hydra: https://hydra.nixos.org/jobset/nix/master#tabs-jobs

2. Run the installer with: ./install --daemon --no-channel-add

3. Edit `/etc/nix/nix.conf` to include the line: experimental-features = nix-command flakes ca-references

4. Restart the daemon with: sudo launchctl kickstart -k system/org.nixos.nix-daemon

5. Done!

At this point you have a Nix installation, without any legacy channels, which uses aarch64-darwin by default. If you have Rosetta2 installed, Nix will automatically detect it and set `extra-platforms = x86_64-darwin` so you can seamlessly use / build software for other architectures. If you want to specifically get an Intel version of something in nixpkgs, you have to explicitly state it like: `nixpkgs#legacyPackages.x86_64-darwin.foo`

I found Alexander Bantyev's blog post, "Practical Nix Flakes" (https://serokell.io/blog/practical-nix-flakes) especially helpful in figuring out how things are intended to work, followed by the unstable branch of the Nix documentation at https://nixos.org/manual/nix/unstable/command-ref/new-cli/ni..., which covers the new CLI commands.


That would explain why nix-env --install kept failing because I am using M1.

I recently helped somebody get Nix set up on an M1 Macbook and it seemed to work fine overall. We just used the standard installer, then mostly reused a home-manager-based config that I use on my x86-64 Macbook. Core stuff like Git and Emacs worked with no fiddling, and the few problems we did encounter seemed to be from issues in my personal config, not Nix on aarch64 in general.

That said, we didn't try to build or use anything particularly tricky—just Git, Emacs, Python and a simple Haskell project so far.


Nix / NixOS support AArch64 ( https://nixos.wiki/wiki/NixOS_on_ARM ) however Apple/Mac-devices don't have many drivers available nor have people contributed enough time and resources to have a darwin-aarch64 build farm and binary cache.

Yep, I found the `shell.nix` setup to be too complicated and time consuming, even if it's technically "correct", so I just `nix-env -iA nixpkgs.pkg_name` every time I would have previously used `brew install pkg_name`. Since nix isolates each package from every other package, there's no risk of package incompatibilities when I do this (compare to homebrew, where package A needs one version of python and package B needs another version, and updating python can break both...), and so every project I work on just has all the tools it'll ever need.

For package management within a project, I just whatever tool is appropriate for the language -- NPM, Poetry, Cargo, etc.


Nothing about a shell.nix is complicated. You just copy the boiler plate and add the packages you want. Pretty damn easy in my opinion.

You don't strictly even need a `shell.nix`, you can just name packages verbatim on the command line a la `nix-shell -p python39.pkgs.ipython -p python39.pkgs.numpy --pure` and you're away.

Legal | privacy