Personal NixOS and macOS configuration flake. Built on snowfall-lib, with home-manager, nix-darwin, NixOS impermanence, and sops-nix.
Ported from my previous Ubuntu setup at .dotfiles-old.
- NixOS workstation with Sway / Wayland
- Impermanent NixOS root: only
/nix,/boot, and/persistsurvive reboots - Apple Silicon MacBook managed with nix-darwin and Home Manager
- SOPS + age for secrets, scoped per host
- Custom xkb layouts on Linux, plumbed through to Sway keybindings
- Darwin keyboard defaults for Dvorak, Caps Lock, and non-US tilde behavior
- Homebrew-managed macOS apps through the Darwin layer
Everything defined by this repo uses the custom. namespace.
| Path | Purpose |
|---|---|
flake.nix |
Flake entry point and inputs |
systems/ |
Per-host NixOS / nix-darwin configurations |
homes/ |
Per-user Home Manager configurations |
modules/nixos/ |
NixOS system modules |
modules/darwin/ |
nix-darwin system and app modules |
modules/home/ |
Home Manager modules |
modules/shared/ |
Modules shared between system and home |
lib/ |
Snowfall library extensions exposed under lib.custom.* |
packages/ |
Custom packages surfaced as flake outputs |
overlays/ |
nixpkgs overlays |
shells/ |
Per-language nix develop shells |
secrets/ |
SOPS-encrypted secrets |
systems/x86_64-linux/workstation- main NixOS desktopsystems/x86_64-linux/vm- virtualized test targetsystems/aarch64-darwin/macbook- Apple Silicon MacBook
Use just as the normal entry point:
just switch # Darwin: HM then sudo darwin-rebuild; Linux: sudo nixos-rebuild
just hm-switch # standalone Home Manager switch
just darwin-switch # sudo darwin-rebuild for macbook
just nixos-switch # sudo nixos-rebuild for workstationDevelopment shells:
nix develop .#nix
nix develop .#go
nix develop .#luaRun custom packages:
nix run .#backup
nix run .#monitor-control
nix run .#gammastep-helper
nix run .#waybar-vpn-status
nix run .#networkmonFormat the tree:
nix fmtThe rule for Darwin is:
- CLI tools: use nixpkgs, Home Manager, flake inputs, overlays, or local packages.
- GUI apps and macOS app bundles: use nix-darwin-managed Homebrew, with nix-homebrew as the preferred bootstrap layer if Homebrew ownership needs to be made fully declarative.
This keeps the Mac simple and reliable. Even if a nixpkgs package exposes a
.app, pinning that app into the Dock can leave a missing question mark after
rebuilds because the Dock points at an old store path. Use Homebrew casks for
apps that live in /Applications.
Current examples:
ghosttyandweztermare Homebrew casks inmodules/darwin/apps/terminals/default.nixworktrunkis a Homebrew formula on macOSworktrunkis installed from its upstream Nix flake on Linux
Install Nix on a clean macOS machine:
curl -L https://nixos.org/nix/install | sh -s -- --daemonRestart the terminal, then enable flakes for bootstrap:
mkdir -p ~/.config/nix
printf 'experimental-features = nix-command flakes\n' >> ~/.config/nix/nix.confClone this repo:
mkdir -p ~/Desktop
cd ~/Desktop
git clone https://github.com/Nikola-Milovic/.dotfiles.git dotfiles
cd dotfilesInstall the MacBook age key before activating SOPS-backed Home Manager:
mkdir -p ~/.config/sops/age
install -m 600 ~/Downloads/macbook-keys.txt ~/.config/sops/age/keys.txtBootstrap with just through Nix:
nix run nixpkgs#just -- switchAfter the first successful activation:
just switchdarwin-rebuild switch must run as root. The just recipes already do that
with sudo.
The NixOS root filesystem is reset on every boot. To keep state across reboots, opt in explicitly:
- System state:
modules/nixos/system/impermanence/default.nix - User state:
modules/home/impermanence/default.nix - App-specific state: the relevant module's own impermanence block
Persistent data lives under /persist/... and is mounted back to where apps
expect it. Before major changes, snapshot it:
nix run .#backupDarwin does not use impermanence.
Heavy inspiration and borrowed patterns from:
- Security enhancements
- Evaluate Looking Glass as an alternative to dual-booting
- YubiKey setup
- Fix sway brightness hotkeys
- Wrong audio device picked as default
- BTRFS rollback not working