]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - systems/eldiron/mail/dovecot.nix
Add monitoring script with smartctl
[perso/Immae/Config/Nix.git] / systems / eldiron / 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 myServices.dns.zones."immae.eu".subdomains =
17 with config.myServices.dns.helpers;
18 {
19 imap = ips servers.eldiron.ips.main;
20 pop3 = ips servers.eldiron.ips.main;
21 };
22
23 myServices.chatonsProperties.services.email = {
24 file.datetime = "2022-08-22T01:00:00";
25 service = {
26 name = "E-mail account";
27 description = "Compte e-mail avec configuration imap et smtp/pop3";
28 logo = "https://www.dovecot.org/wp-content/uploads/2021/09/favicon.ico";
29 website = "https://mail.immae.eu/";
30 status.level = "OK";
31 status.description = "OK";
32 registration."" = ["MEMBER" "CLIENT"];
33 registration.load = "OPEN";
34 install.type = "PACKAGE";
35 };
36 software = {
37 name = "Dovecot";
38 website = "https://www.dovecot.org/";
39 license.url = "https://github.com/dovecot/core/blob/main/COPYING";
40 license.name = "MIT and LGPLv2.1 Licenses";
41 version = pkgs.dovecot.version;
42 source.url = "https://github.com/dovecot/core";
43 modules = ["roundcube" "rainloop"] ++ map (a: a.pname) config.services.dovecot2.modules;
44 };
45 };
46 systemd.services.dovecot2.serviceConfig.Slice = "mail.slice";
47 secrets.keys."dovecot/sql" = {
48 user = config.services.dovecot2.user;
49 group = config.services.dovecot2.group;
50 permissions = "0400";
51 text = ''
52 driver = mysql
53 connect = host=${config.myEnv.mail.dovecot.mysql.socket} dbname=${config.myEnv.mail.dovecot.mysql.database} user=${config.myEnv.mail.dovecot.mysql.user} password=${config.myEnv.mail.dovecot.mysql.password}
54 password_query = SELECT NULL AS password, 'Y' as noauthenticate, destination AS user \
55 FROM forwardings WHERE \
56 ((regex = 1 AND '%u' REGEXP CONCAT('^',source,'$')) OR (regex = 0 AND source = '%u')) \
57 AND active = 1
58 '';
59 };
60 secrets.keys."dovecot/ldap" = {
61 user = config.services.dovecot2.user;
62 group = config.services.dovecot2.group;
63 permissions = "0400";
64 text = ''
65 hosts = ${config.myEnv.mail.dovecot.ldap.host}
66 tls = yes
67
68 dn = ${config.myEnv.mail.dovecot.ldap.dn}
69 dnpass = ${config.myEnv.mail.dovecot.ldap.password}
70
71 auth_bind = yes
72
73 ldap_version = 3
74
75 base = ${config.myEnv.mail.dovecot.ldap.base}
76 scope = subtree
77
78 pass_filter = ${config.myEnv.mail.dovecot.ldap.filter}
79 pass_attrs = ${config.myEnv.mail.dovecot.ldap.pass_attrs}
80
81 user_attrs = ${config.myEnv.mail.dovecot.ldap.user_attrs}
82 user_filter = ${config.myEnv.mail.dovecot.ldap.filter}
83 iterate_attrs = ${config.myEnv.mail.dovecot.ldap.iterate_attrs}
84 iterate_filter = ${config.myEnv.mail.dovecot.ldap.iterate_filter}
85 '';
86 };
87
88 users.users.vhost = {
89 group = "vhost";
90 uid = config.ids.uids.vhost;
91 };
92 users.groups.vhost.gid = config.ids.gids.vhost;
93 users.users."${config.services.dovecot2.user}".extraGroups = [ "acme" ];
94
95 nixpkgs.overlays = [
96 (self: super: {
97 dovecot = super.dovecot.override { withMySQL = true; openldap = self.openldap_libressl_cyrus; };
98 })
99 ];
100
101 # https://blog.zeninc.net/index.php?post/2018/04/01/Un-annuaire-pour-les-gouverner-tous.......
102 services.dovecot2 = {
103 enable = true;
104 enablePAM = false;
105 enablePop3 = true;
106 enableImap = true;
107 enableLmtp = true;
108 protocols = [ "sieve" ];
109 modules = [
110 pkgs.dovecot_pigeonhole
111 pkgs.dovecot_fts_xapian
112 ];
113 mailUser = "vhost";
114 mailGroup = "vhost";
115 createMailUser = false;
116 mailboxes = {
117 Trash = { auto = "subscribe"; specialUse = "Trash"; };
118 Junk = { auto = "subscribe"; specialUse = "Junk"; };
119 Sent = { auto = "subscribe"; specialUse = "Sent"; };
120 Drafts = { auto = "subscribe"; specialUse = "Drafts"; };
121 };
122 mailLocation = "mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap";
123 sslServerCert = "/etc/dovecot/fullchain.pem";
124 sslServerKey = "/var/lib/acme/mail/key.pem";
125 sslCACert = "/etc/dovecot/fullchain.pem";
126 extraConfig = builtins.concatStringsSep "\n" [
127 # For printer which doesn’t support elliptic curve
128 ''
129 ssl_alt_cert = </etc/dovecot/fullchain-rsa.pem
130 ssl_alt_key = </var/lib/acme/mail-rsa/key.pem
131 ''
132
133 ''
134 postmaster_address = postmaster@immae.eu
135 mail_attribute_dict = file:%h/dovecot-attributes
136 imap_idle_notify_interval = 20 mins
137 namespace inbox {
138 type = private
139 separator = /
140 inbox = yes
141 list = yes
142 }
143 ''
144
145 # ACL
146 ''
147 mail_plugins = $mail_plugins acl
148 plugin {
149 acl = vfile:${pkgs.writeText "dovecot-acl" ''
150 Backup/* owner lrp
151 ''}
152 acl_globals_only = yes
153 }
154 ''
155
156 # Full text search
157 ''
158 # needs to be bigger than any mailbox size
159 default_vsz_limit = 2GB
160 mail_plugins = $mail_plugins fts fts_xapian
161 plugin {
162 plugin = fts fts_xapian
163 fts = xapian
164 fts_xapian = partial=2 full=20
165 fts_autoindex = yes
166 fts_autoindex_exclude = \Junk
167 fts_autoindex_exclude2 = \Trash
168 fts_autoindex_exclude3 = Virtual/*
169 }
170 ''
171
172 # Antispam
173 # https://docs.iredmail.org/dovecot.imapsieve.html
174 ''
175 # imap_sieve plugin added below
176
177 plugin {
178 sieve_plugins = sieve_imapsieve sieve_extprograms
179 imapsieve_url = sieve://127.0.0.1:4190
180
181 sieve_before = file:${./sieve_scripts}/backup.sieve;bindir=/var/lib/vhost/.sieve_bin
182
183 # From elsewhere to Junk folder
184 imapsieve_mailbox1_name = Junk
185 imapsieve_mailbox1_causes = COPY APPEND
186 imapsieve_mailbox1_before = file:${./sieve_scripts}/report_spam.sieve;bindir=/var/lib/vhost/.imapsieve_bin
187
188 # From Junk folder to elsewhere
189 imapsieve_mailbox2_name = *
190 imapsieve_mailbox2_from = Junk
191 imapsieve_mailbox2_causes = COPY
192 imapsieve_mailbox2_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
193
194 # From anywhere to NoJunk folder
195 imapsieve_mailbox3_name = NoJunk
196 imapsieve_mailbox3_causes = COPY APPEND
197 imapsieve_mailbox3_before = file:${./sieve_scripts}/report_ham.sieve;bindir=/var/lib/vhost/.imapsieve_bin
198
199 sieve_pipe_bin_dir = ${sieve_bin}
200
201 sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
202 }
203 ''
204 # Services to listen
205 ''
206 service imap-login {
207 inet_listener imap {
208 }
209 inet_listener imaps {
210 }
211 }
212 service pop3-login {
213 inet_listener pop3 {
214 }
215 inet_listener pop3s {
216 }
217 }
218 service imap {
219 }
220 service pop3 {
221 }
222 service auth {
223 unix_listener auth-userdb {
224 }
225 unix_listener ${config.services.postfix.config.queue_directory}/private/auth {
226 mode = 0666
227 }
228 }
229 service auth-worker {
230 }
231 service dict {
232 unix_listener dict {
233 }
234 }
235 service stats {
236 unix_listener stats-reader {
237 user = vhost
238 group = vhost
239 mode = 0660
240 }
241 unix_listener stats-writer {
242 user = vhost
243 group = vhost
244 mode = 0660
245 }
246 }
247 ''
248
249 # Authentification
250 ''
251 first_valid_uid = ${toString config.ids.uids.vhost}
252 disable_plaintext_auth = yes
253 passdb {
254 driver = sql
255 args = ${config.secrets.fullPaths."dovecot/sql"}
256 }
257 passdb {
258 driver = ldap
259 args = ${config.secrets.fullPaths."dovecot/ldap"}
260 }
261 userdb {
262 driver = ldap
263 args = ${config.secrets.fullPaths."dovecot/ldap"}
264 }
265 ''
266
267 # Zlib
268 ''
269 mail_plugins = $mail_plugins zlib
270 plugin {
271 zlib_save_level = 6
272 zlib_save = gz
273 }
274 ''
275
276 # Sieve
277 ''
278 plugin {
279 sieve = file:~/sieve;bindir=~/.sieve-bin;active=~/.dovecot.sieve
280 }
281 service managesieve-login {
282 }
283 service managesieve {
284 }
285 ''
286
287 # Virtual mailboxes
288 ''
289 mail_plugins = $mail_plugins virtual
290 namespace Virtual {
291 prefix = Virtual/
292 location = virtual:~/Virtual
293 }
294 ''
295
296 # Protocol specific configuration
297 # Needs to come last if there are mail_plugins entries
298 ''
299 protocol imap {
300 mail_plugins = $mail_plugins imap_sieve imap_acl
301 }
302 protocol lda {
303 mail_plugins = $mail_plugins sieve
304 }
305 ''
306 ];
307 };
308 networking.firewall.allowedTCPPorts = [ 110 143 993 995 4190 ];
309 system.activationScripts.dovecot = {
310 deps = [ "users" ];
311 text =''
312 install -m 0755 -o vhost -g vhost -d /var/lib/vhost
313 '';
314 };
315
316 services.cron.systemCronJobs = let
317 cron_script = pkgs.writeScriptBin "cleanup-imap-folders" ''
318 ${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"
319 ${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"
320 ${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"
321 '';
322 in
323 [
324 "0 2 * * * root ${cron_script}/bin/cleanup-imap-folders"
325 ];
326 security.acme.certs."mail-rsa" = {
327 postRun = ''
328 systemctl restart dovecot2.service
329 '';
330 extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
331 };
332 security.acme.certs."mail" = {
333 postRun = ''
334 systemctl restart dovecot2.service
335 '';
336 extraDomainNames = [ "imap.immae.eu" "pop3.immae.eu" ];
337 };
338 myServices.monitoring.fromMasterActivatedPlugins = [ "imap" "tcp" ];
339 myServices.monitoring.fromMasterObjects.service = [
340 {
341 service_description = "imap connection works";
342 host_name = config.hostEnv.fqdn;
343 use = "external-service";
344 check_command = "check_imap_connection";
345
346 servicegroups = "webstatus-remote-services,webstatus-email";
347 _webstatus_name = "IMAP";
348 _webstatus_url = "imap.immae.eu";
349 }
350
351 {
352 service_description = "imap SSL is up to date";
353 host_name = config.hostEnv.fqdn;
354 use = "external-service";
355 check_command = ["check_tcp_ssl" "993"];
356
357 servicegroups = "webstatus-ssl";
358 _webstatus_name = "IMAP";
359 _webstatus_url = "imap.immae.eu";
360 }
361
362 ];
363 };
364 }
365