NixOS deployment: from push to pull

I’m maintaining several laptops and private servers. All of these machines runs NixOS.

An advantage of NixOS is that the configuration of all of these machines is described in a Git repository. To apply a change to one of these machines, I need to:

  1. modify a file in the repository
  2. deploy this change on impacted machines

For the last 7 years, I’ve been using several tools to deploy these configurations and they were mainly based on a push model (the change is pushed to machines). The NixOS ecosystem provides a lot a tools to efficiently achieve this. However, it often ended with divergences between the configuration committed in the repository and the configuration actually deployed on machines (because I forgot to commit or deploy on all machines).

In the meantime, i was contributing to a project maintaining a machine running the auto-upgrade NixOS module 1. This module periodically fetches a Git repository and deploys the configuration found in this repository. This is a pull mode deployment tool (the change is pulled by machines). I really liked how simple it was to deploy a change: edit the configuration.nix file, commit, push and observe the machine reconfiguring itself.

I’ve then been thinking about using this pattern for my other machines. But it didn’t look applicable because of these two major drawbacks:

  • live testing is hard because a commit to the main branch is required to deploy the change
  • feedback loop is slow (because i don’t want to pull a remote repository each second)

However, i think it should be possible to mitigate this two drawbacks.

Live testing changes

The deployment tool could checkout the main branch and a testing branch. When deploying the testing branch , the tool runs nixos-rebuild test to avoid updating the boot loader of the machine. This allows the user to test changes on the target machine by committing to a testing branch. (And if the configuration doesn’t work, it would still be possible to reboot.)

Improving feedback loop

The second improvement consists on fetching several Git remotes. This allows the user to have a Git remote on the local file system that can be fetched each second for a fast feedback loop.

Release of comin v0.1.0

These features have been implemented in comin, a pull mode deployment tool that I’m experimenting since several months on all my machines. I released the version 0.1.0 and a lot of more features are coming!

  1. it was actually runnning a modified version of the auto-upgrade module, but this is another story. ↩︎