home-manager, or: how not to yakhave


⇠ back | date: 2019-03-21 | tags: /dev/diary, nix, programming, reflections | duration: 04:07 minutes

Don't expect the bait-and-switch titles to remain forever. I just thought it was fitting for this one too 😉.

Some background

Ever since I started venturing into computer programming and using more and more tools that used dotfiles, I've been frustrated at the lack of good tools when it came to synchronising these files.

And that's not for lack of options. Either I disagree fundamentally with what I want a sync tool to do or nobody had come at the problem from the same angle as me before. This is not to bash on other projects or solutions. I know many people who are very happy with either keeping their dotfiles in a large git repo, symlinking manually, making ~ a git repo or using various tools that automate the symlink process.

The problem I had was that not all my computers were the same. As in, I didn't neccessarily want the same configs on all of them. Because this is where it becomes complicated.

I had been thinking about writing a tool to do the things I wanted to do before. Thinking back to my post about failure and limiting scope, I never started it. While making a lot of drawing board attempts, I never wrote a single line of code because I could tell that it would lead me down a dark path.

Reading about people on reddit from time to time who started their own "ansible but for dotfiles" projects that never went anywhere, I felt like I was doing the right thing by not even starting.

So nothing happened for a while. Until recently.

Enter: nix

In case you don't know it, nix is a functional programming language and pure package-manager for unix systems. Yes, that includes MacOS. There is a linux distribution built around it called NixOS which utilises nix as a package manager and configuration language heavily.

So what does pure-packaging really even mean? Have you ever had the situation where you upgraded your system and half way through something failed and now you ended up with a broken system because some of the packages had already changed while others had not?

Yea, that's what people would call "impure packaging".

With nix on the other hand this cannot happen, since packages are atomic, meaning that after something is built, it can't be changed again. Doing an update? New package. Changing a small config? New package. It means that not only can failing upgrades be seemlessly be rolled back but also that two different versions of the same library can easily be installed at the same time.

Yes, that's right: no more "DLL hell"!

Well okay so why am I fangirling about nix here? Apart from the fact that I've been dabbling with NixOS quite a bit recently, to the point where I have basically replaced all my Arch installs with NixOS now...

Enter: home-manager

You already saw it in the title of this post, but I wanted to re-introduce it. What exactly is home-manager?

It's nix, but for your userspace! Not only does it not require root permissions, meaning you can install packages just for you locally (well okay, nix can do this as well but...besides the point).

More importantly, home-manager adds modules and utilities to manage userspace configurations. Everything is sourced from ~/.config/nixpkgs/ (you can move that IIRC) which is then used to generate all your configuration files.

Config files are kept in the nix store (which is usually located at /nix) and then symlinked to their destination.

Right. Now I can practically hear you all saying: "but didn't you say you didn't like tools that just symlinked stuff?"

Well..yes, and no. Obviously symlinking a config is much nicer than having to copy them around. What I disliked about tools that symlink configs to places from some other place was that I was still responsible for manage that "other place".

With nix, I never touch the store directly. In fact you don't ever do that! Instead I edit the home.nix configuration (or sub-configs when it gets too complicated) that then take some inputs, define the outputs and nix makes sure that the configs are then where they need to be.

It gives me a single source of truth, but the best thing is that it's not a dumb source of truth: nix is a programming language! What that means is that I can dynamically adjust some config contents according to what system I'm running on, while not having to worry about keeping it all sane.

I'm really happy I didn't write my own "ansible but for dotfiles" and I think I'd recommend nobody do that (I mean...unless that's your kink - I don't judge!). But I'm even more happy of having been introduced to nix and home-manager in particular.

I'd much rather help write some re-usable modules, that other people can also take advantage of, than reinventing the wheel from scratch. Again.