summaryrefslogtreecommitdiff
path: root/hosts/surtr/email
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2022-05-05 19:13:41 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2022-05-05 19:13:41 +0200
commitaefbe2d5a0cd10daa555433b14230ede07225372 (patch)
tree4a6d082ec4a973f8e2be7d645a8a16948fdf05d0 /hosts/surtr/email
parent845d0340201db81e6c605537ef27ed13f946d892 (diff)
downloadnixos-aefbe2d5a0cd10daa555433b14230ede07225372.tar
nixos-aefbe2d5a0cd10daa555433b14230ede07225372.tar.gz
nixos-aefbe2d5a0cd10daa555433b14230ede07225372.tar.bz2
nixos-aefbe2d5a0cd10daa555433b14230ede07225372.tar.xz
nixos-aefbe2d5a0cd10daa555433b14230ede07225372.zip
surtr: ...
Diffstat (limited to 'hosts/surtr/email')
-rw-r--r--hosts/surtr/email/default.nix225
1 files changed, 222 insertions, 3 deletions
diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix
index 68690d55..5f4d9725 100644
--- a/hosts/surtr/email/default.nix
+++ b/hosts/surtr/email/default.nix
@@ -2,7 +2,14 @@
2 2
3with lib; 3with lib;
4 4
5{ 5let
6 compileSieve = name: text: pkgs.runCommand name {} ''
7 mkdir $out
8 cp ${pkgs.writeText name ''
9 ''} $out/${name}
10 ${pkgs.dovecot_pigeonhole}/bin/sievec $out/${name}
11 ''};
12in {
6 config = { 13 config = {
7 services.postfix = { 14 services.postfix = {
8 enable = true; 15 enable = true;
@@ -40,6 +47,8 @@ with lib;
40 #enable TLS logging to see the ciphers for outbound connections 47 #enable TLS logging to see the ciphers for outbound connections
41 smtp_tls_loglevel = "1"; 48 smtp_tls_loglevel = "1";
42 49
50 smtpd_tls_received_header = true;
51
43 smtpd_tls_ask_ccert = true; 52 smtpd_tls_ask_ccert = true;
44 smtpd_tls_CAfile = toString ./ca/ca.crt; 53 smtpd_tls_CAfile = toString ./ca/ca.crt;
45 54
@@ -88,8 +97,8 @@ with lib;
88 authorized_verp_clients = "$mynetworks"; 97 authorized_verp_clients = "$mynetworks";
89 98
90 milter_default_action = "accept"; 99 milter_default_action = "accept";
91 smtpd_milters = [config.services.opendkim.socket]; 100 smtpd_milters = [config.services.opendkim.socket "local:/run/rspamd/rspamd-milter.sock"];
92 non_smtpd_milters = [config.services.opendkim.socket]; 101 non_smtpd_milters = [config.services.opendkim.socket "local:/run/rspamd/rspamd-milter.sock"];
93 102
94 alias_maps = ""; 103 alias_maps = "";
95 104
@@ -113,6 +122,19 @@ with lib;
113 sender_canonical_classes = "envelope_sender"; 122 sender_canonical_classes = "envelope_sender";
114 recipient_canonical_maps = "tcp:localhost:${toString config.services.postsrsd.reversePort}"; 123 recipient_canonical_maps = "tcp:localhost:${toString config.services.postsrsd.reversePort}";
115 recipient_canonical_classes = ["envelope_recipient" "header_recipient"]; 124 recipient_canonical_classes = ["envelope_recipient" "header_recipient"];
125
126 virtual_mailbox_domains = ''pgsql:${pkgs.writeText "virtual_mailbox_domains.cf" ''
127 dbname = emails
128 table = virtual_mailbox_domain
129 select_field = domain
130 where_field = domain
131 ''}'';
132 virtual_mailbox_maps = ''pgsql:${pkgs.writeText "virtual_mailbox_maps.cf" ''
133 dbname = emails
134 table = virtual_mailbox_mapping
135 select_field = mailbox
136 where_field = lookup
137 ''}'';
116 }; 138 };
117 masterConfig = { 139 masterConfig = {
118 smtps = { 140 smtps = {
@@ -155,6 +177,187 @@ with lib;
155 ''; 177 '';
156 }; 178 };
157 179
180 services.rspamd = {
181 enable = true;
182 workers = {
183 controller = {};
184 external = {
185 type = "rspamd_proxy";
186 bindSockets = [
187 { mode = "0660";
188 socket = "/run/rspamd/rspamd-milter.sock";
189 owner = config.services.rspamd.user;
190 group = config.services.rspamd.group;
191 }
192 ];
193 extraConfig = ''
194 milter = yes;
195
196 upstream "local" {
197 default = yes;
198 self_scan = yes;
199 }
200 '';
201 };
202 };
203 locals = {
204 "milter_headers.conf".text = ''
205 use = ["authentication-results", "x-spamd-result", "x-rspamd-queue-id", "x-rspamd-server", "x-spam-level", "x-spam-status"];
206 extended_headers_rcpt = [];
207 '';
208 "actions.conf".text = ''
209 reject = 15;
210 add_header = 10;
211 greylist = 5;
212 '';
213 "groups.conf".text = ''
214 symbols {
215 "BAYES_SPAM" {
216 weight = 2.0;
217 }
218 }
219 '';
220 "dmarc.conf".text = ''
221 reporting = true;
222 send_reports = true;
223 report_settings {
224 org_name = "Yggdrasil.li";
225 domain = "yggdrasil.li";
226 email = "postmaster@yggdrasil.li";
227 }
228 '';
229 "redis.conf".text = ''
230 servers = "${config.services.redis.servers.rspamd.unixSocket}";
231 '';
232 "dkim_signing.conf".text = "enabled = false;";
233 "neural.conf".text = "enabled = false;";
234 "classifier-bayes.conf".text = ''
235 enable = true;
236 expire = 8640000;
237 new_schema = true;
238 backend = "redis";
239 per_user = true;
240 min_learns = 0;
241
242 autolearn = [0, 10];
243
244 statfile {
245 symbol = "BAYES_HAM";
246 spam = false;
247 }
248 statfile {
249 symbol = "BAYES_SPAM";
250 spam = true;
251 }
252 '';
253 # "redirectors.inc".text = ''
254 # visit.creeper.host
255 # '';
256 };
257 };
258
259 users.groups.${config.services.rspamd.group}.members = [ config.services.postfix.user ];
260
261 services.redis.servers.rspamd = {
262 enable = true;
263 vmOverCommit = true;
264 };
265
266 users.groups.${config.services.redis.servers.rspamd.user}.members = [ config.services.rspamd.user ];
267
268 services.dovecot2 = {
269 enable = true;
270 enableImap = false;
271 sslServerCert = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.pem";
272 sslServerKey = "/run/credentials/dovecot2.service/surtr.yggdrasil.li.key.pem";
273 sslCACert = ./ca/ca.crt;
274 mailLocation = "maildir:/var/lib/mail/%u/maildir:UTF-8";
275 modules = with pkgs; [ dovecot_pigeonhole ];
276 protocols = [ "imaps" "lmtp" "sieve" ];
277 extraConfig = ''
278 mail_home = /var/lib/mail/%u
279
280 local_name imap.bouncy.email {
281 ssl_cert = <$/run/credentials/dovecot2.service/imap.bouncy.email.pem
282 ssl_key = <$/run/credentials/dovecot2.service/imap.bouncy.email.key.pem
283 }
284 local_name bouncy.email {
285 ssl_cert = <$/run/credentials/dovecot2.service/bouncy.email.pem
286 ssl_key = <$/run/credentials/dovecot2.service/bouncy.email.key.pem
287 }
288
289 ssl_require_crl = yes
290 ssl_verify_client_cert = yes
291 auth_ssl_username_from_cert = yes
292 auth_mechanisms = external
293
294 userdb sql {
295 args = ${pkgs.writeText "dovecot-sql.conf" ''
296 driver = pgsql
297 connect = host=localhost dbname=email
298 user_query = SELECT mailbox AS user, quota_rule FROM mailbox WHERE mailbox = '%u'
299 ''}
300 default_fields = uid=dovecot2 gid=dovecot2
301 }
302
303 mail_plugins = $mail_plugins quota
304 mailbox_list_index = yes
305 postmaster_address = postmaster@yggdrasil.li
306 recipient_delimiter = +
307
308 sieve_plugins = $sieve_plugins sieve_imapsieve
309
310 service lmtp {
311 vsz_limit = 1G
312
313 unix_listener /run/postfix/dovecot-lmtp {
314 mode = 0600
315 user = postfix
316 group = postfix
317 }
318 }
319
320 namespace inbox {
321 separator = /
322 inbox = yes
323 prefix =
324 }
325
326 plugin {
327 quota = maildir
328 quota_rule = *:storage=1GB
329 quota_rule2 = Trash:storage=+10%%
330 quota_status_overquota = "552 5.2.2 Mailbox is full"
331 quota_status_success = DUNNO
332 quota_status_nouser = DUNNO
333 quota_grace = 10%%
334 }
335
336 protocol imap {
337 mail_max_userip_connections = 50
338 mail_plugins = $mail_plugins imap_quota imap_sieve
339 }
340
341 service managesieve-login {
342 inet_listener sieve {
343 port = 4190
344 ssl = yes
345 }
346 }
347
348 plugin {
349 sieve_redirect_envelope_from = orig_recipient
350 sieve_before = ${compileSieve "tag-junk.sieve" ''
351 require ["imap4flags"];
352
353 if header :contains "X-Spam-Flag" "YES" {
354 addflag ["\\Junk"];
355 }
356 ''}
357 }
358 '';
359 };
360
158 security.dhparams = { 361 security.dhparams = {
159 params = { 362 params = {
160 "postfix-512".bits = 512; 363 "postfix-512".bits = 512;
@@ -166,6 +369,7 @@ with lib;
166 "bouncy.email" = {}; 369 "bouncy.email" = {};
167 "mailin.bouncy.email" = {}; 370 "mailin.bouncy.email" = {};
168 "mailsub.bouncy.email" = {}; 371 "mailsub.bouncy.email" = {};
372 "imap.bouncy.email" = {};
169 "surtr.yggdrasil.li" = {}; 373 "surtr.yggdrasil.li" = {};
170 }; 374 };
171 375
@@ -178,5 +382,20 @@ with lib;
178 "mailsub.bouncy.email.full.pem:${config.security.acme.certs."mailsub.bouncy.email".directory}/full.pem" 382 "mailsub.bouncy.email.full.pem:${config.security.acme.certs."mailsub.bouncy.email".directory}/full.pem"
179 ]; 383 ];
180 }; 384 };
385
386 systemd.services.dovecot2 = {
387 serviceConfig = {
388 LoadCredential = [
389 "surtr.yggdrasil.li.key.pem:${config.security.acme.certs."surtr.yggdrasil.li".directory}/key.pem"
390 "surtr.yggdrasil.li.pem:${config.security.acme.certs."surtr.yggdrasil.li".directory}/fullchain.pem"
391 "bouncy.email.key.pem:${config.security.acme.certs."bouncy.email".directory}/key.pem"
392 "bouncy.email.pem:${config.security.acme.certs."bouncy.email".directory}/fullchain.pem"
393 "imap.bouncy.email.key.pem:${config.security.acme.certs."imap.bouncy.email".directory}/key.pem"
394 "imap.bouncy.email.pem:${config.security.acme.certs."imap.bouncy.email".directory}/fullchain.pem"
395 ];
396
397 StateDirectory = "mail";
398 };
399 };
181 }; 400 };
182} 401}