]> Git — Sourcephile - sourcephile-nix.git/blob - nixos/modules/services/mail/dovecot2.nix
mermet: set nix.maxJobs
[sourcephile-nix.git] / nixos / modules / services / mail / dovecot2.nix
1 {pkgs, lib, config, system, ...}:
2 let inherit (builtins) toString toFile attrNames;
3 inherit (lib) types;
4 inherit (pkgs.lib) unlinesAttrs unlinesValues unwords;
5 inherit (config.services) dovecot2 openldap;
6 inherit (config) networking;
7 stateDir = "/var/lib/dovecot";
8 mailDir = "${stateDir}/mail";
9 sieveDir = "${stateDir}/sieve";
10 authDir = "${stateDir}/auth";
11 escapeGroup = lib.stringAsChars (c: if "a"<=c && c<="z"
12 || "0"<=c && c<="9"
13 || c=="-"
14 then c else "_");
15 domainGroup = escapeGroup "${networking.domainBase}";
16 in
17 {
18 options.services.dovecot2 = {
19 domains = lib.mkOption {
20 default = {};
21 type = types.attrsOf (types.submodule ({domain, ...}: {
22 #config.domain = lib.mkDefault domain;
23 options = {
24 accounts = lib.mkOption {
25 type = types.attrsOf (types.submodule ({account, ...}: {
26 options = {
27 password = lib.mkOption {
28 type = types.str;
29 example = "{SSHA512}uyjL1KYx4z7HpfNvnKzuVxpMLD2KVueGGBvOcj7AF1EZCTVhT++IIKUVOC4xpZtWdqVD0OVmZqgYr2qpn/3t3Aj4oU0=";
30 description = ''Password.
31 Use: `doveadm pw -s SSHA512 -p "$password"`
32 '';
33 };
34 aliases = lib.mkOption {
35 type = with types; listOf types.str;
36 example = [ "abuse@${config.networking.domain}" ];
37 default = [];
38 description = ''Aliases of this account.'';
39 };
40 quota = lib.mkOption {
41 type = with types; nullOr types.str;
42 default = null;
43 example = "2G";
44 description = ''
45 Per user quota rules. Accepted sizes are `xx k/M/G/T` with the
46 obvious meaning. Leave blank for the standard quota `100G`.
47 '';
48 };
49 sieves = lib.mkOption {
50 type = with types; attrsOf str;
51 default = { main = ''
52 require ["include"];
53
54 #include :personal "roundcube";
55 include :global "spam";
56 include :global "list";
57 include :global "extension";
58 '';
59 };
60 };
61 groups = lib.mkOption {
62 type = with types; listOf str;
63 default = [];
64 };
65 };
66 }));
67 };
68 };
69 }));
70 };
71 debug = lib.mkOption {
72 type = types.bool;
73 default = false;
74 description = ''
75 Whether to enable verbose logging or not in mail related services.
76 '';
77 };
78 sieves = {
79 global = lib.mkOption {
80 description = "global scripts.";
81 type = types.attrsOf types.str;
82 default = {};
83 };
84 before = lib.mkOption {
85 description = "before scripts.";
86 type = types.attrsOf types.str;
87 default = {};
88 };
89 after = lib.mkOption {
90 description = "after scripts.";
91 type = types.attrsOf types.str;
92 default = {};
93 };
94 };
95 };
96
97 config = lib.mkIf dovecot2.enable {
98 systemd.services.dovecot2 = {
99 preStart = unlinesValues {
100 installMailDir = ''
101 # SEE: http://wiki2.dovecot.org/SharedMailboxes/Permissions
102 install -D -d -m 0771 \
103 -o ${dovecot2.mailUser} \
104 -g ${dovecot2.mailGroup} \
105 ${mailDir}
106 '';
107
108 installSieve = ''
109 rm -rf "${sieveDir}"
110 install -D -d -m 0755 -o root -g root \
111 "${sieveDir}/bin"
112 '' + unlinesAttrs (dir: sieves: ''
113 install -D -d -m 0755 -o root -g root \
114 ${sieveDir} ${sieveDir}/${dir}.d
115 '' + unlinesAttrs (name: text: ''
116 src=${pkgs.writeText "${name}.sieve" text}
117 dst="${sieveDir}/${dir}.d/${name}.sieve"
118 ln -fns "$src" "$dst"
119 ${pkgs.dovecot_pigeonhole}/bin/sievec "$dst"
120 '') sieves
121 ) dovecot2.sieves;
122
123 installDomains =
124 lib.optionalString openldap.enable ''
125 # NOTE: make sure nslcd cache is in sync with the LDAP data
126 systemctl restart nslcd
127 '' + ''
128 install -D -d -m 1770 \
129 -o ${dovecot2.mailUser} \
130 -g ${domainGroup} \
131 ${mailDir}/${networking.domain} \
132 ${stateDir}/control/${networking.domain} \
133 ${stateDir}/index/${networking.domain}
134
135 # NOTE: do not set the sticky bit (+t)
136 # on acl/<domain>/, to let dovecot
137 # rename acl.db.lock (own by new user)
138 # to acl.db (own by old user)
139 install -D -d -m 0770 \
140 -o ${dovecot2.mailUser} \
141 -g ${domainGroup} \
142 ${stateDir}/acl/${networking.domain}
143
144 # NOTE: domainAliases point to the very same mailboxes as domain's.
145 for domainAlias in ${unwords networking.domainAliases}
146 do
147 ln -fns ${networking.domain} ${mailDir}/$domainAlias
148 ln -fns ${networking.domain} ${stateDir}/control/$domainAlias
149 ln -fns ${networking.domain} ${stateDir}/index/$domainAlias
150 ln -fns ${networking.domain} ${stateDir}/acl/$domainAlias
151 done
152 '';
153 };
154 };
155 };
156 }