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