Nix-managed dotfiles for macOS (nix-darwin + home-manager) and Linux (home-manager standalone) with full feature parity. Built on Determinate Nix (nixd).
Here are some of the screenshots from time to time (the config may or may not be still here, idk):
Built with Den — aspect-oriented Nix. Every file under modules/ is loaded by import-tree, and each one contributes either an aspect (den.aspects.<name>), an entity (den.hosts / den.homes), or a global default. Den resolves those into the flake outputs.
flake.nix # inputs + evalModules + import-tree, nothing else
└── modules/
├── den.nix # Den wiring: schema defaults + den.default (stateVersion, …)
├── hosts.nix # den.hosts (melon) + den.homes (linux)
├── user.nix # den.aspects.elianiva + platform variants
├── _lib/ # ignored by import-tree: plain data & helpers
│ ├── identity.nix # username / home dir / git identity
│ ├── fonts.nix
│ └── brews.nix casks.nix vp-global-packages.nix
└── aspects/ # one concern per file, all platforms
├── host-darwin.nix # melon: system defaults, nixpkgs overlays, home-manager opts
├── homebrew.nix # nix-homebrew taps + homebrew brews/casks
├── home-linux.nix # genericLinux + nixGL + nix.gc
├── packages.nix fonts.nix go.nix
├── programs.nix # direnv, bat, btop, fzf, carapace, zoxide, starship
├── git.nix gpg.nix agents.nix shell-files.nix vp-global-packages.nix
└── nvim.nix fish.nix nushell.nix ghostty.nix kitty.nix …
Resolved outputs:
darwinConfigurations.melon aarch64-darwin — nix-darwin + home-manager + nix-homebrew
homeConfigurations.elianiva aarch64-linux — home-manager standalone
homeConfigurations.elianiva@intel x86_64-linux
homeConfigurations.elianiva@asahi aarch64-linux
An aspect holds the config a single concern needs in every class it touches, e.g. aspects/packages.nix puts CLI tools in darwin.environment.systemPackages and in (Linux) homeManager.home.packages; aspects/ghostty.nix holds the config symlink, the macOS Library/Application Support symlink, and the Linux nixGL-wrapped package. Hosts/users/homes only pick aspects (den.aspects.elianiva.includes, den.aspects.elianiva-linux.includes, den.aspects.melon.includes).
Shared sources of truth:
| Concern | Defined once | Used by |
|---|---|---|
| CLI tools & editors | aspects/packages.nix |
darwin environment.systemPackages, linux home.packages |
| Rust toolchain (fenix) | aspects/rust.nix |
same split |
| Go toolchain + dev tools (delve, golangci-lint, gofumpt) | aspects/go.nix |
same split |
| Fonts (MonaSpace, Inter, Lora, Lilex, Departure Mono, Ioshelfka, Iosevka 34.8 TTC) | _lib/fonts.nix via aspects/fonts.nix |
darwin fonts.packages, linux home.packages + fonts.fontconfig |
| Terminal configs (ghostty/kitty/wezterm) | their own aspect | both — aspects/ghostty.nix carries the nixGL wrap and the macOS Application Support symlink |
| Direnv integrations, shell programs | aspects/programs.nix |
both |
Platform extras are thin:
aspects/host-darwin.nix— macOS system defaults,nixpkgs.overlays(fenix, jj-starship),home-manager.useGlobalPkgsaspects/homebrew.nix— nix-homebrew taps +homebrewbrews/casksaspects/home-linux.nix—targets.genericLinux, nixGL,nix.gc- Darwin-only
[ iina ]and Linux-only[ pinentry-gnome3, nixGLIntel, lazydocker, zathura ]live next to the shared list inaspects/packages.nix
- Nix: Determinate Nix is assumed throughout. It ships
nixd(determinate-nixd), manages/etc/nix/nix.conf(includingnix.custom.conf), enablesflakes+nix-commandby default, and provides FlakeHub caching. Stocknixworks too, but commands below use Determinate's layout. - Git & curl: needed to clone and fetch flakes.
- Identity: default user is
elianiva(/Users/elianivaon macOS,/home/elianivaon Linux) and hostnamemelon— seemodules/_lib/identity.nixand the host/home names inmodules/hosts.nix. If your username/home differs, edit those before the first switch (or pass--impurewith an override — not recommended). - Dotfiles location:
~/.dotfilesmust remain at~/.dotfiles— configs are linked viamkOutOfStoreSymlinkto that path. Moving it breaks allxdg.configFile/home.filesymlinks until you re-switch.
Tested on Ubuntu/Debian/Fedora/Arch (x86_64-linux). For aarch64-linux, see notes at the end.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
# restart shell so /nix/var/nix/profiles/default/etc/profile.d/nix.sh is sourced
exec $SHELL -l
nix --version # should print: nix (Determinate Nix 3.x) 2.28.xDeterminate writes:
/etc/nix/nix.conf(managed, includesnix.custom.confand FlakeHubextra-substituters)/etc/nix/nix.custom.conf— yourtrusted-usersetc. (installer addstrusted-users = root <you>)/nixstore +determinate-nixddaemon
Verify daemon:
sudo determinate-nixd status 2>/dev/null || systemctl status determinate-nixd 2>/dev/null | head -n 20No manual experimental-features edit needed — Determinate enables nix-command flakes out of the box (lazy-trees as well).
# Debian/Ubuntu
sudo apt update && sudo apt install -y git curl
# Fedora
sudo dnf install -y git curl
# Arch
sudo pacman -S --needed git curlgit clone git@github.com:elianiva/dotfiles ~/.dotfiles
# or HTTPS if no SSH key yet:
# git clone https://github.com/elianiva/dotfiles ~/.dotfiles
cd ~/.dotfilesnh (nix helper) is in packages.nix so it will be available after the first switch. Bootstrap with nix run:
# From inside ~/.dotfiles
nix run home-manager -- switch --flake .#elianiva --print-build-logsWhat this does:
- Each
den.homes.<system>.<name>gets its ownpkgs:nixpkgswithallowUnfree = true+fenix+jj-starshipoverlays (modules/hosts.nix) den.aspects.packages+den.aspects.go+den.aspects.fontscontributehome.packagesthrough their Linux branchden.aspects.home-linuxenablestargets.genericLinux+nixGL(mesawrapper),nix.gc- Symlinks everything via
mkOutOfStoreSymlink, one aspect per tool —~/.config/nvim,~/.config/ghostty,fish,nushell,jjui,yazi, etc. all point into~/.dotfiles
First-run conflict handling: if you have existing ~/.config/fish, ~/.bashrc, etc., home-manager will error with existing file ... would be clobbered. Either back up and remove:
mv ~/.config/fish ~/.config/fish.bak 2>/dev/null; mv ~/.bashrc ~/.bashrc.bak 2>/dev/null
nix run home-manager -- switch --flake .#elianiva --print-build-logs -b bak
# -b bak tells home-manager to move conflicts to *.bak automaticallyRe-login or source the new shell:
exec $SHELL -l
# or if using fish/nushell:
# exec fish -lnh and just are now in PATH:
# rebuild after editing dotfiles
just linux
# equivalent to: nh home switch --flake .#elianiva --print-build-logs
# update flake inputs
nix flake update
just linux
# garbage collect
just clean # nh clean
nix-collect-garbage -d
# Determinate upgrade (when Determinate publishes a new Nix)
sudo determinate-nixd upgradehome-manager generations | head
ghostty --version # wrapped via nixGL.mesa on non-NixOS
fc-list | grep -i iosevka | head
gpg --list-keys
jj --version
cargo --version # fenix rustGPU (nixGL): modules/aspects/ghostty.nix wraps ghostty with nixGLIntel + targets.genericLinux.nixGL.defaultWrapper = "mesa". On non-NixOS you need Mesa/Intel drivers from the host. If ghostty fails with GL errors, try nix run nixGL -- ghostty or install host mesa-utils.
Fonts: fonts.fontconfig is enabled with defaultFonts.monospace = ["JetBrainsMono"]. All fonts from _lib/fonts.nix are in home.packages; fc-cache -f runs automatically via home-manager.
- Username/home mismatch: edit
modules/_lib/identity.nix(homeDirFor) before the first switch, otherwise home-manager creates/home/elianivawhile your actual$HOMEis different. - aarch64-linux:
modules/hosts.nixdeclaresaarch64-linuxhomes (elianiva,elianiva@asahi) and anx86_64-linuxone (elianiva@intel) — add anotherden.homes.<system>.<name>entry for a new machine.nixGLIntelis Intel-only and is already skipped onisAarch64. - Nix-managed Nix:
modules/aspects/home-linux.nixsetsnix.enable = true(home-manager manages Nix). This is intentional for standalone home-manager — on NixOS you'd disable it. On macOS,nix.enable = falsebecause Determinate manages Nix. - Docker:
lazydocker+zathuraare Linux-only extras; install Docker Engine separately (sudo apt install docker.ioetc.) — not managed by this flake. - FlakeHub 401 warning (
unable to download https://cache.flakehub.com/nix-cache-info): harmless if you haven't rundeterminate-nixd auth login. Eitherdeterminate-nixd loginor ignore —cache.nixos.org+nix-communityare still used vianixConfig.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
exec $SHELL -l
nix --versionxcode-select --install
# verify
xcode-select -p
git clone git@github.com:elianiva/dotfiles ~/.dotfiles
cd ~/.dotfilesnix-darwin needs sudo on first run to install the system profile and create /etc/nix/nix.conf integration. Determinate already manages Nix, so darwin-config.nix sets nix.enable = false.
# first time — builds darwin system + home-manager generation
sudo nix run nix-darwin -- switch --flake .
# after that, via just/nh (nh is in systemPackages after first switch)
just darwin
# equivalent to: nh darwin switch .What this does:
den.hosts.aarch64-darwin.melon→darwinConfigurations.melon, withnixpkgs.overlays=fenix+jj-starship(aspects/host-darwin.nix)den.aspects.homebrewdeclaratively tapshomebrew/core,cask,bundle,BarutSRB,onevcat(mutableTaps = false)homebrewbrews/casks frommodules/_lib/brews.nix/casks.nix(onActivation.cleanup = "zap")environment.systemPackagesfrom the darwin branch ofaspects/packages.nix+aspects/go.nixfonts.packagesfrom the darwin branch ofaspects/fonts.nix(includes Iosevka 34.8 TTC)home-manageruserelianiva=den.aspects.elianiva(every tool aspect + git + gpg), sharing the host pkgs viauseGlobalPkgs- Symlinks
~/Library/Application Support/nushelland…/com.mitchellh.ghosttyfrom the nushell/ghostty aspects, plus~/.config/*, viamkOutOfStoreSymlink
just darwin
# or: nh darwin switch .
nix flake update
just darwin
just clean
sudo determinate-nixd upgrade- Hostname: the host name (and
networking.hostName, viaden.batteries.hostname) comes fromden.hosts.aarch64-darwin.meloninmodules/hosts.nix; change it there orsudo scutil --set HostName <new>before switch. - Homebrew: managed declaratively. Do not
brew installmanually — add tomodules/_lib/brews.nix/casks.nix.mutableTaps = falsemeans manualbrew tapwill be reverted. - Rosetta:
nix-homebrew.enableRosetta = trueallows x86 brews on Apple Silicon. - Touch ID for sudo:
security.pam.services.sudo_local.touchIdAuth = true— works after first switch. - Determinate
nix.conf:/etc/nix/nix.confis owned by Determinate (!include nix.custom.conf). Do not edit directly — usenix.custom.confornixConfiginflake.nix.
| Task | macOS | Linux |
|---|---|---|
| Rebuild | just darwin |
just linux |
| Update inputs | nix flake update && just darwin |
nix flake update && just linux |
| Check flake | nix flake check |
same |
| Dry build | nix build .#darwinConfigurations.melon.system --dry-run |
nix build .#homeConfigurations.elianiva.activationPackage --dry-run |
| GC | just clean |
same |
| Edit identity (user/home/host) | modules/_lib/identity.nix + modules/hosts.nix |
same |
| Add CLI tool | modules/aspects/packages.nix |
same (shared) |
| Add font | modules/_lib/fonts.nix |
same |
| Add macOS-only package | modules/aspects/packages.nix (mkDarwin) |
— |
| Add Linux-only package | — | modules/aspects/packages.nix (mkLinux) |
| Add a tool/config | new file in modules/aspects/ + add it to den.aspects.elianiva.includes (modules/user.nix) |
same |
| Add a machine | den.hosts.<system>.<host> (modules/hosts.nix) |
den.homes.<system>.<name> |
| Add brew/cask | modules/_lib/brews.nix / casks.nix |
n/a (use nixpkgs) |
existing file … would be clobbered on first switch — backup or use -b bak:
nix run home-manager -- switch --flake .#elianiva -b bak
sudo nix run nix-darwin -- switch --flake . -b bakattribute 'aarch64-darwin' missing for ioshelfka — _lib/fonts.nix already guards with if ioshelfka.packages ? system then ... else []. If you add a new font flake, guard similarly.
error: Path 'modules/…' is not tracked by Git — git add modules/… (Nix only sees git-tracked files for flakes; modules/_lib is intentionally not imported as modules, but its files still need to be tracked because aspects import them).
command not found: nh before first switch — expected. Use nix run nixpkgs#nh -- home switch --flake .#elianiva or nix run home-manager -- switch ... for bootstrap.
Linux ghostty GL errors — ensure nixGLIntel matches your GPU. For AMD/Generic Mesa: change targets.genericLinux.nixGL.defaultWrapper = "mesa" is already set; for NVIDIA use nixGLNvidia.
Home not at ~/.dotfiles — re-clone to ~/.dotfiles, or change the dotfiles field produced by modules/_lib/identity.nix and the ${config.home.homeDirectory}/.dotfiles paths used by the tool aspects.
Personal dotfiles — no license, use at your own risk.






