Rename mailserver.loginAccounts to mailserver.accounts

The "login" prefix makes this option more confusing rather than clearer,
because what other account types are there? LDAP ones for example, but
you can login with those too, so the prefix is pointless.
This commit is contained in:
Martin Weinelt
2026-03-20 01:14:43 +01:00
parent 5fdb686c66
commit e9337b346f
16 changed files with 35 additions and 34 deletions
+10 -9
View File
@@ -136,7 +136,7 @@ in
description = "Message size limit enforced by Postfix.";
};
loginAccounts = mkOption {
accounts = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
@@ -170,7 +170,7 @@ in
storing hashed secrets in the world-readable Nix store.
Passing the hash through
{option}`mailserver.loginAccounts.<name>.hashedPasswordFile`
{option}`mailserver.accounts.<name>.hashedPasswordFile`
allows relying on filesystem discretionary access control as
another security boundary.
:::
@@ -231,7 +231,7 @@ in
example = [ ''/^tom\..*@domain\.com$/'' ];
default = [ ];
description = ''
Same as {option}`mailserver.loginAccounts.<name>.aliases` but
Same as {option}`mailserver.accounts.<name>.aliases` but
using PCRE (Perl compatible regex).
'';
};
@@ -248,7 +248,7 @@ in
:::{warning}
Does not allow sending from all addresses of these domains.
Use {option}`mailserver.loginAccounts.<name>.aliases` if that
Use {option}`mailserver.accounts.<name>.aliases` if that
is required.
:::
'';
@@ -295,7 +295,7 @@ in
Emails sent to send-only accounts will
be rejected with the reason configured in
{option}`mailserver.loginAccounts.<name>.sendOnlyRejectMessage`.
{option}`mailserver.accounts.<name>.sendOnlyRejectMessage`.
'';
};
@@ -305,7 +305,7 @@ in
description = ''
The message returned to the sender for a send-only account.
See {option}`mailserver.loginAccounts.<name>.sendOnly`.
See {option}`mailserver.accounts.<name>.sendOnly`.
'';
};
};
@@ -684,13 +684,13 @@ in
aliases = mkOption {
type =
let
loginAccount = mkOptionType {
account = mkOptionType {
name = "Login Account";
check = account: builtins.elem account (builtins.attrNames cfg.loginAccounts);
check = account: builtins.elem account (builtins.attrNames cfg.accounts);
};
in
with types;
attrsOf (either loginAccount (nonEmptyListOf loginAccount));
attrsOf (either account (nonEmptyListOf account));
example = {
"postmaster@example.com" = "user1@example.com";
"abuse@example.com" = "user1@example.com";
@@ -1714,5 +1714,6 @@ in
[ "mailserver" "ldap" "attributes" "mail" ]
)
(mkRenamedOptionModule [ "mailserver" "extraVirtualAliases" ] [ "mailserver" "aliases" ])
(mkRenamedOptionModule [ "mailserver" "loginAccounts" ] [ "mailserver" "accounts" ])
];
}
+1 -1
View File
@@ -13,7 +13,7 @@ domain ``example.com`` and send mails with any address of this domain:
.. code:: nix
mailserver.loginAccounts = {
mailserver.accounts = {
"user@example.com" = {
aliases = [ "@example.com" ];
};
+1 -1
View File
@@ -12,7 +12,7 @@ let
mapAttrsToList
;
mailAccounts = config.mailserver.loginAccounts;
mailAccounts = config.mailserver.accounts;
htpasswd = pkgs.writeText "radicale.users" (
concatStrings (flip mapAttrsToList mailAccounts (mail: user: "${mail}+:${user.hashedPassword}\n"))
);
+1 -1
View File
@@ -10,7 +10,7 @@ Limitations
Radicale since the 3.x release (introduced in NixOS 20.09) does not support
traditional crypt() password hashes any longer. To establish access for
existing :option:`mailserver.loginAccounts`, the hashing method used
existing :option:`mailserver.accounts`, the hashing method used
for ``hashedPassword`` needs to be compatible with one of the available
`htpasswd_encryption`_ methods. Such hashes can for example be created using
+1 -1
View File
@@ -21,7 +21,7 @@ NixOS 26.05
is an alternative to hashed passwords that integrates well with workflows
established by `agenix`_/`sops-nix`_ that instead rely on encryption. This
option prevents files from leaking in to the Nix store.
See :option:`mailserver.loginAccounts.<name>.passwordFile`.
See :option:`mailserver.accounts.<name>.passwordFile`.
- LDAP setups require a migration of Dovecot home directories to
`UUID based home directories`_. The exact UUID attribute can be customized
through :option:`mailserver.ldap.attributes.uuid`.
+1 -1
View File
@@ -38,7 +38,7 @@
# A list of all login accounts. To create the password hashes, use
# nix-shell -p mkpasswd --run 'mkpasswd -s'
loginAccounts = {
accounts = {
"user1@example.com" = {
# Reads the password hash from a file on the server
hashedPasswordFile = "/a/file/containing/a/hashed/password";
+4 -4
View File
@@ -51,12 +51,12 @@ rec {
builtins.toString (mkHashFile name value.hashedPassword)
else
value.passwordFile
) cfg.loginAccounts;
) cfg.accounts;
# Collect accounts with plain text passwords that require hashing
accountsWithPlaintextPasswordFiles = lib.filter (
name: cfg.loginAccounts.${name}.passwordFile != null
) (builtins.attrNames cfg.loginAccounts);
accountsWithPlaintextPasswordFiles = lib.filter (name: cfg.accounts.${name}.passwordFile != null) (
builtins.attrNames cfg.accounts
);
# Appends the LDAP bind password to files to avoid writing this
# password into the Nix store.
+3 -3
View File
@@ -115,7 +115,7 @@ let
umask 077
for f in ${
builtins.toString (lib.mapAttrsToList (name: _: passwordFiles."${name}") cfg.loginAccounts)
builtins.toString (lib.mapAttrsToList (name: _: passwordFiles."${name}") cfg.accounts)
}; do
if [ ! -f "$f" ]; then
echo "Expected password hash file $f does not exist!"
@@ -131,7 +131,7 @@ let
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' pkgs.dovecot "doveadm"} pw)"}::::::"
else
"${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
) cfg.loginAccounts
) cfg.accounts
)}
EOF
@@ -141,7 +141,7 @@ let
name: value:
"${name}:::::::"
+ lib.optionalString (value.quota != null) "userdb_quota_rule=*:storage=${value.quota}"
) cfg.loginAccounts
) cfg.accounts
)}
EOF
'';
+4 -4
View File
@@ -51,7 +51,7 @@ let
to = name;
in
map (from: { "${from}" = to; }) (value.aliases ++ lib.singleton name)
) cfg.loginAccounts
) cfg.accounts
)
);
regex_valiases_postfix = mergeLookupTables (
@@ -62,7 +62,7 @@ let
to = name;
in
map (from: { "${from}" = to; }) value.aliasesRegexp
) cfg.loginAccounts
) cfg.accounts
)
);
@@ -75,7 +75,7 @@ let
to = name;
in
map (from: { "@${from}" = to; }) value.catchAll
) cfg.loginAccounts
) cfg.accounts
)
);
@@ -127,7 +127,7 @@ let
# denied_recipients_postfix :: [ String ]
denied_recipients_postfix = map (acct: "${acct.name} REJECT ${acct.sendOnlyRejectMessage}") (
lib.filter (acct: acct.sendOnly) (lib.attrValues cfg.loginAccounts)
lib.filter (acct: acct.sendOnly) (lib.attrValues cfg.accounts)
);
denied_recipients_file = builtins.toFile "denied_recipients" (
lib.concatStringsSep "\n" denied_recipients_postfix
+3 -3
View File
@@ -86,7 +86,7 @@ let
rm "${sieveDirectory}/${name}/default.svbin"
fi
''
) (map (user: { inherit (user) name sieveScript; }) (lib.attrValues loginAccounts))}
) (map (user: { inherit (user) name sieveScript; }) (lib.attrValues accounts))}
'';
in
{
@@ -102,14 +102,14 @@ in
]
) == 1;
message = "Login account ${acct.name} must provide exactly one of password file, hashed password, or hashed password file";
}) (lib.attrValues loginAccounts);
}) (lib.attrValues accounts);
# warn for accounts that specify both password and file
warnings =
map (acct: "${acct.name} specifies both a password hash and hash file; hash file will be used")
(
lib.filter (acct: (acct.hashedPassword != null && acct.hashedPasswordFile != null)) (
lib.attrValues loginAccounts
lib.attrValues accounts
)
);
+1 -1
View File
@@ -25,7 +25,7 @@ f = open(sys.argv[1])
options = json.load(f)
groups = [
"mailserver.loginAccounts",
"mailserver.accounts",
"mailserver.x509",
"mailserver.dkim",
"mailserver.srs",
+1 -1
View File
@@ -77,7 +77,7 @@
];
virusScanning = true;
loginAccounts = {
accounts = {
"user1@example.com" = {
hashedPassword = "$6$/z4n8AQl6K$kiOkBTWlZfBd7PvF5GsJ8PmPgdZsFGN1jPGZufxxr60PoR0oUsrvzm2oQiflyz5ir9fFJ.d/zKm/NgLXNUsNX/";
aliases = [ "postmaster@example.com" ];
+1 -1
View File
@@ -66,7 +66,7 @@
};
dmarcReporting.enable = true;
loginAccounts = {
accounts = {
"user1@example.com" = {
hashedPassword = "$6$/z4n8AQl6K$kiOkBTWlZfBd7PvF5GsJ8PmPgdZsFGN1jPGZufxxr60PoR0oUsrvzm2oQiflyz5ir9fFJ.d/zKm/NgLXNUsNX/";
aliases = [ "postmaster@example.com" ];
+1 -1
View File
@@ -87,7 +87,7 @@ in
];
localDnsResolver = false;
loginAccounts = {
accounts = {
"user1@example.com" = {
hashedPasswordFile = hashedPasswordFile;
};
+1 -1
View File
@@ -133,7 +133,7 @@ in
"frank@example.com" = "mallory@example.com";
};
loginAccounts = {
accounts = {
# Colliding local account takes precedence over LDAP account with
# same address.
"carol@example.com" = {
+1 -1
View File
@@ -35,7 +35,7 @@ let
fqdn = "mail.${domain}";
domains = [ domain ];
localDnsResolver = false;
loginAccounts = {
accounts = {
"user@${domain}" = {
hashedPasswordFile = hashPassword "password";
};