]>
Commit | Line | Data |
---|---|---|
1 | { lib, pkgs, config, name, nodes, ... }: | |
2 | let | |
3 | getDomains = p: lib.mapAttrsToList (n: v: v.fqdn) (lib.filterAttrs (n: v: v.receive) p.emailPolicies); | |
4 | bydomain = builtins.mapAttrs (n: getDomains) nodes.eldiron.config.myServices.dns.zones; | |
5 | receiving_domains = lib.flatten (builtins.attrValues bydomain); | |
6 | in | |
7 | { | |
8 | options.myServices.mailBackup.enable = lib.mkEnableOption "enable MX backup services"; | |
9 | config = lib.mkIf config.myServices.mailBackup.enable { | |
10 | myServices.mail.milters.enable = true; | |
11 | security.acme.certs."mail" = { | |
12 | postRun = '' | |
13 | systemctl restart postfix.service | |
14 | ''; | |
15 | domain = config.hostEnv.fqdn; | |
16 | extraDomainNames = let | |
17 | zonesWithMx = builtins.attrNames (lib.filterAttrs (n: v: v.hasEmail) nodes.eldiron.config.myServices.dns.zones); | |
18 | mxs = map (n: "${config.myEnv.servers."${name}".mx.subdomain}.${n}") zonesWithMx; | |
19 | in mxs; | |
20 | }; | |
21 | secrets.keys = { | |
22 | "postfix/mysql_alias_maps" = { | |
23 | user = config.services.postfix.user; | |
24 | group = config.services.postfix.group; | |
25 | permissions = "0440"; | |
26 | text = '' | |
27 | # We need to specify that option to trigger ssl connection | |
28 | tls_ciphers = TLSv1.2 | |
29 | user = ${config.myEnv.mail.postfix.mysql.user} | |
30 | password = ${config.myEnv.mail.postfix.mysql.password} | |
31 | hosts = ${config.myEnv.mail.postfix.mysql.remoteHost} | |
32 | dbname = ${config.myEnv.mail.postfix.mysql.database} | |
33 | query = SELECT DISTINCT 1 | |
34 | FROM forwardings | |
35 | WHERE | |
36 | ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s')) | |
37 | AND active = 1 | |
38 | AND '%s' NOT IN | |
39 | ( | |
40 | SELECT source | |
41 | FROM forwardings_blacklisted | |
42 | WHERE source = '%s' | |
43 | ) UNION | |
44 | SELECT 'devnull@immae.eu' | |
45 | FROM forwardings_blacklisted | |
46 | WHERE source = '%s' | |
47 | ''; | |
48 | }; | |
49 | "postfix/ldap_mailboxes" = { | |
50 | user = config.services.postfix.user; | |
51 | group = config.services.postfix.group; | |
52 | permissions = "0440"; | |
53 | text = '' | |
54 | server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636 | |
55 | search_base = ${config.myEnv.mail.dovecot.ldap.base} | |
56 | query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter} | |
57 | bind_dn = ${config.myEnv.mail.dovecot.ldap.dn} | |
58 | bind_pw = ${config.myEnv.mail.dovecot.ldap.password} | |
59 | result_attribute = immaePostfixAddress | |
60 | result_format = dummy | |
61 | version = 3 | |
62 | ''; | |
63 | }; | |
64 | "postfix/sympa_mailbox_maps" = { | |
65 | user = config.services.postfix.user; | |
66 | group = config.services.postfix.group; | |
67 | permissions = "0440"; | |
68 | text = '' | |
69 | hosts = ${config.myEnv.mail.sympa.postgresql.host} | |
70 | user = ${config.myEnv.mail.sympa.postgresql.user} | |
71 | password = ${config.myEnv.mail.sympa.postgresql.password} | |
72 | dbname = ${config.myEnv.mail.sympa.postgresql.database} | |
73 | query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN ( | |
74 | CONCAT(name_list, '@', robot_list), | |
75 | CONCAT(name_list, '-request@', robot_list), | |
76 | CONCAT(name_list, '-editor@', robot_list), | |
77 | CONCAT(name_list, '-unsubscribe@', robot_list), | |
78 | CONCAT(name_list, '-owner@', robot_list), | |
79 | CONCAT('sympa-request@', robot_list), | |
80 | CONCAT('sympa-owner@', robot_list), | |
81 | CONCAT('sympa@', robot_list), | |
82 | CONCAT('listmaster@', robot_list), | |
83 | CONCAT('bounce@', robot_list), | |
84 | CONCAT('abuse-feedback-report@', robot_list) | |
85 | ) | |
86 | ''; | |
87 | }; | |
88 | "postfix/ldap_ejabberd_users_immae_fr" = { | |
89 | user = config.services.postfix.user; | |
90 | group = config.services.postfix.group; | |
91 | permissions = "0440"; | |
92 | text = '' | |
93 | server_host = ldaps://${config.myEnv.jabber.ldap.host}:636 | |
94 | search_base = ${config.myEnv.jabber.ldap.base} | |
95 | query_filter = ${config.myEnv.jabber.postfix_user_filter} | |
96 | domain = immae.fr | |
97 | bind_dn = ${config.myEnv.jabber.ldap.dn} | |
98 | bind_pw = ${config.myEnv.jabber.ldap.password} | |
99 | result_attribute = immaeXmppUid | |
100 | result_format = ejabberd@localhost | |
101 | version = 3 | |
102 | ''; | |
103 | }; | |
104 | }; | |
105 | ||
106 | networking.firewall.allowedTCPPorts = [ 25 ]; | |
107 | ||
108 | users.users."${config.services.postfix.user}".extraGroups = [ "keys" ]; | |
109 | services.filesWatcher.postfix = { | |
110 | restart = true; | |
111 | paths = [ | |
112 | config.secrets.fullPaths."postfix/mysql_alias_maps" | |
113 | config.secrets.fullPaths."postfix/sympa_mailbox_maps" | |
114 | config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr" | |
115 | config.secrets.fullPaths."postfix/ldap_mailboxes" | |
116 | ]; | |
117 | }; | |
118 | services.postfix = { | |
119 | mapFiles = let | |
120 | virtual_map = { | |
121 | virtual = let | |
122 | cfg = config.myEnv.monitoring.email_check.eldiron; | |
123 | address = "${cfg.mail_address}@${cfg.mail_domain}"; | |
124 | aliases = config.myEnv.mail.postfix.common_aliases; | |
125 | in pkgs.writeText "postfix-virtual" ( | |
126 | builtins.concatStringsSep "\n" ( | |
127 | [ "${address} 1" | |
128 | ] ++ | |
129 | map (a: "${a} 1") config.myEnv.mail.postfix.other_aliases ++ | |
130 | lib.lists.flatten (map (domain: map (alias: "${alias}@${domain} 1") aliases) receiving_domains) | |
131 | ) | |
132 | ); | |
133 | }; | |
134 | in | |
135 | virtual_map; | |
136 | config = { | |
137 | ### postfix module overrides | |
138 | readme_directory = "${pkgs.postfix}/share/postfix/doc"; | |
139 | smtp_tls_CAfile = lib.mkForce ""; | |
140 | smtp_tls_cert_file = lib.mkForce ""; | |
141 | smtp_tls_key_file = lib.mkForce ""; | |
142 | ||
143 | message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited" | |
144 | mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts | |
145 | alias_database = "\$alias_maps"; | |
146 | ||
147 | ### Relay domains | |
148 | relay_domains = receiving_domains; | |
149 | relay_recipient_maps = let | |
150 | virtual_alias_maps = [ | |
151 | "hash:/etc/postfix/virtual" | |
152 | "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}" | |
153 | "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}" | |
154 | ]; | |
155 | virtual_mailbox_maps = [ | |
156 | "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}" | |
157 | "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}" | |
158 | ]; | |
159 | in | |
160 | virtual_alias_maps ++ virtual_mailbox_maps; | |
161 | smtpd_relay_restrictions = [ | |
162 | "defer_unauth_destination" | |
163 | ]; | |
164 | ||
165 | ### Additional smtpd configuration | |
166 | smtpd_tls_received_header = "yes"; | |
167 | smtpd_tls_loglevel = "1"; | |
168 | ||
169 | ### Email sending configuration | |
170 | smtp_tls_security_level = "may"; | |
171 | smtp_tls_loglevel = "1"; | |
172 | ||
173 | ### Force ip bind for smtp | |
174 | smtp_bind_address = builtins.head config.myEnv.servers."${name}".ips.main.ip4; | |
175 | smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6; | |
176 | ||
177 | smtpd_milters = [ | |
178 | "unix:${config.myServices.mail.milters.sockets.opendkim}" | |
179 | "unix:${config.myServices.mail.milters.sockets.openarc}" | |
180 | "unix:${config.myServices.mail.milters.sockets.opendmarc}" | |
181 | ]; | |
182 | }; | |
183 | enable = true; | |
184 | enableSmtp = true; | |
185 | enableSubmission = false; | |
186 | destination = ["localhost"]; | |
187 | # This needs to reverse DNS | |
188 | hostname = config.hostEnv.fqdn; | |
189 | setSendmail = false; | |
190 | sslCert = "/var/lib/acme/mail/fullchain.pem"; | |
191 | sslKey = "/var/lib/acme/mail/key.pem"; | |
192 | recipientDelimiter = "+"; | |
193 | }; | |
194 | }; | |
195 | } | |
196 |