-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: implement a secret vars store in nixpkgs #370444
base: master
Are you sure you want to change the base?
Conversation
How this compares to sops-nix? |
This enhances sops-nix, It is more of an upstream evolution of agenix-rekey. The gist is: This supports declaring how to generate the secrets you store in sops-nix in nixpkgs in the service module. I will add a declaration to a service soon, so it is easier to understand :) |
alright, removed some features to make the first implementation easier. |
3f0acbe
to
339d2bc
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2025-01-08-clan-weekly-changelog/58501/1 |
This looks awesome, I'll have to play around with it a bit more to understand all the details. Have you already thought about how this would work when someone wants to use vars/secrets in the initrd in stage1? I imagine there could be some kind of hen-egg problem since the initrd will be generated pretty early on when a new generation is activated. The configured vars/secrets may probably not exist at that time, so this might require activating twice (?) |
I am curious about how it would work in stage 1 because AFAIK / is not mounted yet in this phase, so how it will read the host key to decrypt the secrets. |
The current code here doesn't run during activation but creates a script that can be run before activation. in clan.lol we solved that issue differently by having a requiredBy option which can take "activation". We would create the files necessary for activation beforehand in that case, but I think this adds too much complexity to this initial PR. Another problem is also the prompts which some vars can ask for. Having the generation run in the activation would make prompting for input very hard. So I think a better way would be to prompt in nixos-install/nixos-rebuild, so before running activation. But this is also something I will add in a later iteration :) |
This is not really in scope for this PR. The current on-machine implementation I added here, doesn't encrypt the secrets (yet?) so there should be no issue with stage-1. secrets can still be added to initrd if they are required to early boot and they should be available at that time. |
46b881c
to
b6b0bed
Compare
prompts = lib.mkOption { | ||
description = '' | ||
A set of prompts to ask the user for values. | ||
Prompts are available to the generator script as files. | ||
For example, a prompt named 'prompt1' will be available via $prompts/prompt1 | ||
''; | ||
default = { }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a value
option or something similar to each prompt? I would like to be able to pre-define the value of the prompt to ensure that a user can always opt-in to a purely declarative configuration.
Btw, I currently don't understand when an author of a nixos module would decide to utilize a prompt instead of a generated random value. If I am writing a generator for my personal configuration, I can understand that I might want to use prompt for certain things - but when would I want to use a prompt in an upstream module and force interactivity on every user?
I'm just a little worried right now that introducing prompts without a way to declaratively set their value will sooner or later result in some generators being added to nixpkgs which depend on some form of interactivity. Therefore I'd like to have a way to specify the value of a prompt ahead of time, so the generation script can then just copy the specified file to prompts/$name
instead of asking the user a question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we mainly use prompts for API keys, which we usually don't want to leak into the config. I guess we can think about pre declaring things, this would also make the testing code a bit easier which I worked on last time I touched that code. But this increases the surface every backend implementation has to take care of.
lib.types.submodule (generator: { | ||
options = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to propose an additional option for each generator called backend
, which is just an empty submodule by default and can be extended by the used backend similar to how you designed the fileModule:
backend = lib.mkOption {
type = lib.types.submodule {
imports = [
config.vars.settings.backendModule
];
};
default = {};
description = ''
Additional options for the backend in use.
'';
};
This would allow the specific backend implementation to expose additional options for each generator, allowing users who opt-in to a specific backend to use additional features of that generator:
- One example would be a generator which can both generate secrets before deploying a machine in the repository as well as on the machine to have selected vars be generated on the machine (e.g. dhparams, temporary keys, ...).
- Another example is specifying an owner/group for the generated secrets, in case they are stored in the repository (as with sops-nix/agenix) so the backend knows which key to use to encrypt a generated secret when there are multiple administrators involved in writing a single configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but I'm not sure yet what complexities this can introduce. It sounds like a good idea for a follow up PR maybe? :)
Also how do we force modules in nixpkgs to be backend agnostic? since it would be sad, if some generators use backend specific features and lock out other backends this way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also I don't think we need to use the backendModule here, defining the additional options in a new module should just work? we use the fileModule in that way, because we need to set some values in every file for a specific backend, but this wouldn't be the case here, right?
This allows to create secrets (and public files) outside or inside the nix store in a more delclarative way. This is shipped with an example (working) implementation of an on-machine storage. The vars options can easily be used to implement custom backends and extend the behaviour to integrate with already existing solutions, like sops-nix or agenix.
This allows to create secrets (and public files) outside or inside the nix store in a more delclarative way. This is shipped with an example (working) implementation of an on-machine storage. The vars options can easily be used to implement custom backends and extend the behaviour to integrate with already existing solutions, like sops-nix or agenix.
I wanted to upstream this, since we use code similiar to this in https://clan.lol now for a while. Happy to discuss it a bit more. I'm not very fond of the name vars anymore, so maybe a first change could be to come up with a better name :)
I'm not sure if this code is working yet, I will try to develop it a bit more in the next coming days, but I wanted to get this out earlier so other people can throw in some feedback already :)