From 309ccbd03c262743cc339887e70082757b3cd247 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 10 May 2022 14:23:12 +0200 Subject: surtr: ... --- hosts/surtr/email/ca/.gitignore | 1 + hosts/surtr/email/default.nix | 148 ++++++++++++++++++++--- hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh | 3 + hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh | 3 + 4 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh create mode 100644 hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh diff --git a/hosts/surtr/email/ca/.gitignore b/hosts/surtr/email/ca/.gitignore index bc1d3eaf..adafac92 100644 --- a/hosts/surtr/email/ca/.gitignore +++ b/hosts/surtr/email/ca/.gitignore @@ -2,4 +2,5 @@ *.cnf *.old *.crt +*.pkcs12 certs \ No newline at end of file diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix index 5d366ac5..e005a3c1 100644 --- a/hosts/surtr/email/default.nix +++ b/hosts/surtr/email/default.nix @@ -3,12 +3,22 @@ with lib; let - compileSieve = name: text: pkgs.runCommand name {} '' - mkdir $out - cp ${pkgs.writeText name '' - ''} $out/${name} - ${pkgs.dovecot_pigeonhole}/bin/sievec $out/${name} - ''; + dovecotSievePipeBin = pkgs.stdenv.mkDerivation { + name = "dovecot-sieve-pipe-bin"; + src = ./dovecot-pipe-bin; + buildInputs = with pkgs; [ makeWrapper coreutils bash rspamd ]; + buildCommand = '' + mkdir -p $out/pipe/bin + cp $src/* $out/pipe/bin/ + chmod a+x $out/pipe/bin/* + patchShebangs $out/pipe/bin + + for file in $out/pipe/bin/*; do + wrapProgram $file \ + --set PATH "${pkgs.coreutils}/bin:${pkgs.rspamd}/bin" + done + ''; + }; in { config = { nixpkgs.overlays = [ @@ -193,7 +203,21 @@ in { services.rspamd = { enable = true; workers = { - controller = {}; + controller = { + type = "controller"; + count = 1; + bindSockets = [ + { mode = "0660"; + socket = "/run/rspamd/worker-controller.sock"; + owner = config.services.rspamd.user; + group = config.services.rspamd.group; + } + ]; + includes = []; + extraConfig = '' + static_dir = "''${WWWDIR}"; # Serve the web UI static assets + ''; + }; external = { type = "rspamd_proxy"; bindSockets = [ @@ -205,6 +229,7 @@ in { ]; extraConfig = '' milter = yes; + timeout = 120s; upstream "local" { default = yes; @@ -269,7 +294,7 @@ in { }; }; - users.groups.${config.services.rspamd.group}.members = [ config.services.postfix.user ]; + users.groups.${config.services.rspamd.group}.members = [ config.services.postfix.user "dovecot2" ]; services.redis.servers.rspamd.enable = true; @@ -281,8 +306,9 @@ in { sslServerCert = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.pem"; sslServerKey = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.key.pem"; sslCACert = toString ./ca/ca.crt; - mailLocation = "maildir:/var/lib/mail/%u/maildir:UTF-8"; - modules = with pkgs; [ dovecot_pigeonhole ]; + mailLocation = "maildir:/var/lib/mail/%u/maildir:UTF-8:INDEX=/var/lib/dovecot/indices/%u"; + modules = with pkgs; [ dovecot_pigeonhole dovecot_fts_xapian ]; + mailPlugins.globally.enable = [ "fts" "fts_xapian" ]; protocols = [ "lmtp" "sieve" ]; extraConfig = let dovecotSqlConf = pkgs.writeText "dovecot-sql.conf" '' @@ -377,6 +403,23 @@ in { separator = / inbox = yes prefix = + + mailbox Trash { + auto = no + special_use = \Trash + } + mailbox Drafts { + auto = no + special_use = \Drafts + } + mailbox Sent { + auto = subscribe + special_use = \Sent + } + mailbox "Sent Messages" { + auto = no + special_use = \Sent + } } plugin { @@ -410,20 +453,89 @@ in { plugin { sieve_plugins = sieve_imapsieve - + sieve = file:~/sieve;active=~/dovecot.sieve sieve_redirect_envelope_from = orig_recipient sieve_before = /etc/dovecot/sieve_before.d + + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment + sieve_pipe_bin_dir = ${dovecotSievePipeBin}/pipe/bin + + imapsieve_mailbox1_name = * + imapsieve_mailbox1_causes = FLAG + imapsieve_mailbox1_before = /etc/dovecot/sieve_flag.d + } + + plugin { + plugin = fts fts_xapian + fts = xapian + fts_xapian = partial=2 full=20 attachments=1 verbose=1 + + fts_autoindex = yes + + fts_enforced = no + } + + service indexer-worker { + vsz_limit = ${toString (1024 * 1024 * 1024)} } ''; }; - environment.etc."dovecot/sieve_before.d/tag-junk.sieve".text = '' - require ["imap4flags"]; + systemd.services.dovecot-fts-xapian-optimize = { + description = "Optimize dovecot indices for fts_xapian"; + requisite = [ "dovecot2.service" ]; + after = [ "dovecot2.service" ]; + startAt = "*-*-* 22:00:00 Europe/Berlin"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.dovecot}/bin/doveadm fts optimize -A"; + PrivateDevices = true; + PrivateNetwork = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectSystem = true; + PrivateTmp = true; + }; + }; + systemd.timers.dovecot-fts-xapian-optimize = { + timerConfig = { + RandomizedDelaySec = 4 * 3600; + }; + }; + + environment.etc = { + "dovecot/sieve_before.d/tag-junk.sieve".text = '' + require ["imap4flags"]; - if header :contains "X-Spam-Flag" "YES" { - addflag ["\\Junk"]; - } - ''; + if header :contains "X-Spam-Flag" "YES" { + addflag ["\\Junk"]; + } + ''; + + "dovecot/sieve_flag.d/learn-junk.sieve".text = '' + require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables", "imap4flags"]; + + if environment :matches "imap.user" "*" { + set "username" "''${1}"; + } + + if environment :contains "imap.changedflags" "\\Junk" { + if hasflag "\\Junk" { + pipe :copy "learn_spam.sh" [ "''${username}" ]; + } else { + if environment :matches "imap.mailbox" "*" { + set "mailbox" "''${1}"; + } + + if not string "''${mailbox}" "Trash" { + pipe :copy "learn_ham.sh" [ "''${username}" ]; + } + } + } + ''; + }; security.dhparams = { params = { @@ -452,7 +564,7 @@ in { systemd.services.dovecot2 = { preStart = '' - for f in /etc/dovecot/sieve_before.d/*.sieve; do + for f in /etc/dovecot/sieve_flag.d/*.sieve /etc/dovecot/sieve_before.d/*.sieve; do ${pkgs.dovecot_pigeonhole}/bin/sievec $f done ''; diff --git a/hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh b/hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh new file mode 100644 index 00000000..6e0bb076 --- /dev/null +++ b/hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh @@ -0,0 +1,3 @@ +#!/bin/bash -e + +exec rspamc -h /run/rspamd/worker-controller.sock learn_ham diff --git a/hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh b/hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh new file mode 100644 index 00000000..91dbd6c1 --- /dev/null +++ b/hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh @@ -0,0 +1,3 @@ +#!/bin/bash -e + +exec rspamc -h /run/rspamd/worker-controller.sock learn_spam -- cgit v1.2.3