]> Git — Sourcephile - sourcephile-nix.git/blob - servers/mermet/dovecot.nix
dovecot: fix INDEX corruption by INDEXPVT
[sourcephile-nix.git] / servers / mermet / dovecot.nix
1 { pkgs, lib, config, system, ... }:
2 let inherit (builtins) toString toFile;
3 inherit (builtins.extraBuiltins) pass;
4 inherit (lib) types;
5 inherit (pkgs.lib) loadFile unlines unlinesAttrs unlinesValues unwords;
6 inherit (config) networking;
7 inherit (config.services) dovecot2 postfix openldap;
8 when = x: y: if x == null then "" else y;
9 extSep = postfix.recipientDelimiter;
10 dirSep = extSep;
11 # NOTE: nixpkgs' dovecot2.stateDir is currently not exported
12 stateDir = "/var/lib/dovecot";
13 mailDir = "${stateDir}/mail";
14 sieveDir = "${stateDir}/sieve";
15 authDir = "${stateDir}/auth";
16 authUser = dovecot2.mailUser; # TODO: php_roundcube
17 authGroup = dovecot2.mailGroup; # TODO: php_roundcube
18 escapeGroup = lib.stringAsChars (c: if "a"<=c && c<="z"
19 || "0"<=c && c<="9"
20 || c=="-"
21 then c else "_");
22 domainGroup = escapeGroup "${networking.domainBase}";
23 etc_dovecot = [
24 { target = "dovecot/${networking.domain}/dovecot-ldap.conf";
25 source = pkgs.writeText "dovecot-ldap.conf" ''
26 debug_level = 0
27
28 # LDAP database
29 uris = ldapi://
30 base = ou=posix,${openldap.domainSuffix}
31 scope = subtree
32 deref = never
33 # NOTE: sufficient for small systems and uses less resources.
34 blocking = no
35
36 # LDAP auth
37 sasl_bind = yes
38 sasl_mech = EXTERNAL
39 #dn = cn=admin,${openldap.domainSuffix}
40 #dnpass = useless with sasl_mech=EXTERNAL
41 auth_bind = no
42 #auth_bind_userdn = cn=%n,ou=accounts,ou=posix,dc=${openldap.domainSuffix}
43
44 # dovecot passdb query
45 # DOC: http://wiki2.dovecot.org/PasswordDatabase/ExtraFields
46 pass_filter = (&(objectClass=posixAccount)(uid=%n)(mailEnabled=TRUE))
47 # TODO: userdb_quota_rule=*:storage=
48 pass_attrs = userPassword=password,\
49 uidNumber=userdb_uid,\
50 gidNumber=userdb_gid,\
51 mailGroupMember=userdb_mail_access_groups=${domainGroup},\
52 quotaBytes=userdb_quota_rule=*:bytes=%{ldap:quotaBytes},\
53 =user=%n@%d
54 #homeDirectory=userdb_home
55 default_pass_scheme = CRYPT
56
57 # dovecot userdb query
58 # DOC: http://wiki2.dovecot.org/UserDatabase/ExtraFields
59 user_filter = (&(objectClass=posixAccount)(uid=%n)(mailEnabled=TRUE))
60 #user_filter = (&(objectClass=inetOrgPerson)(uid=%n))
61 #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
62 #user_attrs = mailHomeDirectory=home,\
63 # mailStorageDirectory=mail,\
64 # mailUidNumber=uid,\
65 # mailGidNumber=gid,\
66 # mailQuota=quota_rule=*:bytes=%$
67
68 # doveadm user query
69 iterate_attrs = =user=%{ldap:uid}@${networking.domain}
70 iterate_filter = (&(objectClass=posixAccount)(mailEnabled=TRUE))
71 '';
72 }
73 ];
74 dovecot-virtual-pop3 = pkgs.writeTextFile {
75 name = "dovecot-virtual-pop3";
76 destination = "/pop3/INBOX/dovecot-virtual";
77 text = ''
78 All
79 All+*
80 all
81 '';
82 };
83
84 learn-spam = pkgs.writeShellScriptBin "learn-spam.sh" ''
85 exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd/learner.sock learn_spam
86 '';
87 learn-ham = pkgs.writeShellScriptBin "learn-ham.sh" ''
88 exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd/learner.sock learn_ham
89 '';
90 sieve_pipe_bin_dir = pkgs.buildEnv {
91 name = "sieve_pipe_bin_dir";
92 pathsToLink = [ "/bin" ];
93 paths = [
94 learn-spam
95 learn-ham
96 ];
97 };
98 dovecot-virtual-all = pkgs.writeTextFile {
99 name = "dovecot-virtual-all";
100 destination = "/All/dovecot-virtual";
101 text = ''
102 *
103 all
104 '';
105 };
106 dovecot-virtual-recents = pkgs.writeTextFile {
107 name = "dovecot-virtual-recents";
108 destination = "/Recents/dovecot-virtual";
109 text = ''
110 *
111 all younger 172800
112 '';
113 };
114 dovecot-virtual = pkgs.buildEnv {
115 name = "dovecot-virtual";
116 pathsToLink = [ "/" ];
117 paths = [
118 dovecot-virtual-all
119 dovecot-virtual-recents
120 ];
121 };
122 in
123 {
124 imports = [
125 dovecot/autoconfig.nix
126 ];
127 #services.postfix.mapFiles."transport-dovecot" =
128 # toFile "transport-dovecot"
129 # (unlines
130 # (lib.mapAttrsToList
131 # (dom: {...}: "${transportSubDomain}.${dom} lmtp:unix:private/dovecot-lmtp")
132 # dovecot2.domains));
133 systemd.services.dovecot2 = {
134 after = [
135 "postfix.service"
136 "openldap.service"
137 "dovecot.${networking.domainBase}.key.pem-key.service"
138 ];
139 restartTriggers = map (f: f.source) etc_dovecot;
140 };
141 deployment.keys = {
142 "dovecot.${networking.domainBase}.key.pem" = {
143 text = pass "x509/${networking.domainBase}/key.pem";
144 user = dovecot2.user;
145 group = "root";
146 destDir = "/run/keys/";
147 permissions = "0400"; # WARNING: not enforced when deployment.storeKeysOnMachine = true
148 };
149 };
150 environment.etc = etc_dovecot;
151 users.users."${dovecot2.mailUser}".isSystemUser = true; # Fix nixpkgs
152 services.dovecot2 = {
153 enable = true;
154 mailUser = "dovemail";
155 mailGroup = "dovemail";
156 modules = [
157 pkgs.dovecot_pigeonhole
158 pkgs.dovecot_fts_xapian
159 ];
160 sieves = {
161 global = {
162 list = ''
163 require [ "date", "fileinto", "mailbox", "variables" ];
164
165 if currentdate :matches "year" "*" { set "year" "''${1}"; }
166 if currentdate :matches "month" "*" { set "month" "''${1}"; }
167
168 if exists "List-ID" {
169 if header :matches "List-ID" "*<*.*.*.*>*" {
170 set "list" "''${2}";
171 set "domain" "''${4}";
172 }
173 elsif header :matches "List-ID" "*<*.*.*>*" {
174 set "list" "''${2}";
175 set "domain" "''${3}";
176 }
177 fileinto :create "Listes+''${domain}+''${list}+''${year}+''${month}";
178 stop;
179 }
180 '';
181 spam = ''
182 require [ "imap4flags" ];
183
184 if header :contains "X-Spam-Level" "***" {
185 addflag "Junk";
186 }
187 '';
188 extension = ''
189 require
190 [ "envelope"
191 , "fileinto"
192 , "mailbox"
193 , "subaddress"
194 , "variables"
195 ];
196 if envelope :matches :detail "TO" "*" {
197 set "extension" "''${1}";
198 }
199 if not string :is "''${extension}" "" {
200 fileinto :create "INBOX+''${extension}";
201 stop;
202 }
203 '';
204 spam-or-ham = ''
205 require ["vnd.dovecot.pipe", "copy", "imapsieve", "variables", "imap4flags", "environment"];
206
207 if environment :is "imap.changedflags" "Junk" {
208 if hasflag :is "Junk" {
209 pipe :copy :try "learn-spam.sh";
210 } elsif not hasflag :is "Junk" {
211 pipe :copy :try "learn-ham.sh";
212 }
213 }
214 '';
215 report-spam = ''
216 require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
217
218 if environment :matches "imap.user" "*" {
219 set "username" "''${1}";
220 }
221
222 pipe :copy :try "learn-spam.sh" [ "''${username}" ];
223 '';
224 report-ham = ''
225 require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
226
227 if environment :matches "imap.mailbox" "*" {
228 set "mailbox" "''${1}";
229 }
230
231 if string "''${mailbox}" "Trash" {
232 stop;
233 }
234
235 if environment :matches "imap.user" "*" {
236 set "username" "''${1}";
237 }
238
239 pipe :copy :try "learn-ham.sh" [ "''${username}" ];
240 '';
241 };
242 };
243 configFile = toString ( pkgs.writeText "dovecot.conf" ''
244 auth_debug = yes
245 mail_debug = yes
246 verbose_ssl = yes
247
248 passdb {
249 driver = ldap
250 args = /etc/dovecot/${networking.domain}/dovecot-ldap.conf
251 default_fields = userdb_mail_access_groups=${domainGroup}
252 override_fields =
253 }
254 userdb {
255 driver = prefetch
256 }
257 userdb {
258 # NOTE: this userdb is only used by lda.
259 driver = ldap
260 args = /etc/dovecot/${networking.domain}/dovecot-ldap.conf
261 default_fields = mail_access_groups=${domainGroup}
262 override_fields =
263 skip = found
264 }
265 auth_cache_verify_password_with_worker = yes
266 #passdb {
267 # driver = passwd-file
268 # args = scheme=crypt username_format=%n ${authDir}/%d/passwd
269 #}
270 #userdb {
271 # # NOTE: this userdb is only used by lda.
272 # driver = passwd-file
273 # args = username_format=%n ${authDir}/%d/passwd
274 # #default_fields = home=${mailDir}/%d/%n
275 # skip = found
276 #}
277 # If needed, may be overrided by userdb_mail
278 mail_home = ${mailDir}/%d/%n
279 # NOTE: if needed, may be overrided by userdb_mail
280 # NOTE: INDEX and CONTROL are on a partition without quota, as explain in the doc.
281 # SEE: http://wiki2.dovecot.org/Quota/FS
282 auth_mechanisms = plain login
283 # NOTE: postfix does not supply a client cert.
284 auth_ssl_require_client_cert = no
285 #auth_ssl_username_from_cert = yes
286 auth_verbose = yes
287 # NOTE: lowercase the username, help with LDAP?
288 auth_username_format = %Lu
289 default_internal_user = ${dovecot2.user}
290 default_internal_group = ${dovecot2.group}
291 disable_plaintext_auth = yes
292 # NOTE: sync with LDAP's data.
293 first_valid_uid = 1000
294 lda_mailbox_autocreate = yes
295 lda_mailbox_autosubscribe = yes
296 listen = *
297 log_timestamp = "%Y-%m-%d %H:%M:%S "
298 mail_location = sdbox:/var/lib/dovecot/mail/%d/%n/mail.d:UTF-8:CONTROL=/var/lib/dovecot/control/%d/%n:INDEX=/var/lib/dovecot/index/%d/%n
299 # No dirty syncs while I'm using neomutt directly on the Maildirs
300 #maildir_very_dirty_syncs = yes
301 #maildir_copy_with_hardlinks = yes
302 namespace Inbox {
303 type = private
304 inbox = yes
305 hidden = no
306 list = yes
307 prefix =
308 separator = ${dirSep}
309 }
310 namespace Shared {
311 type = shared
312 #list = children
313 # NOTE: always listed in the LIST command.
314 list = yes
315 # NOTE: how to access the other users' mailboxes.
316 # NOTE: %var expands to the logged in user's variable, while
317 # %%var expands to the other users' variables.
318 # NOTE: INDEX and CONTROL are shared, INDEXPVT is not.
319 location = sdbox:${mailDir}/%%d/%%n/mail.d:UTF-8:CONTROL=${stateDir}/control/%%d/%%n/Shared:INDEX=${stateDir}/index/%%d/%%n/Shared:INDEXPVT=${stateDir}/index/%d/%n/Shared/%%n
320 prefix = Partages+%%n+
321 separator = ${dirSep}
322 subscriptions = yes
323 }
324 namespace Virtual {
325 prefix = Virtual+
326 separator = ${dirSep}
327 hidden = no
328 list = yes
329 subscriptions = no
330 location = virtual:${dovecot-virtual}:UTF-8:INDEX=${stateDir}/index/%d/%n/virtual
331 }
332 # Default VSZ (virtual memory size) limit for service processes. This is mainly
333 # intended to catch and kill processes that leak memory before they eat up everything.
334 # Increased for fts_xapian.
335 default_vsz_limit = 1G
336 mail_plugins = $mail_plugins acl quota virtual fts fts_xapian
337 #mail_uid = ${dovecot2.mailUser}
338 #mail_gid = ${dovecot2.mailGroup}
339 # NOTE: each user has a dedicated (uid,gid) pair
340 #mail_privileged_group = mail
341 #mail_access_groups =
342 plugin {
343 plugin = fts fts_xapian
344
345 acl = vfile:/etc/dovecot/acl/global.d
346 acl_anyone = allow
347 # NOTE: to let users LIST mailboxes shared by other users,
348 # Dovecot needs a shared mailbox dictionary.
349 # FIXME: %d not working with userdb ldap
350 acl_shared_dict = file:${stateDir}/acl/%d/acl.db
351
352 fts = xapian
353 fts_autoindex = yes
354 fts_autoindex_exclude = \Junk
355 fts_autoindex_exclude2 = \Trash
356 fts_enforced = yes
357 # 2 and 20 are the NGram values for header fields, which means the
358 # keywords created for fields (To, Cc, ...) are between is 2 and 20 chars long.
359 # Full words are also added by default.
360 fts_xapian = partial=2 full=20 verbose=0
361
362 quota = maildir:User quota
363 quota_rule = *:storage=256M
364 quota_rule2 = Trash:storage=+64M
365 quota_max_mail_size = 20M
366 #quota_exceeded_message = </path/to/quota_exceeded_message.txt
367 quota_warning = storage=95%% quota-warning 95 %u
368 quota_warning2 = storage=80%% quota-warning 80 %u
369 quota_warning3 = -storage=100%% quota-warning below %u
370
371 # Let extension.sieve do the handling of the detail
372 #lmtp_save_to_detail_mailbox = yes
373 recipient_delimiter = ${extSep}
374
375 #sieve_default = file:${mailDir}/%u/default.sieve
376 #sieve_default_name = default
377 sieve_plugins = sieve_imapsieve sieve_extprograms
378 sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
379 #sieve_extensions = +editheader
380 sieve = file:~/sieve.d;active=~/sieve
381 sieve_after = ${sieveDir}/after.d/
382 sieve_before = ${sieveDir}/before.d/
383 sieve_pipe_bin_dir = ${sieve_pipe_bin_dir}/bin
384 sieve_global = ${sieveDir}/global.d/
385 sieve_max_script_size = 1M
386 sieve_quota_max_scripts = 0
387 sieve_quota_max_storage = 10M
388 #sieve_spamtest_max_value = 10
389 #sieve_spamtest_status_header = X-Spam-Score
390 #sieve_spamtest_status_type = strlen
391 sieve_user_log = /var/log/dovecot/%d/sieve.%n.log
392 # Enables support for user Sieve scripts in IMAP
393 #imapsieve_url = sieve://mail.${networking.domain}:4190
394
395 # When a flag changes, spam or ham according to the \Junk or \NonJunk flags
396 imapsieve_mailbox1_name = *
397 imapsieve_mailbox1_causes = FLAG
398 imapsieve_mailbox1_before = file:${sieveDir}/global.d/spam-or-ham.sieve
399
400 # From elsewhere to Junk folder
401 imapsieve_mailbox2_name = Pourriel
402 imapsieve_mailbox2_causes = COPY APPEND
403 imapsieve_mailbox2_before = file:${sieveDir}/global.d/report-spam.sieve
404
405 # From Junk folder to elsewhere
406 imapsieve_mailbox3_name = *
407 imapsieve_mailbox3_from = Pourriel
408 imapsieve_mailbox3_causes = COPY
409 imapsieve_mailbox3_before = file:${sieveDir}/global.d/report-ham.sieve
410 }
411 # If you have Dovecot v2.2.8+ you may get a significant performance improvement with fetch-headers:
412 imapc_features = $imapc_features fetch-headers
413 # Read multiple mails in parallel, improves performance
414 mail_prefetch_count = 20
415 service quota-warning {
416 executable = script ${
417 pkgs.writeScript "quota-warning" ''
418 #!/bin/sh -eu
419 PERCENT=$1
420 USER=$2
421 cat << EOF | ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -d $USER -o
422 "plugin/quota=maildir:User quota:noenforcing"
423 From: postmaster@${networking.domain}
424 Subject: [WARNING] your mailbox is now $PERCENT% full.
425
426 Please remove some mails to make room for new ones.
427 EOF
428 ''
429 }
430 # use some unprivileged user for executing the quota warnings
431 user = ${dovecot2.user}
432 unix_listener quota-warning {
433 }
434 }
435 # Store METADATA information within user's HOME directory
436 mail_attribute_dict = file:%h/dovecot-attributes
437 protocol imap {
438 #mail_max_userip_connections = 10
439 mail_plugins = $mail_plugins imap_acl imap_quota imap_sieve virtual
440 imap_metadata = yes
441
442 # DOC: https://wiki.dovecot.org/MailboxSettings
443 # Due to a bug in Dovecot v2.2.30+ if special-use flags are used,
444 # SPECIAL-USE needs to be added to post-login CAPABILITY response as RFC 6154 mandates.
445 imap_capability = +SPECIAL-USE
446
447 namespace Inbox {
448 mailbox "Archives" {
449 auto = subscribe
450 special_use = \Archive
451 }
452 mailbox "Drafts" {
453 auto = no
454 special_use = \Drafts
455 }
456 mailbox "Brouillons" {
457 auto = subscribe
458 special_use = \Drafts
459 }
460 mailbox "Junk" {
461 auto = no
462 #autoexpunge = 30d
463 special_use = \Junk
464 }
465 mailbox "Spams" {
466 auto = no
467 special_use = \Junk
468 }
469 mailbox "Spam" {
470 auto = no
471 special_use = \Junk
472 }
473 mailbox "Pourriels" {
474 auto = no
475 special_use = \Junk
476 }
477 mailbox "Pourriel" {
478 auto = no
479 special_use = \Junk
480 }
481 mailbox "Sent" {
482 auto = no
483 special_use = \Sent
484 }
485 mailbox "Sent Items" {
486 auto = no
487 special_use = \Sent
488 }
489 mailbox "Sent Messages" {
490 auto = no
491 special_use = \Sent
492 }
493 mailbox "Envoyés" {
494 auto = no
495 special_use = \Sent
496 }
497 mailbox "Trash" {
498 auto = no
499 special_use = \Trash
500 #autoexpunge = 30d
501 }
502 mailbox "Corbeille" {
503 auto = no
504 special_use = \Trash
505 }
506 }
507 namespace Virtual {
508 mailbox All {
509 auto = no
510 comment = All messages from all mailboxes
511 special_use = \All
512 }
513 mailbox Recents {
514 auto = no
515 comment = All messages from all mailboxes arrived in the past 48h
516 }
517 }
518 }
519 protocol lda {
520 auth_socket_path = /var/run/dovecot/auth-userdb
521 hostname = ${networking.domain}
522 info_log_path =
523 log_path =
524 mail_plugins = $mail_plugins sieve
525 postmaster_address = postmaster${extSep}dovecot${extSep}lda@${networking.domain}
526 syslog_facility = mail
527 }
528 protocol lmtp {
529 #info_log_path = /tmp/dovecot-lmtp.log
530 mail_plugins = $mail_plugins sieve
531 postmaster_address = postmaster${extSep}dovecot${extSep}lmtp@${networking.domain}
532 }
533 protocol pop3 {
534 mail_plugins = $mail_plugins virtual
535 #mail_max_userip_connections = 10
536 # Virtual namespace for the virtual INBOX.
537 # Use a global directory for dovecot-virtual files.
538 #namespace Inbox {
539 # hidden = yes
540 # list = no
541 # location = virtual:''${dovecot-virtual-pop3}/pop3:INDEX=${stateDir}/index/%d/%n/virtual/pop3:LAYOUT=fs
542 # prefix = pop3+
543 #}
544 pop3_client_workarounds =
545 pop3_fast_size_lookups = yes
546 pop3_lock_session = yes
547 pop3_no_flag_updates = yes
548 # Use GUIDs to avoid accidental POP3 UIDL changes instead of IMAP UIDs.
549 pop3_uidl_format = %g
550 }
551 # DOC: https://wiki2.dovecot.org/Pigeonhole/ManageSieve/Configuration
552 protocol sieve {
553 # Maximum number of ManageSieve connections allowed for a user from each IP address.
554 # NOTE: The username is compared case-sensitively.
555 mail_max_userip_connections = 10
556
557 # To fool ManageSieve clients that are focused on CMU's timesieved you can specify
558 # the IMPLEMENTATION capability that the dovecot reports to clients.
559 # For example: 'Cyrus timsieved v2.2.13'
560 managesieve_implementation_string = Dovecot Pigeonhole
561
562 # The maximum number of compile errors that are returned to the client upon script
563 # upload or script verification.
564 managesieve_max_compile_errors = 5
565
566 #mail_max_userip_connections = 10
567 #managesieve_implementation_string = Dovecot Pigeonhole
568 managesieve_max_compile_errors = 5
569 #managesieve_max_line_length = 65536
570 #managesieve_notify_capability = mailto
571 #managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave
572 }
573 protocols = imap lmtp pop3 sieve
574 service lmtp {
575 #executable = lmtp -L
576 process_min_avail = ${toString config.nix.maxJobs}
577 unix_listener /var/lib/postfix/queue/private/dovecot-lmtp {
578 user = ${postfix.user}
579 group = ${postfix.group}
580 mode = 0600
581 }
582 #user = mail
583 }
584 service auth {
585 # FIXME: may be user=dovecot-auth with LDAP?
586 user = root
587 unix_listener auth-userdb {
588 user = ${dovecot2.user}
589 group = ${dovecot2.group}
590 mode = 0660
591 }
592 unix_listener /var/lib/postfix/queue/private/auth {
593 user = ${postfix.user}
594 group = ${postfix.group}
595 mode = 0660
596 }
597 }
598 service imap {
599 # Most of the memory goes to mmap()ing files.
600 # You may need to increase this limit if you have huge mailboxes.
601 #vsz_limit =
602 process_limit = 1024
603 }
604 service imap-login {
605 #inet_listener imap {
606 # address = 127.0.0.1
607 # port = 143
608 # ssl = no
609 #}
610 inet_listener imaps {
611 port = 993
612 ssl = yes
613 }
614 }
615 service pop3 {
616 process_limit = 1024
617 }
618 service pop3-login {
619 inet_listener pop3s {
620 port = 995
621 ssl = yes
622 }
623 }
624 service managesieve-login {
625 inet_listener sieve {
626 port = 4190
627 #ssl = yes
628 }
629
630 # Number of connections to handle before starting a new process. Typically
631 # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
632 # is faster. <doc/wiki/LoginProcess.txt>
633 service_count = 1
634
635 # Number of processes to always keep waiting for more connections.
636 process_min_avail = 0
637
638 # If you set service_count=0, you probably need to grow this.
639 #vsz_limit = 64M
640 }
641 ssl = required
642 ssl_dh = <${../../../sec/openssl/dh.pem}
643 ssl_cipher_list = HIGH:!LOW:!SSLv2:!EXP:!aNULL
644 ssl_cert = <${loadFile (../../../sec + "/openssl/${networking.domainBase}/cert.self-signed.pem")}
645 ssl_key = </run/keys/dovecot.${networking.domainBase}.key.pem
646 #ssl_ca = <''${caPath}
647 #ssl_verify_client_cert = yes
648 '' );
649 #${lib.concatMapStringsSep "\n"
650 # (dom: ''
651 # local_name mail.${dom} {
652 # #ssl_ca = <''${caPath}
653 # ssl_cert = <${x509.cert dom}
654 # ssl_key = <${x509.key dom}
655 # }
656 # '')
657 # dovecot2.domains
658 #}
659 };
660 }