Thereās an effort to upstream this to nixpkgs. This is linked in the post above as well, just thought it might be worth highlighting that this isnāt tied to clan or so. Thanks for your work on this!
Soā¦
- I love this and I think will single-handedly solve NixOSā secrets issues
- How can I start using it?
This might be my inexperience with flake-parts, but it doesnāt look like the module is exposed unless I fully buy into clan (not that I dislike it, seems like a cool project, just doesnāt suit my needs):
- clan-core/flake.nix at main - clan-core - gitea: Gitea Service
- clan-core/flake-module.nix at main - clan-core - gitea: Gitea Service
⦠unless flake-parts magically includes the default.nix
, at which point it looks like it needs other parts of clan to function?
Is it a case of waiting for the PR/forking nixpkgs so I can get in on the action early?
How does this avoid copying secret files into the /nix/store in multi-user deployments? Furthermore, does this scheme only work for NixOS module attributes that require a secret by path-string? How would you address modules that cannot use such a measure for secrets, or is that even a goal?
That is indeed a good question. I guess for testing purposes I could move parts of the draft PR into an external repo/flake so people can easier test it. It will duplicate some work on my side and maybe delay the upstreaming a bit, so not sure that is the right call here.
But as Iām currently travelling I didnāt had as much time as I wanted to finish the upstreaming effort, so doing a one day push to externalize it could gather good feedback to continue the upstreaming when I have more time again.
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.
Interesting. I have two somewhat weird kinds of secrets and I wonder how would they ā if at all ā fit into this.
The first one is encrypted-at-rest secrets that go into the initrdSecrets
attribute ā I handle them currently with sops-nix
, but the downside is that they are available during all the uptime of a machine, because as far as I know there only exists a way to scope them to a systemd serviceās lifetime and not to runtime of an arbitrary command, like nixos-rebuild
(or otherwise have them be queried with the secret append script, maybe via some socket injected into the sandbox or something).
The second one is a stage1 keyfile secret I use for my LUKS setup ācurrently I have a hacky socket-activated service that asks for the pasphrase using systemd-ask-password
and sends the decrypted keyfile via the socket (if you specify a domain socket as a keyfile in the crypttab
it will use it to retrieve the key).
I know such things are probably out of scope for now (I think you explicitly called out stage1 in the PR), but do you think it might make sense to support both eventually? Iāve been thinking about turning my ad-hoc hacks into a proper tool, but if youāre planning to even upstream this, then maybe it makes sense to implement Yet Another Nix Secret Tool and maybe instead support those kinds of secrets in Vars? Well, at least at some point, given that it would require implementing some way to provide the secrets on demand and also at initrd build time and during stage1 first.
We do actually support initrd secrets already in clan: clan-infra/initrd-networking.nix at 2f6ca0cb85b892d4998fdf381b8885dadfe2e3b1 - clan-infra - gitea: Gitea Service and also for disko: clan-infra/disko.nix at 2f6ca0cb85b892d4998fdf381b8885dadfe2e3b1 - clan-infra - gitea: Gitea Service
I think systemd-exec
with the correct properties can achieve this?
I see. That said, my configs predate either of those ā is this something you can integrate easily into existing configs, or do you have to buy into Clan wholesale? Donāt get me wrong, itās certainly an interesting project, but moving your whole homelab infra over to something new would be a big project (especially if Iām not sure I can even set up everything the same way).
I guess at worst I can always install Clan into a VM and explore the limitations that way?
Did you mean: systemd-run
? But yeah, that sounds like a way simpler solution than having some kind of a daemon you query via a socket shuttled into the sandbox, Iāll try to experiment with it, thanks ;ā ) That said, part of the problem is that it seems sops-nix
doesnāt allow you to decrypt certain secrets on-demand, but thatās also probably simpler to bolt onto it than implement my initial idea.
I created now a flake for people that want to test it outside of clan, itās not tested deeply yet. Will be happy for issues/PRs which I can integrate into the PR again
I share the same excitement @TLATER does. Huge thanks to the Clan team for having worked on this, and to @lassulus for taking the time and effort to patiently upstream this (and going out of his way to have an external flake repo for easier testing!); this is spectacular work. Canāt wait to see where this goes once merged!
This looks very cool! It reminds me a lot of agenix-rekey, which is another great tool on top of agenix that Iāve been using to manage all my secrets. I think the store back end opens up even more flexibility for getting things like Vault secrets. Iāll definitely have to consider the cost-benefit of switching to this.
I believe is built atop agenix-rekey. See https://github.com/NixOS/nixpkgs/pull/370444#issuecomment-2569950304
vars
is inspired by previous projects, like sops-nix
, and agenix-rekey
, however itās really just an interface. vars
is not built upon some existing secrets management solution, and is agnostic to how secrets are encrypted, stored, and decrypted.