Merge branch 'dovecot-rfc42' into 'main'
dovecot: migrate to settings option See merge request simple-nixos-mailserver/nixos-mailserver!498
This commit is contained in:
+47
-12
@@ -137,6 +137,35 @@ in
|
||||
description = "Message size limit enforced by Postfix.";
|
||||
};
|
||||
|
||||
quota = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable quota support.
|
||||
|
||||
When enabled, incoming mail can be rejected if a mailbox exceeds its
|
||||
quota.
|
||||
'';
|
||||
};
|
||||
|
||||
defaults = {
|
||||
perUser = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
example = "10G";
|
||||
description = ''
|
||||
Default quota applied to all users.
|
||||
|
||||
The value must use a size format like `500M`, `2G`, `10G`.
|
||||
|
||||
If set to `null`, no default per user quota is applied and only
|
||||
explicit per user quotas apply, if set.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
accounts = mkOption {
|
||||
type = types.attrsOf (
|
||||
types.submodule (
|
||||
@@ -260,8 +289,11 @@ in
|
||||
default = null;
|
||||
example = "2G";
|
||||
description = ''
|
||||
Per user quota rules. Accepted sizes are `xx k/M/G/T` with the
|
||||
obvious meaning. Leave blank for the standard quota `100G`.
|
||||
The quota limit for this user.
|
||||
|
||||
The value is must use a size format like `500M`, `2G`, `10G`.
|
||||
|
||||
If unset, will fall back to {option}`mailserver.quota.defaults.perUser` if set.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -654,11 +686,8 @@ in
|
||||
};
|
||||
|
||||
lmtpSaveToDetailMailbox = mkOption {
|
||||
type = types.enum [
|
||||
"yes"
|
||||
"no"
|
||||
];
|
||||
default = "yes";
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
If an email address is delimited by a "+", should it be filed into a
|
||||
mailbox matching the string after the "+"? For example,
|
||||
@@ -882,25 +911,31 @@ in
|
||||
|
||||
mailboxes = mkOption {
|
||||
description = ''
|
||||
The mailboxes for dovecot.
|
||||
The default mailboxes for Dovecot maildirs.
|
||||
|
||||
The [`special_use`] option must refer to an [RFC6154 2] attribute and lead with an escaped backslash.
|
||||
|
||||
Depending on the mail client used it might be necessary to change some mailbox's name.
|
||||
|
||||
[special_use]: https://doc.dovecot.org/2.3/configuration_manual/namespace/#core_setting-namespace/mailbox/special_use
|
||||
[RFC6154 2]: https://datatracker.ietf.org/doc/html/rfc6154.html#section-2
|
||||
'';
|
||||
default = {
|
||||
Trash = {
|
||||
auto = "no";
|
||||
specialUse = "Trash";
|
||||
special_use = "\\Trash";
|
||||
};
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Junk";
|
||||
special_use = "\\Junk";
|
||||
};
|
||||
Drafts = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Drafts";
|
||||
special_use = "\\Drafts";
|
||||
};
|
||||
Sent = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Sent";
|
||||
special_use = "\\Sent";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Generated
+3
-3
@@ -79,11 +79,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774935083,
|
||||
"narHash": "sha256-Mh6bLcYAcENBAZk3RoMPMFCGGMZmfaGMERE4siZOgP4=",
|
||||
"lastModified": 1776030597,
|
||||
"narHash": "sha256-H2CYM/RmVqCo1iud5BhPp8Pim2d1ESGt2FDHjbmju8A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2f4fd5e1abf9bac8c1d22750c701a7a5e6b524c6",
|
||||
"rev": "c88e63f4caf12c731f61ce71f300680ce73c180e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
+253
-231
@@ -32,6 +32,16 @@ with (import ./common.nix {
|
||||
});
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
attrNames
|
||||
concatMapStringsSep
|
||||
filterAttrs
|
||||
mapAttrs'
|
||||
mkForce
|
||||
mkIf
|
||||
nameValuePair
|
||||
;
|
||||
|
||||
cfg = config.mailserver;
|
||||
|
||||
passwdDir = "/run/dovecot2";
|
||||
@@ -39,8 +49,6 @@ let
|
||||
userdbFile = "${passwdDir}/userdb";
|
||||
# This file contains the ldap bind password
|
||||
ldapConfFile = "${passwdDir}/dovecot-ldap.conf.ext";
|
||||
boolToYesNo = x: if x then "yes" else "no";
|
||||
listToLine = lib.concatStringsSep " ";
|
||||
listToMultiAttrs =
|
||||
keyPrefix: attrs:
|
||||
lib.listToAttrs (
|
||||
@@ -53,14 +61,6 @@ let
|
||||
maildirLayoutAppendix = lib.optionalString (cfg.storage.directoryLayout == "fs") ":LAYOUT=fs";
|
||||
maildirUTF8FolderNames = lib.optionalString cfg.useUTF8FolderNames ":UTF-8";
|
||||
|
||||
# https://doc.dovecot.org/2.3/configuration_manual/home_directories_for_virtual_users/#ways-to-set-up-home-directory
|
||||
# Mail directory below the home directory
|
||||
dovecotMaildir =
|
||||
"maildir:~/mail${maildirLayoutAppendix}${maildirUTF8FolderNames}"
|
||||
+ (lib.optionalString (cfg.indexDir != null) ":INDEX=${cfg.indexDir}/%{domain}/%{username}");
|
||||
|
||||
postfixCfg = config.services.postfix;
|
||||
|
||||
ldapConfig = pkgs.writeTextFile {
|
||||
name = "dovecot-ldap.conf.ext.template";
|
||||
text = ''
|
||||
@@ -128,12 +128,13 @@ let
|
||||
lib.mapAttrsToList (
|
||||
name: _:
|
||||
if lib.elem name accountsWithPlaintextPasswordFiles then
|
||||
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' pkgs.dovecot "doveadm"} pw)"}::::::"
|
||||
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' config.services.dovecot2.package "doveadm"} pw)"}::::::"
|
||||
else
|
||||
"${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
|
||||
) cfg.accounts
|
||||
)}
|
||||
EOF
|
||||
chown dovecot2:dovecot2 ${passwdFile}
|
||||
|
||||
cat <<EOF > ${userdbFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
@@ -144,10 +145,11 @@ let
|
||||
) cfg.accounts
|
||||
)}
|
||||
EOF
|
||||
chown dovecot2:dovecot2 ${userdbFile}
|
||||
'';
|
||||
|
||||
junkMailboxes = builtins.attrNames (
|
||||
lib.filterAttrs (_: v: v ? "specialUse" && v.specialUse == "Junk") cfg.mailboxes
|
||||
lib.filterAttrs (_: v: v ? "special_use" && v.special_use == "\\Junk") cfg.mailboxes
|
||||
);
|
||||
junkMailboxNumber = builtins.length junkMailboxes;
|
||||
# The assertion guarantees there is exactly one Junk mailbox.
|
||||
@@ -163,30 +165,29 @@ let
|
||||
else
|
||||
scope
|
||||
);
|
||||
|
||||
ftsPluginSettings = {
|
||||
fts = "flatcurve";
|
||||
fts_languages = listToLine cfg.fullTextSearch.languages;
|
||||
fts_tokenizers = listToLine [
|
||||
"generic"
|
||||
"email-address"
|
||||
];
|
||||
fts_tokenizer_email_address = "maxlen=100"; # default 254 too large for Xapian
|
||||
fts_flatcurve_substring_search = boolToYesNo cfg.fullTextSearch.substringSearch;
|
||||
fts_filters = listToLine cfg.fullTextSearch.filters;
|
||||
fts_header_excludes = listToLine cfg.fullTextSearch.headerExcludes;
|
||||
fts_autoindex = boolToYesNo cfg.fullTextSearch.autoIndex;
|
||||
fts_enforced = cfg.fullTextSearch.enforced;
|
||||
}
|
||||
// (listToMultiAttrs "fts_autoindex_exclude" cfg.fullTextSearch.autoIndexExclude);
|
||||
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = junkMailboxNumber == 1;
|
||||
message = "nixos-mailserver requires exactly one dovecot mailbox with the 'special use' flag set to 'Junk' (${builtins.toString junkMailboxNumber} have been found)";
|
||||
message = "nixos-mailserver requires exactly one dovecot mailbox with the 'special_use' flag set to '\\Junk' (${builtins.toString junkMailboxNumber} have been found)";
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
let
|
||||
usersWithQuota = attrNames (
|
||||
filterAttrs (_: account: account.quota != null) config.mailserver.loginAccounts
|
||||
);
|
||||
in
|
||||
!cfg.quota.enable -> usersWithQuota == { };
|
||||
message = ''
|
||||
Without quota support enabled, per-user quotas cannot be applied to the following accounts:
|
||||
|
||||
${concatMapStringsSep "\n" (account: "- ${account}") quotaUsers}
|
||||
|
||||
Either remove per user quota settings or re-enable `mailserver.quota.enable`.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
@@ -215,7 +216,7 @@ in
|
||||
# the global config and tries to open shared libraries configured in there,
|
||||
# which are usually not compatible.
|
||||
environment.systemPackages = [
|
||||
pkgs.dovecot_pigeonhole
|
||||
pkgs.dovecot_pigeonhole_0_5
|
||||
]
|
||||
++ lib.optional cfg.fullTextSearch.enable pkgs.dovecot-fts-flatcurve;
|
||||
|
||||
@@ -223,30 +224,9 @@ in
|
||||
environment.etc."dovecot/modules".source = "/run/current-system/sw/lib/dovecot/modules";
|
||||
|
||||
services.dovecot2 = {
|
||||
package = pkgs.dovecot_2_3;
|
||||
enable = true;
|
||||
enableImap = cfg.enableImap || cfg.enableImapSsl;
|
||||
enablePop3 = cfg.enablePop3 || cfg.enablePop3Ssl;
|
||||
enablePAM = false;
|
||||
enableQuota = true;
|
||||
mailGroup = cfg.storage.group;
|
||||
mailUser = cfg.storage.owner;
|
||||
mailLocation = dovecotMaildir;
|
||||
sslServerCert = x509CertificateFile;
|
||||
sslServerKey = x509PrivateKeyFile;
|
||||
enableDHE = lib.mkDefault false;
|
||||
enableLmtp = true;
|
||||
mailPlugins.globally.enable = lib.optionals cfg.fullTextSearch.enable [
|
||||
"fts"
|
||||
"fts_flatcurve"
|
||||
];
|
||||
protocols = lib.optional cfg.enableManageSieve "sieve";
|
||||
|
||||
pluginSettings = {
|
||||
sieve = "file:${cfg.sieveDirectory}/%{user}/scripts;active=${cfg.sieveDirectory}/%{user}/active.sieve";
|
||||
sieve_default = "file:${cfg.sieveDirectory}/%{user}/default.sieve";
|
||||
sieve_default_name = "default";
|
||||
}
|
||||
// (lib.optionalAttrs cfg.fullTextSearch.enable ftsPluginSettings);
|
||||
enablePAM = mkForce false;
|
||||
|
||||
sieve = {
|
||||
extensions = [
|
||||
@@ -285,196 +265,238 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
mailboxes = cfg.mailboxes;
|
||||
settings = {
|
||||
# vmail user
|
||||
mail_uid = cfg.storage.owner;
|
||||
mail_gid = cfg.storage.group;
|
||||
mail_access_groups = cfg.storage.group;
|
||||
|
||||
extraConfig = ''
|
||||
#Extra Config
|
||||
${lib.optionalString cfg.debug.dovecot ''
|
||||
mail_debug = yes
|
||||
auth_debug = yes
|
||||
verbose_ssl = yes
|
||||
''}
|
||||
# authentication
|
||||
auth_mechanisms = [
|
||||
"plain"
|
||||
"login"
|
||||
];
|
||||
disable_plaintext_auth = true;
|
||||
|
||||
${lib.optionalString (cfg.enableImap || cfg.enableImapSsl) ''
|
||||
service imap-login {
|
||||
inet_listener imap {
|
||||
${
|
||||
if cfg.enableImap then
|
||||
''
|
||||
port = 143
|
||||
''
|
||||
else
|
||||
''
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = 0
|
||||
''
|
||||
}
|
||||
}
|
||||
inet_listener imaps {
|
||||
${
|
||||
if cfg.enableImapSsl then
|
||||
''
|
||||
port = 993
|
||||
ssl = yes
|
||||
''
|
||||
else
|
||||
''
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = 0
|
||||
''
|
||||
}
|
||||
}
|
||||
}
|
||||
''}
|
||||
${lib.optionalString (cfg.enablePop3 || cfg.enablePop3Ssl) ''
|
||||
service pop3-login {
|
||||
inet_listener pop3 {
|
||||
${
|
||||
if cfg.enablePop3 then
|
||||
''
|
||||
port = 110
|
||||
''
|
||||
else
|
||||
''
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = 0
|
||||
''
|
||||
}
|
||||
}
|
||||
inet_listener pop3s {
|
||||
${
|
||||
if cfg.enablePop3Ssl then
|
||||
''
|
||||
port = 995
|
||||
ssl = yes
|
||||
''
|
||||
else
|
||||
''
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = 0
|
||||
''
|
||||
}
|
||||
}
|
||||
}
|
||||
''}
|
||||
# backend services
|
||||
"service auth" = {
|
||||
"unix_listener auth" = {
|
||||
mode = "0660";
|
||||
user = config.services.postfix.user;
|
||||
group = config.services.postfix.group;
|
||||
};
|
||||
};
|
||||
"service indexer-worker" = mkIf (cfg.fullTextSearch.memoryLimit != null) {
|
||||
vsz_limit = "${toString cfg.fullTextSearch.memoryLimit} MB";
|
||||
};
|
||||
"service lmtp" = {
|
||||
"unix_listener dovecot-lmtp" = {
|
||||
group = config.services.postfix.group;
|
||||
mode = "0600";
|
||||
user = config.services.postfix.user;
|
||||
};
|
||||
user = cfg.storage.owner;
|
||||
vsz_limit = "${toString cfg.lmtpMemoryLimit} MB";
|
||||
};
|
||||
"service quota-status" = mkIf cfg.quota.enable {
|
||||
executable = toString [
|
||||
"${config.services.dovecot2.package}/libexec/dovecot/quota-status"
|
||||
"-p"
|
||||
"postfix"
|
||||
];
|
||||
"unix_listener quota-status" = {
|
||||
user = "postfix";
|
||||
};
|
||||
client_limit = 1;
|
||||
vsz_limit = "${toString cfg.quotaStatusMemoryLimit} MB";
|
||||
};
|
||||
|
||||
protocol imap {
|
||||
mail_max_userip_connections = ${toString cfg.maxConnectionsPerUser}
|
||||
mail_plugins = $mail_plugins imap_sieve
|
||||
}
|
||||
# frontend services
|
||||
"service imap-login" = mkIf (cfg.enableImap || cfg.enableImapSsl) {
|
||||
"inet_listener imap" = {
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = if cfg.enableImap then 143 else 0;
|
||||
};
|
||||
"inet_listener imaps" = {
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = if cfg.enableImapSsl then 993 else 0;
|
||||
ssl = true;
|
||||
};
|
||||
};
|
||||
"service pop3-login" = mkIf (cfg.enablePop3 || cfg.enablePop3Ssl) {
|
||||
"inet_listener pop3" = {
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = if cfg.enablePop3 then 110 else 0;
|
||||
};
|
||||
"inet_listener pop3s" = {
|
||||
# see https://dovecot.org/pipermail/dovecot/2010-March/047479.html
|
||||
port = if cfg.enablePop3Ssl then 995 else 0;
|
||||
ssl = true;
|
||||
};
|
||||
};
|
||||
"service imap" = {
|
||||
vsz_limit = "${toString cfg.imapMemoryLimit} MB";
|
||||
};
|
||||
|
||||
service imap {
|
||||
vsz_limit = ${builtins.toString cfg.imapMemoryLimit} MB
|
||||
}
|
||||
# protocols
|
||||
protocols = [
|
||||
"lmtp"
|
||||
]
|
||||
++ lib.optionals (cfg.enableImap || cfg.enableImapSsl) [ "imap" ]
|
||||
++ lib.optionals (cfg.enablePop3 || cfg.enablePop3Ssl) [ "pop3" ]
|
||||
++ lib.optionals cfg.enableManageSieve [ "sieve" ];
|
||||
|
||||
protocol pop3 {
|
||||
mail_max_userip_connections = ${toString cfg.maxConnectionsPerUser}
|
||||
}
|
||||
|
||||
mail_access_groups = ${cfg.storage.group}
|
||||
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.21&config=intermediate&openssl=3.4.1&guideline=5.7
|
||||
ssl = required
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_prefer_server_ciphers = no
|
||||
ssl_cipher_list = ${
|
||||
lib.concatStringsSep ":" [
|
||||
# TLS1.3
|
||||
"TLS_AES_128_GCM_SHA256"
|
||||
"TLS_CHACHA20_POLY1305_SHA256"
|
||||
"TLS_AES_256_GCM_SHA384"
|
||||
# TLS1.2
|
||||
# EC key material
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256"
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||
"ECDHE-ECDSA-AES256-GCM-SHA384"
|
||||
# RSA key material
|
||||
"ECDHE-RSA-AES128-GCM-SHA256"
|
||||
"ECDHE-RSA-CHACHA20-POLY1305"
|
||||
"ECDHE-RSA-AES256-GCM-SHA384"
|
||||
"protocol lmtp" = {
|
||||
mail_plugins = [
|
||||
"$mail_plugins"
|
||||
"sieve"
|
||||
];
|
||||
};
|
||||
"protocol imap" = {
|
||||
mail_max_userip_connections = cfg.maxConnectionsPerUser;
|
||||
mail_plugins = [
|
||||
"$mail_plugins"
|
||||
"imap_sieve"
|
||||
]
|
||||
}
|
||||
ssl_curve_list = X25519MLKEM768:X25519:prime256v1:secp384r1
|
||||
++ lib.optionals cfg.quota.enable [
|
||||
"imap_quota"
|
||||
];
|
||||
};
|
||||
"protocol pop3" = {
|
||||
mail_max_userip_connections = cfg.maxConnectionsPerUser;
|
||||
};
|
||||
|
||||
service lmtp {
|
||||
unix_listener dovecot-lmtp {
|
||||
group = ${postfixCfg.group}
|
||||
mode = 0600
|
||||
user = ${postfixCfg.user}
|
||||
# globally enabled plugins
|
||||
mail_plugins = [
|
||||
"$mail_plugins"
|
||||
]
|
||||
++ lib.optionals cfg.quota.enable [
|
||||
"quota"
|
||||
]
|
||||
++ lib.optionals cfg.fullTextSearch.enable [
|
||||
"fts"
|
||||
"fts_flatcurve"
|
||||
];
|
||||
|
||||
# tls settings
|
||||
ssl_cert = "<${x509CertificateFile}";
|
||||
ssl_key = "<${x509PrivateKeyFile}";
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.21&config=intermediate&openssl=3.4.1&guideline=5.7
|
||||
ssl = "required";
|
||||
ssl_min_protocol = "TLSv1.2";
|
||||
ssl_prefer_server_ciphers = false;
|
||||
ssl_cipher_list = lib.concatStringsSep ":" [
|
||||
# TLS1.3
|
||||
"TLS_AES_128_GCM_SHA256"
|
||||
"TLS_CHACHA20_POLY1305_SHA256"
|
||||
"TLS_AES_256_GCM_SHA384"
|
||||
# TLS1.2
|
||||
# EC key material
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256"
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||
"ECDHE-ECDSA-AES256-GCM-SHA384"
|
||||
# RSA key material
|
||||
"ECDHE-RSA-AES128-GCM-SHA256"
|
||||
"ECDHE-RSA-CHACHA20-POLY1305"
|
||||
"ECDHE-RSA-AES256-GCM-SHA384"
|
||||
];
|
||||
ssl_curve_list = lib.concatStringsSep ":" [
|
||||
"X25519MLKEM768"
|
||||
"X25519"
|
||||
"prime256v1"
|
||||
"secp384r1"
|
||||
];
|
||||
|
||||
# default mail storage
|
||||
# https://doc.dovecot.org/2.3/configuration_manual/home_directories_for_virtual_users/#ways-to-set-up-home-directory
|
||||
mail_location =
|
||||
"maildir:~/mail${maildirLayoutAppendix}${maildirUTF8FolderNames}"
|
||||
+ (lib.optionalString (cfg.indexDir != null) ":INDEX=${cfg.indexDir}/%{domain}/%{username}");
|
||||
|
||||
passdb = [
|
||||
{
|
||||
driver = "passwd-file";
|
||||
args = "${passwdFile}";
|
||||
}
|
||||
vsz_limit = ${builtins.toString cfg.lmtpMemoryLimit} MB
|
||||
}
|
||||
|
||||
service quota-status {
|
||||
inet_listener {
|
||||
port = 0
|
||||
]
|
||||
++ lib.optionals cfg.ldap.enable [
|
||||
{
|
||||
driver = "ldap";
|
||||
args = "${ldapConfFile}";
|
||||
}
|
||||
unix_listener quota-status {
|
||||
user = postfix
|
||||
];
|
||||
userdb = [
|
||||
{
|
||||
driver = "passwd-file";
|
||||
args = "${userdbFile}";
|
||||
default_fields = [
|
||||
"home=${cfg.storage.path}/%{domain}/%{username}"
|
||||
"uid=${builtins.toString cfg.storage.uid}"
|
||||
"gid=${builtins.toString cfg.storage.gid}"
|
||||
];
|
||||
}
|
||||
vsz_limit = ${builtins.toString cfg.quotaStatusMemoryLimit} MB
|
||||
}
|
||||
|
||||
recipient_delimiter = ${cfg.recipientDelimiter}
|
||||
lmtp_save_to_detail_mailbox = ${cfg.lmtpSaveToDetailMailbox}
|
||||
|
||||
protocol lmtp {
|
||||
mail_plugins = $mail_plugins sieve
|
||||
}
|
||||
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = ${passwdFile}
|
||||
}
|
||||
|
||||
userdb {
|
||||
driver = passwd-file
|
||||
args = ${userdbFile}
|
||||
default_fields = \
|
||||
home=${cfg.storage.path}/%{domain}/%{username} \
|
||||
uid=${builtins.toString cfg.storage.uid} \
|
||||
gid=${builtins.toString cfg.storage.uid}
|
||||
}
|
||||
|
||||
${lib.optionalString cfg.ldap.enable ''
|
||||
passdb {
|
||||
driver = ldap
|
||||
args = ${ldapConfFile}
|
||||
]
|
||||
++ lib.optionals cfg.ldap.enable [
|
||||
{
|
||||
driver = "ldap";
|
||||
args = "${ldapConfFile}";
|
||||
override_fields = [
|
||||
"uid=${toString cfg.storage.uid}"
|
||||
"gid=${toString cfg.storage.gid}"
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
userdb {
|
||||
driver = ldap
|
||||
args = ${ldapConfFile}
|
||||
override_fields = \
|
||||
uid=${toString cfg.storage.uid} \
|
||||
gid=${toString cfg.storage.uid}
|
||||
# default user mailboxes
|
||||
"namespace inbox" = {
|
||||
inbox = true;
|
||||
separator = ".";
|
||||
}
|
||||
// mapAttrs' (name: value: nameValuePair ''mailbox "${name}"'' value) cfg.mailboxes;
|
||||
lda_mailbox_autosubscribe = true;
|
||||
lda_mailbox_autocreate = true;
|
||||
|
||||
# subaddressing
|
||||
recipient_delimiter = cfg.recipientDelimiter;
|
||||
lmtp_save_to_detail_mailbox = cfg.lmtpSaveToDetailMailbox;
|
||||
|
||||
plugin = {
|
||||
sieve = "file:${cfg.sieveDirectory}/%{user}/scripts;active=${cfg.sieveDirectory}/%{user}/active.sieve";
|
||||
sieve_default = "file:${cfg.sieveDirectory}/%{user}/default.sieve";
|
||||
sieve_default_name = "default";
|
||||
}
|
||||
// lib.optionalAttrs cfg.fullTextSearch.enable (
|
||||
{
|
||||
fts = "flatcurve";
|
||||
fts_languages = cfg.fullTextSearch.languages;
|
||||
fts_tokenizers = [
|
||||
"generic"
|
||||
"email-address"
|
||||
];
|
||||
fts_tokenizer_email_address = "maxlen=100"; # default 254 too large for Xapian
|
||||
fts_flatcurve_substring_search = cfg.fullTextSearch.substringSearch;
|
||||
fts_filters = cfg.fullTextSearch.filters;
|
||||
fts_header_excludes = cfg.fullTextSearch.headerExcludes;
|
||||
fts_autoindex = cfg.fullTextSearch.autoIndex;
|
||||
fts_enforced = cfg.fullTextSearch.enforced;
|
||||
}
|
||||
''}
|
||||
|
||||
service auth {
|
||||
unix_listener auth {
|
||||
mode = 0660
|
||||
user = ${postfixCfg.user}
|
||||
group = ${postfixCfg.group}
|
||||
}
|
||||
}
|
||||
|
||||
auth_mechanisms = plain login
|
||||
|
||||
namespace inbox {
|
||||
separator = ${cfg.hierarchySeparator}
|
||||
inbox = yes
|
||||
}
|
||||
|
||||
service indexer-worker {
|
||||
${lib.optionalString (cfg.fullTextSearch.memoryLimit != null) ''
|
||||
vsz_limit = ${toString (cfg.fullTextSearch.memoryLimit * 1024 * 1024)}
|
||||
''}
|
||||
}
|
||||
|
||||
lda_mailbox_autosubscribe = yes
|
||||
lda_mailbox_autocreate = yes
|
||||
'';
|
||||
// (listToMultiAttrs "fts_autoindex_exclude" cfg.fullTextSearch.autoIndexExclude)
|
||||
)
|
||||
// lib.optionalAttrs cfg.quota.enable {
|
||||
quota_rule = mkIf (cfg.quota.defaults.perUser != null) "*:storage=${cfg.quota.defaults.perUser}";
|
||||
quota = "count:User quota"; # per virtual mail user quota
|
||||
quota_status_success = "DUNNO";
|
||||
quota_status_nouser = "DUNNO";
|
||||
quota_status_overquota = "552 5.2.2 Mailbox is full";
|
||||
quota_grace = "10%%";
|
||||
quota_vsizes = true;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs cfg.debug.dovecot {
|
||||
mail_debug = true;
|
||||
auth_debug = true;
|
||||
verbose_ssl = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.dovecot = {
|
||||
|
||||
@@ -27,7 +27,7 @@ in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
dovecot
|
||||
config.services.dovecot2.package
|
||||
openssh
|
||||
postfix
|
||||
rspamd
|
||||
|
||||
@@ -373,6 +373,8 @@ in
|
||||
# reject selected recipients
|
||||
"check_recipient_access ${mappedFile "denied_recipients"}"
|
||||
"check_recipient_access ${mappedFile "reject_recipients"}"
|
||||
]
|
||||
++ lib.optionals cfg.quota.enable [
|
||||
# quota checking
|
||||
"check_policy_service unix:/run/dovecot2/quota-status"
|
||||
];
|
||||
|
||||
@@ -33,6 +33,7 @@ groups = [
|
||||
"mailserver.dmarcReporting",
|
||||
"mailserver.tlsrpt",
|
||||
"mailserver.fullTextSearch",
|
||||
"mailserver.quota",
|
||||
"mailserver.redis",
|
||||
"mailserver.ldap",
|
||||
"mailserver.monitoring",
|
||||
|
||||
Reference in New Issue
Block a user