From 0da7a14f16ad150a28bf50fb2f11797f9c5c4456 Mon Sep 17 00:00:00 2001 From: Symphorien Gibol Date: Tue, 31 Dec 2019 12:00:00 +0000 Subject: nixos/dovecot: add an option to enable mail_plugins Motivation: if enableQuota is true, mail plugins cannot be enabled in extraConfig because of the problem described here: https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion doveconf: Warning: /etc/dovecot/dovecot.conf line 8: Global setting mail_plugins won't change the setting inside an earlier filter at /etc/dovecot/dovecot.conf line 5 (if this is intentional, avoid this warning by moving the global setting before /etc/dovecot/dovecot.conf line 5) --- nixos/modules/services/mail/dovecot.nix | 52 +++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'nixos') diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index b5ed2c594f77..37ee3c8494e8 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -14,8 +14,16 @@ let base_dir = ${baseDir} protocols = ${concatStringsSep " " cfg.protocols} sendmail_path = /run/wrappers/bin/sendmail + # defining mail_plugins must be done before the first protocol {} filter because of https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion + mail_plugins = $mail_plugins ${concatStringsSep " " cfg.mailPlugins.globally.enable} '' + (concatStringsSep "\n" (mapAttrsToList (protocol: plugins: '' + protocol ${protocol} { + mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable} + } + '') cfg.mailPlugins.perProtocol)) + (if cfg.sslServerCert == null then '' ssl = no disable_plaintext_auth = no @@ -72,7 +80,6 @@ let '') (optionalString cfg.enableQuota '' - mail_plugins = $mail_plugins quota service quota-status { executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix inet_listener { @@ -81,10 +88,6 @@ let client_limit = 1 } - protocol imap { - mail_plugins = $mail_plugins imap_quota - } - plugin { quota_rule = *:storage=${cfg.quotaGlobalPerUser} quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working @@ -183,6 +186,40 @@ in description = "Additional entries to put verbatim into Dovecot's config file."; }; + mailPlugins = + let plugins = hint: types.submodule { + options = { + enable = mkOption { + type = types.listOf types.str; + default = []; + description = "mail plugins to enable as a list of strings to append to the ${hint} $mail_plugins configuration variable"; + }; + }; + }; + in + mkOption { + type = with types; submodule { + options = { + globally = mkOption { + type = plugins "top-level"; + example = { enable =[ "virtual" ]; }; + default = { enable = []; }; + }; + perProtocol = mkOption { + type = attrsOf (plugins "corresponding per-protocol"); + default = {}; + example = { imap = [ "imap_acl" ]; }; + }; + }; + }; + description = "Additional entries to add to the mail_plugins variable, globally and per protocol"; + example = { + globally.enable = [ "acl" ]; + perProtocol.imap.enable = [ "imap_acl" ]; + }; + default = { globally.enable = []; perProtocol = {};}; + }; + configFile = mkOption { type = types.nullOr types.path; default = null; @@ -310,6 +347,11 @@ in ++ optional cfg.enablePop3 "pop3" ++ optional cfg.enableLmtp "lmtp"; + services.dovecot2.mailPlugins = mkIf cfg.enableQuota { + globally.enable = [ "quota" ]; + perProtocol.imap.enable = [ "imap_quota" ]; + }; + users.users = { dovenull = { uid = config.ids.uids.dovenull2; -- cgit 1.4.1 From 56f9c51b05669c60489bdff2ba8a31f07aadc479 Mon Sep 17 00:00:00 2001 From: symphorien Date: Tue, 28 Jan 2020 19:21:38 +0000 Subject: Update nixos/modules/services/mail/dovecot.nix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Léo Gaspard --- nixos/modules/services/mail/dovecot.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nixos') diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 37ee3c8494e8..4dda69ae33c5 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -202,7 +202,7 @@ in options = { globally = mkOption { type = plugins "top-level"; - example = { enable =[ "virtual" ]; }; + example = { enable = [ "virtual" ]; }; default = { enable = []; }; }; perProtocol = mkOption { -- cgit 1.4.1 From 7a40ced06b02cfca5086209326180175953bef6a Mon Sep 17 00:00:00 2001 From: Symphorien Gibol Date: Tue, 28 Jan 2020 12:00:00 +0000 Subject: nixos/modules/services/mail/dovecot.nix: nixpkgs-fmt --- nixos/modules/services/mail/dovecot.nix | 246 ++++++++++++++++++-------------- 1 file changed, 136 insertions(+), 110 deletions(-) (limited to 'nixos') diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 4dda69ae33c5..11d4e4ae5f8a 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -18,22 +18,30 @@ let mail_plugins = $mail_plugins ${concatStringsSep " " cfg.mailPlugins.globally.enable} '' - (concatStringsSep "\n" (mapAttrsToList (protocol: plugins: '' - protocol ${protocol} { - mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable} - } - '') cfg.mailPlugins.perProtocol)) - - (if cfg.sslServerCert == null then '' - ssl = no - disable_plaintext_auth = no - '' else '' - ssl_cert = <${cfg.sslServerCert} - ssl_key = <${cfg.sslServerKey} - ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)} - ssl_dh = <${config.security.dhparams.params.dovecot2.path} - disable_plaintext_auth = yes - '') + ( + concatStringsSep "\n" ( + mapAttrsToList ( + protocol: plugins: '' + protocol ${protocol} { + mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable} + } + '' + ) cfg.mailPlugins.perProtocol + ) + ) + + ( + if cfg.sslServerCert == null then '' + ssl = no + disable_plaintext_auth = no + '' else '' + ssl_cert = <${cfg.sslServerCert} + ssl_key = <${cfg.sslServerKey} + ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)} + ssl_dh = <${config.security.dhparams.params.dovecot2.path} + disable_plaintext_auth = yes + '' + ) '' default_internal_user = ${cfg.user} @@ -53,50 +61,58 @@ let } '' - (optionalString cfg.enablePAM '' - userdb { - driver = passwd - } - - passdb { - driver = pam - args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2 - } - '') - - (optionalString (cfg.sieveScripts != {}) '' - plugin { - ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)} - } - '') + ( + optionalString cfg.enablePAM '' + userdb { + driver = passwd + } - (optionalString (cfg.mailboxes != []) '' - protocol imap { - namespace inbox { - inbox=yes - ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)} + passdb { + driver = pam + args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2 } - } - '') + '' + ) - (optionalString cfg.enableQuota '' - service quota-status { - executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix - inet_listener { - port = ${cfg.quotaPort} + ( + optionalString (cfg.sieveScripts != {}) '' + plugin { + ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)} + } + '' + ) + + ( + optionalString (cfg.mailboxes != []) '' + protocol imap { + namespace inbox { + inbox=yes + ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)} + } + } + '' + ) + + ( + optionalString cfg.enableQuota '' + service quota-status { + executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix + inet_listener { + port = ${cfg.quotaPort} + } + client_limit = 1 } - client_limit = 1 - } - plugin { - quota_rule = *:storage=${cfg.quotaGlobalPerUser} - quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working - quota_status_success = DUNNO - quota_status_nouser = DUNNO - quota_status_overquota = "552 5.2.2 Mailbox is full" - quota_grace = 10%% - } - '') + plugin { + quota_rule = *:storage=${cfg.quotaGlobalPerUser} + quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working + quota_status_success = DUNNO + quota_status_nouser = DUNNO + quota_status_overquota = "552 5.2.2 Mailbox is full" + quota_grace = 10%% + } + '' + ) cfg.extraConfig ]; @@ -110,7 +126,7 @@ let mailbox "${mailbox.name}" { auto = ${toString mailbox.auto} '' + optionalString (mailbox.specialUse != null) '' - special_use = \${toString mailbox.specialUse} + special_use = \${toString mailbox.specialUse} '' + "}"; mailboxes = { ... }: { @@ -163,7 +179,7 @@ in protocols = mkOption { type = types.listOf types.str; - default = [ ]; + default = []; description = "Additional listeners to start when Dovecot is enabled."; }; @@ -187,38 +203,39 @@ in }; mailPlugins = - let plugins = hint: types.submodule { - options = { - enable = mkOption { - type = types.listOf types.str; - default = []; - description = "mail plugins to enable as a list of strings to append to the ${hint} $mail_plugins configuration variable"; + let + plugins = hint: types.submodule { + options = { + enable = mkOption { + type = types.listOf types.str; + default = []; + description = "mail plugins to enable as a list of strings to append to the ${hint} $mail_plugins configuration variable"; + }; }; }; - }; - in - mkOption { - type = with types; submodule { - options = { - globally = mkOption { - type = plugins "top-level"; - example = { enable = [ "virtual" ]; }; - default = { enable = []; }; + in + mkOption { + type = with types; submodule { + options = { + globally = mkOption { + type = plugins "top-level"; + example = { enable = [ "virtual" ]; }; + default = { enable = []; }; + }; + perProtocol = mkOption { + type = attrsOf (plugins "corresponding per-protocol"); + default = {}; + example = { imap = [ "imap_acl" ]; }; + }; + }; }; - perProtocol = mkOption { - type = attrsOf (plugins "corresponding per-protocol"); - default = {}; - example = { imap = [ "imap_acl" ]; }; + description = "Additional entries to add to the mail_plugins variable, globally and per protocol"; + example = { + globally.enable = [ "acl" ]; + perProtocol.imap.enable = [ "imap_acl" ]; }; + default = { globally.enable = []; perProtocol = {}; }; }; - }; - description = "Additional entries to add to the mail_plugins variable, globally and per protocol"; - example = { - globally.enable = [ "acl" ]; - perProtocol.imap.enable = [ "imap_acl" ]; - }; - default = { globally.enable = []; perProtocol = {};}; - }; configFile = mkOption { type = types.nullOr types.path; @@ -342,10 +359,10 @@ in enable = true; params.dovecot2 = {}; }; - services.dovecot2.protocols = - optional cfg.enableImap "imap" - ++ optional cfg.enablePop3 "pop3" - ++ optional cfg.enableLmtp "lmtp"; + services.dovecot2.protocols = + optional cfg.enableImap "imap" + ++ optional cfg.enablePop3 "pop3" + ++ optional cfg.enableLmtp "lmtp"; services.dovecot2.mailPlugins = mkIf cfg.enableQuota { globally.enable = [ "quota" ]; @@ -354,20 +371,21 @@ in users.users = { dovenull = - { uid = config.ids.uids.dovenull2; + { + uid = config.ids.uids.dovenull2; description = "Dovecot user for untrusted logins"; group = "dovenull"; }; } // optionalAttrs (cfg.user == "dovecot2") { dovecot2 = - { uid = config.ids.uids.dovecot2; - description = "Dovecot user"; - group = cfg.group; - }; + { + uid = config.ids.uids.dovecot2; + description = "Dovecot user"; + group = cfg.group; + }; } // optionalAttrs (cfg.createMailUser && cfg.mailUser != null) { ${cfg.mailUser} = - { description = "Virtual Mail User"; } // - optionalAttrs (cfg.mailGroup != null) + { description = "Virtual Mail User"; } // optionalAttrs (cfg.mailGroup != null) { group = cfg.mailGroup; }; }; @@ -376,7 +394,7 @@ in } // optionalAttrs (cfg.group == "dovecot2") { dovecot2.gid = config.ids.gids.dovecot2; } // optionalAttrs (cfg.createMailUser && cfg.mailGroup != null) { - ${cfg.mailGroup} = { }; + ${cfg.mailGroup} = {}; }; environment.etc."dovecot/modules".source = modulesDir; @@ -405,15 +423,19 @@ in rm -rf ${stateDir}/sieve '' + optionalString (cfg.sieveScripts != {}) '' mkdir -p ${stateDir}/sieve - ${concatStringsSep "\n" (mapAttrsToList (to: from: '' - if [ -d '${from}' ]; then - mkdir '${stateDir}/sieve/${to}' - cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}' - else - cp -p '${from}' '${stateDir}/sieve/${to}' - fi - ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}' - '') cfg.sieveScripts)} + ${concatStringsSep "\n" ( + mapAttrsToList ( + to: from: '' + if [ -d '${from}' ]; then + mkdir '${stateDir}/sieve/${to}' + cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}' + else + cp -p '${from}' '${stateDir}/sieve/${to}' + fi + ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}' + '' + ) cfg.sieveScripts + )} chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve' ''; }; @@ -421,17 +443,21 @@ in environment.systemPackages = [ dovecotPkg ]; assertions = [ - { assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != []; + { + assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != []; message = "dovecot needs at least one of the IMAP or POP3 listeners enabled"; } - { assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null) - && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null)); + { + assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null) + && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null)); message = "dovecot needs both sslServerCert and sslServerKey defined for working crypto"; } - { assertion = cfg.showPAMFailure -> cfg.enablePAM; + { + assertion = cfg.showPAMFailure -> cfg.enablePAM; message = "dovecot is configured with showPAMFailure while enablePAM is disabled"; } - { assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null); + { + assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null); message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set"; } ]; -- cgit 1.4.1 From 28321223d8cc44bd67371c2f5543fe748582edce Mon Sep 17 00:00:00 2001 From: Symphorien Gibol Date: Tue, 28 Jan 2020 12:00:00 +0000 Subject: dovecot: add missing descriptions --- nixos/modules/services/mail/dovecot.nix | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nixos') diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 11d4e4ae5f8a..230a2ae3f825 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -218,11 +218,13 @@ in type = with types; submodule { options = { globally = mkOption { + description = "Additional entries to add to the mail_plugins variable for all protocols"; type = plugins "top-level"; example = { enable = [ "virtual" ]; }; default = { enable = []; }; }; perProtocol = mkOption { + description = "Additional entries to add to the mail_plugins variable, per protocol"; type = attrsOf (plugins "corresponding per-protocol"); default = {}; example = { imap = [ "imap_acl" ]; }; -- cgit 1.4.1