Background
I want to try out nixos-facter. I want to replace my hardware-specific option values in some configuration with usage of nixos-facter, and then examine the resulting differences. So I want the ability to compare two NixOS configurations.
Derivation-level Comparison
I did try using nix-diff on the derivations obtained via <my-configuration>.config.system.build.toplevel
and of course it did show me the changes betweeen the two derivations. Which is useful and sometimes all one needs.
But what I really want in this case, is a higher level view. A view on the changes between the configurations. Well, at least that’s what I think I want. It’s hard to tell before I take a good look at such a comparison.
What is a configuration?
To the best of my understanding, a configuration is an evaluated set of modules. For example, a NixOS configuration is obtained in such a manner:
let
evaluated = nixpkgs.lib.nixosSystem {
modules = [
oneModule
anotherModule
];
};
in
evaluated.config
Kind of.
So just serialize them and compare
Using builtins.toJSON
. Well, you can’t just do that, because:
- This value also includes functions, for some reason. So these can be filtered away or mapped to strings.
- This value also includes derivations. The attempt to serialize these results in building them. Okay, so map them to their
.drvPath
, instead. - Some values included are never evaluable, because the expressions simply always throw. For example, renamed options, I suppose. This can be worked-around using
builtins.tryEval
.
We’re stuck at attempts to access non-existent attributes
The options for some values are meant to be accessed/evaluated only when some other option has some value. For example, foo.contents
is meant to be evaluated only if foo.enable
is true
. To the effect that the value of foo.contents
is an expression that would fail to evaluated with a missing attribute error otherwise. And missing attribute errors such as {}.a
are not caught by builtins.tryEval
, it seems. And I don’t see any other Nix language feature that can handle such an error.
How to proceed?
Does anyone else want to compare configurations? Or to serialize or just deeply evaluate a configuration for some purpose? Is Nixpkgs virtually full of these options that must not be evaluated unless some other option has some value? Are we missing something?
Mentions
A previous post of mine about this
Co-authored-by @A-jay98