A developer shares a technique for symlinking dotfiles on NixOS using systemd-tmpfiles, without relying on home-manager or additional tools.
<header>
<h1>TIL: Symlinking NixOS Dotfiles</h1>
<time class="meta" datetime="2026-05-21">May 21, 2026</time>
</header>
<p>The standard answer to managing dotfiles on NixOS is
<a href="https://github.com/nix-community/home-manager">home-manager</a>. I’ve never used it, due to two
aesthetic and one practical objection:</p>
<ul>
<li>
I avoid dependencies, especially in nix, which rivals Python in the number of approaches to
dependency management.
</li>
<li>
home-manager installs packages for the current user only, which makes sense on non-NixOS systems.
But on a single-user desktop system, I prefer having just one set of packages.
</li>
<li>
Having a source of truth for dotfiles be in nix store requires rebuilding your system to change
config, which gets in the way of Emacs-style direct tinkering.
</li>
</ul>
<p>The approach I like is storing dotfiles in the same repository as <code>flake.nix</code> / <code>configuration.nix</code>
and symlinking them in place.</p>
<p>The problem here is that NixOS seemingly doesn’t have a “native” way to say that <code>/a/b/c</code> should be
a symlink to <code>/c/d/e</code>. Or has it?</p>
<p>If you <a href="https://search.nixos.org/options?query=symlink">search options</a> for <code>symlink</code>, you’ll learn
about <a href="https://search.nixos.org/options?query=environment.etc#show=option%253Aenvironment.etc"><code>environment.etc</code></a> which allows you
to configure symlinks, but only for things in <code>/etc</code>, not your <code>~/.config</code>.</p>
<p>For the latter, you can use <a href="https://www.gnu.org/software/stow/">gnu stow</a> or some other dotfile
link manager, but the complexity of the problem of <em>just</em> managing symlinks doesn’t warrant yet
another dependency. It’s fine to do
<a href="https://github.com/matklad/config/blob/346afb44f0cc50a04b8e7008ab389a90a1dfdd0f/xtool/src/autostart.rs#L75-L105">this manually</a>.</p>
<p>But wouldn’t it be nice if this framework for declarative configuration of your system allowed you to
declaratively configure symlinks? Turns out this is possible, in roundabout way. Inaptly-named
<a href="https://www.man7.org/linux/man-pages/man8/systemd-tmpfiles.8.html">systemd-tmpfiles</a> allows
creating symlinks from a declarative config, and you can use NixOS to
<a href="https://search.nixos.org/options?channel=25.11&query=systemd.tmpfiles.rules">configure</a>
<code>systemd-tmpfiles</code> itself (thanks, <a href="https://discourse.nixos.org/t/managing-config-files-why-not-use-mkoutofstoresymlink-for-everything/77643/21">Noobz</a>!).</p>
<p>For example, if I want to symlink <code>~/dotfiles/git/config</code> to <code>.config/git/config</code>:</p>
<figure class="code-block">
<pre><code><span class="line">{</span>
<span class="line"> systemd.tmpfiles.<span class="hl-attr">rules</span> = [</span>
<span class="line"> <span class="hl-string">"L+ /home/matklad/.config/git/config - - - - /home/matklad/dotfiles/git/config"</span></span>
<span class="line"> ];</span>
<span class="line">}</span></code></pre>
</figure>
<p>No opinion at this point how this compares to a bespoke script or
<a href="https://github.com/feel-co/smfh">something more purpose-built</a>.</p>
# TIL: Symlinking NixOS Dotfiles
Source: [https://matklad.github.io/2026/05/21/symlinking-nixos-dotfiles.html](https://matklad.github.io/2026/05/21/symlinking-nixos-dotfiles.html)
May 21, 2026The standard answer to managing dotfiles on NixOS is[home\-manager](https://github.com/nix-community/home-manager)\. I’ve never used it, due to two aesthetic and one practical objection:
- I avoid dependencies, especially in nix, which rivals Python in the number of approaches to dependency management\.
- home\-manager installs packages for the current user only, which makes sense on non\-NixOS systems\. But on a single\-user desktop system, I prefer having just one set of packages\.
- Having a source of truth for dotfiles be in nix store requires rebuilding your system to change config, which gets in the way of Emacs\-style direct tinkering\.
The approach I like is storing dotfiles in the same repository as`flake\.nix`/`configuration\.nix`and symlinking them in place\.
The problem here is that NixOS seemingly doesn’t have a “native” way to say that`/a/b/c`should be a symlink to`/c/d/e`\. Or has it?
If you[search options](https://search.nixos.org/options?query=symlink)for`symlink`, you’ll learn about[`environment\.etc`](https://search.nixos.org/options?query=environment.etc#show=option%253Aenvironment.etc)which allows you to configure symlinks, but only for things in`/etc`, not your`~/\.config`\.
For the latter, you can use[gnu stow](https://www.gnu.org/software/stow/)or some other dotfile link manager, but the complexity of the problem of*just*managing symlinks doesn’t warrant yet another dependency\. It’s fine to do[this manually](https://github.com/matklad/config/blob/346afb44f0cc50a04b8e7008ab389a90a1dfdd0f/xtool/src/autostart.rs#L75-L105)\.
But wouldn’t it be nice if this framework for declarative configuration of your system allowed you to declaratively configure symlinks? Turns out this is possible, in roundabout way\. Inaptly\-named[systemd\-tmpfiles](https://www.man7.org/linux/man-pages/man8/systemd-tmpfiles.8.html)allows creating symlinks from a declarative config, and you can use NixOS to[configure](https://search.nixos.org/options?channel=25.11&query=systemd.tmpfiles.rules)`systemd\-tmpfiles`itself \(thanks,[Noobz](https://discourse.nixos.org/t/managing-config-files-why-not-use-mkoutofstoresymlink-for-everything/77643/21)\!\)\.
For example, if I want to symlink`~/dotfiles/git/config`to`\.config/git/config`:
```
{
systemd.tmpfiles.rules = [
"L+ /home/matklad/.config/git/config - - - - /home/matklad/dotfiles/git/config"
];
}
```
No opinion at this point how this compares to a bespoke script or[something more purpose\-built](https://github.com/feel-co/smfh)\.
A guide on declaratively installing NixOS over the network using tools like nixos-anywhere, with an emphasis on managing configuration files under version control.
The author shares their pride in a comprehensive Nix configuration that manages all their machines efficiently, while explaining the personal and security reasons for keeping it private.
The article identifies the problem that Nix binaries are not relocatable, causing hash changes and recompilation when the store prefix changes, and proposes using relative paths with $ORIGIN in RUNPATH to achieve relocatability without invalidating caches.
The NNN Stack combines NixOS, Niri compositor, and Noctalia shell to create a declarative, scrollable, and reproducible desktop environment, inviting users to contribute their dotfiles.