]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - systems/eldiron/mail/dovecot.nix
Squash changes containing private information
[perso/Immae/Config/Nix.git] / systems / eldiron / mail / dovecot.nix
diff --git a/systems/eldiron/mail/dovecot.nix b/systems/eldiron/mail/dovecot.nix
new file mode 100644 (file)
index 0000000..a1282e3
--- /dev/null
@@ -0,0 +1,348 @@
+{ lib, pkgs, config, ... }:
+let
+  sieve_bin = pkgs.runCommand "sieve_bin" {
+    buildInputs = [ pkgs.makeWrapper ];
+  } ''
+    cp -a ${./sieve_bin} $out
+    chmod -R u+w $out
+    patchShebangs $out
+    for i in $out/*; do
+      wrapProgram "$i" --prefix PATH : ${lib.makeBinPath [ pkgs.coreutils ]}
+    done
+    '';
+in
+{
+  config = lib.mkIf config.myServices.mail.enable {
+    myServices.dns.zones."immae.eu".subdomains =
+      with config.myServices.dns.helpers;
+      {
+        imap = ips servers.eldiron.ips.main;
+        pop3 = ips servers.eldiron.ips.main;
+      };
+
+    myServices.chatonsProperties.services.email = {
+      file.datetime = "2022-08-22T01:00:00";
+      service = {
+        name = "E-mail account";
+        description = "Compte e-mail avec configuration imap et smtp/pop3";
+        logo = "https://www.dovecot.org/wp-content/uploads/2021/09/favicon.ico";
+        website = "https://mail.immae.eu/";
+        status.level = "OK";
+        status.description = "OK";
+        registration."" = ["MEMBER" "CLIENT"];
+        registration.load = "OPEN";
+        install.type = "PACKAGE";
+      };
+      software = {
+        name = "Dovecot";
+        website = "https://www.dovecot.org/";
+        license.url = "https://github.com/dovecot/core/blob/main/COPYING";
+        license.name = "MIT and LGPLv2.1 Licenses";
+        version = pkgs.dovecot.version;
+        source.url = "https://github.com/dovecot/core";
+        modules = ["roundcube" "rainloop"] ++ map (a: a.pname) config.services.dovecot2.modules;
+      };
+    };
+    systemd.services.dovecot2.serviceConfig.Slice = "mail.slice";
+    secrets.keys."dovecot/ldap" = {
+      user = config.services.dovecot2.user;
+      group = config.services.dovecot2.group;
+      permissions = "0400";
+      text = ''
+        hosts = ${config.myEnv.mail.dovecot.ldap.host}
+        tls = yes
+
+        dn = ${config.myEnv.mail.dovecot.ldap.dn}
+        dnpass = ${config.myEnv.mail.dovecot.ldap.password}
+
+        auth_bind = yes
+
+        ldap_version = 3
+
+        base = ${config.myEnv.mail.dovecot.ldap.base}
+        scope = subtree
+
+        pass_filter = ${config.myEnv.mail.dovecot.ldap.filter}
+        pass_attrs = ${config.myEnv.mail.dovecot.ldap.pass_attrs}
+
+        user_attrs = ${config.myEnv.mail.dovecot.ldap.user_attrs}
+        user_filter = ${config.myEnv.mail.dovecot.ldap.filter}
+        iterate_attrs = ${config.myEnv.mail.dovecot.ldap.iterate_attrs}
+        iterate_filter = ${config.myEnv.mail.dovecot.ldap.iterate_filter}
+        '';
+    };
+
+    users.users.vhost = {
+      group = "vhost";
+      uid = config.ids.uids.vhost;
+    };
+    users.groups.vhost.gid = config.ids.gids.vhost;
+    users.users."${config.services.dovecot2.user}".extraGroups = [ "acme" ];
+
+    nixpkgs.overlays = [
+      (self: super: {
+        dovecot = super.dovecot.override { openldap = self.openldap_libressl_cyrus; };
+      })
+    ];
+
+    # https://blog.zeninc.net/index.php?post/2018/04/01/Un-annuaire-pour-les-gouverner-tous.......
+    services.dovecot2 = {
+      enable = true;
+      enablePAM = false;
+      enablePop3 = true;
+      enableImap = true;
+      enableLmtp = true;
+      protocols = [ "sieve" ];
+      modules = [
+        pkgs.dovecot_pigeonhole
+        pkgs.dovecot_fts_xapian
+      ];
+      mailUser = "vhost";
+      mailGroup = "vhost";
+      createMailUser = false;
+      mailboxes = {
+        Trash  = { auto = "subscribe"; specialUse = "Trash"; };
+        Junk   = { auto = "subscribe"; specialUse = "Junk"; };
+        Sent   = { auto = "subscribe"; specialUse = "Sent"; };
+        Drafts = { auto = "subscribe"; specialUse = "Drafts"; };
+      };
+      mailLocation = "mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap";
+      sslServerCert = "/etc/dovecot/fullchain.pem";
+      sslServerKey = "/var/lib/acme/mail/key.pem";
+      sslCACert = "/etc/dovecot/fullchain.pem";
+      extraConfig = builtins.concatStringsSep "\n" [
+        # For printer which doesn’t support elliptic curve
+        ''
+          ssl_alt_cert = </etc/dovecot/fullchain-rsa.pem
+          ssl_alt_key = </var/lib/acme/mail-rsa/key.pem
+        ''
+
+        ''
+          postmaster_address = postmaster@immae.eu
+          mail_attribute_dict = file:%h/dovecot-attributes
+          imap_idle_notify_interval = 20 mins
+          namespace inbox {
+            type = private
+            separator = /
+            inbox = yes
+            list = yes
+          }
+        ''
+
+        # ACL
+        ''
+          mail_plugins = $mail_plugins acl
+          plugin {
+            acl = vfile:${pkgs.writeText "dovecot-acl" ''
+              Backup/* owner lrp
+              ''}
+            acl_globals_only = yes
+          }
+        ''
+
+        # Full text search
+        ''
+          # needs to be bigger than any mailbox size
+          default_vsz_limit = 2GB
+          mail_plugins = $mail_plugins fts fts_xapian
+          plugin {
+            plugin = fts fts_xapian
+            fts = xapian
+            fts_xapian = partial=2 full=20
+            fts_autoindex = yes
+            fts_autoindex_exclude = \Junk
+            fts_autoindex_exclude2 = \Trash
+            fts_autoindex_exclude3 = Virtual/*
+          }
+        ''
+
+        # Antispam
+        # https://docs.iredmail.org/dovecot.imapsieve.html
+        ''
+        # imap_sieve plugin added below
+
+        plugin {
+            sieve_plugins = sieve_imapsieve sieve_extprograms
+            imapsieve_url = sieve://127.0.0.1:4190
+
+            sieve_before = file:${./sieve_scripts}/backup.sieve;bindir=/var/lib/vhost/.sieve_bin
+
+            # From elsewhere to Junk folder
+            imapsieve_mailbox1_name = Junk
+            imapsieve_mailbox1_causes = COPY APPEND
+            imapsieve_mailbox1_before = file:${./sieve_scripts}/report_spam.sieve;bindir=/var/lib/vhost/.imapsieve_bin
+
+            # From Junk folder to elsewhere
+            imapsieve_mailbox2_name = *
+            imapsieve_mailbox2_from = Junk
+            imapsieve_mailbox2_causes = COPY
+            imapsieve_mailbox2_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
+
+            # From anywhere to NoJunk folder
+            imapsieve_mailbox3_name = NoJunk
+            imapsieve_mailbox3_causes = COPY APPEND
+            imapsieve_mailbox3_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
+
+            sieve_pipe_bin_dir = ${sieve_bin}
+
+            sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
+        }
+        ''
+        # Services to listen
+        ''
+        service imap-login {
+          inet_listener imap {
+          }
+          inet_listener imaps {
+          }
+        }
+        service pop3-login {
+          inet_listener pop3 {
+          }
+          inet_listener pop3s {
+          }
+        }
+        service imap {
+        }
+        service pop3 {
+        }
+        service auth {
+          unix_listener auth-userdb {
+          }
+          unix_listener ${config.services.postfix.config.queue_directory}/private/auth {
+            mode = 0666
+          }
+        }
+        service auth-worker {
+        }
+        service dict {
+          unix_listener dict {
+          }
+        }
+        service stats {
+          unix_listener stats-reader {
+            user = vhost
+            group = vhost
+            mode = 0660
+          }
+          unix_listener stats-writer {
+            user = vhost
+            group = vhost
+            mode = 0660
+          }
+        }
+        ''
+
+        # Authentification
+        ''
+        first_valid_uid = ${toString config.ids.uids.vhost}
+        disable_plaintext_auth = yes
+        passdb {
+          driver = ldap
+          args = ${config.secrets.fullPaths."dovecot/ldap"}
+        }
+        userdb {
+          driver = ldap
+          args = ${config.secrets.fullPaths."dovecot/ldap"}
+        }
+        ''
+
+        # Zlib
+        ''
+        mail_plugins = $mail_plugins zlib
+        plugin {
+          zlib_save_level = 6
+          zlib_save = gz
+        }
+        ''
+
+        # Sieve
+        ''
+        plugin {
+          sieve = file:~/sieve;bindir=~/.sieve-bin;active=~/.dovecot.sieve
+        }
+        service managesieve-login {
+        }
+        service managesieve {
+        }
+        ''
+
+        # Virtual mailboxes
+        ''
+        mail_plugins = $mail_plugins virtual
+        namespace Virtual {
+          prefix = Virtual/
+          location = virtual:~/Virtual
+        }
+        ''
+
+        # Protocol specific configuration
+        # Needs to come last if there are mail_plugins entries
+        ''
+        protocol imap {
+          mail_plugins = $mail_plugins imap_sieve imap_acl
+        }
+        protocol lda {
+          mail_plugins = $mail_plugins sieve
+        }
+        ''
+      ];
+    };
+    networking.firewall.allowedTCPPorts = [ 110 143 993 995 4190 ];
+    system.activationScripts.dovecot = {
+      deps = [ "users" ];
+      text  =''
+        install -m 0755 -o vhost -g vhost -d /var/lib/vhost
+        '';
+    };
+
+    services.cron.systemCronJobs = let
+      cron_script = pkgs.writeScriptBin "cleanup-imap-folders" ''
+        ${pkgs.dovecot}/bin/doveadm expunge -A MAILBOX "Backup/*" NOT FLAGGED BEFORE 8w 2>&1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB"
+        ${pkgs.dovecot}/bin/doveadm expunge -A MAILBOX Junk SEEN NOT FLAGGED BEFORE 4w 2>&1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB"
+        ${pkgs.dovecot}/bin/doveadm expunge -A MAILBOX Trash NOT FLAGGED BEFORE 4w 2>&1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB"
+        '';
+      in
+      [
+        "0 2 * * * root ${cron_script}/bin/cleanup-imap-folders"
+      ];
+    security.acme.certs."mail-rsa" = {
+      postRun = ''
+        systemctl restart dovecot2.service
+      '';
+      extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
+    };
+    security.acme.certs."mail" = {
+      postRun = ''
+        systemctl restart dovecot2.service
+      '';
+      extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
+    };
+    myServices.monitoring.fromMasterActivatedPlugins = [ "imap" "tcp" ];
+    myServices.monitoring.fromMasterObjects.service = [
+      {
+        service_description = "imap connection works";
+        host_name = config.hostEnv.fqdn;
+        use = "external-service";
+        check_command = "check_imap_connection";
+
+        servicegroups = "webstatus-remote-services,webstatus-email";
+        _webstatus_name = "IMAP";
+        _webstatus_url = "imap.immae.eu";
+      }
+
+      {
+        service_description = "imap SSL is up to date";
+        host_name = config.hostEnv.fqdn;
+        use = "external-service";
+        check_command = ["check_tcp_ssl" "993"];
+
+        servicegroups = "webstatus-ssl";
+        _webstatus_name = "IMAP";
+        _webstatus_url = "imap.immae.eu";
+      }
+
+    ];
+  };
+}
+