1 { config, lib, pkgs, ... }:
4 cfg = config.services.postfix;
7 setgidGroup = cfg.setgidGroup;
9 haveAliases = cfg.postmasterAlias != "" || cfg.rootAlias != ""
10 || cfg.extraAliases != "";
11 haveCanonical = cfg.canonical != "";
12 haveTransport = cfg.transport != "";
13 haveVirtual = cfg.virtual != "";
14 haveLocalRecipients = cfg.localRecipients != null;
17 lib.optional (cfg.dnsBlacklistOverrides != "")
18 "check_client_access hash:/etc/postfix/client_access";
21 lib.optionals (cfg.dnsBlacklists != [])
22 (map (s: "reject_rbl_client " + s) cfg.dnsBlacklists);
24 clientRestrictions = lib.concatStringsSep ", " (clientAccess ++ dnsBl);
27 escape = lib.replaceStrings ["$"] ["$$"];
28 mkList = items: "\n " + lib.concatStringsSep ",\n " items;
30 if lib.isList value then mkList value
31 else " " + (if value == true then "yes"
32 else if value == false then "no"
34 mkEntry = name: value: "${escape name} =${mkVal value}";
36 lib.concatStringsSep "\n" (lib.mapAttrsToList mkEntry cfg.config)
37 + "\n" + cfg.extraConfig;
39 masterCfOptions = { options, config, name, ... }: {
46 The name of the service to run. Defaults to the attribute set key.
51 type = lib.types.enum [ "inet" "unix" "unix-dgram" "fifo" "pass" ];
54 description = "The type of the service";
57 private = lib.mkOption {
58 type = lib.types.bool;
61 Whether the service's sockets and storage directory is restricted to
62 be only available via the mail system. If `null` is
63 given it uses the postfix default `true`.
67 privileged = lib.mkOption {
68 type = lib.types.bool;
73 chroot = lib.mkOption {
74 type = lib.types.bool;
77 Whether the service is chrooted to have only access to the
78 {option}`services.postfix.queueDir` and the closure of
79 store paths specified by the {option}`program` option.
83 wakeup = lib.mkOption {
87 Automatically wake up the service after the specified number of
88 seconds. If `0` is given, never wake the service
93 wakeupUnusedComponent = lib.mkOption {
94 type = lib.types.bool;
97 If set to `false` the component will only be woken
98 up if it is used. This is equivalent to postfix' notion of adding a
99 question mark behind the wakeup time in
104 maxproc = lib.mkOption {
105 type = lib.types.int;
108 The maximum number of processes to spawn for this service. If the
109 value is `0` it doesn't have any limit. If
110 `null` is given it uses the postfix default of
115 command = lib.mkOption {
116 type = lib.types.str;
120 A program name specifying a Postfix service/daemon process.
121 By default it's the attribute {option}`name`.
125 args = lib.mkOption {
126 type = lib.types.listOf lib.types.str;
128 example = [ "-o" "smtp_helo_timeout=5" ];
130 Arguments to pass to the {option}`command`. There is no shell
131 processing involved and shell syntax is passed verbatim to the
136 rawEntry = lib.mkOption {
137 type = lib.types.listOf lib.types.str;
141 The raw configuration line for the {file}`master.cf`.
146 config.rawEntry = let
147 mkBool = bool: if bool then "y" else "n";
148 mkArg = arg: "${lib.optionalString (lib.hasPrefix "-" arg) "\n "}${arg}";
150 maybeOption = fun: option:
151 if options.${option}.isDefined then fun config.${option} else "-";
153 # This is special, because we have two options for this value.
155 wakeupDefined = options.wakeup.isDefined;
156 wakeupUCDefined = options.wakeupUnusedComponent.isDefined;
157 finalValue = toString config.wakeup
158 + lib.optionalString (wakeupUCDefined && !config.wakeupUnusedComponent) "?";
159 in if wakeupDefined then finalValue else "-";
164 (maybeOption mkBool "private")
165 (maybeOption (b: mkBool (!b)) "privileged")
166 (maybeOption mkBool "chroot")
168 (maybeOption toString "maxproc")
169 (config.command + " " + lib.concatMapStringsSep " " mkArg config.args)
173 masterCfContent = let
176 "# service" "type" "private" "unpriv" "chroot" "wakeup" "maxproc"
181 "# " "" "(yes)" "(yes)" "(no)" "(never)" "(100)" "" ""
184 masterCf = lib.mapAttrsToList (lib.const (lib.getAttr "rawEntry")) cfg.masterConfig;
186 # A list of the maximum width of the columns across all lines and labels
188 foldLine = line: acc: let
189 columnLengths = map lib.stringLength line;
190 in lib.zipListsWith lib.max acc columnLengths;
191 # We need to handle the last column specially here, because it's
192 # open-ended (command + args).
193 lines = [ labels labelDefaults ] ++ (map (l: lib.init l ++ [""]) masterCf);
194 in lib.foldr foldLine (lib.genList (lib.const 0) (lib.length labels)) lines;
196 # Pad a string with spaces from the right (opposite of fixedWidthString).
197 pad = width: str: let
198 padWidth = width - lib.stringLength str;
199 padding = lib.concatStrings (lib.genList (lib.const " ") padWidth);
200 in str + lib.optionalString (padWidth > 0) padding;
202 # It's + 2 here, because that's the amount of spacing between columns.
203 fullWidth = lib.foldr (width: acc: acc + width + 2) 0 maxWidths;
205 formatLine = line: lib.concatStringsSep " " (lib.zipListsWith pad maxWidths line);
207 formattedLabels = let
208 sep = "# " + lib.concatStrings (lib.genList (lib.const "=") (fullWidth + 5));
209 lines = [ sep (formatLine labels) (formatLine labelDefaults) sep ];
210 in lib.concatStringsSep "\n" lines;
212 in formattedLabels + "\n" + lib.concatMapStringsSep "\n" formatLine masterCf + "\n" + cfg.extraMasterConf;
214 headerCheckOptions = { ... }:
217 pattern = lib.mkOption {
218 type = lib.types.str;
220 example = "/^X-Mailer:/";
221 description = "A regexp pattern matching the header";
223 action = lib.mkOption {
224 type = lib.types.str;
226 example = "BCC mail@example.com";
227 description = "The action to be executed when the pattern is matched";
232 headerChecks = lib.concatStringsSep "\n" (map (x: "${x.pattern} ${x.action}") cfg.headerChecks) + cfg.extraHeaderChecks;
234 aliases = let separator = lib.optionalString (cfg.aliasMapType == "hash") ":"; in
235 lib.optionalString (cfg.postmasterAlias != "") ''
236 postmaster${separator} ${cfg.postmasterAlias}
238 + lib.optionalString (cfg.rootAlias != "") ''
239 root${separator} ${cfg.rootAlias}
244 aliasesFile = pkgs.writeText "postfix-aliases" aliases;
245 canonicalFile = pkgs.writeText "postfix-canonical" cfg.canonical;
246 virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
247 localRecipientMapFile = pkgs.writeText "postfix-local-recipient-map" (lib.concatMapStrings (x: x + " ACCEPT\n") cfg.localRecipients);
248 checkClientAccessFile = pkgs.writeText "postfix-check-client-access" cfg.dnsBlacklistOverrides;
249 mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
250 masterCfFile = pkgs.writeText "postfix-master.cf" masterCfContent;
251 transportFile = pkgs.writeText "postfix-transport" cfg.transport;
252 headerChecksFile = pkgs.writeText "postfix-header-checks" headerChecks;
264 enable = lib.mkOption {
265 type = lib.types.bool;
267 description = "Whether to run the Postfix mail server.";
270 enableSmtp = lib.mkOption {
271 type = lib.types.bool;
273 description = "Whether to enable smtp in master.cf.";
276 enableSubmission = lib.mkOption {
277 type = lib.types.bool;
279 description = "Whether to enable smtp submission.";
282 enableSubmissions = lib.mkOption {
283 type = lib.types.bool;
286 Whether to enable smtp submission via smtps.
288 According to RFC 8314 this should be preferred
289 over STARTTLS for submission of messages by end user clients.
293 submissionOptions = lib.mkOption {
294 type = with lib.types; attrsOf str;
296 smtpd_tls_security_level = "encrypt";
297 smtpd_sasl_auth_enable = "yes";
298 smtpd_client_restrictions = "permit_sasl_authenticated,reject";
299 milter_macro_daemon_name = "ORIGINATING";
302 smtpd_tls_security_level = "encrypt";
303 smtpd_sasl_auth_enable = "yes";
304 smtpd_sasl_type = "dovecot";
305 smtpd_client_restrictions = "permit_sasl_authenticated,reject";
306 milter_macro_daemon_name = "ORIGINATING";
308 description = "Options for the submission config in master.cf";
311 submissionsOptions = lib.mkOption {
312 type = with lib.types; attrsOf str;
314 smtpd_sasl_auth_enable = "yes";
315 smtpd_client_restrictions = "permit_sasl_authenticated,reject";
316 milter_macro_daemon_name = "ORIGINATING";
319 smtpd_sasl_auth_enable = "yes";
320 smtpd_sasl_type = "dovecot";
321 smtpd_client_restrictions = "permit_sasl_authenticated,reject";
322 milter_macro_daemon_name = "ORIGINATING";
325 Options for the submission config via smtps in master.cf.
327 smtpd_tls_security_level will be set to encrypt, if it is missing
328 or has one of the values "may" or "none".
330 smtpd_tls_wrappermode with value "yes" will be added automatically.
334 setSendmail = lib.mkOption {
335 type = lib.types.bool;
337 description = "Whether to set the system sendmail to postfix's.";
340 user = lib.mkOption {
341 type = lib.types.str;
343 description = "What to call the Postfix user (must be used only for postfix).";
346 group = lib.mkOption {
347 type = lib.types.str;
349 description = "What to call the Postfix group (must be used only for postfix).";
352 setgidGroup = lib.mkOption {
353 type = lib.types.str;
354 default = "postdrop";
356 How to call postfix setgid group (for postdrop). Should
357 be uniquely used group.
361 networks = lib.mkOption {
362 type = lib.types.nullOr (lib.types.listOf lib.types.str);
364 example = ["192.168.0.1/24"];
366 Net masks for trusted - allowed to relay mail to third parties -
367 hosts. Leave empty to use mynetworks_style configuration or use
368 default (localhost-only).
372 networksStyle = lib.mkOption {
373 type = lib.types.str;
376 Name of standard way of trusted network specification to use,
377 leave blank if you specify it explicitly or if you want to use
378 default (localhost-only).
382 hostname = lib.mkOption {
383 type = lib.types.str;
386 Hostname to use. Leave blank to use just the hostname of machine.
391 domain = lib.mkOption {
392 type = lib.types.str;
395 Domain to use. Leave blank to use hostname minus first component.
399 origin = lib.mkOption {
400 type = lib.types.str;
403 Origin to use in outgoing e-mail. Leave blank to use hostname.
407 destination = lib.mkOption {
408 type = lib.types.nullOr (lib.types.listOf lib.types.str);
410 example = ["localhost"];
412 Full (!) list of domains we deliver locally. Leave blank for
413 acceptable Postfix default.
417 relayDomains = lib.mkOption {
418 type = lib.types.nullOr (lib.types.listOf lib.types.str);
420 example = ["localdomain"];
422 List of domains we agree to relay to. Default is empty.
426 relayHost = lib.mkOption {
427 type = lib.types.str;
430 Mail relay for outbound mail.
434 relayPort = lib.mkOption {
435 type = lib.types.int;
438 SMTP port for relay mail relay.
442 lookupMX = lib.mkOption {
443 type = lib.types.bool;
446 Whether relay specified is just domain whose MX must be used.
450 postmasterAlias = lib.mkOption {
451 type = lib.types.str;
454 Who should receive postmaster e-mail. Multiple values can be added by
455 separating values with comma.
459 rootAlias = lib.mkOption {
460 type = lib.types.str;
463 Who should receive root e-mail. Blank for no redirection.
464 Multiple values can be added by separating values with comma.
468 extraAliases = lib.mkOption {
469 type = lib.types.lines;
472 Additional entries to put verbatim into aliases file, cf. man-page aliases(8).
476 aliasMapType = lib.mkOption {
477 type = with lib.types; enum [ "hash" "regexp" "pcre" ];
480 description = "The format the alias map should have. Use regexp if you want to use regular expressions.";
483 config = lib.mkOption {
484 type = with lib.types; attrsOf (oneOf [ bool int str (listOf str) ]);
486 The main.cf configuration file as key value set.
489 mail_owner = "postfix";
490 smtp_tls_security_level = "may";
494 extraConfig = lib.mkOption {
495 type = lib.types.lines;
498 Extra lines to be added verbatim to the main.cf configuration file.
502 tlsTrustedAuthorities = lib.mkOption {
503 type = lib.types.str;
504 default = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
505 defaultText = lib.literalExpression ''"''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"'';
507 File containing trusted certification authorities (CA) to verify certificates of mailservers contacted for mail delivery. This basically sets smtp_tls_CAfile and enables opportunistic tls. Defaults to NixOS trusted certification authorities.
511 sslCert = lib.mkOption {
512 type = lib.types.str;
514 description = "SSL certificate to use.";
517 sslKey = lib.mkOption {
518 type = lib.types.str;
520 description = "SSL key to use.";
523 recipientDelimiter = lib.mkOption {
524 type = lib.types.str;
528 Delimiter for address extension: so mail to user+test can be handled by ~user/.forward+test
532 canonical = lib.mkOption {
533 type = lib.types.lines;
536 Entries for the {manpage}`canonical(5)` table.
540 virtual = lib.mkOption {
541 type = lib.types.lines;
544 Entries for the virtual alias map, cf. man-page virtual(5).
548 virtualMapType = lib.mkOption {
549 type = lib.types.enum ["hash" "regexp" "pcre"];
552 What type of virtual alias map file to use. Use `"regexp"` for regular expressions.
556 localRecipients = lib.mkOption {
557 type = with lib.types; nullOr (listOf str);
560 List of accepted local users. Specify a bare username, an
561 `"@domain.tld"` wild-card, or a complete
562 `"user@domain.tld"` address. If set, these names end
563 up in the local recipient map -- see the local(8) man-page -- and
564 effectively replace the system user database lookup that's otherwise
569 transport = lib.mkOption {
571 type = lib.types.lines;
573 Entries for the transport map, cf. man-page transport(8).
577 dnsBlacklists = lib.mkOption {
579 type = with lib.types; listOf str;
580 description = "dns blacklist servers to use with smtpd_client_restrictions";
583 dnsBlacklistOverrides = lib.mkOption {
585 type = lib.types.lines;
586 description = "contents of check_client_access for overriding dnsBlacklists";
589 masterConfig = lib.mkOption {
590 type = lib.types.attrsOf (lib.types.submodule masterCfOptions);
595 args = [ "-o" "smtpd_tls_security_level=encrypt" ];
599 An attribute set of service options, which correspond to the service
600 definitions usually done within the Postfix
601 {file}`master.cf` file.
605 extraMasterConf = lib.mkOption {
606 type = lib.types.lines;
608 example = "submission inet n - n - - smtpd";
609 description = "Extra lines to append to the generated master.cf file.";
612 enableHeaderChecks = lib.mkOption {
613 type = lib.types.bool;
616 description = "Whether to enable postfix header checks";
619 headerChecks = lib.mkOption {
620 type = lib.types.listOf (lib.types.submodule headerCheckOptions);
622 example = [ { pattern = "/^X-Spam-Flag:/"; action = "REDIRECT spam@example.com"; } ];
623 description = "Postfix header checks.";
626 extraHeaderChecks = lib.mkOption {
627 type = lib.types.lines;
629 example = "/^X-Spam-Flag:/ REDIRECT spam@example.com";
630 description = "Extra lines to /etc/postfix/header_checks file.";
633 aliasFiles = lib.mkOption {
634 type = lib.types.attrsOf lib.types.path;
636 description = "Aliases' tables to be compiled and placed into /var/lib/postfix/conf.";
639 mapFiles = lib.mkOption {
640 type = lib.types.attrsOf lib.types.path;
642 description = "Maps to be compiled and placed into /var/lib/postfix/conf.";
645 useSrs = lib.mkOption {
646 type = lib.types.bool;
648 description = "Whether to enable sender rewriting scheme";
656 ###### implementation
658 config = lib.mkIf config.services.postfix.enable (lib.mkMerge [
662 etc.postfix.source = "/var/lib/postfix/conf";
664 # This makes it comfortable to run 'postqueue/postdrop' for example.
665 systemPackages = [ pkgs.postfix ];
668 services.pfix-srsd.enable = config.services.postfix.useSrs;
670 services.mail.sendmailSetuidWrapper = lib.mkIf config.services.postfix.setSendmail {
671 program = "sendmail";
672 source = "${pkgs.postfix}/bin/sendmail";
679 security.wrappers.mailq = {
681 source = "${pkgs.postfix}/bin/mailq";
688 security.wrappers.postqueue = {
689 program = "postqueue";
690 source = "${pkgs.postfix}/bin/postqueue";
697 security.wrappers.postdrop = {
698 program = "postdrop";
699 source = "${pkgs.postfix}/bin/postdrop";
706 users.users = lib.optionalAttrs (user == "postfix")
708 description = "Postfix mail server user";
709 uid = config.ids.uids.postfix;
715 lib.optionalAttrs (group == "postfix")
716 { ${group}.gid = config.ids.gids.postfix;
718 // lib.optionalAttrs (setgidGroup == "postdrop")
719 { ${setgidGroup}.gid = config.ids.gids.postdrop;
722 systemd.services.postfix-setup =
723 { description = "Setup for Postfix mail server";
724 serviceConfig.RemainAfterExit = true;
725 serviceConfig.Type = "oneshot";
727 # Backwards compatibility
728 if [ ! -d /var/lib/postfix ] && [ -d /var/postfix ]; then
730 mv /var/postfix /var/lib/postfix
733 # All permissions set according ${pkgs.postfix}/etc/postfix/postfix-files script
734 mkdir -p /var/lib/postfix /var/lib/postfix/queue/{pid,public,maildrop}
735 chmod 0755 /var/lib/postfix
736 chown root:root /var/lib/postfix
738 rm -rf /var/lib/postfix/conf
739 mkdir -p /var/lib/postfix/conf
740 chmod 0755 /var/lib/postfix/conf
741 ln -sf ${pkgs.postfix}/etc/postfix/postfix-files /var/lib/postfix/conf/postfix-files
742 ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
743 ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
745 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (to: from: ''
746 ln -sf ${from} /var/lib/postfix/conf/${to}
747 ${pkgs.postfix}/bin/postalias -o -p /var/lib/postfix/conf/${to}
749 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (to: from: ''
750 ln -sf ${from} /var/lib/postfix/conf/${to}
751 ${pkgs.postfix}/bin/postmap /var/lib/postfix/conf/${to}
754 mkdir -p /var/spool/mail
755 chown root:root /var/spool/mail
756 chmod a+rwxt /var/spool/mail
757 ln -sf /var/spool/mail /var/
759 #Finally delegate to postfix checking remain directories in /var/lib/postfix and set permissions on them
760 ${pkgs.postfix}/bin/postfix set-permissions config_directory=/var/lib/postfix/conf
764 systemd.services.postfix =
765 { description = "Postfix mail server";
767 wantedBy = [ "multi-user.target" ];
768 after = [ "network.target" "postfix-setup.service" ];
769 requires = [ "postfix-setup.service" ];
770 path = [ pkgs.postfix ];
775 PIDFile = "/var/lib/postfix/queue/pid/master.pid";
776 ExecStart = "${pkgs.postfix}/bin/postfix start";
777 ExecStop = "${pkgs.postfix}/bin/postfix stop";
778 ExecReload = "${pkgs.postfix}/bin/postfix reload";
782 PrivateDevices = true;
783 ProtectSystem = "full";
784 CapabilityBoundingSet = [ "~CAP_NET_ADMIN CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_MODULE" ];
785 MemoryDenyWriteExecute = true;
786 ProtectKernelModules = true;
787 ProtectKernelTunables = true;
788 ProtectControlGroups = true;
789 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" "AF_UNIX" ];
790 RestrictNamespaces = true;
791 RestrictRealtime = true;
795 services.postfix.config = (lib.mapAttrs (_: v: lib.mkDefault v) {
796 compatibility_level = pkgs.postfix.version;
797 mail_owner = cfg.user;
798 default_privs = "nobody";
800 # NixOS specific locations
801 data_directory = "/var/lib/postfix/data";
802 queue_directory = "/var/lib/postfix/queue";
804 # Default location of everything in package
805 meta_directory = "${pkgs.postfix}/etc/postfix";
806 command_directory = "${pkgs.postfix}/bin";
807 sample_directory = "/etc/postfix";
808 newaliases_path = "${pkgs.postfix}/bin/newaliases";
809 mailq_path = "${pkgs.postfix}/bin/mailq";
810 readme_directory = false;
811 sendmail_path = "${pkgs.postfix}/bin/sendmail";
812 daemon_directory = "${pkgs.postfix}/libexec/postfix";
813 manpage_directory = "${pkgs.postfix}/share/man";
814 html_directory = "${pkgs.postfix}/share/postfix/doc/html";
815 shlib_directory = false;
816 mail_spool_directory = "/var/spool/mail/";
817 setgid_group = cfg.setgidGroup;
819 // lib.optionalAttrs (cfg.relayHost != "") { relayhost = if cfg.lookupMX
820 then "${cfg.relayHost}:${toString cfg.relayPort}"
821 else "[${cfg.relayHost}]:${toString cfg.relayPort}"; }
822 // lib.optionalAttrs (!config.networking.enableIPv6) { inet_protocols = lib.mkDefault "ipv4"; }
823 // lib.optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
824 // lib.optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
825 // lib.optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
826 // lib.optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
827 // lib.optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
828 // lib.optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
829 // lib.optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
830 // lib.optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
831 // lib.optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
832 // lib.optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
833 // lib.optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
834 // lib.optionalAttrs haveLocalRecipients { local_recipient_maps = [ "hash:/etc/postfix/local_recipients" ] ++ lib.optional haveAliases "$alias_maps"; }
835 // lib.optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
836 // lib.optionalAttrs cfg.useSrs {
837 sender_canonical_maps = [ "tcp:127.0.0.1:10001" ];
838 sender_canonical_classes = [ "envelope_sender" ];
839 recipient_canonical_maps = [ "tcp:127.0.0.1:10002" ];
840 recipient_canonical_classes = [ "envelope_recipient" ];
842 // lib.optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
843 // lib.optionalAttrs (cfg.tlsTrustedAuthorities != "") {
844 smtp_tls_CAfile = cfg.tlsTrustedAuthorities;
845 smtp_tls_security_level = lib.mkDefault "may";
847 // lib.optionalAttrs (cfg.sslCert != "") {
848 smtp_tls_cert_file = cfg.sslCert;
849 smtp_tls_key_file = cfg.sslKey;
851 smtp_tls_security_level = lib.mkDefault "may";
853 smtpd_tls_cert_file = cfg.sslCert;
854 smtpd_tls_key_file = cfg.sslKey;
856 smtpd_tls_security_level = "may";
859 services.postfix.masterConfig = {
876 wakeupUnusedComponent = false;
880 command = "trivial-rewrite";
899 wakeupUnusedComponent = false;
903 command = "proxymap";
907 command = "proxymap";
931 } // lib.optionalAttrs cfg.enableSubmission {
937 mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
938 in lib.concatLists (lib.mapAttrsToList mkKeyVal cfg.submissionOptions);
940 } // lib.optionalAttrs cfg.enableSmtp {
950 args = [ "-o" "smtp_fallback_relay=" ];
952 } // lib.optionalAttrs cfg.enableSubmissions {
958 mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
959 adjustSmtpTlsSecurityLevel = !(cfg.submissionsOptions ? smtpd_tls_security_level) ||
960 cfg.submissionsOptions.smtpd_tls_security_level == "none" ||
961 cfg.submissionsOptions.smtpd_tls_security_level == "may";
962 submissionsOptions = cfg.submissionsOptions // {
963 smtpd_tls_wrappermode = "yes";
964 } // lib.optionalAttrs adjustSmtpTlsSecurityLevel {
965 smtpd_tls_security_level = "encrypt";
967 in lib.concatLists (lib.mapAttrsToList mkKeyVal submissionsOptions);
972 (lib.mkIf haveAliases {
973 services.postfix.aliasFiles.aliases = aliasesFile;
975 (lib.mkIf haveCanonical {
976 services.postfix.mapFiles.canonical = canonicalFile;
978 (lib.mkIf haveTransport {
979 services.postfix.mapFiles.transport = transportFile;
981 (lib.mkIf haveVirtual {
982 services.postfix.mapFiles.virtual = virtualFile;
984 (lib.mkIf haveLocalRecipients {
985 services.postfix.mapFiles.local_recipients = localRecipientMapFile;
987 (lib.mkIf cfg.enableHeaderChecks {
988 services.postfix.mapFiles.header_checks = headerChecksFile;
990 (lib.mkIf (cfg.dnsBlacklists != []) {
991 services.postfix.mapFiles.client_access = checkClientAccessFile;
996 (lib.mkRemovedOptionModule [ "services" "postfix" "sslCACert" ]
997 "services.postfix.sslCACert was replaced by services.postfix.tlsTrustedAuthorities. In case you intend that your server should validate requested client certificates use services.postfix.extraConfig.")
999 (lib.mkChangedOptionModule [ "services" "postfix" "useDane" ]
1000 [ "services" "postfix" "config" "smtp_tls_security_level" ]
1001 (config: lib.mkIf config.services.postfix.useDane "dane"))