]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - modules/private/mail/dovecot.nix
ae06f2f0f2b22f191a740c06d47f528f6017f7d4
[perso/Immae/Config/Nix.git] / modules / private / mail / dovecot.nix
1 { lib, pkgs, config, ... }:
2 let
3 sieve_bin = pkgs.runCommand "sieve_bin" {
4 buildInputs = [ pkgs.makeWrapper ];
5 } ''
6 cp -a ${./sieve_bin} $out
7 chmod -R u+w $out
8 patchShebangs $out
9 for i in $out/*; do
10 wrapProgram "$i" --prefix PATH : ${lib.makeBinPath [ pkgs.coreutils ]}
11 done
12 '';
13 in
14 {
15 config = lib.mkIf config.myServices.mail.enable {
16 systemd.services.dovecot2.serviceConfig.Slice = "mail.slice";
17 secrets.keys."dovecot/ldap" = {
18 user = config.services.dovecot2.user;
19 group = config.services.dovecot2.group;
20 permissions = "0400";
21 text = ''
22 hosts = ${config.myEnv.mail.dovecot.ldap.host}
23 tls = yes
24
25 dn = ${config.myEnv.mail.dovecot.ldap.dn}
26 dnpass = ${config.myEnv.mail.dovecot.ldap.password}
27
28 auth_bind = yes
29
30 ldap_version = 3
31
32 base = ${config.myEnv.mail.dovecot.ldap.base}
33 scope = subtree
34
35 pass_filter = ${config.myEnv.mail.dovecot.ldap.filter}
36 pass_attrs = ${config.myEnv.mail.dovecot.ldap.pass_attrs}
37
38 user_attrs = ${config.myEnv.mail.dovecot.ldap.user_attrs}
39 user_filter = ${config.myEnv.mail.dovecot.ldap.filter}
40 iterate_attrs = ${config.myEnv.mail.dovecot.ldap.iterate_attrs}
41 iterate_filter = ${config.myEnv.mail.dovecot.ldap.iterate_filter}
42 '';
43 };
44
45 users.users.vhost = {
46 group = "vhost";
47 uid = config.ids.uids.vhost;
48 };
49 users.groups.vhost.gid = config.ids.gids.vhost;
50 users.users."${config.services.dovecot2.user}".extraGroups = [ "acme" ];
51
52 # https://blog.zeninc.net/index.php?post/2018/04/01/Un-annuaire-pour-les-gouverner-tous.......
53 services.dovecot2 = {
54 enable = true;
55 enablePAM = false;
56 enablePop3 = true;
57 enableImap = true;
58 enableLmtp = true;
59 protocols = [ "sieve" ];
60 modules = [
61 pkgs.dovecot_pigeonhole
62 pkgs.dovecot_fts_xapian
63 ];
64 mailUser = "vhost";
65 mailGroup = "vhost";
66 createMailUser = false;
67 mailboxes = {
68 Trash = { auto = "subscribe"; specialUse = "Trash"; };
69 Junk = { auto = "subscribe"; specialUse = "Junk"; };
70 Sent = { auto = "subscribe"; specialUse = "Sent"; };
71 Drafts = { auto = "subscribe"; specialUse = "Drafts"; };
72 };
73 mailLocation = "mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap";
74 sslServerCert = "/etc/dovecot/fullchain.pem";
75 sslServerKey = "/var/lib/acme/mail/key.pem";
76 sslCACert = "/etc/dovecot/fullchain.pem";
77 extraConfig = builtins.concatStringsSep "\n" [
78 # For printer which doesn’t support elliptic curve
79 ''
80 ssl_alt_cert = </etc/dovecot/fullchain-rsa.pem
81 ssl_alt_key = </var/lib/acme/mail-rsa/key.pem
82 ''
83
84 ''
85 postmaster_address = postmaster@immae.eu
86 mail_attribute_dict = file:%h/dovecot-attributes
87 imap_idle_notify_interval = 20 mins
88 namespace inbox {
89 type = private
90 separator = /
91 inbox = yes
92 list = yes
93 }
94 ''
95
96 # ACL
97 ''
98 mail_plugins = $mail_plugins acl
99 plugin {
100 acl = vfile:${pkgs.writeText "dovecot-acl" ''
101 Backup/* owner lrp
102 ''}
103 acl_globals_only = yes
104 }
105 ''
106
107 # Full text search
108 ''
109 # needs to be bigger than any mailbox size
110 default_vsz_limit = 2GB
111 mail_plugins = $mail_plugins fts fts_xapian
112 plugin {
113 plugin = fts fts_xapian
114 fts = xapian
115 fts_xapian = partial=2 full=20
116 fts_autoindex = yes
117 fts_autoindex_exclude = \Junk
118 fts_autoindex_exclude2 = \Trash
119 fts_autoindex_exclude3 = Virtual/*
120 }
121 ''
122
123 # Antispam
124 # https://docs.iredmail.org/dovecot.imapsieve.html
125 ''
126 # imap_sieve plugin added below
127
128 plugin {
129 sieve_plugins = sieve_imapsieve sieve_extprograms
130 imapsieve_url = sieve://127.0.0.1:4190
131
132 sieve_before = file:${./sieve_scripts}/backup.sieve;bindir=/var/lib/vhost/.sieve_bin
133
134 # From elsewhere to Junk folder
135 imapsieve_mailbox1_name = Junk
136 imapsieve_mailbox1_causes = COPY APPEND
137 imapsieve_mailbox1_before = file:${./sieve_scripts}/report_spam.sieve;bindir=/var/lib/vhost/.imapsieve_bin
138
139 # From Junk folder to elsewhere
140 imapsieve_mailbox2_name = *
141 imapsieve_mailbox2_from = Junk
142 imapsieve_mailbox2_causes = COPY
143 imapsieve_mailbox2_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
144
145 # From anywhere to NoJunk folder
146 imapsieve_mailbox3_name = NoJunk
147 imapsieve_mailbox3_causes = COPY APPEND
148 imapsieve_mailbox3_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
149
150 sieve_pipe_bin_dir = ${sieve_bin}
151
152 sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
153 }
154 ''
155 # Services to listen
156 ''
157 service imap-login {
158 inet_listener imap {
159 }
160 inet_listener imaps {
161 }
162 }
163 service pop3-login {
164 inet_listener pop3 {
165 }
166 inet_listener pop3s {
167 }
168 }
169 service imap {
170 }
171 service pop3 {
172 }
173 service auth {
174 unix_listener auth-userdb {
175 }
176 unix_listener ${config.services.postfix.config.queue_directory}/private/auth {
177 mode = 0666
178 }
179 }
180 service auth-worker {
181 }
182 service dict {
183 unix_listener dict {
184 }
185 }
186 service stats {
187 unix_listener stats-reader {
188 user = vhost
189 group = vhost
190 mode = 0660
191 }
192 unix_listener stats-writer {
193 user = vhost
194 group = vhost
195 mode = 0660
196 }
197 }
198 ''
199
200 # Authentification
201 ''
202 first_valid_uid = ${toString config.ids.uids.vhost}
203 disable_plaintext_auth = yes
204 passdb {
205 driver = ldap
206 args = ${config.secrets.fullPaths."dovecot/ldap"}
207 }
208 userdb {
209 driver = ldap
210 args = ${config.secrets.fullPaths."dovecot/ldap"}
211 }
212 ''
213
214 # Zlib
215 ''
216 mail_plugins = $mail_plugins zlib
217 plugin {
218 zlib_save_level = 6
219 zlib_save = gz
220 }
221 ''
222
223 # Sieve
224 ''
225 plugin {
226 sieve = file:~/sieve;bindir=~/.sieve-bin;active=~/.dovecot.sieve
227 }
228 service managesieve-login {
229 }
230 service managesieve {
231 }
232 ''
233
234 # Virtual mailboxes
235 ''
236 mail_plugins = $mail_plugins virtual
237 namespace Virtual {
238 prefix = Virtual/
239 location = virtual:~/Virtual
240 }
241 ''
242
243 # Protocol specific configuration
244 # Needs to come last if there are mail_plugins entries
245 ''
246 protocol imap {
247 mail_plugins = $mail_plugins imap_sieve imap_acl
248 }
249 protocol lda {
250 mail_plugins = $mail_plugins sieve
251 }
252 ''
253 ];
254 };
255 networking.firewall.allowedTCPPorts = [ 110 143 993 995 4190 ];
256 system.activationScripts.dovecot = {
257 deps = [ "users" ];
258 text =''
259 install -m 0755 -o vhost -g vhost -d /var/lib/vhost
260 '';
261 };
262
263 services.cron.systemCronJobs = let
264 cron_script = pkgs.writeScriptBin "cleanup-imap-folders" ''
265 ${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"
266 ${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"
267 ${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"
268 '';
269 in
270 [
271 "0 2 * * * root ${cron_script}/bin/cleanup-imap-folders"
272 ];
273 security.acme.certs."mail-rsa" = {
274 postRun = ''
275 systemctl restart dovecot2.service
276 '';
277 extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
278 };
279 security.acme.certs."mail" = {
280 postRun = ''
281 systemctl restart dovecot2.service
282 '';
283 extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
284 };
285 };
286 }
287