Hi, I’ve painted myself into a corner and I can’t seem to get out. I’ve created an age file for use with msmtp
, but I can’t figure out how to actually use it. I don’t use flakes so everything I’m trying to do is within configuration.nix
. Here’s what I’ve hobbled together so far:
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
<home-manager/nixos>
<agenix/modules/age.nix>
];
age = {
secrets = {
msmtp.file = "/home/michael/.secrets/msmtp.age";
};
identityPaths = [ "/home/michael/.ssh/id_ed25519" ];
};
programs.msmtp = {
enable = true;
accounts = {
default = {
auth = true;
tls = true;
tls_starttls = false;
...
passwordeval = "$(cat ${config.age.secrets.msmtp.path})";
};
};
};
Previously, I had my password stored as plaintext, and the passwordeval line in the msmtp
section looked like this:
passwordeval = "cat /home/michael/.secrets/smtp.txt";
Sending email worked just fine using that plaintext method, but I can’t seem to get it to work using the age file. All I want to do is keep my password secret using agenix and then call it up from within msmtp
. Can anyone tell me what I’m doing wrong?
EDIT: The error I’m getting is:
cat: /run/agenix/msmtp: Permission denied
sendmail: cannot read output of '$(cat /run/agenix/msmtp)'
Can passwordeval do command substitution with “$()”? I use sops and the two differences for me is the command substitution and I use an absolute path to cat:
passwordeval = "${pkgs.coreutils-full}/bin/cat ${config.sops.secrets."email/password".path}";
Actually, I missed the permission denied error. I think msmtp makes a user, and secrets are only readable by root by default. You likely need to do this:
age = {
secrets = {
msmtp = {
file = "/home/michael/.secrets/msmtp.age";
owner = "root";
group = config.users.groups.sendmail.name;
mode = "0440";
};
};
identityPaths = [ "/home/michael/.ssh/id_ed25519" ];
};
Thanks for the response! I have to admit I don’t understand the differences between ${}
and $({})
, so I’m probably grossly misusing it.
When I updated my passwordeval
line to resemble yours, my error messages changed to:
/nix/store/ab5hdxr437ng76bayc5r3crfwm3yds9r-coreutils-full-9.3/bin/cat: /run/agenix/msmtp: Permission denied
sendmail: cannot read output of '/nix/store/ab5hdxr437ng76bayc5r3crfwm3yds9r-coreutils-full-9.3/bin/cat /run/agenix/msmtp'
I also added the extra age.secrets.msmtp
details you recommended, but nixos-rebuild
keeps throwing an error about the group
attribute:
error: attribute 'sendmail' missing
90| group = config.users.users.sendmail.group;
| ^
For grins I edited the group line as:
group = "root";
I made it through the rebuild that time, but I still got the same permissions errors as before.
I just figured it out. According to the NixOS wiki entry on msmtp
:
Note that msmtp has no daemon and runs as the invoking user. If using passwordeval
, the file must be readable by any user that wishes to send mail.
So that gave me the idea to change the owner
and group
declarations to:
owner = "michael";
group = "users";
And voila, it works. Thanks @ttamttam1 for pointing me in the right direction!
1 Like
Glad you figured it out! I must have made a sendmail group on my own when I set it up and forgot about it.
And for reference $()
is a command substitution that happens at the shell level (or runtime). It replaces the contents with the output of the command. ${}
is a nix thing where the contents get replaced with the nix expression at evaluation time. $()
means nothing special in the nix expression language itself, but you’ll see it a lot because in shell scripts that are configured with nix.
1 Like