diff options
Diffstat (limited to 'hosts/surtr/email/default.nix')
-rw-r--r-- | hosts/surtr/email/default.nix | 148 |
1 files changed, 130 insertions, 18 deletions
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 @@ | |||
3 | with lib; | 3 | with lib; |
4 | 4 | ||
5 | let | 5 | let |
6 | compileSieve = name: text: pkgs.runCommand name {} '' | 6 | dovecotSievePipeBin = pkgs.stdenv.mkDerivation { |
7 | mkdir $out | 7 | name = "dovecot-sieve-pipe-bin"; |
8 | cp ${pkgs.writeText name '' | 8 | src = ./dovecot-pipe-bin; |
9 | ''} $out/${name} | 9 | buildInputs = with pkgs; [ makeWrapper coreutils bash rspamd ]; |
10 | ${pkgs.dovecot_pigeonhole}/bin/sievec $out/${name} | 10 | buildCommand = '' |
11 | ''; | 11 | mkdir -p $out/pipe/bin |
12 | cp $src/* $out/pipe/bin/ | ||
13 | chmod a+x $out/pipe/bin/* | ||
14 | patchShebangs $out/pipe/bin | ||
15 | |||
16 | for file in $out/pipe/bin/*; do | ||
17 | wrapProgram $file \ | ||
18 | --set PATH "${pkgs.coreutils}/bin:${pkgs.rspamd}/bin" | ||
19 | done | ||
20 | ''; | ||
21 | }; | ||
12 | in { | 22 | in { |
13 | config = { | 23 | config = { |
14 | nixpkgs.overlays = [ | 24 | nixpkgs.overlays = [ |
@@ -193,7 +203,21 @@ in { | |||
193 | services.rspamd = { | 203 | services.rspamd = { |
194 | enable = true; | 204 | enable = true; |
195 | workers = { | 205 | workers = { |
196 | controller = {}; | 206 | controller = { |
207 | type = "controller"; | ||
208 | count = 1; | ||
209 | bindSockets = [ | ||
210 | { mode = "0660"; | ||
211 | socket = "/run/rspamd/worker-controller.sock"; | ||
212 | owner = config.services.rspamd.user; | ||
213 | group = config.services.rspamd.group; | ||
214 | } | ||
215 | ]; | ||
216 | includes = []; | ||
217 | extraConfig = '' | ||
218 | static_dir = "''${WWWDIR}"; # Serve the web UI static assets | ||
219 | ''; | ||
220 | }; | ||
197 | external = { | 221 | external = { |
198 | type = "rspamd_proxy"; | 222 | type = "rspamd_proxy"; |
199 | bindSockets = [ | 223 | bindSockets = [ |
@@ -205,6 +229,7 @@ in { | |||
205 | ]; | 229 | ]; |
206 | extraConfig = '' | 230 | extraConfig = '' |
207 | milter = yes; | 231 | milter = yes; |
232 | timeout = 120s; | ||
208 | 233 | ||
209 | upstream "local" { | 234 | upstream "local" { |
210 | default = yes; | 235 | default = yes; |
@@ -269,7 +294,7 @@ in { | |||
269 | }; | 294 | }; |
270 | }; | 295 | }; |
271 | 296 | ||
272 | users.groups.${config.services.rspamd.group}.members = [ config.services.postfix.user ]; | 297 | users.groups.${config.services.rspamd.group}.members = [ config.services.postfix.user "dovecot2" ]; |
273 | 298 | ||
274 | services.redis.servers.rspamd.enable = true; | 299 | services.redis.servers.rspamd.enable = true; |
275 | 300 | ||
@@ -281,8 +306,9 @@ in { | |||
281 | sslServerCert = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.pem"; | 306 | sslServerCert = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.pem"; |
282 | sslServerKey = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.key.pem"; | 307 | sslServerKey = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.key.pem"; |
283 | sslCACert = toString ./ca/ca.crt; | 308 | sslCACert = toString ./ca/ca.crt; |
284 | mailLocation = "maildir:/var/lib/mail/%u/maildir:UTF-8"; | 309 | mailLocation = "maildir:/var/lib/mail/%u/maildir:UTF-8:INDEX=/var/lib/dovecot/indices/%u"; |
285 | modules = with pkgs; [ dovecot_pigeonhole ]; | 310 | modules = with pkgs; [ dovecot_pigeonhole dovecot_fts_xapian ]; |
311 | mailPlugins.globally.enable = [ "fts" "fts_xapian" ]; | ||
286 | protocols = [ "lmtp" "sieve" ]; | 312 | protocols = [ "lmtp" "sieve" ]; |
287 | extraConfig = let | 313 | extraConfig = let |
288 | dovecotSqlConf = pkgs.writeText "dovecot-sql.conf" '' | 314 | dovecotSqlConf = pkgs.writeText "dovecot-sql.conf" '' |
@@ -377,6 +403,23 @@ in { | |||
377 | separator = / | 403 | separator = / |
378 | inbox = yes | 404 | inbox = yes |
379 | prefix = | 405 | prefix = |
406 | |||
407 | mailbox Trash { | ||
408 | auto = no | ||
409 | special_use = \Trash | ||
410 | } | ||
411 | mailbox Drafts { | ||
412 | auto = no | ||
413 | special_use = \Drafts | ||
414 | } | ||
415 | mailbox Sent { | ||
416 | auto = subscribe | ||
417 | special_use = \Sent | ||
418 | } | ||
419 | mailbox "Sent Messages" { | ||
420 | auto = no | ||
421 | special_use = \Sent | ||
422 | } | ||
380 | } | 423 | } |
381 | 424 | ||
382 | plugin { | 425 | plugin { |
@@ -410,20 +453,89 @@ in { | |||
410 | 453 | ||
411 | plugin { | 454 | plugin { |
412 | sieve_plugins = sieve_imapsieve | 455 | sieve_plugins = sieve_imapsieve |
413 | 456 | sieve = file:~/sieve;active=~/dovecot.sieve | |
414 | sieve_redirect_envelope_from = orig_recipient | 457 | sieve_redirect_envelope_from = orig_recipient |
415 | sieve_before = /etc/dovecot/sieve_before.d | 458 | sieve_before = /etc/dovecot/sieve_before.d |
459 | |||
460 | sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment | ||
461 | sieve_pipe_bin_dir = ${dovecotSievePipeBin}/pipe/bin | ||
462 | |||
463 | imapsieve_mailbox1_name = * | ||
464 | imapsieve_mailbox1_causes = FLAG | ||
465 | imapsieve_mailbox1_before = /etc/dovecot/sieve_flag.d | ||
466 | } | ||
467 | |||
468 | plugin { | ||
469 | plugin = fts fts_xapian | ||
470 | fts = xapian | ||
471 | fts_xapian = partial=2 full=20 attachments=1 verbose=1 | ||
472 | |||
473 | fts_autoindex = yes | ||
474 | |||
475 | fts_enforced = no | ||
476 | } | ||
477 | |||
478 | service indexer-worker { | ||
479 | vsz_limit = ${toString (1024 * 1024 * 1024)} | ||
416 | } | 480 | } |
417 | ''; | 481 | ''; |
418 | }; | 482 | }; |
419 | 483 | ||
420 | environment.etc."dovecot/sieve_before.d/tag-junk.sieve".text = '' | 484 | systemd.services.dovecot-fts-xapian-optimize = { |
421 | require ["imap4flags"]; | 485 | description = "Optimize dovecot indices for fts_xapian"; |
486 | requisite = [ "dovecot2.service" ]; | ||
487 | after = [ "dovecot2.service" ]; | ||
488 | startAt = "*-*-* 22:00:00 Europe/Berlin"; | ||
489 | serviceConfig = { | ||
490 | Type = "oneshot"; | ||
491 | ExecStart = "${pkgs.dovecot}/bin/doveadm fts optimize -A"; | ||
492 | PrivateDevices = true; | ||
493 | PrivateNetwork = true; | ||
494 | ProtectKernelTunables = true; | ||
495 | ProtectKernelModules = true; | ||
496 | ProtectControlGroups = true; | ||
497 | ProtectHome = true; | ||
498 | ProtectSystem = true; | ||
499 | PrivateTmp = true; | ||
500 | }; | ||
501 | }; | ||
502 | systemd.timers.dovecot-fts-xapian-optimize = { | ||
503 | timerConfig = { | ||
504 | RandomizedDelaySec = 4 * 3600; | ||
505 | }; | ||
506 | }; | ||
507 | |||
508 | environment.etc = { | ||
509 | "dovecot/sieve_before.d/tag-junk.sieve".text = '' | ||
510 | require ["imap4flags"]; | ||
422 | 511 | ||
423 | if header :contains "X-Spam-Flag" "YES" { | 512 | if header :contains "X-Spam-Flag" "YES" { |
424 | addflag ["\\Junk"]; | 513 | addflag ["\\Junk"]; |
425 | } | 514 | } |
426 | ''; | 515 | ''; |
516 | |||
517 | "dovecot/sieve_flag.d/learn-junk.sieve".text = '' | ||
518 | require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables", "imap4flags"]; | ||
519 | |||
520 | if environment :matches "imap.user" "*" { | ||
521 | set "username" "''${1}"; | ||
522 | } | ||
523 | |||
524 | if environment :contains "imap.changedflags" "\\Junk" { | ||
525 | if hasflag "\\Junk" { | ||
526 | pipe :copy "learn_spam.sh" [ "''${username}" ]; | ||
527 | } else { | ||
528 | if environment :matches "imap.mailbox" "*" { | ||
529 | set "mailbox" "''${1}"; | ||
530 | } | ||
531 | |||
532 | if not string "''${mailbox}" "Trash" { | ||
533 | pipe :copy "learn_ham.sh" [ "''${username}" ]; | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | ''; | ||
538 | }; | ||
427 | 539 | ||
428 | security.dhparams = { | 540 | security.dhparams = { |
429 | params = { | 541 | params = { |
@@ -452,7 +564,7 @@ in { | |||
452 | 564 | ||
453 | systemd.services.dovecot2 = { | 565 | systemd.services.dovecot2 = { |
454 | preStart = '' | 566 | preStart = '' |
455 | for f in /etc/dovecot/sieve_before.d/*.sieve; do | 567 | for f in /etc/dovecot/sieve_flag.d/*.sieve /etc/dovecot/sieve_before.d/*.sieve; do |
456 | ${pkgs.dovecot_pigeonhole}/bin/sievec $f | 568 | ${pkgs.dovecot_pigeonhole}/bin/sievec $f |
457 | done | 569 | done |
458 | ''; | 570 | ''; |