Versioning is Hard
Updates, bug fixes, performance improvements, and stability. How can we meaningfully identify software dependencies?
Put a Pin In It
Using Nix means that your equivalent of a lock file is a particular commit of the
nixpkgs repository that specifies how to build all the software you depend on (i.e. system libraries and OS components as well as libraries for the programming language you are using). What can then be challenging is the update step: you want to update a particular high-level library you directly depend on, or pull in something like an
openssl security update (remember, you’re responsible for monitoring all possible vulnerabilities because you are working from a snapshot of the entire internet), but a
nixpkgs commit that includes that update will also include updates to other things. Now you must take control of your destiny and manually import the particular update you want, ensuring that you also pull in any required dependency updates. Undertaking this personal exploration of the combinatorial space of package versions should give one pause.
Working with language-specific package sets (e.g. Stackage) here is somewhat more comfortable because it offers minor and major updates itself, and even those ride atop your system software that is presumably receiving security updates asynchronously from the libraries for your programming language. That comfort comes at a cost, though: the whole-system snapshot
nixpkgs provides is surely a better bet for reproducibility.
So where does that leave us? Probably the usual answer: we could use better tooling. Specifically, personal CI services that can provide a binary cache of whatever franken-snapshot you depend on (perhaps along the lines of hercules), and more decoupled swathes of stability. By the latter, I mean something like layering a Stackage snapshot over a stable NixOS release.