Caveat emptor: I’ve not contributed to any of this, and my assessment may be mildly inaccurate. I’ve only read the code (and not deeply enough to review it yet, was just checking to see if I could try it, after the blog post resonated incredibly well with me).
So the really cool thing about this is that it completely abstracts where the secrets are stored. I’ve been theorizing about a module like this for years now, and I’m delighted to see someone actually went and did it before my lazy ass got to it; and in a much more featureful way than I ever imagined, to boot.
Rather than thinking about secrets storage, vars just defines a very flexible interface for defining a way to create a secret, and maps it to arbitrary config. attributes so that you can easily use the resulting paths in your NixOS config (like what sops-nix and agenix do). The secrets can be created with arbitrary bash snippets - which are not executed by nix, they are collated into a bigger script that runs at runtime - and the snippet can be empty, so you can map secrets you need to ensure by other means - say, SSL certs - too. It even offers a prompting feature so you can type out passwords at deployment time if you so wish (and I imagine it’ll tell you if a secret is missing at runtime if you neither set a generator nor prompt, but I’ve not asserted that yet).
We can then define arbitrary “backends” to define where the secrets should be stored. The draft PR includes a backend which just stores them on a path on the host (i.e., not in the nix store, this is just a random directory). Clan also has backends for sops, pass, and some others which I don’t fully understand.
Imagine the possibilities!
This is incredibly awesome; at a glance it looks flexible enough to bridge the gap between NixOS config and all kinds of secrets backends. I can imagine AWS key stores, hashicorp vault or whatever with some effort, and I’ll probably hook it up to the systemd credentials store. It also enhances the functionality offered by sops-nix/agenix by providing a nice way to handle non-secret data you don’t want to paste plaintext into config with a separate store, which is very handy for e.g. public keys.
IMO this solves the #1 problem NixOS has with secrets: Most users don’t actually need encryption, they just need to not store secrets in the nix store, but figuring out encryption is simply too much effort for many. With this I’d be able to just point such folks at the on-machine backend and not have to send them into the rabbit hole of pgp/age.
But it also serves as a generic implementation of almost everything sops-nix/agenix actually do (besides, the actual storage/decryption work), so we can stop having multiple secrets management tools that duplicate practically the same couple thousand lines of module code, and expand on them with the myriad of other backend offerings without having to rewrite that again. Hell, this already offers backends much more suited for e.g. home-manager.
Just imagine what we could do if we pushed this generic interface to systemd-creds integration, all our modules could correctly use systemd to provision their secrets. No other distro even comes close to that level of integration, hell, show me corporate entities that actually manage all their secrets with kernel-level memory protection - I have yet to work with any, at any rate, despite occasional regulatory requirements to do so.
If somehow you couldn’t tell, I’m incredibly excited about the possibilities of this.
Much like sops-nix and agenix it lets you change the permissions of the secrets exposed by the store, so this isn’t a problem.
Yes, like all secrets management on NixOS. I’m aware that there are modules which just expose config files that want secrets to be stringly encoded into them. However:
- This is an anti-pattern from upstream. Open issues upstream whenever you see this.
- This is an anti-pattern in nixpkgs. Where upstream doesn’t want to allow importing from files (or at least environment variables, even if those have their issues too), module authors should place a generator in-between you and the generated configuration that substitutes out secrets.
There’s no other way around this, and there can inherently not be one, because anything else just exposes secrets in configuration files. Other NixOS extensions you may have seen just generalize the latter approach, there’s nothing stopping you doing this downstream when a module author was lazy, and we should fix instances of that in nixpkgs.
There is nothing like that in the module, and see the above for my (again, not the authors’) opinion on that.