Open RuRo opened 1 year ago
I'll answer your questions here, but I intend to incorporate this into the docs too eventually.
agenix
has a CLI and a NixOS module. What's the purpose of each component? It seems, that the CLI handles encryption and the NixOS module handles the decryption, but this is not clear.
This project provides a NixOS module age
for adding age-encrypted secrets into the Nix store and decrypting them on NixOS at boot or rebuild time. It also provides a commandline tool agenix
which can be used to edit and rekey the secrets and manage who can decrypt them. The documentation mostly assumes you are encrypting the secrets with your SSH keys, but all age methods can be used.
- Assuming that my understanding of (1) is correct, what does the CLI provide over plain
age
/rage
? Can I just encrypt my secrets with plainage
(or with something likegit-agecrypt
) and then decrypt them at system startup with theagenix.nixosModule
?
Yes, you can encrypt your secrets with plain age
. You need to make sure you encrypt it such that both your user and system age identities can decrypt them.
Also, the first line of the documentation seems to imply, that the NixOS module is a secondary part of the project. This seems a bit backwards to me. If my understanding is correct, the CLI would be basically useless without the NixOS module.
Correct, the module is critical and the cli is technically optional.
The tutorial suggests, that you should "Make a directory to store secrets and secrets.nix", but it is not clear
- Is creating this directory merely a suggestion, or does the NixOS module explicitly rely on this layout (even though
age.secrets.<name>.file
seems to accept arbitrary paths)?
Merely a suggestion. The module does not rely on this layout.
- Where should you create this directory? In the system flake repository? On the development machine (that will encrypt the secrets)? On the deployment machine (that will decrypt the secrets)?
I typically make the secrets directory next to my configuration. So I guess the default vanilla way would be to put it at /etc/nixos/secrets
.
- Is this directory used by the
agenix
CLI or the NixOS module, or both?
The agenix CLI uses it, in the sense that you must run the cli from a directory that contains a secrets.nix
file, but the encrypted secrets don't need to be in that directory. The module doesn't care about the secrets.nix
at all.
- The documentation states that SSH keys are supported as identity files, but GPG isn't.
age
also has its own key mechanism (AGE-SECRET-KEY-...
andage1...
). Is this type of key supported?
All default age identities are supported.
- At which point in the boot process are the secrets decrypted?
The age module's activation scripts run after the "specialfs" activation scripts, and don't finish until after the "users" and "groups" activation scripts have finished.
Add-on Q:
Currently the documentation emphasizes, re: secrets/secrets.nix
:
This file is not imported into your NixOS configuration
The bold makes me think this is an important point -- is it? It's literally just a mapping of (non-secret) public keys to filenames, I wouldn't think it would matter if it were imported to the configuration (and hence the store).
I use a flake which defines several systems; for purity this requires all referenced files to be in the git repo, so my current setup is:
flake.nix
...
secrets/secrets.nix
secrets/secret1.age
All of which will be included in my repo, which is fine because none of it is ~"secret"~ secret and unencrypted. Is that correct?
If so, I might propose some clarification that makes it explicit:
The contents of
secrets/*.age
are encrypted andsecrets/secrets.nix
are public, sosecrets
can reasonably be checked into VCS if it contains no other private files.
You need to make sure you encrypt it such that both your user and system age identities can decrypt them.
By "system identity" I assume you mean the ones specified in age.identityPaths
, but what is the "user identity" in this case and why is it needed?
Where should you create this directory? In the system flake repository? On the development machine (that will encrypt the secrets)? On the deployment machine (that will decrypt the secrets)?
I typically make the secrets directory next to my configuration. So I guess the default vanilla way would be to put it at /etc/nixos/secrets.
So, please correct me if I am wrong, the "minimal" usage with separate build/target systems would be
1) [on the build system] Encrypt some secret file foo
and store the resulting file bar.age
somewhere (inside the repo in case of flakes)
2) [on the build system] Build the NixOS system derivation with age.secrets.foo.file = ./path/to/bar.age;
(optionally set age.identityPaths = [ /custom/path/to/identity ];
)
3) [on the target system] Ensure that /etc/ssh/ssh_host_*_key
(or /custom/path/to/identity
if identityPaths
were set) exist and can decrypt bar.age
4) [on the target system] Push the derivation to target system and switch/reboot into it
Crucially, the build system doesn't need to be able to decrypt the secrets (no /etc/ssh/ssh_host_*_key
or /custom/path/to/identity
) and the target system doesn't need to have bar.age
stored anywhere (no /etc/nixos/path/to/bar.age
for example). Is this correct?
I find the current documentation to be a bit lacking. There is no link to further documentation in the
README
, so I am assuming that theREADME
is the full documentation.Here are some questions that are (imho) not fully addressed in the readme:
1)
agenix
has a CLI and a NixOS module. What's the purpose of each component? It seems, that the CLI handles encryption and the NixOS module handles the decryption, but this is not clear.2) Assuming that my understanding of (1) is correct, what does the CLI provide over plain
age
/rage
? Can I just encrypt my secrets with plainage
(or with something likegit-agecrypt
) and then decrypt them at system startup with theagenix.nixosModule
?3) The tutorial suggests, that you should "Make a directory to store secrets and secrets.nix", but it is not clear
4) The documentation states that SSH keys are supported as identity files, but GPG isn't.
age
also has its own key mechanism (AGE-SECRET-KEY-...
andage1...
). Is this type of key supported?5) At which point in the boot process are the secrets decrypted?
P.S. The
Installation
section takes up way too much space and for most users 75% of it won't be actually useful to them. Consider using<details><summary>blah</summary>contents</details>
in some parts of the documentation. Something like this:### Install via [niv](https://github.com/nmattia/niv)
First add it to niv: ```ShellSession $ niv add ryantm/agenix ``` #### Install module via niv Then add the following to your `configuration.nix` in the `imports` list: ```nix { imports = [ "${(import ./nix/sources.nix).agenix}/modules/age.nix" ]; } ``` #### Install CLI via niv To install the `agenix` binary: ```nix { environment.systemPackages = [ (pkgs.callPackage "${(import ./nix/sources.nix).agenix}/pkgs/agenix.nix" {}) ]; } ```### Install via nix-channel
As root run: ```ShellSession $ sudo nix-channel --add https://github.com/ryantm/agenix/archive/main.tar.gz agenix $ sudo nix-channel --update ``` #### Install module via nix-channel Then add the following to your `configuration.nix` in the `imports` list: ```nix { imports = [### Install via fetchTarball
#### Install module via fetchTarball Add the following to your configuration.nix: ```nix { imports = [ "${builtins.fetchTarball "https://github.com/ryantm/agenix/archive/main.tar.gz"}/modules/age.nix" ]; } ``` or with pinning: ```nix { imports = let # replace this with an actual commit id or tag commit = "298b235f664f925b433614dc33380f0662adfc3f"; in [ "${builtins.fetchTarball { url = "https://github.com/ryantm/agenix/archive/${commit}.tar.gz"; # replace this with an actual hash sha256 = "0000000000000000000000000000000000000000000000000000"; }}/modules/age.nix" ]; } ``` #### Install CLI via fetchTarball To install the `agenix` binary: ```nix { environment.systemPackages = [ (pkgs.callPackage "${builtins.fetchTarball "https://github.com/ryantm/agenix/archive/main.tar.gz"}/pkgs/agenix.nix" {}) ]; } ```### Install via Flakes
#### Install module via Flakes ```nix { inputs.agenix.url = "github:ryantm/agenix"; # optional, not necessary for the module #inputs.agenix.inputs.nixpkgs.follows = "nixpkgs"; outputs = { self, nixpkgs, agenix }: { # change `yourhostname` to your actual hostname nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem { # change to your system: system = "x86_64-linux"; modules = [ ./configuration.nix agenix.nixosModule ]; }; }; } ``` #### Install CLI via Flakes You don't need to install it, ```ShellSession nix run github:ryantm/agenix -- --help ``` but, if you want to (change the system based on your system): ```nix { environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ]; } ```