nix: remove upstreamed PR patches
[sourcephile-nix.git] / servers / mermet / dovecot.nix
index 5b3364b8eda106960c7fa6ba787d4fb241c11f91..2488e3cb65842ee44c50e925f222484d917d5cf9 100644 (file)
@@ -1,6 +1,6 @@
 { pkgs, lib, config, system, ... }:
 let
-  inherit (builtins) toString toFile;
+  inherit (builtins) toString toFile readFile;
   inherit (builtins.extraBuiltins) pass;
   inherit (lib) types;
   inherit (pkgs.lib) loadFile unlines unlinesAttrs unlinesValues unwords;
@@ -8,7 +8,7 @@ let
   inherit (config.services) dovecot2 postfix openldap;
 
   # NOTE: nixpkgs' dovecot2.stateDir is currently not exported
-  stateDir    = "/var/lib/dovecot";
+  stateDir = "/var/lib/dovecot";
 
   sieve_pipe_bin_dir = pkgs.buildEnv {
     name = "sieve_pipe_bin_dir";
@@ -61,28 +61,42 @@ let
 in
 {
 imports = [
-  dovecot/autoconfig.nix
+  dovecot/sourcephile.fr.nix
+  dovecot/autogeree.net.nix
 ];
+users.groups.acme.members = [ dovecot2.user ];
 systemd.services.dovecot2 = {
   after = [
     "postfix.service"
     "openldap.service"
-    "${networking.domain}.key.pem-key.service"
   ];
+  /*
+  preStart = ''
+    # SEE: http://wiki2.dovecot.org/SharedMailboxes/Permissions
+    install -D -d -m 0771 \
+     -o "${dovecot2.user}" \
+     -g "${dovecot2.group}" \
+     ${stateDir}/mail
+  '';
+  */
 };
 #users.users."${dovecot2.mailUser}".isSystemUser = true; # Fix nixpkgs
 services.dovecot2 = {
-  enable    = true;
-  modules   = [
+  enable = true;
+  modules = [
     pkgs.dovecot_pigeonhole
     pkgs.dovecot_fts_xapian
   ];
   enablePAM = false;
   enableImap = true;
   enableLmtp = true;
-  enablePop3 = true;
+  enablePop3 = false;
   protocols = [ "sieve" ];
-  mailLocation = "sdbox:${stateDir}/mail/%d/%n/mail.d:UTF-8:CONTROL=${stateDir}/control/%d/%n:INDEX=${stateDir}/index/%d/%n";
+  # If needed, may be overrided by userdb_mail= in passdb, or mail= in userdb
+  # Here INDEX and CONTROL are separated,
+  # it's not useful since there is no quota at the filesystem level
+  # it's just to let this possibility later on.
+  mailLocation = "sdbox:${stateDir}/home/%d/%n/mail:UTF-8:CONTROL=${stateDir}/control/%d/%n:INDEX=${stateDir}/index/%d/%n";
   createMailUser = false;
   mailUser = "";
   mailGroup = "";
@@ -93,21 +107,21 @@ services.dovecot2 = {
   extraConfig = ''
     auth_verbose = no
     auth_debug = no
-    mail_debug = yes
+    mail_debug = no
     verbose_ssl = no
     log_timestamp = "%Y-%m-%d %H:%M:%S "
 
     ssl = required
     ssl_dh = <${../../../sec/openssl/dh.pem}
     ssl_cipher_list = HIGH:!LOW:!SSLv2:!EXP:!aNULL
-    ssl_cert = <${loadFile (../../../sec + "/openssl/${networking.domain}/cert.self-signed.pem")}
-    ssl_key = </run/keys/${networking.domain}.key.pem
+    ssl_prefer_server_ciphers = yes
+    ssl_cert = </var/lib/acme/${networking.domain}/fullchain.pem
+    ssl_key = </var/lib/acme/${networking.domain}/key.pem
     #ssl_ca = <''${caPath}
     #ssl_verify_client_cert = yes
 
     listen = *
-    # If needed, may be overrided by userdb_mail
-    mail_home = ${stateDir}/mail/%d/%n
+    mail_home = ${stateDir}/home/%d/%n
     # Read multiple mails in parallel, improves performance
     mail_prefetch_count = 20
     # Default VSZ (virtual memory size) limit for service processes. This is mainly
@@ -115,26 +129,25 @@ services.dovecot2 = {
     # Increased for fts_xapian.
     default_vsz_limit = 1G
 
-    passdb {
-      driver = ldap
-      args = ${loadFile (dovecot/ldap + "/${networking.domainBase}.conf")}
-      default_fields = userdb_mail_access_groups=${networking.domainBase}
-      override_fields =
-    }
-    userdb {
-      driver = prefetch
-    }
-    userdb {
-      # NOTE: this userdb is only used by lda.
-      driver = ldap
-      args = ${loadFile (dovecot/ldap + "/${networking.domainBase}.conf")}
-      default_fields = mail_access_groups=${networking.domainBase}
-      override_fields =
-      skip = found
-    }
+    # DOC: https://doc.dovecot.org/configuration_manual/authentication/authentication_mechanisms/
+    # DOC: https://ldapwiki.com/wiki/DIGEST-MD5
+    # The misunderstanding is the notion "password sent over the network in plain-text" is not secure,
+    # when in fact, storing the password in the directory server using a Salted SHA-2 hash
+    # and transmitting the clear text password over a secure connection
+    # is more secure than having the directory server store the password in clear text
+    # or in a reversible encryption scheme.
+    # Therefore, SASL with DIGEST-MD5 (or CRAM-MD5) should be avoided.
+    # Use doveadm pw -s SSHA
+    # or doveadm pw -s PBKDF2 -r 10000
+    # or slappasswd -o module-load=pw-pbkdf2 -h "{PBKDF2-SHA256}"
+    auth_mechanisms = plain login
+    auth_username_format = %Ln
     service auth {
-      # FIXME: may be user=dovecot-auth with LDAP?
-      user = root
+      user = ${dovecot2.user}
+      # auth_socket_path points to this userdb socket by default. It's typically
+      # used by dovecot-lda, doveadm, possibly imap process, etc.
+      # Users that have access to this socket are able to get a list
+      # of all usernames and get results of everyone's userdb lookups.
       unix_listener auth-userdb {
         user  = ${dovecot2.user}
         group = ${dovecot2.group}
@@ -146,11 +159,11 @@ services.dovecot2 = {
         mode  = 0660
       }
     }
+    service auth-worker {
+      user = ${dovecot2.user}
+    }
     auth_cache_verify_password_with_worker = yes
-    # NOTE: if needed, may be overrided by userdb_mail
-    # NOTE: INDEX and CONTROL are on a partition without quota, as explain in the doc.
     # SEE: http://wiki2.dovecot.org/Quota/FS
-    auth_mechanisms = plain login
     # NOTE: postfix does not supply a client cert.
     auth_ssl_require_client_cert = no
     #auth_ssl_username_from_cert = yes
@@ -160,17 +173,13 @@ services.dovecot2 = {
     first_valid_uid = 1000
     disable_plaintext_auth = yes
 
-    #passdb {
-    #  driver = passwd-file
-    #  args   = scheme=crypt username_format=%n ${stateDir}/passwd/%d
-    #}
-    #userdb {
-    #  # NOTE: this userdb is only used by LDA.
-    #  driver = passwd-file
-    #  args = username_format=%n ${stateDir}/passwd/%d
-    #  #default_fields = home=${stateDir}/mail/%d/%n
-    #  skip = found
-    #}
+    userdb {
+      driver = ldap
+      # A different path than passdb's args enables non-blocking LDAP requests
+      args = ${pkgs.symlinkJoin {name="ldap"; paths=[./dovecot];}}/ldap.conf
+      default_fields =
+      override_fields =
+    }
 
     # No dirty syncs for maildir: locations which may be used directly by neomutt
     maildir_very_dirty_syncs = no
@@ -191,7 +200,7 @@ services.dovecot2 = {
       # NOTE: %var expands to the logged in user's variable, while
       #       %%var expands to the other users' variables.
       # NOTE: INDEX and CONTROL are shared, INDEXPVT is not.
-      location = sdbox:${stateDir}/mail/%%d/%%n/${stateDir}/mail.d:UTF-8:CONTROL=${stateDir}/control/%%d/%%n/Shared:INDEX=${stateDir}/index/%%d/%%n/Shared:INDEXPVT=${stateDir}/index/%d/%n/Shared/%%n
+      location = sdbox:${stateDir}/home/%%d/%%n/${stateDir}/mail:UTF-8:CONTROL=${stateDir}/control/%%d/%%n/shared:INDEX=${stateDir}/index/%%d/%%n/shared:INDEXPVT=${stateDir}/index/%d/%n/shared/%%n
       prefix = Partages+%%n+
       separator = +
       subscriptions = yes
@@ -208,7 +217,7 @@ services.dovecot2 = {
 
     mail_plugins = $mail_plugins acl
     plugin {
-      acl = vfile:/etc/dovecot/acl/global.d
+      acl = vfile:/etc/dovecot/acl/global
       acl_anyone = allow
       # NOTE: to let users LIST mailboxes shared by other users,
       #       Dovecot needs a shared mailbox dictionary.
@@ -218,6 +227,9 @@ services.dovecot2 = {
 
     mail_plugins = $mail_plugins fts fts_xapian
     plugin {
+      # WARNING: doveadm fts rescan is buggy, it will delete the index:
+      # https://dovecot.org/pipermail/dovecot/2019-February/114709.html
+      # If need be, use rather: doveadm index -u "*@sourcephile.fr" -q '*'
       plugin = fts fts_xapian
       fts = xapian
       fts_autoindex = yes
@@ -227,7 +239,9 @@ services.dovecot2 = {
       # 2 and 20 are the NGram values for header fields, which means the
       # keywords created for fields (To, Cc, ...) are between is 2 and 20 chars long.
       # Full words are also added by default.
-      fts_xapian = partial=2 full=20 verbose=0
+      fts_xapian = partial=2 full=20 attachments=1 verbose=0
+      fts_languages = en fr
+      #fts_dovecot_fs = posix:prefix=%h/fts/
     }
 
     mail_plugins = $mail_plugins quota
@@ -243,11 +257,8 @@ services.dovecot2 = {
     }
 
     protocol lda {
-      auth_socket_path = /var/run/dovecot/auth-userdb
-      hostname         = ${networking.domain}
-      info_log_path    =
-      log_path         =
-      mail_plugins     = $mail_plugins sieve
+      hostname = ${networking.domain}
+      mail_plugins = $mail_plugins sieve
       postmaster_address = postmaster+dovecot+lda@${networking.domain}
       syslog_facility = mail
     }
@@ -255,19 +266,16 @@ services.dovecot2 = {
     lda_mailbox_autosubscribe = yes
 
     protocol lmtp {
-      #info_log_path = /tmp/dovecot-lmtp.log
       mail_plugins = $mail_plugins sieve
       postmaster_address = postmaster+dovecot+lmtp@${networking.domain}
     }
     service lmtp {
-      #executable = lmtp -L
       process_min_avail = ${toString config.nix.maxJobs}
       unix_listener /var/lib/postfix/queue/private/dovecot-lmtp {
         user  = ${postfix.user}
         group = ${postfix.group}
         mode  = 0600
       }
-      #user = mail
     }
     plugin {
       # Let extension.sieve do the handling of the detail
@@ -370,21 +378,22 @@ services.dovecot2 = {
         mailbox All {
           auto = no
           comment = All messages from all mailboxes
+          # This flag is confused with \Archives by K9-Mail
           special_use = \All
         }
         mailbox Recents {
           auto = no
-          comment = All messages from all mailboxes arrived in the past 48h
+          comment = All messages from all mailboxes, arrived in the past 48h
         }
       }
     }
     plugin {
-      #sieve_default = file:${stateDir}/mail/%u/default.sieve
-      #sieve_default_name = default
       sieve_plugins = sieve_imapsieve sieve_extprograms
-      sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
+      sieve_global_extensions = +vnd.dovecot.environment +vnd.dovecot.pipe
       #sieve_extensions = +editheader
-      sieve = file:~/sieve.d;active=~/sieve
+      sieve = file:~/sieve;active=~/active.sieve
+      sieve_default = file:${stateDir}/sieve/global/default.sieve
+      sieve_default_name = main
       sieve_pipe_bin_dir = ${sieve_pipe_bin_dir}/bin
       sieve_max_script_size = 1M
       sieve_quota_max_scripts = 0
@@ -392,7 +401,7 @@ services.dovecot2 = {
       #sieve_spamtest_max_value = 10
       #sieve_spamtest_status_header = X-Spam-Score
       #sieve_spamtest_status_type = strlen
-      sieve_user_log = /var/log/dovecot/%d/sieve.%n.log
+      #sieve_user_log = ~/sieve.log
       # Enables support for user Sieve scripts in IMAP
       #imapsieve_url = sieve://mail.${networking.domain}:4190
 
@@ -419,7 +428,7 @@ services.dovecot2 = {
 
       # To fool ManageSieve clients that are focused on CMU's timesieved you can specify
       # the IMPLEMENTATION capability that the dovecot reports to clients.
-      # For example: 'Cyrus timsieved v2.2.13'
+      # For example: 'Cyrus timesieved v2.2.13'
       managesieve_implementation_string = Dovecot Pigeonhole
 
       # The maximum number of compile errors that are returned to the client upon script
@@ -453,8 +462,8 @@ services.dovecot2 = {
 
     service quota-warning {
       executable = script ${
-        pkgs.writeScript "quota-warning" ''
-          #!/bin/sh -eu
+        pkgs.writeShellScript "quota-warning" ''
+          set -eu
           PERCENT=$1
           USER=$2
           cat << EOF | ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -d $USER -o
@@ -500,21 +509,5 @@ services.dovecot2 = {
       }
     }
   '';
-  #${lib.concatMapStringsSep "\n"
-  #    (dom: ''
-  #      local_name mail.${dom} {
-  #        #ssl_ca   = <''${caPath}
-  #        ssl_cert = <${x509.cert dom}
-  #        ssl_key  = <${x509.key dom}
-  #        }
-  #    '')
-  #    dovecot2.domains
-  #}
 };
-#services.postfix.mapFiles."transport-dovecot" =
-#  toFile "transport-dovecot"
-#   (unlines
-#     (lib.mapAttrsToList
-#       (dom: {...}: "${transportSubDomain}.${dom} lmtp:unix:private/dovecot-lmtp")
-#       dovecot2.domains));
 }