Dovecot: Difference between revisions

drop 24.05 compat
Upgrade settings to Dovecot 2.4 and new `dovecot2.settings` option
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This article is about [https://www.dovecot.org/ dovecot], a secure imap server.
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.


== Troubleshooting ==
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.


=== sievec fails to compile basic sieve scripts ===
= 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.4.4/howto/lmtp/postfix.html
    # https://doc.dovecot.org/2.4.4/howto/sasl/postfix.html
    settings = {
      # dovecot_config_version and dovecot_storage_version must be explicitly set
      # to retain compatibility with future updates.
      dovecot_config_version = "2.4.2";
      dovecot_storage_version = "2.4.0";
 
      auth_username_format = "%{user | lower}";
      auth_mechanisms = [ "plain" ];
      "passdb passwd-file" = {
        driver = "passwd-file";
        passwd_file_path = config.age.secrets.dovecot.path;
      };
    };
  };
</syntaxhighlight>
 
= Setup virtual users =
<syntaxhighlight lang="nix"># /var/spool/mail/vmail needs to be created and owned by vmail
  systemd.tmpfiles.rules = [
    "d /var/spool/mail/vmail 0700 vmail vmail -"
  ];
 
  services.dovecot2 = {
    settings = {
      # dovecot_config_version and dovecot_storage_version must be explicitly set
      # to retain compatibility with future updates.
      dovecot_config_version = "2.4.2";
      dovecot_config_version = "2.4.0";
 
      # If config.services.dovecot2.createMailUser is true (which is the default),
      # the user defined in mail_uid and mail_gid will be automatically created.
      mail_uid = "vmail";
      mail_gid = "vmail";
 
      # implement virtual users
      # https://doc.dovecot.org/2.4.4/howto/virtual/simple_install.html
      # store virtual mail under /var/spool/mail/vmail/<DOMAIN>/<USER>/Maildir
      mail_driver = "maildir";
      mail_path = "~/Maildir";
 
      "namespace inbox" = {
        "mailbox All" = { auto = "create"; special_use = "\\All"; };
        "mailbox Archive" = { auto = "create"; special_use = "\\Archive"; };
        "mailbox Drafts" = { auto = "create"; special_use = "\\Drafts"; };
        "mailbox Flagged" = { auto = "create"; special_use = "\\Flagged"; };
        "mailbox Junk" = { auto = "create"; special_use = "\\Junk"; autoexpunge = "60d"; };
        "mailbox Sent" = { auto = "create"; special_use = "\\Sent"; };
        "mailbox Trash" = { auto = "create"; special_use = "\\Trash"; autoexpunge = "60d"; };
      };
 
      "userdb static" = {
        fields = {
          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">  # create path for dovecot socket
  systemd.tmpfiles.rules = [
    "d /var/spool/postfix 0700 postfix postfix -";
  ];
 
  services.dovecot2 = {
    settings = {
      # dovecot_config_version and dovecot_storage_version must be explicitly set
      # to retain compatibility with future updates.
      dovecot_config_version = "2.4.2";
      dovecot_config_version = "2.4.0";
 
      protocols = [ "imap" "lmtp" ];
 
      # https://doc.dovecot.org/2.4.4/howto/lmtp/postfix.html
      "service lmtp" = {
        # Note that the socket needs to be placed here because Postfix access is limited to this directory
        "unix_listener /var/spool/postfix/dovecot-lmtp" = {
          user = "postfix";
          group = "postfix";
          mode = "0600";
        };
      };
 
      # https://doc.dovecot.org/2.4.4/howto/sasl/postfix.html
      "service auth" = {
        "unix_listener /var/spool/postfix/auth" = {
          user = "postfix";
          group = "postfix";
          mode = "0600";
        };
      };
    };
 
  # postfix connection to dovecot
  services.postfix.config = {
    # https://doc.dovecot.org/2.4.4/howto/lmtp/postfix.html
    mailbox_transport = "lmtp:unix:/var/spool/postfix/dovecot-lmtp";
    virtual_transport = "lmtp:unix:/var/spool/postfix/dovecot-lmtp";
 
    # https://doc.dovecot.org/2.4.4/howto/sasl/postfix.html
    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";
  };
</syntaxhighlight>
 
= Configure SSL Certificates =
<syntaxhighlight lang="nix">
  services.dovecot2 = {
    settings = {
      # dovecot_config_version and dovecot_storage_version must be explicitly set
      # to retain compatibility with future updates.
      dovecot_config_version = "2.4.2";
      dovecot_config_version = "2.4.0";
 
      # https://doc.dovecot.org/2.4.4/core/config/ssl.html
      ssl = true; # see also "required"
      ssl_server_cert_file = "${sslCertDir}/fullchain.pem";
      ssl_server_key_file = "${sslCertDir}/key.pem";
      ssl_server_ca_file = "${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) =
{{Outdated}}
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:
Sieve commands such as ''fileinto'' need to be enabled explicitly with: