Skip Navigation

Asking for guidance on managing dotfiles in a declarative and 'immutable'(/read-only) way across multiple systems

Incoming long post, please consider reading at least the following TL;DR before commenting.

TL;DR: Interested in finding the means to manage my dotfiles in a declarative, 'immutable'/read-only way and with automatic sync across two devices (and a fleet of container environments). The method shouldn't require the management of my packages.


First of all, I'm still relatively new to managing dotfiles. So far, git has been doing fine, but time has come to upgrade.

Goals: As I've moved from a non-declarative way of administrating my system to one in which some elements are declarative, it just feels appropriate to apply a touch of 'declarative-ness' to managing dotfiles as well.

Furthermore, as I've been using image-based ('immutable') distros for some time already, I want to explore the possibilities of managing dotfiles within that 'immutable' paradigm.

Specifics of my usage: The primary desire is to have it working on two systems simultaneously. If possible, changes to one should 'automatically' apply to the other and vice versa. Furthermore, the exact content of the managed dotfiles is not the same on both, so differentiation is a requirement. My container workloads can be handled by the likes of chezmoi and or yadm. Nonetheless, being able to manage their dotfiles as well is definitely a plus.

Options that I've explored and associated (potential) challenges:

  • Nix' Home Manager. From what I've gathered, this offers by default most of what I desire. However, I'm interested to know what the limitations are of managing dotfiles only as I'm not interested in installing any Nix packages. So it would have to manage the dotfiles of packages/software/whatever that weren't installed with Nix. Furthermore, to my knowledge, Nix doesn't play nice with container environments; while this is not a hard requirement, I hope to be wrong on this. EDIT: Could not find sources to back this up.
  • Guix with guix home. Unless I'm wrong, this is Guix' Home Manager. So it's met with similar challenges like those found in the previous paragraph. Furthermore, I'm interested to know if either of the two fares better than the other for my use case.
  • While chezmoi, yadm and other known dotfiles managers technically offer a solution, their respective solutions aren't declarative or 'immutable' by default. While I'm sure someone might be able to hack one of them to better fit my needs, I'm not sure if I'm personally willing to commit to that. EDIT: Apparently chezmoi is declarative. I currently wonder which other dotfiles managers I might have mistakenly dismissed for disregarding the possibility that they might be declarative. Furthermore, chezmoi seems to allow declarative control on the read-write permissions of files, which might allow restricting files to just read-only.
  • Old, trusty git. Probably furthest removed from what I desire by default, but perhaps someone knows how to make it fit regardless.

Please feel free to inform me if I've missed anything! Thanks in regards 🙂 !

EDIT: So far chezmoi has surprised me pleasantly with the possibilities it offers. But before committing, I would like to have some input from our residents that swear by Nix/Guix.


Update: It has been over 24 hours since the last time a comment was posted under this post. While I do hope to receive replies from at least two commenters eventually, I'm less optimistic on getting any replies from those that have significant experience with guix home. Though I'd love to be wrong on that.

For posterity's sake; first of all, this has been a great conversation and so I'd like to thank everyone that has contributed! Secondly, I've tried to spend a good portion of the last 24 hours to read up on the subjects that were touched upon and evaluate them accordingly. This has led to the following discoveries that might be worth sharing:

  • Ansible is a legitimately good piece of software that can be used for this purpose, even if chezmoi's author implies not to be a fan of this.
  • While Ansible applies configs 'convergent' (when done right), Nix' Home Manager is able to do so 'congruent' and does so effortlessly in the sense that -with the advent of flakes- one 'simply' does it the 'correct' way regardless (though checks and whatnot help elevate everyone to that level relatively easily). I'm not confident on how chezmoi fares compared to the other two. Refer to this article for more info on what 'convergent' and 'congruent' mean in this context. (TL;DR: "ansible will make changes to get it closer to a target state, whereas nix will reach the target state by constructing the target state again")
  • Due to the point raised in the previous bullet, (when mastered) Nix' Home Manager simply seems a far superior option compared to Ansible. Thus Ansible is dismissed in favor of Nix' Home Manager.
  • I've also come to appreciate how powerful of a tool chezmoi is. Nonetheless, I couldn't stop noticing how many people that have used chezmoi at some point in time eventually switched to Nix' Home Manager for salvation. With those that didn't stick to Nix' Home Manager being open that it was often related to not being able to get it to work gulp...
  • At this point it seems that Nix' Home Manager is the clear victor, but Guix' guix home hasn't been represented (yet). So that's what I intend to figure out before committing fully to either Nix' Home Manager or (perhaps) Guix' guix home.
  • As a final note, using any of the tools mentioned doesn't exclude the use of the other tools. Sometimes one tool just fares better in one particular task compared to the other. Thus, one should not be afraid to mix and match these to best fit their needs. As such; a setup in which Ansible, chezmoi and Nix' Home Manager are used together to manage the dotfiles is perfectly fine.

Final update: (for the foreseeable future)

  • The question how Nix' Home Manager fares against Guix' guix home didn't matter in the end 😅, but this is related to how my system works. In case it wasn't clear yet, I daily drive Fedora Silverblue. And as it stands, I'm unaware of any method that enables one to install Guix on Fedora Silverblue without putting SELinux from enforcing to permissive. I don't want to forego SELinux' enforcing mode for Guix, especially when Nix can be installed without being forced to do that. As such, I'll start my (perhaps long overdue) journey into the wonderful world of Nix. I would like to once again thank everyone that has contributed! And also thank you for reading this :P !
23 comments
  • I'm currently learning home-manager. There are some configuration options that let you define common program configurations in nix (the language). But those options are limited and might even require package installation.

    So for complex (or existing) configs withou package management, you can just tell home-manager explicitly to take dot file at path A (in a git repo, for instance) and link it to path B. This will check for overwrites too, so if path B already exists it will yell at you and no write over existing files, so no sweat.

    You can also define different profiles per machine, so if you need something different per machine home-manager can let you do that too. And since its nix, you can break out configuration files as you would in any other language to organize you dotfiles however you like.

    There might be something clever in home manager for mapping a file path in your dotfiles repo to the same directory relative to your $HOME, but it's likely you'll just explicitely write something like xdg.configFile.nvim = { source = ./neovim/init.lua; }, mapping precisely each file in your git repo to the appropriate config location.

    Let me know if you have other questions. I'm all aboard on the nixos train so I could be bias.

  • I would use nix home manager for this. Home manager has basically three separate layers. The ability to install nix packages for a user, the ability to generate config files, and special modules that combine these things things as an easy way to manage popular programs (like vim or tmux or something). You could probably just stick to the config file generation (see the xdg.configFile module).

    A big downside is that you will have to install the basic nix package manager to get home manager working. You don't have to use it to install all of your software, but it will still need a /nix and a system daemon for home manager as far as I know.

    nix doesn't play well with container environments

    I'm not sure what this means. What specific things are you trying to do with containers and nix?

    If you don't want to install a bug, complicated piece of software just to manage dotfiles, maybe you could consider Ansible? I know some sysadmin types who keep their local machine configs in Ansible. It has some nice bonus features, like deployment over ssh (nix can do this too btw).

    • A big downside is that you will have to install the basic nix package manager to get home manager working. You don’t have to use it to install all of your software, but it will still need a /nix and a system daemon for home manager as far as I know.

      It's part of the package-deal I'm willing to commit to as long as the solution suffices 🙂 .

      nix doesn’t play well with container environments

      I’m not sure what this means.

      Perhaps I should have been more precise, but I (seemed to) recall that Nix and/or Nix' Home Manager were not installable on rootless containers. Though, I failed at finding sources on this. So it might be outdated or just blatantly false (and thus a brain fart). Thus, I'll edit the OP to reflect this. Thank you for bringing this to my attention!

      What specific things are you trying to do with containers and nix?

      The final solution should also be applicable in containers. Thus I thought that Nix and Nix' Home Manager therefore required to be installed/setup within the container environments as well. I might be wrong to assume this, though*.

      If you don’t want to install a bug big (I suppose), complicated piece of software just to manage dotfiles, maybe you could consider Ansible? I know some sysadmin types who keep their local machine configs in Ansible. It has some nice bonus features, like deployment over ssh (nix can do this too btw).

      Did I understand you correctly in that you posit that Ansible is more compact, less intrusive and less complicated than Nix' Home Manager? I'm not comfortable talking about Ansible, but it seemed to me like a grand tool for complete system management (at least for on new installation). Which, honestly, is pretty cool, but seemed to be overkill for what I tried to achieve here. Though, I'd love to be wrong on this. Furthermore, is Ansible container-friendly ?

23 comments