]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - systems/backup-2/mail/relay.nix
Squash changes containing private information
[perso/Immae/Config/Nix.git] / systems / backup-2 / mail / relay.nix
diff --git a/systems/backup-2/mail/relay.nix b/systems/backup-2/mail/relay.nix
new file mode 100644 (file)
index 0000000..1b7e25e
--- /dev/null
@@ -0,0 +1,196 @@
+{ lib, pkgs, config, name, nodes, ... }:
+let
+  getDomains = p: lib.mapAttrsToList (n: v: v.fqdn) (lib.filterAttrs (n: v: v.receive) p.emailPolicies);
+  bydomain = builtins.mapAttrs (n: getDomains) nodes.eldiron.config.myServices.dns.zones;
+  receiving_domains = lib.flatten (builtins.attrValues bydomain);
+in
+{
+  options.myServices.mailBackup.enable = lib.mkEnableOption "enable MX backup services";
+  config = lib.mkIf config.myServices.mailBackup.enable {
+    myServices.mail.milters.enable = true;
+    security.acme.certs."mail" = {
+      postRun = ''
+        systemctl restart postfix.service
+        '';
+      domain = config.hostEnv.fqdn;
+      extraDomainNames = let
+        zonesWithMx = builtins.attrNames (lib.filterAttrs (n: v: v.hasEmail) nodes.eldiron.config.myServices.dns.zones);
+        mxs = map (n: "${config.myEnv.servers."${name}".mx.subdomain}.${n}") zonesWithMx;
+      in mxs;
+    };
+    secrets.keys = {
+      "postfix/mysql_alias_maps" = {
+        user = config.services.postfix.user;
+        group = config.services.postfix.group;
+        permissions = "0440";
+        text = ''
+          # We need to specify that option to trigger ssl connection
+          tls_ciphers = TLSv1.2
+          user = ${config.myEnv.mail.postfix.mysql.user}
+          password = ${config.myEnv.mail.postfix.mysql.password}
+          hosts = ${config.myEnv.mail.postfix.mysql.remoteHost}
+          dbname = ${config.myEnv.mail.postfix.mysql.database}
+          query = SELECT DISTINCT 1
+            FROM forwardings
+            WHERE
+              ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s'))
+              AND active = 1
+              AND '%s' NOT IN
+              (
+                SELECT source
+                FROM forwardings_blacklisted
+                WHERE source = '%s'
+              ) UNION
+              SELECT 'devnull@immae.eu'
+              FROM forwardings_blacklisted
+              WHERE source = '%s'
+          '';
+      };
+      "postfix/ldap_mailboxes" = {
+        user = config.services.postfix.user;
+        group = config.services.postfix.group;
+        permissions = "0440";
+        text = ''
+          server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636
+          search_base = ${config.myEnv.mail.dovecot.ldap.base}
+          query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter}
+          bind_dn = ${config.myEnv.mail.dovecot.ldap.dn}
+          bind_pw = ${config.myEnv.mail.dovecot.ldap.password}
+          result_attribute = immaePostfixAddress
+          result_format = dummy
+          version = 3
+        '';
+      };
+      "postfix/sympa_mailbox_maps" = {
+        user = config.services.postfix.user;
+        group = config.services.postfix.group;
+        permissions = "0440";
+        text = ''
+          hosts = ${config.myEnv.mail.sympa.postgresql.host}
+          user = ${config.myEnv.mail.sympa.postgresql.user}
+          password = ${config.myEnv.mail.sympa.postgresql.password}
+          dbname = ${config.myEnv.mail.sympa.postgresql.database}
+          query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN (
+              CONCAT(name_list, '@', robot_list),
+              CONCAT(name_list, '-request@', robot_list),
+              CONCAT(name_list, '-editor@', robot_list),
+              CONCAT(name_list, '-unsubscribe@', robot_list),
+              CONCAT(name_list, '-owner@', robot_list),
+              CONCAT('sympa-request@', robot_list),
+              CONCAT('sympa-owner@', robot_list),
+              CONCAT('sympa@', robot_list),
+              CONCAT('listmaster@', robot_list),
+              CONCAT('bounce@', robot_list),
+              CONCAT('abuse-feedback-report@', robot_list)
+            )
+        '';
+      };
+      "postfix/ldap_ejabberd_users_immae_fr" = {
+        user = config.services.postfix.user;
+        group = config.services.postfix.group;
+        permissions = "0440";
+        text = ''
+          server_host = ldaps://${config.myEnv.jabber.ldap.host}:636
+          search_base = ${config.myEnv.jabber.ldap.base}
+          query_filter = ${config.myEnv.jabber.postfix_user_filter}
+          domain = immae.fr
+          bind_dn = ${config.myEnv.jabber.ldap.dn}
+          bind_pw = ${config.myEnv.jabber.ldap.password}
+          result_attribute = immaeXmppUid
+          result_format = ejabberd@localhost
+          version = 3
+          '';
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = [ 25 ];
+
+    users.users."${config.services.postfix.user}".extraGroups = [ "keys" ];
+    services.filesWatcher.postfix = {
+      restart = true;
+      paths = [
+        config.secrets.fullPaths."postfix/mysql_alias_maps"
+        config.secrets.fullPaths."postfix/sympa_mailbox_maps"
+        config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"
+        config.secrets.fullPaths."postfix/ldap_mailboxes"
+      ];
+    };
+    services.postfix = {
+      mapFiles = let
+        virtual_map = {
+          virtual = let
+            cfg = config.myEnv.monitoring.email_check.eldiron;
+            address = "${cfg.mail_address}@${cfg.mail_domain}";
+            aliases = config.myEnv.mail.postfix.common_aliases;
+          in pkgs.writeText "postfix-virtual" (
+            builtins.concatStringsSep "\n" (
+              [ "${address} 1"
+              ] ++
+              map (a: "${a} 1") config.myEnv.mail.postfix.other_aliases ++
+              lib.lists.flatten (map (domain: map (alias: "${alias}@${domain} 1") aliases) receiving_domains)
+            )
+          );
+        };
+      in
+        virtual_map;
+      config = {
+        ### postfix module overrides
+        readme_directory = "${pkgs.postfix}/share/postfix/doc";
+        smtp_tls_CAfile = lib.mkForce "";
+        smtp_tls_cert_file = lib.mkForce "";
+        smtp_tls_key_file = lib.mkForce "";
+
+        message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited"
+        mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts
+        alias_database = "\$alias_maps";
+
+        ### Relay domains
+        relay_domains = receiving_domains;
+        relay_recipient_maps = let
+          virtual_alias_maps = [
+            "hash:/etc/postfix/virtual"
+            "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}"
+            "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}"
+          ];
+          virtual_mailbox_maps = [
+            "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}"
+            "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}"
+          ];
+        in
+          virtual_alias_maps ++ virtual_mailbox_maps;
+        smtpd_relay_restrictions = [
+          "defer_unauth_destination"
+        ];
+
+        ### Additional smtpd configuration
+        smtpd_tls_received_header = "yes";
+        smtpd_tls_loglevel = "1";
+
+        ### Email sending configuration
+        smtp_tls_security_level = "may";
+        smtp_tls_loglevel = "1";
+
+        ### Force ip bind for smtp
+        smtp_bind_address  = builtins.head config.myEnv.servers."${name}".ips.main.ip4;
+        smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6;
+
+        smtpd_milters = [
+          "unix:${config.myServices.mail.milters.sockets.opendkim}"
+          "unix:${config.myServices.mail.milters.sockets.openarc}"
+          "unix:${config.myServices.mail.milters.sockets.opendmarc}"
+        ];
+      };
+      enable = true;
+      enableSmtp = true;
+      enableSubmission = false;
+      destination = ["localhost"];
+      # This needs to reverse DNS
+      hostname = config.hostEnv.fqdn;
+      setSendmail = false;
+      sslCert = "/var/lib/acme/mail/fullchain.pem";
+      sslKey = "/var/lib/acme/mail/key.pem";
+      recipientDelimiter = "+";
+    };
+  };
+}
+