Agenix encrypted plaintext passwords and `builtins.readFile`

I am in the progress of transitioning my nixos configuration to agenix. Unfortunately, agenix is geared towards passwordFile options and many modules do not have those yet. So I am using password = lib.strings.removeSuffix "\n" (builtins.readFile config.age.secrets.password.path); to read the password that I encrypted with age beforehand. This causes two issues:

  1. I have to rebuild my system with the plaintext password first for the decrypted file to be generated with agenix
  2. I have to use --impure because the decrypted file is not part of the configuration repo

Does this cause any other issues that I am not seeing at the moment? And more importantly: is there a better way to do this? Thanks for your time and effort!

4 Likes

Does this cause any other issues that I am not seeing at the moment?

I’m not sure if readFile will corece the contents to a store path, so you’re likely coping an unprotected password into global read territory.

3 Likes

I think your best bet is to go upstream and see if you can add options that do this correctly instead, and to look for alternatives where this is not an option at all.

Keep this in mind if you do: NixOS modules: Secrets provided in arguments are exposed to unprivileged users · Issue #156400 · NixOS/nixpkgs · GitHub

3 Likes

jonringer is right. This is not how agenix is intended to be used, you are breaking almost all of its security by doing it, and you are breaking all of its ergonomics too.

What module are you trying to add a password for? Maybe we can help you figure out an alternative way of doing it.

3 Likes

Thanks for your replies, this is along the lines what I expected… :smiley:

The fact that passwords are readable in the nix store does not affect me, I and all other users that have access to the machines are trusted (have sudo access). I wanted to encrypt secrets so I can open source my nix config, I guess for the moment I am better of with something like git crypt…

The modules are: borgbackup, minecraft (rcon password), teamspeak, terraria, and some custom systemd units that I have. After following the link provided by @TLATER I found a lot of information regarding those issues. It seems like systemd provides the LoadCredential directive as of recently. Unfortunately, this is not used throughout a lot of nix modules at the moment because it is not available in ExecStartPre and many people would like to use it there to patch configuration files (as far as I understood). Also, this requires support in the upstream package or a wrapper script. I am just recapping for myself, you all know this already I guess…

I am not sure what the best way forward is: wrapper scripts would not hide the command line parameters of a program and thus the password, not all software is able to read passwords from files. Would it make sense to patch nixos modules to include the config file password replacement in the ExecStart already and move that to ExecStartPre once it is available there?

Thanks again for your time and effort :slight_smile:

1 Like

borgbackup has encryption.passCommand. So you can do:

encryption.passCommand = "cat ${config.age.secrets.borgPassword.path}";

I don’t see anything for Terraria or Minecraft unfortunately. What’s the password option for teamspeak?

Ah, thanks. Terraria does support reading its configuration from a file, that would hide the password on the command line but require preprocessing/creating the configuration file. Teamspeak creates a token that is readable in the systemd log that you then need to enter into the client, so there is no need for agenix, sorry I forgot that.

Would it make sense to change the terraria nixos module to include the generation of the configuration file? I think there I could read the content from the agenix encrypted file and paste it into the config file. It seemed to me like some PRs are waiting for RFE: credentials loaded with LoadCredential should be available to ExecStartPre too · Issue #19604 · systemd/systemd · GitHub do you know why or is that not the case?

1 Like

I think that would be very cool. There’s an open issue asking for exactly that: Provide options for storing secrets outside the Nix store · Issue #24288 · NixOS/nixpkgs · GitHub. Given the maintainers haven’t gotten around to it in 5 years, I think it’s fair game :slight_smile:

1 Like

Another alternative is putting a placeholder into the config file:

Then using an activation script to substitute the placeholder for a real agenix secret.

5 Likes