Dovecot: Difference between revisions
added postfix |
Whitequark (talk | contribs) m fix closing tag |
||
(7 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
authenticated IMAP. | authenticated IMAP. | ||
This article describes a basic Dovecot setup with Postfix and virtual | This article describes a basic Dovecot setup with [[Postfix]] and virtual | ||
users, i.e., e-mail users are configured separately in Dovecot passdb, | users, i.e., e-mail users are configured separately in Dovecot passdb, | ||
and are independent from system users. | and are independent from system users. | ||
Line 9: | Line 9: | ||
= SSL Certificate with ACME = | = SSL Certificate with ACME = | ||
This article assumes a working ACME configuration for certificate | This article assumes a working [[ACME]] configuration for certificate | ||
renewal. | renewal. | ||
Line 79: | Line 79: | ||
args = ${config.age.secrets.dovecot.path} | args = ${config.age.secrets.dovecot.path} | ||
} | } | ||
'' | |||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 115: | Line 116: | ||
= Connect to postfix via lmtp = | = Connect to postfix via lmtp = | ||
See [[Postfix]] for further setup on postfix side. | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.dovecot2 = { | services.dovecot2 = { | ||
Line 152: | Line 155: | ||
smtpd_sasl_auth_enable = "yes"; | smtpd_sasl_auth_enable = "yes"; | ||
smtpd_recipient_restrictions = "permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"; | smtpd_recipient_restrictions = "permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"; | ||
}; | |||
# create path for dovecot socket | |||
users.users."postfix" = { | |||
createHome = true; | |||
home = "/var/spool/postfix"; | |||
}; | }; | ||
Line 165: | Line 174: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== mail_crypt plugin (encryption at rest) | You also need to set proper file permissions on the cert directory and key files. | ||
See [[ACME#Integration_with_service_modules]]. | |||
= Using sieve plugins = | |||
The following is required to use Sieve plugins (<code>imap_sieve</code>, ManageSieve, etc): | |||
<syntaxhighlight lang="nix"> | |||
environment.systemPackages = with pkgs; [ | |||
dovecot_pigeonhole | |||
]; | |||
</syntaxhighlight> | |||
= mail_crypt plugin (encryption at rest) = | |||
The following seems to make mail_crypt work in its per-user/per-folder mode (note that this mode is still described as 'not production quality' in the dovecot docs): | The following seems to make mail_crypt work in its per-user/per-folder mode (note that this mode is still described as 'not production quality' in the dovecot docs): | ||
Line 193: | Line 215: | ||
''; | ''; | ||
}; | }; | ||
</pre> | |||
= Troubleshooting = | = Troubleshooting = | ||
== sievec fails to compile basic sieve scripts == | == sievec fails to compile basic sieve scripts == |
Latest revision as of 17:26, 30 September 2025
Dovecot is a mail storage server. It handles the storage of e-mail messages and their retrieval by a e-mail client (mail user agent) via authenticated IMAP.
This article describes a basic Dovecot setup with Postfix and virtual users, i.e., e-mail users are configured separately in Dovecot passdb, and are independent from system users.
SSL Certificate with ACME
This article assumes a working ACME configuration for certificate renewal.
{
config,
...
}:
let
sslCertDir = config.security.acme.certs."example.org".directory;
domainName = "example.org";
in
{
# further dovecot configuration goes here
...
}
Dovecot passwd database
Create a plaintext virtual user password database in the following format
# authenticate via Passwd-file
#
# bill@example.org:{PLAIN}your_plain_password
# alice@example.org:{PLAIN-MD5}1a1dc91c907325c69271ddf0c944bc72::::::
# This file need to have correct permissions.
age.secrets.dovecot = {
file = "./dovecot-secret.age";
# -rw-------
mode = "600";
owner = "dovecot2";
group = "dovecot2";
};
Open firewall port
Open firewall port for IMAPS clients.
networking.firewall.allowedTCPPorts = [ 993 ]; # dovecot imaps
Setup auth via passwd-file
services.dovecot2 = {
enable = true;
# use my own passwd file for auth, see below
enablePAM = false;
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_dovecot_lmtp/
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_and_dovecot_sasl/
extraConfig = ''
# force to use full user name plus domain name
# for disambiguation
auth_username_format = %Lu
# Authentication configuration:
auth_mechanisms = plain
passdb {
driver = passwd-file
args = ${config.age.secrets.dovecot.path}
}
''
};
Setup virtual users
# /var/spool/mail/vmail needs to be created and owned by vmail
users.users."vmail" = {
createHome = true;
home = "/var/spool/mail/vmail";
};
services.dovecot2 = {
# configure virtual mail user and group
createMailUser = true;
mailUser = "vmail";
mailGroup = "vmail";
# implement virtual users
# https://doc.dovecot.org/2.3/configuration_manual/howto/simple_virtual_install/
# store virtual mail under
# /var/spool/mail/vmail/<DOMAIN>/<USER>/Maildir/
mailLocation = "maildir:~/Maildir";
extraConfig = ''
userdb {
driver = static
# the full e-mail address inside passwd-file is the username (%u)
# user@example.com
# %d for domain_name %n for user_name
args = uid=vmail gid=vmail username_format=%u home=/var/spool/mail/vmail/%d/%n
}
'';
};
Connect to postfix via lmtp
See Postfix for further setup on postfix side.
services.dovecot2 = {
# connection to postfix
enableLmtp = true;
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_dovecot_lmtp/
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_and_dovecot_sasl/
extraConfig = ''
# connection to postfix via lmtp
service lmtp {
unix_listener /var/spool/postfix/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener /var/spool/postfix/auth {
mode = 0600
user = postfix
group = postfix
}
}
'';
};
# postfix connection to dovecot
services.postfix.config = {
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_dovecot_lmtp/
mailbox_transport = "lmtp:unix:/var/spool/postfix/dovecot-lmtp";
virtual_transport = "lmtp:unix:/var/spool/postfix/dovecot-lmtp";
# https://doc.dovecot.org/2.3/configuration_manual/howto/postfix_and_dovecot_sasl/
smtpd_sasl_type = "dovecot";
smtpd_sasl_path = "/var/spool/postfix/auth";
smtpd_sasl_auth_enable = "yes";
smtpd_recipient_restrictions = "permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination";
};
# create path for dovecot socket
users.users."postfix" = {
createHome = true;
home = "/var/spool/postfix";
};
Configure SSL Certificates
services.dovecot2 = {
sslServerCert = "${sslCertDir}/fullchain.pem";
sslServerKey = "${sslCertDir}/key.pem";
sslCACert = "${sslCertDir}/chain.pem";
};
You also need to set proper file permissions on the cert directory and key files. See ACME#Integration_with_service_modules.
Using sieve plugins
The following is required to use Sieve plugins (imap_sieve
, ManageSieve, etc):
environment.systemPackages = with pkgs; [
dovecot_pigeonhole
];
mail_crypt plugin (encryption at rest)
The following seems to make mail_crypt work in its per-user/per-folder mode (note that this mode is still described as 'not production quality' in the dovecot docs):
security.pam.services.dovecot2 = { }; # needed as we disable PAM below services.dovecot2 = { enable = true; enablePAM = false; # need to disable this as we redefine passdb mailPlugins.globally.enable = [ "mail_crypt" ]; pluginSettings = { mail_crypt_curve = "secp521r1"; mail_crypt_save_version = "2"; mail_crypt_require_encrypted_user_key = "yes"; }; extraConfig = '' mail_attribute_dict = file:%h/.attributes userdb { driver = passwd } passdb { driver = pam override_fields = userdb_mail_crypt_private_password=%{sha256:password} userdb_mail_crypt_save_version=2 args = failure_show_msg=yes dovecot2 } ''; };
Troubleshooting
sievec fails to compile basic sieve scripts
Sieve commands such as fileinto need to be enabled explicitly with:
services.dovecot2.sieve.globalExtensions = ["fileinto"];
Otherwise, the sievec command will fail to compile sieve scripts with fileinto
statements and as a result the Dovecot service itself will fail to start if the configuration contains services.dovecot2.sieve.scripts
.