About three years ago, I started using NixOS on my personal laptop. In those days, Ineeded a config that would allow me to have a stable system, that could be reproducibleover all my machines, and that would allow me to have a development environment that wouldbe easy to maintain and to share with others. NixOS comes to fit all these requirements.
But, since I started using a MacBook Pro (2022), I do not feel the necessity of using theNix package manager, since I can use Homebrew to install all the packages that I need andhave some kind of reproducibility with shell scripts. But, for some needs, I would like touse Nix again on my macOS now, and this blog post will be about how to set up Nix on macOSlike me.
Installing Nix on macOS
Installing Nix on macOS is easy. You can use the following command to install Nix on yourmachine:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
This command installs the Nix package manager based on the DeterminateSystem/nix-installer,based on the explanation by the Zero to Nix, it givesbetter error messages, an installation plan (like Terraform), and other cool features that bringa better installation experience for you.
Just follow the step by step of the installation flow and everything will be fine.
Creating the flake file
After installing Nix, you can create a flake.nix
file that will be the entry point for yourentire Nix configuration on your machine. This file will be used to define the packages thatyou want to install, the system configuration, and the home-manager configuration.
{ description = "Nix configuration"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs"; nix-darwin.url = "github:lnl7/nix-darwin/master"; nix-darwin.inputs.nixpkgs.follows = "nixpkgs"; home-manager.url = "github:nix-community/home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = inputs @ { self, ... }: let nixpkgsConfig = { config.allowUnfree = true; }; in { };}
This is the basic structure of my flake.nix
, it defines all the inputs that I will needto use in my configuration, they are:
nixpkgs
: The main NixOS/Nixpkgs repository, that will be used to define the packagesthat I want to install on my machine.nix-darwin
: The nix-darwin repository. It brings all modules to configure your macOSsystem using a declarative way.home-manager
: The home-manager repository. It brings all modules to configure youruser environment using a declarative way.
Configuring nix-darwin
After creating the flake.nix
file, you can configure the nix-darwin
module. You willneed to create a darwinConfigurations
field on the outputs of your flake.nix
file, andadd the hostname of your machine with the darwinSystem
function.
{ # ... outputs = inputs @ { self, nix-homebrew, home-manager ... }: let nixpkgsConfig = { config.allowUnfree = true; }; in { darwinConfigurations = let inherit (inputs.nix-darwin.lib) darwinSystem; in { machine = darwinSystem { system = "aarch64-darwin"; specialArgs = { inherit inputs; }; modules = [ ./hosts/mbp/configuration.nix inputs.home-manager.darwinModules.home-manager { nixpkgs = nixpkgsConfig; home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; home-manager.users.noghartt = import ./home/home.nix; } ]; }; }; };}
In that case, what I’m doing is: creating a new configuration called machine
on the darwinConfigurations
systems, and declaring some specific properties of that given system, they are:
- The system of that machine is
aarch64-darwin
, which is the system of the new Apple SiliconMacs (MacBook Pro M1). - The
specialArgs
field is used to pass the inputs to thedarwinSystem
function. All modulesare functions that accept some arguments, thespecialArgs
field lets you pass new argumentsfor all these imported modules. - The
modules
field is used to define the modules that will be used to configure the system.In that case, I’m using theconfiguration.nix
file to define my system configuration, thehome-manager
module to configure the user environment, thehomebrew.nix
file to installall the packages that I want to install using Homebrew, and thehome.nix
file to configuremy user environment using home-manager.
Configuring my system
The configuration.nix
file is used to define some system configurations related to myMacBook Pro, like user home dir, some extra options related to Nix binaries, and other system-related configurations that you want to declare. In my case, I wrote the following configuration.nix
:
_: { services.nix-daemon.enable = true; users.users.noghartt = { home = "/Users/noghartt"; }; nix.extraOptions = '' auto-optimise-store = true experimental-features = nix-command flakes extra-platforms = x86_64-darwin aarch64-darwin ''; homebrew = { enable = true; casks = [ "discord" "visual-studio-code" ]; };}
Configuring the home-manager
The home.nix
file is used to define the user environment configurations using the home-manager.In my case, I wrote just a simple home.nix
file that installs some packages for me. It islike a configuration.nix
file but for the user environment.
{ pkgs, ... }: { home.stateVersion = "23.11"; home.packages = with pkgs; [ htop curl coreutils jq ]; programs.zsh = { enable = true; shellAliases = { ls = "ls --color"; }; };}
With that configuration, I can install the initial packages that I want to use on mymachine using Nix, and gives me the powerful ability of reproducibility in a declarative way.
Building and activating the configuration
After creating all the files, you can build and activate the configuration using the following.You just need to run two specific commands to build and activate the configuration on yourmachine:
1. Building the configuration
nix build .#darwinConfigurations.machine.config.system
It will build the configuration of your machine targeting the darwinConfigurations.machine
outputs. Do not forget of changing the machine
of the given name of your system configuration.
2. Activating the configuration
./result/sw/bin/darwin-rebuild switch --flake .
It will activate the configuration of your machine using the darwin-rebuild
command. It willswitch the configuration of your machine to the new configuration that you have built.
Conclusion
In this blog post, I showed how to set up Nix on macOS using flakes, nix-darwin, and home-managerlike I do. I hope that this blog post can help you set up your configuration and let youuse Nix on your machine too.
I really love how the Nix package manager works, and I think that it is a great tool to useon your machine since it gives you a lot of power to manage your system and your user environment.You really should give it a try.
If you want to see my configuration, you can check it out on my repository,it’s all open source, feel free to use it as a base for your configuration if you want.
If you have any questions, feel free to ask me on Twitter or send me an email. I will be gladto help you with your doubts.