diff --git a/default.nix b/default.nix index 3f46610..c0d3a03 100644 --- a/default.nix +++ b/default.nix @@ -140,6 +140,60 @@ in ''; }; + customMaildir = mkOption { + type = types.nullOr (types.submodule ({ name, ...}: { + options = { + uid = mkOption { + type = types.int; + example = 1000; + description = '' + User ID for files and directories in the maildir. Files and + directories created by Dovecot will be assigned this UID. + ''; + }; + + gid = mkOption { + type = types.int; + example = 1000; + description = '' + Group ID for files and directories in the maildir. Files and + directories created by Dovecot will be assigned this GID. + ''; + }; + + dovecotHome = mkOption { + type = types.str; + example = "/home/myusername"; + description = '' + Home directory for Dovecot virtual user. This is used to + maintain mail user's private state. This MUST be different + for each Dovecot virtual user and MUST be an absolute path. + Refer to the Dovecot documentation for further information + on this configuration option: + https://wiki.dovecot.org/VirtualUsers/Home + ''; + }; + + mailDirectorySpec = mkOption { + type = types.str; + example = "maildir:~/mail"; + description = '' + Dovecot mail location specification. Refer to the Dovecot + documentation for further information on this configuration + option: + https://doc.dovecot.org/configuration_manual/mail_location/ + ''; + }; + }; + })); + default = null; + description = '' + Configuration options for a custom Maildir location. For instance, + this can be used to implement home-directory Maildirs for specific + users only. If null, a Maildir under /var/vmail will be assigned. + ''; + }; + sieveScript = mkOption { type = with types; nullOr lines; default = null; diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix index 6704426..4ccebe0 100644 --- a/mail-server/dovecot.nix +++ b/mail-server/dovecot.nix @@ -102,10 +102,36 @@ let EOF cat < ${userdbFile} - ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: - "${name}:::::::" - + lib.optionalString (value.quota != null) "userdb_quota_rule=*:storage=${value.quota}" - ) cfg.loginAccounts)} + ${lib.concatStringsSep "\n" ( + lib.mapAttrsToList (name: value: let + # Space-separated "extra fields" options, appended as the 8-th element + # in a userdb entry tuple in passwd format: + # $user:$passwd:$uid:$gid:$uidinfo:$home:$shell:$extraFields + extraFieldsStr = lib.concatStringsSep " " ( + # Custom Maildir location option: + (lib.optional + (value.customMaildir != null) + "userdb_mail=${value.customMaildir.mailDirectorySpec}") + ++ + # Quota option: + (lib.optional + (value.quota != null) + "userdb_quota_rule=*:storage=${value.quota}") + ); + in ( + if value.customMaildir == null then + "${name}:::::::${extraFieldsStr}" + else + "${name}" + + ":" + + ":${builtins.toString value.customMaildir.uid}" + + ":${builtins.toString value.customMaildir.gid}" + + ":" + + ":${value.customMaildir.dovecotHome}" + + ":/run/current-system/sw/bin/nologin" + + ":${extraFieldsStr}" + )) cfg.loginAccounts + )} EOF '';