Imagine you could share bits of your dotfiles with coworkers. Not technically isolated bits like, "my bash profile," but topical bits, like "my vault configuration." It might set some variables, download some files, install a peculiar version of a package.
This is possible with Nix, a functional language for describing and composing packages. In Nix, my dev environment config is just a package composed of a bunch of other packages, such as Docker and OpenJDK 11.
I can configure Nix in interesting ways. I want a boring stable version of Docker but a bleeding edge version of Kakoune with some custom patches. Nix allows me to write and install an overlay which modifies or replaces a package in the main repository. Then, I get the Docker and Kakoune versions I want, but also other packages that want these things depend on my modified versions.
An Example of Sharing Derivations
Overlays are powerful. I’ve started a private overlay repo for work that has pre-configured packages for daily life there.
We use Vault. To configure Vault, you normally
need to edit your .bash_profile
and set VAULT_ADDR
to the address
of the correct server. You also need to download a CA certificate
from somewhere, put it somewhere on your system, and set VAULT_CACERT
to its path. After that, vault works.
While there are ways to set environment variables with nix-darwin, Nix
has interesting ideas about how to compose software packages that tell
us to do this differently: We replace the vault package with a wrapper
that calls the original package’s vault
program with VAULT_ADDR
and
VAULT_CACERT
set correctly [1].
After writing and sharing the overlay, other people at my work can install it and avoid configuring Vault.
Other Strategies
I’ve not gotten all the details on how to share overlays, packages, and necessary machine config hammered out quite yet. It works, but it feels like there are better ways to do it.
History: How I Got Here
My dotfiles repo contains dotfiles, but also scripts to symlink them, bootstrap my package managers, install packages, and change system settings.
It started as hand-rolled bash twiddling Homebrew and running defaults
,
but it’s always bothered me that this is a lot of work for one person.
Surely this is a common problem.
When I got a linux dev server, I found I was duplicating my config — linux package names are slightly different from Homebrew package names, and subtle differences in tooling meant the same scripts didn’t work in both places. Very annoying.
I sought a package manager that worked on both, and found Nix. In fact, I’d already used Nix a little bit to make reproducible dev environments, but it could install the same packages on Mac OS and NixOS, a different Linux or BSD, or it can create a Docker image.
Built on Nix, nix-darwin has modules for declaratively [2] configuring a Mac. NixOS is a Linux distribution configured the same way.
In short, Nix is a reproducible way to store my config, and I’ve been gradually migrating to it ever since.