- Nix (install through Determinate Systems) with flakes enabled
- macOS on Apple Silicon (
aarch64-darwin)
After editing configuration under hosts/, modules/, or overlays/:
-
Build and switch (most common):
nix run .#build-switch -
Build only (validate changes without activating):
nix run .#buildThis compiles the system closure and removes the
./resultsymlink when done. Nothing is activated.
Flake inputs (nixpkgs, darwin, home-manager, Homebrew taps, etc.) are pinned in flake.lock. To refresh them:
# Update all inputs
nix flake updateAfter updating, rebuild and switch. Review flake.lock changes before committing if you track this repo in git.
List available system generations:
sudo darwin-rebuild --list-generationsRoll back interactively (prompts for a generation number):
nix run .#rollbackRemove system generations older than 7 days and collect unreachable store paths:
nix run .#cleanHome Manager and nix-darwin keep their own generation history; darwin-rebuild --list-generations shows system-level
generations.
Although declarative nix is great, there are few things that are not managed through nix:
- cursor
agentcli - GitHub Desktop
- mise global config (e.g., output of
mise use --global) - AstroNvim's plugins (see "Neovim (AstroNvim)" below)
- Enabling the 1Password SSH Agent (Settings > Developer > "Use the SSH Agent" in the 1Password app), required once per machine for SSH-based git commit signing (see modules/shared/home-manager.nix)
AstroNvim is installed as a set of dotfiles rather than a Nix package, since it's fundamentally a Lua config that expects to manage its own plugins. Nix and AstroNvim's own tooling split responsibilities:
- Nix-managed:
- The config itself lives in modules/shared/config/nvim/ (a checked-in copy of the
AstroNvim template) and is symlinked to
~/.config/nvimby home-manager via modules/shared/files.nix. neovimplus AstroNvim's CLI dependencies (ripgrep,lazygit,fd,git) live in modules/shared/packages.nix.- The Nerd Font (
font-jetbrains-mono-nerd-font, used for file icons/statusline) is a Homebrew cask in modules/darwin/casks.nix, wired into Ghostty'sfont-familyin modules/darwin/home-manager.nix.
- The config itself lives in modules/shared/config/nvim/ (a checked-in copy of the
AstroNvim template) and is symlinked to
- Left to AstroNvim's own tooling (pragmatic, not nix-managed):
lazy.nviminstalls AstroNvim core and all plugins by cloning them from git on first launch, andmason.nviminstalls LSPs/formatters/DAPs on demand (:LspInstall,:MasonInstall). Reimplementing this in Nix (e.g. vialazy-nix-helper.nvim) was considered and skipped as unnecessary overhead for this setup.- Because
~/.config/nvimis a read-only symlink into the nix store,lazy.nvim's lockfile is redirected to the (writable, non-nix-managed) state dir inlua/lazy_setup.lua(vim.fn.stdpath("state") .. "/lazy-lock.json") instead of its usual home inside the config directory.
To pin plugin versions across machines (the non-Nix equivalent of flake.lock), copy the generated lockfile into the
repo and commit it:
cp ~/.local/state/nvim/lazy-lock.json modules/shared/config/nvim/lazy-lock.jsonTo change the config itself, edit files under modules/shared/config/nvim/ (not the symlinked ~/.config/nvim path
directly) and run nix run .#build-switch.