✅ Works on my machine
Welcome to my declarative, modular and - of course - opinionated MacOS system configuration using nix-darwin with flakes. Please be aware this might not work out of the box for you.
Features:
- Install and configure software packages via nix
- Build and run NixOS virtual machines using QEMU (see here)
- Manage Homebrew installations via nix-homebrew
- Use Home Manager instead of plain dotfiles
Notes:
- Not everything is installed via nix. I use following guideline:
- Homebrew Bundle keeps track of software installed via App Store or Homebrew
- Not handled by Home Manger:
- Emacs configuration (see here)
- ... and my Hammerspoon configuration (see here)
- Install Nix using the Determinate Nix Installer
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
I use the upstream version of Nix.
- Clone repo
nix shell nixpkgs#git
git clone https://github.com/mrkuz/macos-config
cd macos-config
- Install nix-darwin
nix run nix-darwin/master#darwin-rebuild -- switch --flake .#bootstrap
darwin-rebuild switch --flake .#m4
go.sh
provides a bunch of commands to simplify recurring system maintenance tasks.
Updates flake inputs and brew formulae. Shows outdated brew and App Store packages.
Runs darwin-rebuild
and upgrades outdated brew and App Store packages. Updates the Brewfile.
Deletes old generations, runs garbage collection, removes unused brew dependencies and prunes the brew cache.
To build Linux packages on MacOS, you need a remote Linux builder. Thankfully this can be archived with one line in nix-darwin:
nix.linux-builder.enable = true;
Usually the builder starts automatically. If you dislike this, add following:
launchd.daemons.linux-builder.serviceConfig = {
KeepAlive = lib.mkForce false;
RunAtLoad = lib.mkForce false;
};
You then need to start the builder manually:
sudo launchctl start org.nixos.linux-builder
See host configuration 'm4' for a full example.
After the builder is up and running, you can launch every VM defined in hosts/nixos/vm/
with a single command:
nix run .#playground-vm
In case you run into issues with sandboxed builds, you can disable the sandbox temporary with --option sandbox false
.
Use cases: Run docker, isolate applications, ... see hosts section.
To learn how to add additional VMs, check out flake.nix (look for mkVm
).
VMs can also be build out-of-tree, see this example.
The QEMU package provided and used by this configuration comes with support for hardware accelerated graphics, based on the awesome work of Akihiko Odaki.
The 'qemuGuest' module provides a bunch of useful configuration options for QEMU guests.
Host expressions represent a physical machine. Kind of what you would put in darwin-configuration.nix
or configuration.nix
.
Name | System | Description |
---|---|---|
bootstrap | darwin | Minimal configuration including linux-builder |
m4 | darwin | Configuration for my MacBook Air M4 |
VM expressions are like host expressions, but represent a virtual machine.
Name | System | Description |
---|---|---|
docker | nixos (console) | Runs Docker Engine |
firefox | nixos (graphic) | Runs Firefox Developer Edition |
gnome | nixos (graphic) | Latest GNOME desktop environment (without apps) |
k3s | nixos (console) | Runs k3s |
playground | nixos (console) | NixOS playground to fiddle around |
toolbox | nixos (graphic) | VM with some tools preconfigured |
snapd | nixos (console) | Runs snapd |
Home Manager configuration per user. Usually imported by one ore more hosts (e.g. 'm4' host).
Name | Description |
---|---|
markus | Yeah, that's me |
Modules are used to implement specific features. They can declare options for customization. Learn more about modules in the NixOS manual.
I use following conventions:
- Module options are exposed under
modules.NAME
- Each module has to be enabled explicitly:
modules.NAME.enable = true;
Check out any host or user expression for example usage.
Name | System | Description |
---|---|---|
nix | darwin, nixos | Configures nix, flake registries and more |
fonts | darwin | Adds a bunch of fonts |
hunspell | darwin | Adds Hunspell spell checker and a couple of dictionaries |
socket-vmnet | darwin | Adds and configures socket_vmnet |
tuptime | darwin | Configures tuptime to keep track of system uptime |
alacritty | home-manager | Adds and configures alacritty terminal emulator |
emacs | home-manager | Adds Emacs including some dependencies and runs daemon at log in |
kitty | home-manager | Adds and configures kitty terminal emulator |
tmux | home-manager | Adds and configure tmux terminal multiplexer |
kiosk | nixos | Runs a single application in fullscreen mode |
minimize | nixos | Minimized variant of NixOS (only recommmended for non-interactive systems) |
qemu-guest | nixos | Provides convenience features for QEMU guests |
Takes care of configuring nix and adds some nix-related packages.
Also:
- Creates a link to the revision of this configuration used for building ->
/etc/nix/current/
- Creates a link of the nixpkgs used for building ->
/etc/nix/nixpkgs
- Adds nixpkgs used for building as
nixpkgs
to the flake registry - Adds
nixpkgs-unstable
,nixos-stable
andnixos-unstable
to the flake registry
NixOS-specific
- Creates a compatibility layer in
/etc/nixos/compat
which can be used with tools that do not support flakes (e.g. nixos-option). Powered by flake-compat.
Adds socket_vmnet and a corresponding launch daemon.
Options
Name | Description | Default |
---|---|---|
gateway | Gateway IP used for vmnet | 192.168.105.1 |
dhcpEnd | End of DHCP range | 192.168.105.100 |
Runs a single application in fullscreen mode.
Options
Name | Description | Default | Example |
---|---|---|---|
wayland | Use wayland (cage) instead of X11 | false | |
program | Path to application to run (required) | - | ${pkgs.firefox}/bin/firefox |
user | Run as this user (required) | - |
Creates a minimized variant of NixOS.
Options
Name | Description | Default | Example |
---|---|---|---|
noLogin | Disable console login | false | |
noNix | Remove nix package and disable daemon | false |
Provides convenience features for QEMU guests.
Also check out the existing NixOS options (virtualisation.*
) for customisation.
Options
Name | Description | Default |
---|---|---|
graphics | Run QEMU with graphics window | false |
opengl | Enable hardware accelerated graphics | false |
user | Create user | - |
autoLogin | Auto-login user | false |
dhcp | Use DHCP for network configuration | false |
sshd | Configure and start SSH server | false |
vmnet | Use vmnet for networking | false |
socketVmnet | Use socket_vmnet for networking | false |
Technically profiles are also modules. But they are intended to be used in flake.nix and thus cannot be enabled in hosts or user expressions.
Name | Description |
---|---|
docker-tar | Used to create Docker image (tar) |
qemu-qcow2 | Used to create NixOS QCOW2 disk images |
qemu-vm | Used to create NixOS QEMU VMs |
This profile adds the config.system.build.startVm
derivation, which produces a script start-NAME-vm
. The script launches QEMU with comand line arguments based on the configuration (virtualisation.*
options and the 'qemuGuest' module).
Collection of additional (or patched) software packages.
niv is used to keep track of package sources.
Name | System | Description |
---|---|---|
qemu | darwin | QEMU with patches from Akihiko Odaki, to enable accelerated graphics |
socket_vmnet | darwin | Allows QEMU to use vmnet without root privileges |
angle | darwin | OpenGL ES implementation which provides translation to Apple's Metal |
libepoxy | darwin | Library for OpenGL pointer management (with patches from Akihiko Odaki) |
virglrenderer | darwin | Virtual GPU for QEMU providing 3D acceleration (with patches from Akihiko Odaki) |
k3s-bin | nixos | Single-binary Kubernetes distribution (release binary) |
Overlays are used to extend or modify nixpkgs. Learn more in the NixOS manual.
Name | System | Description |
---|---|---|
nixos-option | nixos | Wraps nixos-option to work with flake-based systems (requires module.nix.enable = true ) |
emacs | darwin | Adds emacs-plus patches |