NixOS + GNU Stow (dotfiles)

I’m managing most of my configuration through NixOS, but I still have some user-specific dotfiles (e.g. gpg-agent.conf, ghci.conf, …), and I’ve been managing these with GNU Stow.

Stow is a tool for managing symlinks (sound familiar?). When you run it, you can specify a “stow directory”, under which the interesting files (dotfiles in my case) live. If it’s preparing to create/update a symlink at location X and it sees that X already exists, if X is a symlink pointing somewhere under the stow directory, Stow knows it’s safe to modify it, otherwise it recognizes that it doesn’t “own” X, and refuses to modify it.

I keep my dotfiles in a central location (so I can version-control them), and I wrote a script that uses Stow to manage symlinking them to the right locations.

It occurred to me to package my script and the dotfiles as a Nix package. Though NixOS wouldn’t be managing the dotfiles, it would provide an executable I can run to link everything up (the links would point at dotfiles within my package, in the nix store).

I got it working. The script resides at:


and it runs Stow with the “stow directory” set to:


I can run dots and it will symlink, for instance:

~/.ghc/ghci.conf -> ../../../nix/store/xxxxxx-nixdots/stow/ghc/.ghc/ghci.conf

If I update and rebuild my package, the store path changes:


The symlinks I previously created could become dangling links, depending on my garbage collection strategy. Worse still, if I try to run my updated script, Stow refuses to update any symlinks because it doesn’t “own” the locations they point at (they point into xxxxxx-nixdots/stow/... and Stow is running with the stow-directory set to yyyyyy-nixdots/stow).

I think it’s fair to say this is a failed experiment, but it was interesting putting it together. I know there’s ongoing work to implement declarative user configs, and I’m keeping an eager eye on it. This was just my wacky experiment.

1 Like

@ivanbrennan home-manager can basically do the exact same thing.

I keep my home-manager config in it’s own repo and add my dotfiles as a submodule.
Then you can just like

home.file.".bashrc".source = ./dotfiles/bash/bashrc;

Mind you that the source file cannot be hidden (start with a . )

But recently I’ve just done away with that because you can just put the text in it too.

home.file.".bashrc".text = ``
  stuff that would be in a .bashrc
1 Like

Yes, I keep putting off looking into home-manager. Looks like it’s got a lot of momentum and satisfied users. Gonna try it.

1 Like