1 { pkgs, lib, config, ... }:
3 inherit (builtins) attrNames concatStringsSep readFile toPath;
4 inherit (builtins.extraBuiltins) pass;
6 inherit (pkgs.lib) loadFile unlines unwords unlinesAttrs;
7 inherit (config) networking users;
8 inherit (config.services) postfix dovecot2 openldap;
12 postfix/sourcephile.fr.nix
13 postfix/autogeree.net.nix
17 tls_server_sni_maps = lib.mkOption {
18 type = types.attrsOf (types.listOf types.path);
20 apply = m: pkgs.writeText "sni" (lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: x509: ''
21 ${domain} ${unwords x509}
27 systemd.services.postfix = {
28 after = ["openldap.service"];
30 install -m 400 -o root -g root ${postfix.tls_server_sni_maps} /run/keys/postfix-sni
31 ${pkgs.postfix}/bin/postmap -F hash:/run/keys/postfix-sni
36 networksStyle = "host";
37 hostname ="${networking.hostName}.${networking.domain}";
38 domain = networking.domain;
39 origin = "$myhostname";
42 "localhost.localdomain"
45 postmasterAlias = "root";
46 rootAlias = "root@${networking.domain}";
47 sslCert = loadFile (../../../sec/openssl + "/${networking.domain}/cert.self-signed.pem");
48 sslKey = "/run/keys/${networking.domain}.key.pem";
54 # Parse the extension in email address, eg. contact+extension@
55 recipientDelimiter = "+";
57 debug_peer_level = "4";
59 #"chomsky.autogeree.net"
61 #"mail.sourcephile.fr"
65 # Sending to the world
67 # Appending .domain is the MUA's job
68 append_dot_mydomain = false;
69 smtp_body_checks = "";
70 #smtp_cname_overrides_servername = false;
71 smtp_connect_timeout = "60s";
72 #smtp_header_checks = "regexp:/var/lib/postfix/smtp_header_checks";
73 smtp_mime_header_checks = "";
74 smtp_nested_header_checks = "";
75 smtp_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ];
76 #smtp_tls_fingerprint_digest = "sha1";
77 smtp_tls_loglevel = "1";
78 #smtp_tls_note_starttls_offer = true;
79 #smtp_tls_policy_maps = "hash:/var/lib/postfix/conf/tls_policy";
80 # Only allow TLSv* protocols
81 smtp_tls_protocols = [ "!SSLv2" "!SSLv3" ];
82 #smtp_tls_scert_verifydepth = "5";
83 #smtp_tls_secure_cert_match = [ "nexthop" "dot-nexthop" ];
84 smtp_tls_security_level = "may";
85 smtp_tls_session_cache_database = "btree:$data_directory/smtp_tls_session_cache";
86 #smtp_tls_session_cache_timeout = "3600s";
87 #smtp_tls_verify_cert_match = "hostname";
90 # Receiving from the world
92 message_size_limit = "20480000";
93 maximal_queue_lifetime = "5d";
94 default_extra_recipient_limit = "5000";
95 line_length_limit = "2048";
96 duplicate_filter_limit = "5000";
97 # Stops mail from poorly written software
98 strict_rfc821_envelopes = true;
99 mime_header_checks = [];
100 milter_header_checks = [];
101 nested_header_checks = [];
104 permit_mx_backup_networks = [];
105 propagate_unmatched_extensions = [ "canonical" "virtual" "alias" ];
106 #masquerade_classes = [ "envelope_sender" "header_sender" "header_recipient" ];
107 #masquerade_domains = "";
108 #masquerade_exceptions = "root";
110 # Stops some techniques used to harvest email addresses
111 disable_vrfy_command = true;
112 enable_long_queue_ids = false;
113 # Useful to test restrictions
114 smtpd_authorized_xclient_hosts = "127.0.0.1";
115 smtpd_banner = "$myhostname ESMTP $mail_name (NixOS)";
116 smtpd_client_connection_count_limit = "50";
117 smtpd_client_connection_rate_limit = "0";
118 smtpd_client_event_limit_exceptions = "$mynetworks";
119 smtpd_client_message_rate_limit = "0";
120 smtpd_client_new_tls_session_rate_limit = "0";
121 smtpd_client_port_logging = false;
122 smtpd_client_recipient_rate_limit = "0";
124 smtpd_error_sleep_time = "5";
125 # Needed to enforce reject_unknown_helo_hostname
126 smtpd_helo_required = true;
127 smtpd_helo_restrictions = [
128 "reject_invalid_helo_hostname"
129 "reject_non_fqdn_helo_hostname"
130 # Don't talk to mail systems that don't know their own hostname.
131 "reject_unknown_helo_hostname"
134 smtpd_client_restrictions = [
136 # Set in postfix/*.nix and used in submissions/smptd
137 # with reject_sender_login_mismatch
138 smtpd_sender_login_maps = [];
139 smtpd_sender_restrictions = [
140 "reject_non_fqdn_sender"
143 smtpd_reject_unlisted_recipient = true;
144 # Check the RCPT TO, before smtpd_recipient_restrictions
145 # Restrictions based on what is allowed or not,
146 # these are applied before smtpd_recipient_restrictions
147 smtpd_relay_restrictions = [
149 # Check the recipient's address in virtual_mailbox_domains and virtual_mailbox_maps
150 "permit_auth_destination"
151 # The world is only authorized to use our relay for the above destinations.
154 # Restrictions based on what is working or not
155 smtpd_recipient_restrictions = [
156 # Reject if the domain is not fully qualified
157 "reject_non_fqdn_recipient"
158 # Reject if the domain is not working, even before bothering to check the address
159 "reject_unknown_recipient_domain"
160 # Reject if the address is not working
161 # WARNING: verify(8) has a cache, dumpable if verify(8) is stopped, with:
162 # postmap -s btree:/var/lib/postfix/data/verify_cache
163 "reject_unverified_recipient"
166 # Trust the verify database
167 unverified_recipient_reject_code = "550";
168 smtpd_data_restrictions = [
169 # Force the smtpd's client to wait OK before sending
170 "reject_unauth_pipelining"
173 smtpd_end_of_data_restrictions = [
174 # Enforce mail volume quota via policy service callouts.
175 #check_policy_service unix:private/policy
178 smtpd_peername_lookup = true;
179 smtpd_recipient_limit = "5000";
180 smtpd_recipient_overshoot_limit = "5000";
181 #smtpd_restriction_classes = "";
182 #smtpd_sasl_auth_enable = true;
183 #smtpd_sasl_path = "private/auth";
184 #smtpd_sasl_security_options = "noanonymous";
185 #smtpd_sasl_type = "dovecot";
186 smtpd_starttls_timeout = "300s";
187 #smtpd_tls_always_issue_session_ids = true;
188 #smtpd_tls_CApath = "/etc/postfix/x509/ca/";
189 smtpd_tls_ask_ccert = false;
190 #smtpd_tls_ccert_verifydepth = "5";
191 smtpd_tls_ciphers = "high";
192 smtpd_tls_eecdh_grade = "auto";
193 # Disable weak ciphers as reported by https://ssl-tools.net
194 # https://serverfault.com/questions/744168/how-to-disable-rc4-on-postfix
195 smtpd_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ];
196 smtpd_tls_fingerprint_digest = "sha512";
197 # Log only a summary message on TLS handshake completion
198 smtpd_tls_loglevel = "1";
199 smtpd_tls_mandatory_ciphers = "high";
200 smtpd_tls_mandatory_protocols = [ "!SSLv2" "!SSLv3" ];
202 smtpd_tls_protocols = [ "!SSLv2" "!SSLv3" ];
203 #smtpd_tls_received_header = false;
204 smtpd_tls_req_ccert = false;
205 # Postfix 2.3 and later
207 # Mandatory TLS encryption: announce STARTTLS support to SMTP clients, and require that clients use TLS
208 # encryption. According to [1720]RFC 2487 this MUST NOT be applied in case of a publicly-referenced
209 # SMTP server. Instead, this option should be used only on dedicated servers.
210 smtpd_tls_security_level = "may";
211 smtpd_tls_session_cache_database = "btree:$data_directory/smtpd_tls_session_cache";
212 #smtpd_tls_session_cache_timeout = "3600s";
213 #smtpd_tls_chain_files =
216 #relay_clientcerts = hash:/var/lib/postfix/conf/relay_clientcerts
217 # This is where to put backup MX domains
219 relay_recipient_maps = [];
221 # Use a non blocking source of randomness
222 tls_random_source = "dev:/dev/urandom";
223 # Map each domain to a specific X.509 certificate
224 tls_server_sni_maps = "hash:/run/keys/postfix-sni";
226 # Only explicitely aliased accounts have a mail, not all the passwd
227 local_recipient_maps = "$alias_maps";
228 # Note that the local transport rewrites the envelope recipient
229 # according to the alias_maps, and thus the aliasing is transparent
230 # to the nexthop (eg. dovecot)
231 #local_transport = local:$myhostname
232 # No console bell on new mail
236 "$home/.forward''${recipient_delimiter}''${extension}"
241 # Filled by the postfix/*.nix
242 virtual_mailbox_domains = [];
243 # Completed by the postfix/*.nix
244 virtual_mailbox_maps = [
245 "hash:/etc/postfix/virtual"
247 virtual_transport = "lmtp:unix:private/dovecot-lmtp";
249 # There is no fallback
250 fallback_transport = "";
252 virtualMapType = "hash";
257 then concatStringsSep "," value
259 if value == true then "yes"
260 else if value == false then "no"
262 mkKeyVal = opt: val: [ "-o" (opt + "=" + mkVal val) ];
263 mkArgs = args: lib.concatLists (lib.mapAttrsToList mkKeyVal args);
267 cleanup_service_name = "submissions-header-cleanup";
270 # Implicit TLS on port 465
271 # https://tools.ietf.org/html/rfc8314#section-3.3
277 syslog_name = "postfix/submissions";
278 # Implicit TLS, not STARTTLS
279 smtpd_tls_wrappermode = true;
280 smtpd_tls_mandatory_protocols = [
282 # K-9 Mail 5.600 still requires this..
285 milter_macro_daemon_name = "ORIGINATING";
286 smtpd_relay_restrictions = [
287 # SASL authorizes to send to the world
288 "permit_sasl_authenticated"
291 smtpd_sasl_auth_enable = true;
292 smtpd_sasl_type = "dovecot";
293 smtpd_sasl_path = "private/auth";
294 smtpd_sasl_local_domain = "";
295 # Offer SASL authentication only after a TLS-encrypted session has been established
296 smtpd_tls_auth_only = true;
297 smtpd_sasl_tls_security_options = [ "noanonymous" ];
298 # Do not put SASL logins in mail headers
299 smtpd_sasl_authenticated_header = false;
300 # Who cares about (old) Outlook
301 broken_sasl_auth_clients = false;
302 smtpd_sender_restrictions = [
303 "reject_non_fqdn_sender"
304 # Check that the SASL user is using only its own
305 # mail addresses on the envelope, as indicated in smtpd_sender_login_maps
306 "reject_sender_login_mismatch"
309 # No X.509 certificates for users, for now
310 smtpd_tls_ask_ccert = false;
311 smtpd_tls_ccert_verifydepth = 0;
312 smtpd_tls_loglevel = 1;
313 smtpd_tls_req_ccert = false;
314 cleanup_service_name = "submissions-header-cleanup";
317 submissions-header-cleanup = {
323 header_checks = "pcre:" + pkgs.writeText "submission_header_cleanup_rules" ''
324 # Removes sensitive headers from mails handed in via the submission or smtps port.
325 # See https://thomas-leister.de/mailserver-debian-stretch/
326 # Uses "pcre" style regex.
329 /^User-Agent:/ IGNORE
330 /^X-Enigmail:/ IGNORE
332 /^X-Originating-IP:/ IGNORE
338 #spfcheck unix - n n - 0 spawn
339 # user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
340 # -o smtpd_sender_restrictions=reject_sender_login_mismatch
341 # -o smtpd_sender_login_maps=hash:/etc/postfix/vaccounts
342 # -o cleanup_service_name=submissions-header-cleanup
343 #spfcheck unix - n n - 0 spawn
344 # user=policyd-spf argv=/usr/bin/postfix-policyd-spf-perl
345 #uucp unix - n n - - pipe
346 # flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
347 #smtp inet n - - - - smtpd
348 # -o cleanup_service_name=pre-cleanup
349 # -o content_filter=amavis:[127.0.0.1]:10024
350 # -o smtpd_sender_restrictions=reject_unauth_pipelining,reject_non_fqdn_sender,permit
351 # -o receive_override_options=no_address_mappings
352 #amavis unix - - n - 2 lmtp
353 # -o lmtp_data_done_timeout=1200
354 # -o lmtp_send_xforward_command=yes
355 # -o lmtp_tls_note_starttls_offer=no
356 #127.0.0.1:10025 inet n - n - - smtpd
358 # -o local_header_rewrite_clients=
359 # -o local_recipient_maps=
360 # -o mynetworks=127.0.0.0/8
361 # -o receive_override_options=no_header_body_checks,no_milters,no_unknown_recipient_checks
362 # -o relay_recipient_maps=
363 # -o smtpd_client_connection_count_limit=0
364 # -o smtpd_client_connection_rate_limit=0
365 # -o smtpd_client_restrictions=permit_mynetworks,reject
366 # -o smtpd_data_restrictions=reject_unauth_pipelining
367 # -o smtpd_delay_reject=no
368 # -o smtpd_end_of_data_restrictions=
369 # -o smtpd_error_sleep_time=0
370 # -o smtpd_hard_error_limit=1000
371 # -o smtpd_helo_restrictions=
373 # -o smtpd_recipient_restrictions=permit_mynetworks,reject
374 # -o smtpd_restriction_classes=
375 # -o smtpd_sender_restrictions=
376 # -o smtpd_soft_error_limit=1001
377 # -o strict_rfc821_envelopes=yes
378 #submission inet n - - - - smtpd
379 # -o cleanup_service_name=pre-cleanup
380 # -o content_filter=amavis:[127.0.0.1]:10024
381 # -o milter_macro_daemon_name=ORIGINATING
382 # -o receive_override_options=no_address_mappings
383 # -o smtpd_sender_restrictions=permit_tls_clientcerts,reject
384 # -o smtpd_tls_ask_ccert=yes
385 # -o smtpd_tls_auth_only=yes
386 # -o smtpd_tls_ccert_verifydepth=2
387 # -o smtpd_tls_loglevel=1
388 # -o smtpd_tls_req_ccert=yes
389 # -o smtpd_tls_security_level=encrypt
390 #smtps inet n - - - - smtpd
391 # -o milter_macro_daemon_name=ORIGINATING
392 # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
393 # -o smtpd_sasl_auth_enable=yes
394 # -o smtpd_tls_ask_ccert=yes
395 # -o smtpd_tls_auth_only=yes
396 # -o smtpd_tls_ccert_verifydepth=0
397 # -o smtpd_tls_loglevel=1
398 # -o smtpd_tls_req_ccert=no
399 # -o smtpd_tls_security_level=encrypt
400 # -o smtpd_tls_wrappermode=yes
401 #pickup fifo n - - 60 1 pickup
402 # -o cleanup_service_name=pre-cleanup
403 # -o content_filter=amavis:[127.0.0.1]:10024
404 #pre-cleanup unix n - - - 0 cleanup
405 # -o virtual_alias_maps=
406 #cleanup unix n - - - 0 cleanup
407 # -o mime_header_checks=
408 # -o nested_header_checks=
412 #sympa unix - n n - - pipe
413 # flags=R user=sympa argv=/usr/lib/sympa/bin/queue ''${recipient}
414 #sympabounce unix - n n - - pipe
415 # flags=R user=sympa argv=/usr/lib/sympa/bin/bouncequeue ''${recipient}
418 #noclue unix - n n - - pipe
419 # flags=q user=noclue argv=/usr/local/bin/noclue-delivery ${recipient} ${sender}