]> Git — Sourcephile - sourcephile-nix.git/blob - install/logical/friot/postfix.nix
rspamd: brittle install
[sourcephile-nix.git] / install / logical / friot / postfix.nix
1 {pkgs, lib, config, nodes, ...}:
2 let inherit (builtins) attrNames toFile;
3 inherit (lib) types;
4 inherit (pkgs.lib) unlines unlinesAttrs;
5 inherit (config) networking;
6 inherit (config.services) x509 postfix dovecot2 openldap;
7 unwords = lib.concatStringsSep " ";
8 when = x: y: if x == null then "" else y;
9
10 submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules" ''
11 # Removes sensitive headers from mails handed in via the submission or smtps port.
12 # See https://thomas-leister.de/mailserver-debian-stretch/
13 # Uses "pcre" style regex.
14
15 /^Received:/ IGNORE
16 /^User-Agent:/ IGNORE
17 /^X-Enigmail:/ IGNORE
18 /^X-Mailer:/ IGNORE
19 /^X-Originating-IP:/ IGNORE
20 '';
21 in
22 {
23 options.services.postfix.aliases = lib.mkOption {
24 type = with types; attrsOf (listOf str);
25 default = {};
26 example = { "root@${networking.domain}" = [
27 "user1@${networking.domain}"
28 "user2@${networking.domain}"
29 ];
30 "@example.coop" = ["user1@${networking.domain}"];
31 };
32 };
33 config = {
34 systemd.services.postfix.after =
35 [ "openldap.service" ] ++
36 (if x509.scheme == "letsencrypt"
37 then [ "nginx.service" ] # XXX: not sure if this is enough
38 else []);
39 services.postfix = {
40 enable = true;
41 #hostname = networking.domain;
42 #domain = "localdomain";
43 networksStyle = "host";
44 #mapFiles."valias" = toFile "valias" (unlines (all_valiases_postfix ++ catchAllPostfix));
45 # See https://blog.grimneko.de/2011/12/24/a-bunch-of-tips-for-improving-your-postfix-setup/
46 # for details on how this file looks. By using the same file as valias,
47 # every alias is uniquely owned by its user.
48 # The user's own address is already in all_valiases_postfix.
49 #mapFiles."vaccounts" = toFile "vaccounts" (unlines all_valiases_postfix);
50 mapFiles."virtual_alias_maps" =
51 toFile "virtual_alias_maps"
52 (unlinesAttrs
53 (from: to: "${from} ${unwords to}")
54 postfix.aliases);
55 mapFiles."ldap-virtual_alias_maps.cf" =
56 toFile "ldap-virtual_alias_maps.cf" ''
57 version = 3
58 debuglevel = 0
59 server_host = ldapi://
60 bind = sasl
61 sasl_mechs = EXTERNAL
62 search_base = ou=posix,${openldap.domainSuffix}
63 scope = sub
64 dereference = 0
65 query_filter = (&(mailAlias=%s)(mailEnabled=TRUE))
66 result_format = %s
67 result_attribute = mail
68 '';
69 mapFiles."ldap-forward.cf" =
70 toFile "ldap-forward.cf" ''
71 version = 3
72 debuglevel = 0
73 server_host = ldapi://
74 bind = sasl
75 sasl_mechs = EXTERNAL
76 search_base = ou=posix,${openldap.domainSuffix}
77 scope = sub
78 dereference = 0
79 query_filter = (&(mail=%s)(mailEnabled=TRUE))
80 result_format = %s
81 result_attribute = mailForwardingAddress
82 '';
83 sslCert = x509.cert;
84 sslKey = x509.key;
85 #enableSubmission = true;
86 #enableSmtp = true;
87 destination = [
88 "localhost"
89 "localhost.localdomain"
90 networking.hostName
91 "${networking.hostName}.localdomain"
92 ];
93 networks = [
94 "127.0.0.0/8"
95 "[::1]/128"
96 ];
97 recipientDelimiter = "+";
98 config = {
99 # Appending .domain is the MUA's job
100 append_dot_mydomain = false;
101 # No console bell on new mail
102 biff = false;
103 body_checks = "";
104 #content_filter = "amavisfeed:[127.0.0.1]:10024";
105 #debug_peer_level = 4;
106 #debug_peer_list = ".$myhostname";
107 default_extra_recipient_limit = "5000";
108 # Uncomment the next line to generate "delayed mail" warnings
109 #delay_warning_time = "4h";
110 # Stops some techniques used to harvest email addresses
111 disable_vrfy_command = true;
112 duplicate_filter_limit = "5000";
113 enable_long_queue_ids = false;
114 # Pass unexisting $mydestination recipients to dovecot
115 fallback_transport = "lmtp:unix:private/dovecot-lmtp";
116 forward_path = [
117 ''$home/.forward''${recipient_delimiter}''${extension}''
118 "$home/.forward"
119 ];
120 #header_checks = "regexp:/var/lib/postfix/conf/header_checks";
121 #inet_interfaces = "all";
122 line_length_limit = "2048";
123
124 # Let $fallback_transport check existence of recipients
125 local_recipient_maps = "";
126 #mail_spool_directory = "/var/spool/mail";
127 # NOTE: nixpkgs's default
128 #local_header_rewrite_clients = "";
129 #home_mailbox = "Maildir/";
130 #mailbox_command = ''
131 # ${pkgs.procmail}/bin/procmail -t -a "$SENDER" -a "$RECIPIENT" -a "$USER" -a "$EXTENSION" -a "$DOMAIN" -a "$ORIGINAL_RECIPIENT" "$HOME/.procmailrc"
132 #'';
133 mailbox_size_limit = "204800000";
134
135 masquerade_classes = [ "envelope_sender" "header_sender" "header_recipient" ];
136 masquerade_domains = "";
137 masquerade_exceptions = "root";
138 maximal_queue_lifetime = "5d";
139 message_size_limit = "20480000";
140 mime_header_checks = "";
141 milter_header_checks = "";
142 nested_header_checks = "";
143 #non_smtpd_milters = "";
144 parent_domain_matches_subdomains = [
145 #"debug_peer_list"
146 #"fast_flush_domains"
147 #"mynetworks"
148 #"permit_mx_backup_networks"
149 #"qmqpd_authorized_clients"
150 #"smtpd_access_maps"
151 ];
152 permit_mx_backup_networks = "";
153 #policy-spf_time_limit = "3600s";
154 propagate_unmatched_extensions = [ "canonical" "virtual" "alias" ];
155 queue_minfree = "0";
156 #receive_override_options = "no_address_mappings";
157 # no_unknown_recipient_checks
158 # Do not try to reject unknown recipients (SMTP server only).
159 # This is typically specified AFTER an external content filter.
160 # no_address_mappings
161 # Disable canonical address mapping, virtual alias map expansion,
162 # address masquerading, and automatic BCC (blind carbon-copy) recipients.
163 # This is typically specified BEFORE an external content filter (eg. amavis).
164 # no_header_body_checks
165 # Disable header/body_checks. This is typically specified AFTER
166 # an external content filter.
167 # no_milters
168 # Disable Milter (mail filter) applications.
169 # This is typically specified AFTER an external content filter.
170 # Parse the extension in email address, eg. contact+extension@
171 relayhost = "";
172 #relay_clientcerts = hash:/var/lib/postfix/conf/relay_clientcerts
173 # This is where to put backup MX domains
174 relay_domains = "$mydestination";
175 relay_recipient_maps = "";
176 smtp_body_checks = "";
177 #smtp_cname_overrides_servername = false;
178 smtp_connect_timeout = "60s";
179 #smtp_header_checks = "regexp:/var/lib/postfix/smtp_header_checks";
180 smtp_mime_header_checks = "";
181 smtp_nested_header_checks = "";
182 smtp_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ];
183 #smtp_tls_fingerprint_digest = "sha1";
184 smtp_tls_loglevel = "1";
185 #smtp_tls_note_starttls_offer = true;
186 #smtp_tls_policy_maps = "hash:/var/lib/postfix/conf/tls_policy";
187 # Only allow TLSv* protocols
188 smtp_tls_protocols = [ "!SSLv2" "!SSLv3" ];
189 smtp_tls_scert_verifydepth = "5";
190 #smtp_tls_secure_cert_match = [ "nexthop" "dot-nexthop" ];
191 smtp_tls_security_level = "may";
192 smtp_tls_session_cache_database = "btree:$data_directory/smtp_tls_session_cache";
193 #smtp_tls_session_cache_timeout = "3600s";
194 #smtp_tls_verify_cert_match = "hostname";
195 # Useful to test restrictions
196 smtpd_authorized_xclient_hosts = "127.0.0.1";
197 smtpd_banner = "${networking.fqdn} ESMTP $mail_name (NixOS)";
198 smtpd_client_connection_count_limit = "50";
199 smtpd_client_connection_rate_limit = "0";
200 smtpd_client_event_limit_exceptions = "$mynetworks";
201 smtpd_client_message_rate_limit = "0";
202 smtpd_client_new_tls_session_rate_limit = "0";
203 smtpd_client_port_logging = false;
204 smtpd_client_recipient_rate_limit = "0";
205 smtpd_client_restrictions = [
206 #"check_client_access hash:/var/lib/postfix/conf/client_blacklist"
207 ];
208 smtpd_data_restrictions = [
209 "reject_unauth_pipelining"
210 # Force the smtp client to wait OK before sending
211 "permit"
212 ];
213 # Disable opportunistic encryption
214 smtpd_discard_ehlo_keywords = "starttls";
215 #smtpd_end_of_data_restrictions = "";
216 # Ban 5 sec on error
217 smtpd_error_sleep_time = "5";
218 smtpd_helo_required = true;
219 smtpd_helo_restrictions = [
220 "reject_invalid_helo_hostname"
221 "reject_non_fqdn_helo_hostname"
222 #"reject_unknown_helo_hostname"
223 # May be useful to fight spam
224 "permit"
225 ];
226 #smtpd_milters = "";
227 smtpd_peername_lookup = true;
228 smtpd_recipient_limit = "5000";
229 smtpd_recipient_overshoot_limit = "5000";
230 smtpd_recipient_restrictions = [
231 "reject_non_fqdn_recipient"
232 #"reject_invalid_hostname"
233 "reject_unknown_recipient_domain"
234 #"reject_non_fqdn_sender"
235 "reject_unauth_pipelining"
236 #"check_policy_service inet:localhost:12340"
237 # check quota
238 "permit_mynetworks"
239 #"permit_tls_clientcerts"
240 "permit_sasl_authenticated"
241 "reject_unverified_recipient"
242 # $fallback_transport is responsible of checking the existence of the recipient
243 # WARNING: verify(8) has a cache, dumpable if verify(8) is stopped, with:
244 # postmap -s btree:/var/lib/postfix/data/verify_cache
245 # Bypass SPF check and postgrey if the recipient is not for us or someone in backup_mx
246 "reject_unauth_destination"
247 # Check SPF
248 #"check_policy_service unix:private/spfcheck"
249 # Greylisting using postgrey
250 #"check_policy_service unix:${postgrey.socket.path}"
251 "permit_auth_destination"
252 "reject"
253 #"reject_unknown_sender_domain"
254 # Maybe better in smtpd_sender_restrictions
255 #"reject_rbl_client bl.spamcop.net"
256 #"reject_rbl_client list.dsbl.org"
257 #"reject_rbl_client zen.spamhaus.org"
258 #"reject_rbl_client dnsbl.sorbs.net"
259 ];
260 smtpd_relay_restrictions = [
261 "permit_mynetworks"
262 "permit_sasl_authenticated"
263 # NOTE: permit auth through dovecot's SASL
264 "reject_unauth_destination"
265 ];
266 #smtpd_restriction_classes = "";
267 broken_sasl_auth_clients = false;
268 #smtpd_sasl_auth_enable = true;
269 #smtpd_sasl_path = "private/auth";
270 #smtpd_sasl_security_options = "noanonymous";
271 #smtpd_sasl_type = "dovecot";
272 smtpd_sender_restrictions = [
273 "permit_mynetworks"
274 #"permit_tls_clientcerts"
275 "permit_sasl_authenticated"
276 # NOTE: permit auth through dovecot's SASL
277 #"check_sender_access hash:/var/lib/postfix/conf/sender_access"
278 "reject_unauth_pipelining"
279 "reject_non_fqdn_sender"
280 #"reject_sender_login_mismatch"
281 #"reject_unknown_sender_domain"
282 "permit"
283 ];
284 smtpd_starttls_timeout = "300s";
285 #smtpd_tls_always_issue_session_ids = true;
286 # No SASL AUTH without TLS
287 smtpd_tls_auth_only = true;
288 #smtpd_tls_CApath = "/etc/postfix/x509/ca/";
289 smtpd_tls_ask_ccert = false;
290 #smtpd_tls_ccert_verifydepth = "5";
291 smtpd_tls_ciphers = "high";
292 smtpd_tls_eecdh_grade = "ultra";
293 # Disable weak ciphers as reported by https://ssl-tools.net
294 # https://serverfault.com/questions/744168/how-to-disable-rc4-on-postfix
295 smtpd_tls_exclude_ciphers = [ "RC4" "aNULL" ];
296 smtpd_tls_fingerprint_digest = "sha512";
297 # Log only a summary message on TLS handshake completion
298 smtpd_tls_loglevel = "1";
299 smtpd_tls_mandatory_ciphers = "high";
300 smtpd_tls_mandatory_protocols = "TLSv1"; # FIXME: TLSv1.3
301 # Only allow TLSv*
302 smtpd_tls_protocols = [ "!SSLv2" "!SSLv3" ];
303 #smtpd_tls_received_header = false;
304 smtpd_tls_req_ccert = false;
305 # Postfix 2.3 and later
306 # encrypt
307 # Mandatory TLS encryption: announce STARTTLS support to SMTP clients, and require that clients use TLS
308 # encryption. According to [1720]RFC 2487 this MUST NOT be applied in case of a publicly-referenced
309 # SMTP server. Instead, this option should be used only on dedicated servers.
310 smtpd_tls_security_level = "may";
311 smtpd_tls_session_cache_database = "btree:$data_directory/smtpd_tls_session_cache";
312 #smtpd_tls_session_cache_timeout = "3600s";
313 # Stops mail from poorly written software
314 strict_rfc821_envelopes = true;
315 #sympa_destination_recipient_limit = "1";
316 #sympabounce_destination_recipient_limit = "1";
317 # postconf(5) discourages to change this
318 #tls_high_cipherlist = "AES256-SHA";
319 #tls_random_bytes = "32";
320 # Must not be in a chroot
321 #tls_random_exchange_name = "$data_directory/prng_exch";
322 #tls_random_prng_update_period = "3600s";
323 #tls_random_reseed_period = "3600s";
324 # Use a non blocking source of randomness
325 tls_random_source = "dev:/dev/urandom";
326 transport_maps = [
327 #"ldap:transport"
328 #"hash:/etc/postfix/transport-dovecot"
329 #"hash:/etc/postfix/$mydomain/transport"
330 #"hash:/etc/dovecot/transport"
331 #"regexp:/etc/sympa/transport"
332 ];
333 # Rejects immediately what $fallback_transport rejects
334 unverified_recipient_reject_code = "550";
335 # Do not specify virtual alias domain names in mydestination
336 # or relay_domains configuration parameters
337 #
338 # With a virtual alias domain, the Postfix SMTP server
339 # accepts mail for known-user@virtual-alias.domain, and
340 # rejects mail for unknown-user@virtual-alias.domain as
341 # undeliverable.
342 virtual_alias_domains = [];
343 virtual_alias_maps = [
344 #"hash:/etc/postfix/virtual_alias_maps"
345 #"hash:/etc/postfix/virtual_domain_alias_maps"
346 "ldap:/etc/postfix/ldap-forward.cf"
347 "ldap:/etc/postfix/ldap-virtual_alias_maps.cf"
348 #"hash:/etc/postfix/virtual_alias-dovecot"
349 #"hash:/var/lib/postfix/conf/valias"
350 #"regexp:/etc/sympa/virtual_alias"
351 ];
352 #virtual_uid_maps = "static:5000";
353 #virtual_gid_maps = "static:5000";
354 #virtual_mailbox_base = dovecot2.mailDir;
355 virtual_mailbox_domains = [ networking.domain ] ++ networking.domainAliases;
356 #virtual_mailbox_maps = "hash:/etc/postfix/virtual_mailbox_maps";
357 virtual_transport = "lmtp:unix:private/dovecot-lmtp";
358 };
359 #submissionOptions = {
360 # smtpd_tls_security_level = "encrypt";
361 # smtpd_sasl_auth_enable = "yes";
362 # smtpd_sasl_type = "dovecot";
363 # smtpd_sasl_path = "private/auth";
364 # smtpd_sasl_security_options = "noanonymous";
365 # smtpd_sasl_local_domain = "$myhostname";
366 # smtpd_client_restrictions = "permit_sasl_authenticated,reject";
367 # smtpd_sender_login_maps = "hash:/etc/postfix/vaccounts";
368 # smtpd_sender_restrictions = "reject_sender_login_mismatch";
369 # smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
370 # cleanup_service_name = "submission-header-cleanup";
371 #};
372 extraMasterConf = ''
373 #spfcheck unix - n n - 0 spawn
374 # user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
375 465 inet n - - - - smtpd
376 -o milter_macro_daemon_name=ORIGINATING
377 -o smtpd_client_restrictions=permit_sasl_authenticated,reject
378 -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
379 -o smtpd_sasl_auth_enable=yes
380 -o smtpd_sasl_local_domain=$myhostname
381 -o smtpd_sasl_path=private/auth
382 -o smtpd_sasl_security_options=noanonymous
383 -o smtpd_sasl_type=dovecot
384 -o smtpd_tls_ask_ccert=no
385 -o smtpd_tls_auth_only=yes
386 -o smtpd_tls_ccert_verifydepth=0
387 -o smtpd_tls_loglevel=1
388 -o smtpd_tls_req_ccert=no
389 -o smtpd_tls_security_level=encrypt
390 -o smtpd_tls_wrappermode=yes
391 # -o smtpd_sender_restrictions=reject_sender_login_mismatch
392 # -o smtpd_sender_login_maps=hash:/etc/postfix/vaccounts
393 # -o cleanup_service_name=submission-header-cleanup
394 submission-header-cleanup unix n - n - 0 cleanup
395 -o header_checks=pcre:${submissionHeaderCleanupRules}
396 #spfcheck unix - n n - 0 spawn
397 # user=policyd-spf argv=/usr/bin/postfix-policyd-spf-perl
398 #uucp unix - n n - - pipe
399 # flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
400 #smtp inet n - - - - smtpd
401 # -o cleanup_service_name=pre-cleanup
402 # -o content_filter=amavis:[127.0.0.1]:10024
403 # -o smtpd_sender_restrictions=reject_unauth_pipelining,reject_non_fqdn_sender,permit
404 # -o receive_override_options=no_address_mappings
405 #amavis unix - - n - 2 lmtp
406 # -o lmtp_data_done_timeout=1200
407 # -o lmtp_send_xforward_command=yes
408 # -o lmtp_tls_note_starttls_offer=no
409 #127.0.0.1:10025 inet n - n - - smtpd
410 # -o content_filter=
411 # -o local_header_rewrite_clients=
412 # -o local_recipient_maps=
413 # -o mynetworks=127.0.0.0/8
414 # -o receive_override_options=no_header_body_checks,no_milters,no_unknown_recipient_checks
415 # -o relay_recipient_maps=
416 # -o smtpd_client_connection_count_limit=0
417 # -o smtpd_client_connection_rate_limit=0
418 # -o smtpd_client_restrictions=permit_mynetworks,reject
419 # -o smtpd_data_restrictions=reject_unauth_pipelining
420 # -o smtpd_delay_reject=no
421 # -o smtpd_end_of_data_restrictions=
422 # -o smtpd_error_sleep_time=0
423 # -o smtpd_hard_error_limit=1000
424 # -o smtpd_helo_restrictions=
425 # -o smtpd_milters=
426 # -o smtpd_recipient_restrictions=permit_mynetworks,reject
427 # -o smtpd_restriction_classes=
428 # -o smtpd_sender_restrictions=
429 # -o smtpd_soft_error_limit=1001
430 # -o strict_rfc821_envelopes=yes
431 #submission inet n - - - - smtpd
432 # -o cleanup_service_name=pre-cleanup
433 # -o content_filter=amavis:[127.0.0.1]:10024
434 # -o milter_macro_daemon_name=ORIGINATING
435 # -o receive_override_options=no_address_mappings
436 # -o smtpd_sender_restrictions=permit_tls_clientcerts,reject
437 # -o smtpd_tls_ask_ccert=yes
438 # -o smtpd_tls_auth_only=yes
439 # -o smtpd_tls_ccert_verifydepth=2
440 # -o smtpd_tls_loglevel=1
441 # -o smtpd_tls_req_ccert=yes
442 # -o smtpd_tls_security_level=encrypt
443 #smtps inet n - - - - smtpd
444 # -o milter_macro_daemon_name=ORIGINATING
445 # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
446 # -o smtpd_sasl_auth_enable=yes
447 # -o smtpd_tls_ask_ccert=yes
448 # -o smtpd_tls_auth_only=yes
449 # -o smtpd_tls_ccert_verifydepth=0
450 # -o smtpd_tls_loglevel=1
451 # -o smtpd_tls_req_ccert=no
452 # -o smtpd_tls_security_level=encrypt
453 # -o smtpd_tls_wrappermode=yes
454 #pickup fifo n - - 60 1 pickup
455 # -o cleanup_service_name=pre-cleanup
456 # -o content_filter=amavis:[127.0.0.1]:10024
457 #pre-cleanup unix n - - - 0 cleanup
458 # -o virtual_alias_maps=
459 #cleanup unix n - - - 0 cleanup
460 # -o mime_header_checks=
461 # -o nested_header_checks=
462 # -o body_checks=
463 # -o header_checks=
464 #-- SYMPA begin
465 #sympa unix - n n - - pipe
466 # flags=R user=sympa argv=/usr/lib/sympa/bin/queue ''${recipient}
467 #sympabounce unix - n n - - pipe
468 # flags=R user=sympa argv=/usr/lib/sympa/bin/bouncequeue ''${recipient}
469 #-- SYMPA end
470 '';
471 #noclue unix - n n - - pipe
472 # flags=q user=noclue argv=/usr/local/bin/noclue-delivery ${recipient} ${sender}
473 };
474 };
475 }