Featured image of post Use Nix as Package Manager in macOS

Use Nix as Package Manager in macOS

A package management tool better than Homebrew (in my opinion)

Why Not Use Brew

Currently, the mainstream package management solution on macOS is still Homebrew, but I find it not very user-friendly for me for several reasons:

  1. It’s really slow: Installing new packages is typically a low-frequency operation, yet Homebrew insists on checking for updates before installation. Even if you skip this step, the time difference required to install a package compared to other package managers is significant. I can’t quite comprehend why Brew takes so long for such a simple task.
  2. “Infect” system files: It’s well-known that Homebrew installs everything into /usr/local/bin, making it easy for certain packages to maliciously integrate into the system’s default PATH. The community-driven nature of Brew’s operation can’t guarantee the safety of all packages, not to mention the potential for supply chain attacks.
  3. Confusing in terms: Homebrew uses a plethora of brewing-related terms: Formula, Keg, Tap, Cellar, Bottle, Cask, etc. For someone like me who isn’t familiar with brewing, the learning curve is quite steep. I’d need to study these terms to understand what they all mean.

In summary, Brew isn’t a package manager that provides a comfortable experience for me. However, due to the necessity of working on macOS to make a living, I can’t just switch to Linux and start coding. Therefore, I’ve turned my attention to Nix.

Nix and NixOS

About a year ago, when I was struggling to manage more than 10 servers efficiently, I found NixOS, and there were many articles that detailed its features, which truly captivated me:

  1. Centered around /etc/nixos: NixOS uses configuration files to control the software installed on the entire system and their configurations.
  2. Reproducible Builds: With the same configuration files, NixOS consistently builds the same operating system.
  3. Nix Is a Programable Package Manager: NixOS’s package manager configuration language, Nix, is Turing complete. By maintaining the configuration in a Git repository, I can share foundational configurations across all my servers, while also recording all historical versions for easy rollback and debugging.
  4. Nix is a Purely Functional Language: Isn’t it fascinating?

Over time, I gradually replaced most of my Debian-based servers with NixOS. During this period, I noticed on NixOS’s download page that Nix (the package manager) has a macOS version available:

Screenshot of https://nixos.org/download

So, I made a plan to completely remove Brew from my system in the future.

“Trigger” for the Replacement

In my company, there’s a policy that allows for a replacement after three years when purchasing MacBook products. You can even choose to repurchase the work laptop. As soon as the three years were up, I initiated the end-of-term replacement process with the IT department. Although this Intel MacBook Pro was configured with an i7 and 32GB of RAM, it was still frustratingly slow and on the verge of mental crashing while coding.

On the day of application, IT informed me that I could come and pick up the new laptop. The replacement was another 16-inch MacBook, equipped with an M2 processor and 32GB of memory, which perfectly met my expectations. As for software, I decided not to migrate data from the old Intel Mac. After all, the architecture transition made me a bit skeptical about its reliability. So this time, I didn’t install Brew, and I planned to give Nix a try outside of NixOS.

Installing nix

As shown in the screenshot from the official website above, installing Nix is as simple as running a curl command.

1
sh <(curl -L https://nixos.org/nix/install)

However, unlike most “one-key” scripts, Nix provides detailed output during the installation process, especially when it needs to use sudo:

Screenshot of macOS terminal during installation of Nix

Once the installation is complete, we can use the nix command in the terminal:

Screenshot of macOS terminal with output of nix --help

Nix has a distinct advantage over Brew: its installed files are placed in an APFS container, making the removal of Nix quite convenient—you just need to delete the container.

At this point, we have completed the installation of Nix, but it’s still a bit different from managing most software with a configuration.nix file as in NixOS.

Installing nix-darwin

nix-darwin brings the software management approach of NixOS to macOS. You can easily install nix-darwin using Nix:

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

After the installation, you’ll find the darwin-configuration.nix file in ~/.nixpkgs. This configuration file will be the key to managing your macOS system using nix-darwin:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{ config, pkgs, ... }:

{
  environment.systemPackages = [
    pkgs.vim
  ];

  services.nix-daemon.enable = true;
  programs.zsh.enable = true;  # default shell on catalina
  system.stateVersion = 4;
}

As I am a frontend developer, I need to install node. Additionally, I’m more accustomed to using GNU’s coreutils rather than BSD’s, so I have adjusted the configuration as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{ config, pkgs, lib, ... }:

{
  nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
    "unrar"
  ];

  environment.systemPackages = with pkgs; [
    vim ffmpeg-full coreutils gnugrep gnused gawk htop mtr
    smartmontools neofetch rsync p7zip hugo ncdu
    ipmitool iperf3 wireguard-tools jq p7zip unrar
  ];

  services.nix-daemon.enable = true;
  programs.zsh.enable = true;
  system.stateVersion = 4;
}

Afterward, you only need to run darwin-rebuild switch to allow darwin-nix to complete the installation and configuration of software (I haven’t used the configuration capabilities here due to personal preference). Once this is done, all the software will be available in the PATH:

Screenshot of darwin-rebuild and neofetch

Looking at the logs, it’s easy to notice the existence of the /Applications/Nix Apps directory. In fact, it’s not just command-line software; GUI software can also be installed through Nix, such as this terminal emulator called kitty:

Screenshot of kitty

comments powered by Disqus
Except where otherwise noted, content on this blog is licensed under CC-BY 2.0.
Built with Hugo
Theme Stack designed by Jimmy