Dovecot: Difference between revisions
Created page with "== Troubleshooting == === sievec fails to compile basic sieve scripts in 24.05 === Since NixOS 24.05 even basic sieve commands such as ''fileinto'' need to be enabled explicitly with: <syntaxhighlight lang="nix">services.dovecot2.sieve.globalExtensions = ["fileinto"];</syntaxhighlight> Otherwise, the ''sievec'' command will fail to compile sieve scripts with <code>fileinto</code> statements and as a result the Dovecot service itself will fail to start if the configu..." |
Whitequark (talk | contribs) m fix closing tag |
||
(13 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
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. | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
config, | |||
... | |||
}: | |||
let | |||
sslCertDir = config.security.acme.certs."example.org".directory; | |||
domainName = "example.org"; | |||
in | |||
{ | |||
# further dovecot configuration goes here | |||
... | |||
} | |||
</syntaxhighlight> | |||
= Dovecot passwd database = | |||
Create a plaintext virtual user password database in the following | |||
format | |||
<syntaxhighlight lang="nix"> | |||
# 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"; | |||
}; | |||
</syntaxhighlight> | |||
= Open firewall port = | |||
Open firewall port for IMAPS clients. | |||
<syntaxhighlight lang="nix"> | |||
networking.firewall.allowedTCPPorts = [ 993 ]; # dovecot imaps | |||
</syntaxhighlight> | |||
= Setup auth via passwd-file = | |||
<syntaxhighlight lang="nix"> | |||
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} | |||
} | |||
'' | |||
}; | |||
</syntaxhighlight> | |||
= Setup virtual users = | |||
<syntaxhighlight lang="nix"> | |||
# /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 | |||
} | |||
''; | |||
}; | |||
</syntaxhighlight> | |||
= Connect to postfix via lmtp = | |||
See [[Postfix]] for further setup on postfix side. | |||
<syntaxhighlight lang="nix"> | |||
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"; | |||
}; | |||
</syntaxhighlight> | |||
= Configure SSL Certificates = | |||
<syntaxhighlight lang="nix"> | |||
services.dovecot2 = { | |||
sslServerCert = "${sslCertDir}/fullchain.pem"; | |||
sslServerKey = "${sslCertDir}/key.pem"; | |||
sslCACert = "${sslCertDir}/chain.pem"; | |||
}; | |||
</syntaxhighlight> | |||
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): | |||
<pre> | |||
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 | |||
} | |||
''; | |||
}; | |||
</pre> | |||
= Troubleshooting = | |||
== sievec fails to compile basic sieve scripts == | |||
Sieve commands such as ''fileinto'' need to be enabled explicitly with: | |||
<syntaxhighlight lang="nix">services.dovecot2.sieve.globalExtensions = ["fileinto"];</syntaxhighlight> | <syntaxhighlight lang="nix">services.dovecot2.sieve.globalExtensions = ["fileinto"];</syntaxhighlight> | ||
Otherwise, the ''sievec'' command will fail to compile sieve scripts with <code>fileinto</code> statements and as a result the Dovecot service itself will fail to start if the configuration contains <code>services.dovecot2.sieve.scripts</code>. | Otherwise, the ''sievec'' command will fail to compile sieve scripts with <code>fileinto</code> statements and as a result the Dovecot service itself will fail to start if the configuration contains <code>services.dovecot2.sieve.scripts</code>. | ||
[[Category:Mail Server]] | |||
[[Category:Server]] |