Managing NixOS Dotfiles with Flakes: Home Manager vs Stow and Where to Put flake.nix

The dotfile problem everyone hits: your config files live scattered across the filesystem, but you want them version-controlled together in one place. The classic fix is GNU Stow or a bare git repo that creates symlinks from each real location back to your dotfiles directory. That works fine on any distro.

On NixOS with Home Manager, the calculus shifts. Home Manager manages those symlinks declaratively as part of its activation, so you may not need Stow at all.

GNU Stow: what it actually does

Stow reads a package directory and creates symlinks in a target — by default the parent of the stow directory. Say your layout is:

~/.dotfiles/
  starship/
    .config/
      starship.toml

Running stow starship inside ~/.dotfiles/ creates ~/.config/starship.toml as a symlink pointing to ~/.dotfiles/starship/.config/starship.toml. Clean, automatic, predictable.

Plain ln -s does the same thing — you just write every link by hand. Stow automates the bookkeeping. For machines not running NixOS, or for files that Home Manager does not touch, Stow is a solid choice.

What Home Manager does instead

Home Manager’s home.file option lets you declare file placements directly in Nix:

home.file.".config/starship.toml".source = ./starship.toml;

When you run home-manager switch, it creates the symlink. More importantly, it tracks it — so if you remove the declaration later, the old symlink gets cleaned up automatically. Stow has no awareness of Nix activations. Home Manager does.

For XDG config paths, xdg.configFile is slightly cleaner:

xdg.configFile."starship.toml".source = ./starship.toml;

Source paths are relative to the Nix file containing the declaration. If your home.nix lives at ~/.dotfiles/home.nix and starship.toml is in the same directory, ./starship.toml just works.

Where to put flake.nix

The NixOS & Flakes Book suggests keeping flake.nix in /etc/nixos/, which means nixos-rebuild switch finds it automatically with no extra flags. Convenient. But plenty of people keep their flake elsewhere and pass the path explicitly:

sudo nixos-rebuild switch --flake ~/.dotfiles#myhostname

Keeping the flake under your home directory has a real advantage: you edit it as a normal user without sudo. The /etc/nixos/ location requires root ownership or loosened permissions, which adds friction to everyday changes.

A middle ground — and roughly what the directory listing in the original question shows — is to keep the flake in ~/.dotfiles/ and create a symlink at /etc/nixos/flake.nix pointing back to it. Then nixos-rebuild finds it automatically, and you still edit as a regular user.

A practical layout

Your current structure already makes sense. Here is a decision tree for what goes where:

  • User config files (shell, XDG apps, starship, etc.): use home.file or xdg.configFile in Home Manager. Skip Stow.
  • System-level NixOS files (configuration.nix, hardware config, service modules): keep them in your dotfiles repo and either symlink into /etc/nixos/ or reference them as inputs in your flake via nixosModules.
  • Files outside NixOS and Home Manager’s reach: that is where Stow still earns its place.

One practical gotcha with flakes: your dotfiles directory needs to be a git repo, and files must be tracked. Nix’s flake evaluation copies from the git index and ignores anything untracked. Running git add . before a rebuild saves you a confusing error early on.

The bare git repo approach

Worth mentioning because it comes up often. Some people skip symlinks entirely and use a bare git repo with the work-tree pointed at $HOME. Files sit at their real paths — no symlinks, no Stow, just git.

On traditional distros this is elegant. On NixOS where Home Manager handles activation anyway, it adds complexity without much benefit. If your whole system is Nix, let Nix own the dotfile placement too.


Similar Posts