summaryrefslogtreecommitdiff
path: root/hosts/surtr
diff options
context:
space:
mode:
Diffstat (limited to 'hosts/surtr')
-rw-r--r--hosts/surtr/email/ca/.gitignore1
-rw-r--r--hosts/surtr/email/default.nix148
-rw-r--r--hosts/surtr/email/dovecot-pipe-bin/learn_ham.sh3
-rw-r--r--hosts/surtr/email/dovecot-pipe-bin/learn_spam.sh3
4 files changed, 137 insertions, 18 deletions
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 @@
2*.cnf 2*.cnf
3*.old 3*.old
4*.crt 4*.crt
5*.pkcs12
5certs \ No newline at end of file 6certs \ 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 @@
3with lib; 3with lib;
4 4
5let 5let
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 };
12in { 22in {
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 '';
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 @@
1#!/bin/bash -e
2
3exec 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 @@
1#!/bin/bash -e
2
3exec rspamc -h /run/rspamd/worker-controller.sock learn_spam