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