From 5fdb686c66d3977da7cf9a2472d4f3b7f2e6ebea Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Fri, 20 Mar 2026 01:06:11 +0100 Subject: [PATCH] docs: improve login account options --- default.nix | 102 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/default.nix b/default.nix index 8461eb1..cc4f7a7 100644 --- a/default.nix +++ b/default.nix @@ -25,7 +25,6 @@ let inherit (lib) literalExpression literalMD - mkDefault mkEnableOption mkOption mkOptionType @@ -145,8 +144,13 @@ in options = { name = mkOption { type = types.str; + default = name; example = "user1@example.com"; - description = "Username"; + readOnly = true; + internal = true; + description = '' + The login username for this account. + ''; }; hashedPassword = mkOption { @@ -154,24 +158,33 @@ in default = null; example = "$y$j9T$vfGrwkAaXCjCEWtVNMQck1$383uIXQmn2z0hnmVAA8kwFQmjNj78.nYbvWeyNLIaP1"; description = '' - The user's hashed password. Use `mkpasswd` as follows + The hashed login password for this account. + Use `mkpasswd` to create password hashes: ``` nix-shell -p mkpasswd --run 'mkpasswd -s' ``` - Warning: this is stored in plaintext in the Nix store! - Use {option}`mailserver.loginAccounts..hashedPasswordFile` instead. + :::{note} + This is a convenience option, when your threat model allows + storing hashed secrets in the world-readable Nix store. + + Passing the hash through + {option}`mailserver.loginAccounts..hashedPasswordFile` + allows relying on filesystem discretionary access control as + another security boundary. + ::: ''; }; hashedPasswordFile = mkOption { type = with types; nullOr path; default = null; - example = "/run/keys/user1-passwordhash"; + example = "/run/keys/user1-pw-hash"; description = '' - A file containing the user's hashed password. Use `mkpasswd` as follows + The hashed login password for this account read from a file. + Use `mkpasswd to create password hashes: ``` nix-shell -p mkpasswd --run 'mkpasswd -s' ``` @@ -185,9 +198,13 @@ in inStore = false; }); default = null; - example = "/run/keys/user1-password"; + example = "/run/keys/user1-pw"; description = '' - A file containing the user's plain text password. The value will be hashed at runtime. + The plaintext login password for this account read from a file. + + :::{note} + The password is hashed before it is passed on to Dovecot. + ::: ''; }; @@ -199,9 +216,13 @@ in ]; default = [ ]; description = '' - A list of aliases of this login account. - Note: Use list entries like "@example.com" to create a catchAll - that allows sending from all email addresses in these domain. + List of additional mail addresses (aliases) that get routed to this account. + + :::{admonition} Catch-all with sending permissions + :class: tip + Configure `@example.com` to create a catch-all for this domain + that also allows sending from all addresses. + ::: ''; }; @@ -224,7 +245,12 @@ in default = [ ]; description = '' For which domains should this account act as a catch all? - Note: Does not allow sending from all addresses of these domains. + + :::{warning} + Does not allow sending from all addresses of these domains. + Use {option}`mailserver.loginAccounts..aliases` if that + is required. + ::: ''; }; @@ -266,9 +292,10 @@ in default = false; description = '' Specifies if the account should be a send-only account. - Emails sent to send-only accounts will be rejected from - unauthorized senders with the `sendOnlyRejectMessage` - stating the reason. + + Emails sent to send-only accounts will + be rejected with the reason configured in + {option}`mailserver.loginAccounts..sendOnlyRejectMessage`. ''; }; @@ -276,33 +303,38 @@ in type = types.str; default = "This account cannot receive emails."; description = '' - The message that will be returned to the sender when an email is - sent to a send-only account. Only used if the account is marked - as send-only. + The message returned to the sender for a send-only account. + + See {option}`mailserver.loginAccounts..sendOnly`. ''; }; }; - - config.name = mkDefault name; } ) ); - example = { - user1 = { - hashedPassword = "$y$j9T$y6eZ1o.IvVNfdGMAsUEvh1$6K/llP52uw2iDh4iSwtAn54/JYy7FzCcoCHmjmx00H5"; - }; - user2 = { - hashedPassword = "$y$j9T$hZ.ubq0M897Hw.znxnGG9.$14EJBoOwbwKeWt.W4vpnBPEBZC9mYz4fWI9kOCLoZf4"; - }; - }; + example = lib.literalExpression '' + { + user1 = { + # This password hash leaks into the Nix store + hashedPassword = "$y$j9T$y6eZ1o.IvVNfdGMAsUEvh1$6K/llP52uw2iDh4iSwtAn54/JYy7FzCcoCHmjmx00H5"; + }; + user2 = { + # Hashed password passed as a file + hashedPasswordFile = "/run/keys/user2-pw-hash"; + }; + user3 = { + # Plaintext password file + passwordFile = "/run/keys/user3-pw"; + }; + } + ''; description = '' - The login account of the domain. Every account is mapped to a unix user, - e.g. `user1@example.com`. To generate the passwords use `mkpasswd` as - follows + Attribute set of mail accounts. - ``` - nix-shell -p mkpasswd --run 'mkpasswd -s' - ``` + Each entry defines a mailbox and login credentials, where the attribute + name is used as the login username and optionally routed mail address. + + Use `mkpasswd` to generate password hashes. ''; default = { }; };