]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - modules/private/mail/relay.nix
Use attrs for secrets instead of lists
[perso/Immae/Config/Nix.git] / modules / private / mail / relay.nix
CommitLineData
619e4f46
IB
1{ lib, pkgs, config, nodes, name, ... }:
2{
3 config = lib.mkIf config.myServices.mailBackup.enable {
5400b9b6 4 security.acme.certs."mail" = config.myServices.certificates.certConfig // {
619e4f46
IB
5 postRun = ''
6 systemctl restart postfix.service
7 '';
8 domain = config.hostEnv.fqdn;
9 extraDomains = let
10 zonesWithMx = builtins.filter (zone:
11 lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0
12 ) config.myEnv.dns.masterZones;
13 mxs = map (zone: "${config.myEnv.servers."${name}".mx.subdomain}.${zone.name}") zonesWithMx;
14 in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs);
15 };
4c4652aa
IB
16 secrets.keys = {
17 "postfix/mysql_alias_maps" = {
619e4f46
IB
18 user = config.services.postfix.user;
19 group = config.services.postfix.group;
20 permissions = "0440";
21 text = ''
22 # We need to specify that option to trigger ssl connection
23 tls_ciphers = TLSv1.2
24 user = ${config.myEnv.mail.postfix.mysql.user}
25 password = ${config.myEnv.mail.postfix.mysql.password}
26 hosts = ${config.myEnv.mail.postfix.mysql.remoteHost}
27 dbname = ${config.myEnv.mail.postfix.mysql.database}
28 query = SELECT DISTINCT 1
418a4ed7 29 FROM forwardings
619e4f46
IB
30 WHERE
31 ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s'))
32 AND active = 1
33 AND '%s' NOT IN
34 (
35 SELECT source
36 FROM forwardings_blacklisted
37 WHERE source = '%s'
38 ) UNION
39 SELECT 'devnull@immae.eu'
40 FROM forwardings_blacklisted
41 WHERE source = '%s'
42 '';
4c4652aa
IB
43 };
44 "postfix/ldap_mailboxes" = {
619e4f46
IB
45 user = config.services.postfix.user;
46 group = config.services.postfix.group;
47 permissions = "0440";
48 text = ''
22b4bd78
IB
49 server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636
50 search_base = ${config.myEnv.mail.dovecot.ldap.base}
51 query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter}
52 bind_dn = ${config.myEnv.mail.dovecot.ldap.dn}
53 bind_pw = ${config.myEnv.mail.dovecot.ldap.password}
54 result_attribute = immaePostfixAddress
55 result_format = dummy
56 version = 3
619e4f46 57 '';
4c4652aa
IB
58 };
59 "postfix/sympa_mailbox_maps" = {
4e07970c
IB
60 user = config.services.postfix.user;
61 group = config.services.postfix.group;
62 permissions = "0440";
63 text = ''
64 hosts = ${config.myEnv.mail.sympa.postgresql.host}
65 user = ${config.myEnv.mail.sympa.postgresql.user}
66 password = ${config.myEnv.mail.sympa.postgresql.password}
67 dbname = ${config.myEnv.mail.sympa.postgresql.database}
22b4bd78
IB
68 query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN (
69 CONCAT(name_list, '@', robot_list),
70 CONCAT(name_list, '-request@', robot_list),
71 CONCAT(name_list, '-editor@', robot_list),
72 CONCAT(name_list, '-unsubscribe@', robot_list),
73 CONCAT(name_list, '-owner@', robot_list),
74 CONCAT('sympa-request@', robot_list),
75 CONCAT('sympa-owner@', robot_list),
76 CONCAT('sympa@', robot_list),
77 CONCAT('listmaster@', robot_list),
78 CONCAT('bounce@', robot_list),
79 CONCAT('abuse-feedback-report@', robot_list)
80 )
4e07970c 81 '';
4c4652aa
IB
82 };
83 "postfix/ldap_ejabberd_users_immae_fr" = {
619e4f46
IB
84 user = config.services.postfix.user;
85 group = config.services.postfix.group;
86 permissions = "0440";
87 text = ''
88 server_host = ldaps://${config.myEnv.jabber.ldap.host}:636
89 search_base = ${config.myEnv.jabber.ldap.base}
90 query_filter = ${config.myEnv.jabber.postfix_user_filter}
91 domain = immae.fr
92 bind_dn = ${config.myEnv.jabber.ldap.dn}
93 bind_pw = ${config.myEnv.jabber.ldap.password}
94 result_attribute = immaeXmppUid
95 result_format = ejabberd@localhost
96 version = 3
97 '';
4c4652aa
IB
98 };
99 };
619e4f46
IB
100
101 networking.firewall.allowedTCPPorts = [ 25 ];
102
619e4f46
IB
103 users.users."${config.services.postfix.user}".extraGroups = [ "keys" ];
104 services.filesWatcher.postfix = {
105 restart = true;
106 paths = [
107 config.secrets.fullPaths."postfix/mysql_alias_maps"
4e07970c 108 config.secrets.fullPaths."postfix/sympa_mailbox_maps"
619e4f46 109 config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"
22b4bd78 110 config.secrets.fullPaths."postfix/ldap_mailboxes"
619e4f46
IB
111 ];
112 };
113 services.postfix = {
114 mapFiles = let
115 recipient_maps = let
116 name = n: i: "relay_${n}_${toString i}";
117 pair = n: i: m: lib.attrsets.nameValuePair (name n i) (
118 if m.type == "hash"
119 then pkgs.writeText (name n i) m.content
120 else null
121 );
122 pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps;
123 in lib.attrsets.filterAttrs (k: v: v != null) (
124 lib.attrsets.listToAttrs (lib.flatten (
125 lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains
126 ))
127 );
128 relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) (
129 lib.attrsets.mapAttrs' (n: v:
130 lib.attrsets.nameValuePair "recipient_access_${n}" (
131 if lib.attrsets.hasAttr "relay_restrictions" v
132 then pkgs.writeText "recipient_access_${n}" v.relay_restrictions
133 else null
134 )
135 ) config.myEnv.mail.postfix.backup_domains
136 );
137 virtual_map = {
71a2425e
IB
138 virtual = let
139 cfg = config.myEnv.monitoring.email_check.eldiron;
140 address = "${cfg.mail_address}@${cfg.mail_domain}";
141 in pkgs.writeText "postfix-virtual" (
619e4f46 142 builtins.concatStringsSep "\n" (
71a2425e 143 ["${address} 1"] ++
619e4f46
IB
144 lib.attrsets.mapAttrsToList (
145 n: v: lib.optionalString v.external ''
146 script_${n}@mail.immae.eu 1
147 ''
148 ) config.myEnv.mail.scripts
149 )
150 );
151 };
619e4f46 152 in
22b4bd78 153 recipient_maps // relay_restrictions // virtual_map;
619e4f46
IB
154 config = {
155 ### postfix module overrides
156 readme_directory = "${pkgs.postfix}/share/postfix/doc";
157 smtp_tls_CAfile = lib.mkForce "";
158 smtp_tls_cert_file = lib.mkForce "";
159 smtp_tls_key_file = lib.mkForce "";
160
161 message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited"
162 mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts
163 alias_database = "\$alias_maps";
164
165 ### Relay domains
166 relay_domains = let
167 backups = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains);
168 virtual_domains = config.myEnv.mail.postfix.additional_mailbox_domains
ccb8bab4 169 ++ lib.remove null (lib.flatten (map
619e4f46
IB
170 (zone: map
171 (e: if e.receive
172 then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}"
173 else null
174 )
175 (zone.withEmail or [])
176 )
177 config.myEnv.dns.masterZones
ccb8bab4 178 ));
619e4f46
IB
179 in
180 backups ++ virtual_domains;
181 relay_recipient_maps = let
182 backup_recipients = lib.flatten (lib.attrsets.mapAttrsToList (n: v:
183 lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps
184 ) config.myEnv.mail.postfix.backup_domains);
185 virtual_alias_maps = [
186 "hash:/etc/postfix/virtual"
187 "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}"
188 "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}"
189 ];
190 virtual_mailbox_maps = [
22b4bd78 191 "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}"
4e07970c 192 "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}"
619e4f46
IB
193 ];
194 in
195 backup_recipients ++ virtual_alias_maps ++ virtual_mailbox_maps;
196 smtpd_relay_restrictions = [
197 "defer_unauth_destination"
198 ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v:
199 if lib.attrsets.hasAttr "relay_restrictions" v
200 then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ]
201 else []
202 ) config.myEnv.mail.postfix.backup_domains);
203
204 ### Additional smtpd configuration
205 smtpd_tls_received_header = "yes";
206 smtpd_tls_loglevel = "1";
207
208 ### Email sending configuration
209 smtp_tls_security_level = "may";
210 smtp_tls_loglevel = "1";
211
212 ### Force ip bind for smtp
213 smtp_bind_address = config.myEnv.servers."${name}".ips.main.ip4;
214 smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6;
215
216 smtpd_milters = [
217 "unix:${config.myServices.mail.milters.sockets.opendkim}"
218 "unix:${config.myServices.mail.milters.sockets.openarc}"
219 "unix:${config.myServices.mail.milters.sockets.opendmarc}"
220 ];
221 };
222 enable = true;
223 enableSmtp = true;
224 enableSubmission = false;
619e4f46
IB
225 destination = ["localhost"];
226 # This needs to reverse DNS
227 hostname = config.hostEnv.fqdn;
228 setSendmail = false;
229 sslCert = "/var/lib/acme/mail/fullchain.pem";
230 sslKey = "/var/lib/acme/mail/key.pem";
231 recipientDelimiter = "+";
232 };
233 };
234}
235