1 { pkgs, lib, config, inputs, ... }:
3 inherit (builtins) attrNames readFile toPath;
5 inherit (config) networking users;
6 inherit (config.services) postfix dovecot2 openldap;
10 postfix/autogeree.net.nix
11 postfix/sourcephile.fr.nix
13 users.groups.acme.members = [ postfix.user ];
14 networking.nftables.ruleset = ''
15 add rule inet filter net2fw tcp dport 25 counter accept comment "SMTP"
16 add rule inet filter net2fw tcp dport 465 counter accept comment "submissions"
17 add rule inet filter fw2net meta skuid ${postfix.user} tcp dport 25 counter accept comment "SMTP"
21 networksStyle = "host";
22 hostname ="${networking.hostName}.${networking.domain}";
23 domain = networking.domain;
24 origin = "$myhostname";
27 "localhost.localdomain"
30 postmasterAlias = "root";
31 rootAlias = "root@${networking.domain}";
32 sslKey = "/var/lib/acme/${networking.domain}/key.pem";
33 sslCert = "/var/lib/acme/${networking.domain}/fullchain.pem";
39 # Parse the extension in email address, eg. contact+extension@
40 recipientDelimiter = "+";
41 mapFiles.sender_access = inputs.secrets + "/postfix/sender_access";
43 debug_peer_level = "4";
45 #"chomsky.autogeree.net"
47 #"mail.sourcephile.fr"
51 # Sending to the world
53 # Appending .domain is the MUA's job
54 append_dot_mydomain = false;
55 smtp_body_checks = "";
56 #smtp_cname_overrides_servername = false;
57 smtp_connect_timeout = "60s";
58 #smtp_header_checks = "regexp:/var/lib/postfix/smtp_header_checks";
59 smtp_mime_header_checks = "";
60 smtp_nested_header_checks = "";
61 smtp_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ];
62 #smtp_tls_fingerprint_digest = "sha1";
63 smtp_tls_loglevel = "1";
64 #smtp_tls_note_starttls_offer = true;
65 #smtp_tls_policy_maps = "hash:/var/lib/postfix/conf/tls_policy";
66 # Only allow TLSv* protocols
67 smtp_tls_protocols = [ "!SSLv2" "!SSLv3" ];
68 #smtp_tls_scert_verifydepth = "5";
69 #smtp_tls_secure_cert_match = [ "nexthop" "dot-nexthop" ];
70 smtp_tls_security_level = "may";
71 smtp_tls_session_cache_database = "btree:$data_directory/smtp_tls_session_cache";
72 #smtp_tls_session_cache_timeout = "3600s";
73 #smtp_tls_verify_cert_match = "hostname";
76 # Receiving from the world
78 message_size_limit = "20480000";
79 maximal_queue_lifetime = "5d";
80 default_extra_recipient_limit = "5000";
81 line_length_limit = "2048";
82 duplicate_filter_limit = "5000";
83 # Stops mail from poorly written software
84 strict_rfc821_envelopes = true;
85 mime_header_checks = [];
86 milter_header_checks = [];
87 nested_header_checks = [];
90 permit_mx_backup_networks = [];
91 propagate_unmatched_extensions = [ "canonical" "virtual" "alias" ];
92 #masquerade_classes = [ "envelope_sender" "header_sender" "header_recipient" ];
93 #masquerade_domains = "";
94 #masquerade_exceptions = "root";
96 # Stops some techniques used to harvest email addresses
97 disable_vrfy_command = true;
98 enable_long_queue_ids = false;
99 # Useful to test restrictions
100 smtpd_authorized_xclient_hosts = "127.0.0.1";
101 smtpd_banner = "$myhostname ESMTP $mail_name (NixOS)";
102 smtpd_client_connection_count_limit = "50";
103 smtpd_client_connection_rate_limit = "0";
104 smtpd_client_event_limit_exceptions = "$mynetworks";
105 smtpd_client_message_rate_limit = "0";
106 smtpd_client_new_tls_session_rate_limit = "0";
107 smtpd_client_port_logging = false;
108 smtpd_client_recipient_rate_limit = "0";
110 smtpd_error_sleep_time = "5";
111 # Needed to enforce reject_unknown_helo_hostname
112 smtpd_helo_required = true;
113 smtpd_helo_restrictions = [
114 "reject_invalid_helo_hostname"
115 "reject_non_fqdn_helo_hostname"
116 # Don't talk to mail systems that don't know their own hostname.
117 "reject_unknown_helo_hostname"
120 smtpd_client_restrictions = [
122 # Set in postfix/*.nix and used in submissions/smptd
123 # with reject_sender_login_mismatch
124 smtpd_sender_login_maps = [];
125 smtpd_sender_restrictions = [
126 "reject_non_fqdn_sender"
127 "check_sender_access hash:/etc/postfix/sender_access"
130 smtpd_reject_unlisted_recipient = true;
131 # Check the RCPT TO, before smtpd_recipient_restrictions
132 # Restrictions based on what is allowed or not,
133 # these are applied before smtpd_recipient_restrictions
134 smtpd_relay_restrictions = [
136 # Check the recipient's address in virtual_mailbox_domains and virtual_mailbox_maps
137 "permit_auth_destination"
138 # The world is only authorized to use our relay for the above destinations.
141 # Restrictions based on what is working or not
142 smtpd_recipient_restrictions = [
143 # Reject if the domain is not fully qualified
144 "reject_non_fqdn_recipient"
145 # Reject if the domain is not working, even before bothering to check the address
146 "reject_unknown_recipient_domain"
147 # Reject if the address is not working
148 # WARNING: this does not work if the recipient is greylisting.
149 # WARNING: verify(8) has a cache, dumpable if verify(8) is stopped, with:
150 # postmap -s btree:/var/lib/postfix/data/verify_cache
151 #"reject_unverified_recipient"
154 # Trust the verify database
155 #unverified_recipient_reject_code = "550";
156 smtpd_data_restrictions = [
157 # Force the smtpd's client to wait OK before sending
158 "reject_unauth_pipelining"
161 smtpd_end_of_data_restrictions = [
162 # Enforce mail volume quota via policy service callouts.
163 #check_policy_service unix:private/policy
166 smtpd_peername_lookup = true;
167 smtpd_recipient_limit = "5000";
168 smtpd_recipient_overshoot_limit = "5000";
169 #smtpd_restriction_classes = "";
170 #smtpd_sasl_auth_enable = true;
171 #smtpd_sasl_path = "private/auth";
172 #smtpd_sasl_security_options = "noanonymous";
173 #smtpd_sasl_type = "dovecot";
174 smtpd_starttls_timeout = "300s";
175 #smtpd_tls_always_issue_session_ids = true;
176 #smtpd_tls_CApath = "/etc/postfix/x509/ca/";
177 smtpd_tls_ask_ccert = false;
178 #smtpd_tls_ccert_verifydepth = "5";
179 smtpd_tls_ciphers = "high";
180 smtpd_tls_eecdh_grade = "auto";
181 # Disable weak ciphers as reported by https://ssl-tools.net
182 # https://serverfault.com/questions/744168/how-to-disable-rc4-on-postfix
183 smtpd_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ];
184 smtpd_tls_fingerprint_digest = "sha512";
185 # Log only a summary message on TLS handshake completion
186 smtpd_tls_loglevel = "1";
187 smtpd_tls_mandatory_ciphers = "high";
188 smtpd_tls_mandatory_protocols = [ "!SSLv2" "!SSLv3" ];
190 smtpd_tls_protocols = [ "!SSLv2" "!SSLv3" ];
191 #smtpd_tls_received_header = false;
192 smtpd_tls_req_ccert = false;
193 # Postfix 2.3 and later
195 # Mandatory TLS encryption: announce STARTTLS support to SMTP clients, and require that clients use TLS
196 # encryption. According to [1720]RFC 2487 this MUST NOT be applied in case of a publicly-referenced
197 # SMTP server. Instead, this option should be used only on dedicated servers.
198 smtpd_tls_security_level = "may";
199 smtpd_tls_session_cache_database = "btree:$data_directory/smtpd_tls_session_cache";
200 #smtpd_tls_session_cache_timeout = "3600s";
201 #smtpd_tls_chain_files =
204 #relay_clientcerts = hash:/var/lib/postfix/conf/relay_clientcerts
205 # This is where to put backup MX domains
207 relay_recipient_maps = [];
209 # Use a non blocking source of randomness
210 tls_random_source = "dev:/dev/urandom";
211 # Map each domain to a specific X.509 certificate
212 tls_server_sni_maps = "hash:/run/keys/postfix-sni";
214 # Only explicitely aliased accounts have a mail, not all the passwd
215 #local_recipient_maps = "$alias_maps";
216 # Note that the local transport rewrites the envelope recipient
217 # according to the alias_maps, and thus the aliasing is transparent
218 # to the nexthop (eg. dovecot)
219 #local_transport = local:$myhostname
220 # No console bell on new mail
224 "$home/.forward''${recipient_delimiter}''${extension}"
229 # Filled by the postfix/*.nix
230 virtual_mailbox_domains = [];
231 # Completed by the postfix/*.nix
232 virtual_mailbox_maps = [
233 "hash:/etc/postfix/virtual"
235 virtual_transport = "lmtp:unix:private/dovecot-lmtp";
237 dovecot_destination_recipient_limit = "1";
238 virtual_transport = "dovecot";
241 # There is no fallback
242 fallback_transport = "";
244 virtualMapType = "hash";
249 then lib.concatStringsSep "," value
251 if value == true then "yes"
252 else if value == false then "no"
254 mkKeyVal = opt: val: [ "-o" (opt + "=" + mkVal val) ];
255 mkArgs = args: lib.concatLists (lib.mapAttrsToList mkKeyVal args);
259 cleanup_service_name = "submissions-header-cleanup";
262 # Implicit TLS on port 465
263 # https://tools.ietf.org/html/rfc8314#section-3.3
269 syslog_name = "postfix/submissions";
270 # Implicit TLS, not STARTTLS
271 smtpd_tls_wrappermode = true;
272 smtpd_tls_mandatory_protocols = [
274 # FIXME: to be removed when K-9 Mail will support TLSv1.3,
275 # K-9 Mail 5.600 does not.
278 milter_macro_daemon_name = "ORIGINATING";
279 smtpd_helo_restrictions = [
280 "permit_sasl_authenticated"
281 ] ++ postfix.config.smtpd_helo_restrictions;
282 smtpd_relay_restrictions = [
283 # SASL authorizes to send to the world
284 "permit_sasl_authenticated"
287 smtpd_sasl_auth_enable = true;
288 smtpd_sasl_type = "dovecot";
289 smtpd_sasl_path = "private/auth";
290 smtpd_sasl_local_domain = "";
291 # Offer SASL authentication only after a TLS-encrypted session has been established
292 smtpd_tls_auth_only = true;
293 smtpd_sasl_tls_security_options = [ "noanonymous" ];
294 # Do not put SASL logins in mail headers
295 smtpd_sasl_authenticated_header = false;
296 # Who cares about (old) Outlook
297 broken_sasl_auth_clients = false;
298 smtpd_sender_restrictions = [
299 "reject_non_fqdn_sender"
300 # Check that the SASL user is using only its own
301 # mail addresses on the envelope, as indicated in smtpd_sender_login_maps
302 "reject_sender_login_mismatch"
305 # No X.509 certificates for users, for now
306 smtpd_tls_ask_ccert = false;
307 smtpd_tls_ccert_verifydepth = 0;
308 smtpd_tls_loglevel = 1;
309 smtpd_tls_req_ccert = false;
310 cleanup_service_name = "submissions-header-cleanup";
315 #spfcheck unix - n n - 0 spawn
316 # user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
317 # -o smtpd_sender_restrictions=reject_sender_login_mismatch
318 # -o smtpd_sender_login_maps=hash:/etc/postfix/vaccounts
319 # -o cleanup_service_name=submissions-header-cleanup
320 #spfcheck unix - n n - 0 spawn
321 # user=policyd-spf argv=/usr/bin/postfix-policyd-spf-perl
322 #uucp unix - n n - - pipe
323 # flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
324 #smtp inet n - - - - smtpd
325 # -o cleanup_service_name=pre-cleanup
326 # -o content_filter=amavis:[127.0.0.1]:10024
327 # -o smtpd_sender_restrictions=reject_unauth_pipelining,reject_non_fqdn_sender,permit
328 # -o receive_override_options=no_address_mappings
329 #amavis unix - - n - 2 lmtp
330 # -o lmtp_data_done_timeout=1200
331 # -o lmtp_send_xforward_command=yes
332 # -o lmtp_tls_note_starttls_offer=no
333 #127.0.0.1:10025 inet n - n - - smtpd
335 # -o local_header_rewrite_clients=
336 # -o local_recipient_maps=
337 # -o mynetworks=127.0.0.0/8
338 # -o receive_override_options=no_header_body_checks,no_milters,no_unknown_recipient_checks
339 # -o relay_recipient_maps=
340 # -o smtpd_client_connection_count_limit=0
341 # -o smtpd_client_connection_rate_limit=0
342 # -o smtpd_client_restrictions=permit_mynetworks,reject
343 # -o smtpd_data_restrictions=reject_unauth_pipelining
344 # -o smtpd_delay_reject=no
345 # -o smtpd_end_of_data_restrictions=
346 # -o smtpd_error_sleep_time=0
347 # -o smtpd_hard_error_limit=1000
348 # -o smtpd_helo_restrictions=
350 # -o smtpd_recipient_restrictions=permit_mynetworks,reject
351 # -o smtpd_restriction_classes=
352 # -o smtpd_sender_restrictions=
353 # -o smtpd_soft_error_limit=1001
354 # -o strict_rfc821_envelopes=yes
355 #submission inet n - - - - smtpd
356 # -o cleanup_service_name=pre-cleanup
357 # -o content_filter=amavis:[127.0.0.1]:10024
358 # -o milter_macro_daemon_name=ORIGINATING
359 # -o receive_override_options=no_address_mappings
360 # -o smtpd_sender_restrictions=permit_tls_clientcerts,reject
361 # -o smtpd_tls_ask_ccert=yes
362 # -o smtpd_tls_auth_only=yes
363 # -o smtpd_tls_ccert_verifydepth=2
364 # -o smtpd_tls_loglevel=1
365 # -o smtpd_tls_req_ccert=yes
366 # -o smtpd_tls_security_level=encrypt
367 #smtps inet n - - - - smtpd
368 # -o milter_macro_daemon_name=ORIGINATING
369 # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
370 # -o smtpd_sasl_auth_enable=yes
371 # -o smtpd_tls_ask_ccert=yes
372 # -o smtpd_tls_auth_only=yes
373 # -o smtpd_tls_ccert_verifydepth=0
374 # -o smtpd_tls_loglevel=1
375 # -o smtpd_tls_req_ccert=no
376 # -o smtpd_tls_security_level=encrypt
377 # -o smtpd_tls_wrappermode=yes
378 #pickup fifo n - - 60 1 pickup
379 # -o cleanup_service_name=pre-cleanup
380 # -o content_filter=amavis:[127.0.0.1]:10024
381 #pre-cleanup unix n - - - 0 cleanup
382 # -o virtual_alias_maps=
383 #cleanup unix n - - - 0 cleanup
384 # -o mime_header_checks=
385 # -o nested_header_checks=
389 #sympa unix - n n - - pipe
390 # flags=R user=sympa argv=/usr/lib/sympa/bin/queue ''${recipient}
391 #sympabounce unix - n n - - pipe
392 # flags=R user=sympa argv=/usr/lib/sympa/bin/bouncequeue ''${recipient}
395 #noclue unix - n n - - pipe
396 # flags=q user=noclue argv=/usr/local/bin/noclue-delivery ${recipient} ${sender}