Add dovecot

This commit is contained in:
Charlotte 🦝 Delenk 2022-01-20 17:02:42 +01:00
parent 9f215c77aa
commit b0b770c4d0
Signed by: darkkirb
GPG key ID: 015E3768A70AFBC5
4 changed files with 225 additions and 2 deletions

118
config/services/dovecot.nix Normal file
View file

@ -0,0 +1,118 @@
{ pkgs, ... }:
let
listenIPs = (import ../../utils/getInternalIP.nix config).listenIP;
sieves = import ../../packages/sieves.nix pkgs;
in
{
services.dovecot2 = {
enable = true;
enableImap = true;
enableLmtp = true;
enablePop3 = true;
enableQuota = true;
mailGroup = "vmail";
mailUser = "vmail";
mailLocation = "maildir:/var/vmail/%h/%n";
mailPlugins = {
globally.enable = [
"old_stats"
];
perProtocol = {
imap.enable = [
"imap_sieve"
];
lda.enable = [
"sieve"
];
lmtp.enable = [
"lmtp_sieve"
];
};
};
mailboxes = {
Drafts = {
specialUse = "Drafts";
auto = "subscribe";
};
Junk = {
specialUse = "Junk";
auto = "subscribe";
};
Trash = {
specialUse = "Trash";
auto = "subscribe";
};
Sent = {
specialUse = "Sent";
auto = "subscribe";
};
"Sent Messages" = {
specialUse = "Sent";
};
"virtual/All" = {
specialUse = "All";
auto = "subscribe";
};
};
sslServerCert = "/var/lib/acme/chir.rs/cert.pem";
sslServerKey = "/var/lib/acme/chir.rs/key.pem";
extraConfig = ''
service old-stats {
unix_listener old-stats {
user = dovecot-exporter
group = dovecot-exporter
mode = 0660
}
fifo_listener old-stats-mail {
mode = 0660
user = dovecot
group = dovecot
}
fifo_listener old-stats-user {
mode = 0660
user = dovecot
group = dovecot
}
}
plugin {
old_stats_refresh = 30 secs
old_stats_track_cmds = yes
}
plugin {
sieve_plugins = sieve_imapsieve sieve_extprograms
# From elsewhere to Spam folder or flag changed in Spam folder
imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY FLAG
imapsieve_mailbox1_before = file:${sieves.report-spam}/report-spam.sieve
# From Spam folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Junk
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:${sieves.report-ham}/report-ham.sieve
sieve_pipe_bin_dir = /nix/store
sieve_global_extensions = +vnd.dovecot.pipe
sieve = ${sieves.default}/default.sieve
}
disable_plaintext_auth = yes
auth_mechanisms = plain login
'';
user = "dovecot";
};
services.prometheus.exporters.dovecot = {
enable = true;
listenAddress = listenIP;
};
sops.secrets."services/dovecot/rspamd_password" = { owner = "dovecot"; };
services.postgresql.ensureUsers = [{
name = "dovecot";
ensurePermissions = {
"DATABASE \"postfix\"" = "CONNECT";
"ALL TABLES IN DATABASE \"postfix\"" = "SELECT"; # can't select more granular permissions
};
}];
}

24
packages/sievec.nix Normal file
View file

@ -0,0 +1,24 @@
{ writeText, stdenv, dovecot_pigeonhole, ... } @ pkgs: { name, src, exts }:
let dummyConfig = writeText "dovecot.cfg" ''
plugin {
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_global_extensions = +vnd.dovecot.pipe
}
'';
in
stdenv.mkDerivation {
inherit name;
inherit src;
phases = [ "copyPhase" "compilePhase" ];
copyPhase = ''
mkdir $out
cp $src $out/${name}.sieve
chmod 0755 $out/${name}.sieve
set +x
'';
compilePhase = ''
${dovecot_pigeonhole}/bin/sievec -c ${dummyConfig} $out/${name}.sieve $out/${name}.svbin -x "${toString exts}"
'';
}

79
packages/sieves.nix Normal file
View file

@ -0,0 +1,79 @@
{ lib, writeText, writeScript, zsh, coreutils-full, rspamd, ... } @ pkgs:
let
sievec = import ./sievec.nix pkgs;
rspamd_host = "fd00:e621:e621:2::2";
sa-learn-ham-script = writeScript "sa-learn-ham" ''
#!${zsh}/bin/zsh
tmpfile=$(${coreutils-full}/bin/mktemp /tmp/spam.XXXXXX)
${coreutils-full}/bin/cat > $tmpfile
password=$(${coreutils-full}/bin/cat /run/secrets/services/dovecot/rspamd_password)
${coreutils-full}/bin/cat $tmpfile | ${rspamd}/bin/rspamc -P $password -h ${rspamd_host} learn_ham
${coreutils-full}/bin/cat $tmpfile | ${rspamd}/bin/rspamc -P $password -h ${rspamd_host} -w 5 -f 11 fuzzy_del
${coreutils-full}/bin/rm $tmpfile
'';
sa-learn-spam-script = writeScript "sa-learn-spam" ''
#!${zsh}/bin/zsh
tmpfile=$(${coreutils-full}/bin/mktemp /tmp/spam.XXXXXX)
${coreutils-full}/bin/cat > $tmpfile
password=$(${coreutils-full}/bin/cat /run/secrets/services/dovecot/rspamd_password)
${coreutils-full}/bin/cat $tmpfile | ${rspamd}/bin/rspamc -P $password -h ${rspamd_host} learn_spam
${coreutils-full}/bin/cat $tmpfile | ${rspamd}/bin/rspamc -P $password -h ${rspamd_host} -w 5 -f 11 fuzzy_add
${coreutils-full}/bin/rm $tmpfile
'';
removeStore = location: lib.removePrefix "/nix/store/" "${location}";
in
{
default = sievec {
name = "default";
src = writeText "default.sieve" ''
require "fileinto";
if header :contains "X-Spam" "YES" {
fileinto "Junk";
}
'';
exts = [ "fileinto" ];
};
report-ham = sievec {
name = "report-ham";
src = writeText "report-ham.sieve" ''
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.mailbox" "*" {
set "mailbox" "$${1}";
}
if string "$${mailbox}" [ "Trash", "train_ham", "train_prob", "train_spam" ] {
stop;
}
pipe :copy "${removeStore sa-learn-ham-script}";
'';
exts = [ "vnd.dovecot.pipe" "copy" "imapsieve" "environment" "variables" ];
};
report-spam = sievec {
name = "report-spam";
src = writeText "report-spam.sieve" ''
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "imap4flags"];
if environment :is "imap.cause" "COPY" {
pipe :copy "${removeStore sa-learn-spam-script}";
}
# Catch replied or forwarded spam
elsif anyof (allof (hasflag "\\Answered",
environment :contains "imap.changedflags" "\\Answered"),
allof (hasflag "$Forwarded",
environment :contains "imap.changedflags" "$Forwarded")) {
pipe :copy "${removeStore sa-learn-spam-script}";
}
'';
exts = [ "vnd.dovecot.pipe" "copy" "imapsieve" "environment" "imap4flags" ];
};
}

View file

@ -16,6 +16,8 @@ services:
postfixadmin:
dbpassword: ENC[AES256_GCM,data:37kEiKKgJVRIzzWXY3o/Wpk5UQ==,iv:LAJXgMr/rTMkds1r1kEWzhwNb6aPzsAhqUEeoLyBDbo=,tag:TI7oYxdpNzw2dXA4hLmVnQ==,type:str]
setupPassword: ENC[AES256_GCM,data:2BiQLOZZ6zCh4F+DkeNpMGLeXoxmMtDkuAU4XGBNvso+f4jupowalLkhTG/kA8yUL6BWOxwtJGMEp5wO,iv:0guj3/elSzoOe/00wgi5Z4R4lVfWeWt8mUDao3RXK6I=,tag:1lFUqfeSGV04mfxaVrmSMg==,type:str]
dovecot:
rspamd_password: ENC[AES256_GCM,data:PYVfbmSR8Uq3gQGkXVhj6Pt4QIo=,iv:jG7BudJT6+RAprllh5dGnSiqr4hS/GtyZesc77bd8eY=,tag:GBRgqg74cp1CPhDOu8IyKw==,type:str]
email:
darkkirb@darkkirb.de: ENC[AES256_GCM,data:DgVyvDHsviJuGqM+YP4jjytnzJE=,iv:KhEJz2+Nl9sxjRe0FmHOXi64QtsxDZhagnYt08sqU4E=,tag:vrhBg9qWBiSLPop/5jyIwA==,type:str]
lotte@chir.rs: ENC[AES256_GCM,data:bkzYVXizG/inJ/MS57G2pEiUkA==,iv:jviAx1B83wPhc128msfSs7oYwRQH+j7PU0aAmNbwi88=,tag:ylYl5k9R5BdLGAXOXVeLZg==,type:str]
@ -44,8 +46,8 @@ sops:
Ync4ejJHR0RXTkpqVzFRQXhEVlFVZjgKPo209jJf8Lwn1j3VmLC+j0633zdbt2yf
bPwO7dlKYGbGeGObprNtBXBS2cUXHeuQ45vRpTtg1cpxYK+TfNH8vQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2022-01-20T08:56:25Z"
mac: ENC[AES256_GCM,data:o7Ssj3mTwoYQN4TeveWxqn9oP/d7ZBw0I/KRfthhFv0ry+avBuIAr4ocgSKC6oCwnp3rNCr3pEsN+wN4kpidQ213ytvP8tSegn936i8WiU2ozD/jBHlRtRQg1abDau8rOps6W65dMBrqoGUDRVdrIsfp63K3myT8pv74u9dkYew=,iv:LU3chaUBP6FOhdR0Ua3YF+OsyEb2utmlnGxacZIcqc4=,tag:WgWXaduAXEbXj3czGHM+CA==,type:str]
lastmodified: "2022-01-20T15:46:48Z"
mac: ENC[AES256_GCM,data:jsQx0yZmcssxTXLzxx10yrSLfYqfa75LIQFRKWmHkTrd/a2w/ZZFfcorqjoNARtsx+F8Das++ZHpenEdHyxyOSPif5JCIsjrBD6RtJyaKVmIuDirhqUhMQNB2ZDLQifIIsA2qCzhJPThP/+ZJygnhUYiOKg86fangLpkAIxF7DM=,iv:R77YqOSBBMEZbwiPAhnDScYCA+DrTVsZfjNYw9S0iMU=,tag:3va+Z/r39RrD9iQ2BIApNw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.1