I’m trying to figure out how to properly use agenix for users.users.<name>.passwordFile
on a fresh install with flakes. I ran into a chicken-and-egg problem with the password and the ssh keys when I tried to add this to the draft config I’ve been learning in.
I’ve pruned and sanitized my draft config and posted it here on github. The main
branch uses passwordFile
without agenix. It’s not as fast or polished as nixos-up
, but it has LUKS, and I’m experimenting with darling erasure.
My goal is to get to a (fairly) minimal example, without a lot of wrappers, on how to bootstrap a new system using agenix for secret management, while keeping the LUKS and darling erasure components. Then I may revise to use ragenix, and compare with sops-nix.
I’ve come up with one potential solution while pruning the example to share, so I’ll start adding agenix in another branch, step-by-step.
In the meantime, if anyone can point me to a working example, or has other advice on how to improve the config, please let me know.
3 Likes
My most recent effort at adding secrets with agenix
is in the agenix branch now.
-
ed8550c I added agenix
as an input, and included it as an installed package in the live iso and the installed system
-
a4ef773 On my development machine, I followed the agenix tutorial and:
- generated two new
ed25519
keys without passphrases – one for the user and the other for the systemssh-keygen -t ed25519 -f /tmp/.ssh/nix/flynn/id_ed25519 -C ""
ssh-keygen -t ed25519 -f /tmp/.ssh/nix/encom/id_ed25519 -C ""
- added
secrets.nix
with those keys specified to decode hashedPassword.age
- edited the secret file using:
nix run github:ryantm/agenix -- -e "hashedPassword.age" -i /tmp/.ssh/nix/flynn/id_ed25519
and pasted in the hashed password output of:mkpasswd -m sha512crypt | xclip -sel clip
- added both
secrets.nix
and hashedPassword.age
to the repo
- added the secret to
user/flynn/default.nix
- changed
users.users.flynn.passwordFile
to config.age.secrets.hashedPassword.path
instead of the earlier out-of-band hashed password file
-
Then I boot into the live iso, connect the network, and copy the keys from my development machine to /root/.ssh
on the live iso.
- I also tried by copying the keys to the
nixos
user of the iso, but don’t expect that to work because nixos-install
needs to be run with sudo
or as root
.
Unfortunately, agenix
gets an error from rage
during nixos-install
, which prevents decryption, so /run/agenix/hashedPassword
does not exist and the user flynn
does not have a password set in the resulting system.
complete error information:
[nixos@nixos:~]$ sudo nixos-install --flake github:bluesquall/tabula-rasa/agenix#encom --no-root-password
copying channel...
building the flake in github:bluesquall/tabula-rasa/8f0a004a1abf7e7e94c7df0429fe99794542cc78...
installing the boot loader...
[agenix] symlinking new secrets to /run/agenix (generation 1)...
[agenix] decrypting root secrets...
decrypting '/nix/store/mk50w869fvji6x7qh0mff4z469xyx7hf-hashedPassword.age' to '/run/agenix.d/1/hashedPassword'...
Error: No such file or directory (os error 2)
[ Did rage not do what you expected? Could an error be more useful? ]
[ Tell us: https://str4d.xyz/rage/report ]
chmod: cannot access '/run/agenix.d/1/hashedPassword.tmp': No such file or directory
chown: cannot access '/run/agenix.d/1/hashedPassword.tmp': No such file or directory
mv: cannot stat '/run/agenix.d/1/hashedPassword.tmp': No such file or directory
Activation script snippet 'agenixRoot' failed (1)
warning: password file ‘/run/agenix/hashedPassword’ does not exist
[agenix] decrypting non-root secrets...
setting up /etc...
Copied "/nix/store/cfhpzlarbhfw3scj91dcz5ai04ayfzik-systemd-249.7/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/systemd/systemd-bootx64.efi".
Copied "/nix/store/cfhpzlarbhfw3scj91dcz5ai04ayfzik-systemd-249.7/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/BOOT/BOOTX64.EFI".
Random seed file /boot/loader/random-seed successfully written (512 bytes).
Not installing system token, since we are running in a virtualized environment.
Created EFI boot entry "Linux Boot Manager".
installation finished!
cool tricks:
- Instead of cutting onto the clipboard from another terminal, if
EDITOR=nvim
, you can generate the password using :r! mkpasswd -msha512crypt <passwd>
and wipe that entry from the vim command history with :call histdel(":", "mkpasswd")
.
1 Like
Probably not surprising, but the branch using ragenix
runs into the same error.
Along a different path, it seems like I got sops-nix
to work in this branch. There was a hint that perhaps the keys need to be on the root subvolume due to boot & build ordering. I’m not sure whether that applies to (r)agenix
as well, but I’ll look into it when I get time to circle back.
Revising the sops-nix branch to enable darling erasure was a bit complicated, but eventually very simple. The exercise actually makes me question if there’s any system state that I would want to persist through boots that isn’t:
- required for bootstrapping in the first place (or almost required)
- a secret that sops-nix or agenix should track
- a non-secret that can be plaintext in the config
(Note that I don’t consider /home
to be system state, so it is on a different subvolume that won’t be wiped by darling erasure.)
It seems impossible to use the same flake for the initial build and for subsequent rebuilds, unless you set everything you want to persist from the start. This effectively makes it necessary information for bootstrapping.
Since I couldn’t make sops-nix happy with the private keys on a separate subvolume, I had to put them on the root subvolume & take a snapshot of it with the minimal files required to bootstrap from. This makes the root-blank
snapshot and the persist
subvolume unnecessary.
I’ll circle back to the (r)agenix approach with this perspective shift after I’ve experimented a bit more with the working sops-nix branch.
This was actually due to a problem with re-keying the secrets file when I switched over from bootstrapping with a user’s age
key to bootstrapping with a pre-generated ssh-ed25519
host key.
I assumed that adding the age
public key derived from the pre-generated ssh-ed25519
host key to .sops.yaml
and then editing the secret with sops -e path/to/secrets.yaml
would encode the secret for the new public key, but it turns out that you need sops updatekeys path/to/secrets.yaml
to re-key.
Once that was fixed, using sops.age.sshKeyPaths = [ "/persist/etc/ssh/ssh_host_ed25519_key" ];
worked just fine.
The perspective shift still applies, though, so I’ll continue to evaluate my alternate approach that uses a bootstrapped snapshot of root rather than symlinking from a separate subvolume.
Looks like both agenix and ragenix now work with the host key. I’ll revisit sometime later with the user key.
In the meantime, the live system iso includes agenix
as a program so that you can re-key the secrets if you have the user key.
1 Like