]> git.immae.eu Git - perso/Immae/Config/Nix.git/commitdiff
Add backup MX
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Thu, 9 Jan 2020 23:01:45 +0000 (00:01 +0100)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Thu, 9 Jan 2020 23:01:45 +0000 (00:01 +0100)
16 files changed:
modules/private/certificates.nix
modules/private/dns.nix
modules/private/environment.nix
modules/private/mail/default.nix
modules/private/mail/milters.nix
modules/private/mail/opensmtpd.nix
modules/private/mail/postfix.nix
modules/private/mail/relay.nix [new file with mode: 0644]
modules/private/monitoring/default.nix
modules/private/monitoring/status.nix
modules/private/system.nix
modules/private/system/backup-2.nix
modules/private/system/eldiron.nix
modules/private/system/monitoring-1.nix
modules/private/websites/tools/git/mantisbt.nix
modules/private/websites/tools/mail/mta-sts.nix

index 9e60a093d1170fcbafa68709bdbccd83c175551a..2d245792919ed6c0b5b5f59fc375d224e7ea892d 100644 (file)
@@ -24,7 +24,7 @@
       '';
     services.nginx = {
       recommendedTlsSettings = true;
-      virtualHosts = { "${config.hostEnv.FQDN}" = { useACMEHost = name; forceSSL = true; }; };
+      virtualHosts = { "${config.hostEnv.fqdn}" = { useACMEHost = name; forceSSL = true; }; };
     };
     services.websites.certs = config.myServices.certificates.certConfig;
     myServices.databasesCerts = config.myServices.certificates.certConfig;
@@ -34,7 +34,7 @@
 
     security.acme.certs = {
       "${name}" = config.myServices.certificates.certConfig // {
-        domain = config.hostEnv.FQDN;
+        domain = config.hostEnv.fqdn;
       };
     };
 
index fb908242f143d759913ecac44121bae56ca2feb3..ebced4271713f048d2e8dc18689ac35de968f447 100644 (file)
             '')
           cfg.zones }
     '';
+    mxes = lib.attrsets.filterAttrs
+      (n: v: v.mx.enable)
+      config.myEnv.servers;
+    ip4mxes = builtins.concatStringsSep "\n" (lib.mapAttrsToList
+      (n: v: "${v.mx.subdomain} IN A     ${v.ips.main.ip4}")
+      mxes);
+    ip6mxes = builtins.concatStringsSep "\n" (lib.mapAttrsToList
+      (n: v: builtins.concatStringsSep "\n" (map (i: "${v.mx.subdomain} IN AAAA  ${i}") v.ips.main.ip6))
+      mxes);
+    mxmxes = n: conf: builtins.concatStringsSep "\n" (lib.mapAttrsToList
+      (_: v: "${n} IN MX ${v.mx.priority} ${v.mx.subdomain}.${conf.name}.")
+      mxes);
   in lib.mkIf config.myServices.dns.enable {
     networking.firewall.allowedUDPPorts = [ 53 ];
     networking.firewall.allowedTCPPorts = [ 53 ];
               ${conf.entries}
 
               ${if lib.attrsets.hasAttr "withEmail" conf && lib.lists.length conf.withEmail > 0 then ''
-              mx-1 IN A     ${config.myEnv.servers.eldiron.ips.main.ip4}
-              mx-2 IN A     ${config.myEnv.servers.immaeEu.ips.main.ip4}
-              ${builtins.concatStringsSep "\n" (map (i: "mx-1 IN AAAA  ${i}") config.myEnv.servers.eldiron.ips.main.ip6)}
-              ${builtins.concatStringsSep "\n" (map (i: "mx-2 IN AAAA  ${i}") config.myEnv.servers.immaeEu.ips.main.ip6)}
+              ${ip4mxes}
+              ${ip6mxes}
               ${lib.concatStringsSep "\n\n" (map (e:
               let
                 n = if e.domain == "" then "@" else "${e.domain}  ";
               in
               ''
               ; ------------------ mail: ${n} ---------------------------
-              ${n} IN MX 10 mx-1.${conf.name}.
-              ${n} IN MX 20 mx-2.${conf.name}.
+              ${mxmxes n conf}
 
               ; https://tools.ietf.org/html/rfc6186
               _submission._tcp${suffix}  SRV  0 1  587 smtp.immae.eu.
               ; MTA-STS
               ; https://blog.delouw.ch/2018/12/16/using-mta-sts-to-enhance-email-transport-security-and-privacy/
               ; https://support.google.com/a/answer/9261504
-              _mta-sts${suffix}   IN TXT  "v=STSv1;id=20190630054629Z"
+              _mta-sts${suffix}   IN TXT  "v=STSv1;id=20200109150200Z"
               _smtp._tls${suffix} IN TXT  "v=TLSRPTv1;rua=mailto:postmaster+mta-sts@immae.eu"
               mta-sts${suffix}    IN A    ${config.myEnv.servers.eldiron.ips.main.ip4}
               ${builtins.concatStringsSep "\n" (map (i: "mta-sts${suffix}    IN AAAA ${i}") config.myEnv.servers.eldiron.ips.main.ip6)}
index 5f5f6c86c43c3377257bcc0c60043bde60e9e3ff..98d50b1d47c5dabea20b21757629f8cfda6828e7 100644 (file)
@@ -1,4 +1,4 @@
-{ lib, ... }:
+{ config, lib, name, ... }:
 with lib;
 with types;
 with lists;
@@ -23,6 +23,7 @@ let
   };
   mysqlOptions = {
     host = mkOption { description = "Host to access Mysql"; type = str; };
+    remoteHost = mkOption { description = "Host to access Mysql from outside"; type = str; };
     port = mkOption { description = "Port to access Mysql"; type = str; };
     socket = mkOption { description = "Socket to access Mysql"; type = path; };
     systemUsers = mkOption {
@@ -107,6 +108,63 @@ let
       };
     };
   };
+  hostEnv = submodule {
+    options = {
+      fqdn = mkOption {
+        description = "Host FQDN";
+        type = str;
+      };
+      emails = mkOption {
+        default = [];
+        description = "List of e-mails that the server can be a sender of";
+        type = listOf str;
+      };
+      ldap = mkOption {
+        description = ''
+          LDAP credentials for the host
+        '';
+        type = submodule {
+          options = {
+            password = mkOption { type = string; description = "Password for the LDAP connection"; };
+            dn = mkOption { type = string; description = "DN for the LDAP connection"; };
+          };
+        };
+      };
+      mx = mkOption {
+        description = "subdomain and priority for MX server";
+        default = { enable = false; };
+        type = submodule {
+          options = {
+            enable = mkEnableOption "Enable MX";
+            subdomain = mkOption { type = nullOr str; description = "Subdomain name (mx-*)"; };
+            priority = mkOption { type = nullOr str; description = "Priority"; };
+          };
+        };
+      };
+      ips = mkOption {
+        description = ''
+          attrs of ip4/ip6 grouped by section
+        '';
+        type = attrsOf (submodule {
+          options = {
+            ip4 = mkOption {
+              type = string;
+              description = ''
+                ip4 address of the host
+              '';
+            };
+            ip6 = mkOption {
+              type = listOf string;
+              default = [];
+              description = ''
+                ip6 addresses of the host
+              '';
+            };
+          };
+        });
+      };
+    };
+  };
 in
 {
   options.myEnv = {
@@ -115,48 +173,7 @@ in
         Attrs of servers information in the cluster (not necessarily handled by nixops)
       '';
       default = {};
-      type = attrsOf (submodule {
-        options = {
-          emails = mkOption {
-            default = [];
-            description = "List of e-mails that the server can be a sender of";
-            type = listOf str;
-          };
-          ldap = mkOption {
-            description = ''
-              LDAP credentials for the host
-            '';
-            type = submodule {
-              options = {
-                password = mkOption { type = string; description = "Password for the LDAP connection"; };
-                dn = mkOption { type = string; description = "DN for the LDAP connection"; };
-              };
-            };
-          };
-          ips = mkOption {
-            description = ''
-              attrs of ip4/ip6 grouped by section
-            '';
-            type = attrsOf (submodule {
-              options = {
-                ip4 = mkOption {
-                  type = string;
-                  description = ''
-                    ip4 address of the host
-                  '';
-                };
-                ip6 = mkOption {
-                  type = listOf string;
-                  default = [];
-                  description = ''
-                    ip6 addresses of the host
-                  '';
-                };
-              };
-            });
-          };
-        };
-      });
+      type = attrsOf hostEnv;
     };
     hetznerCloud = mkOption {
       description = ''
@@ -1172,12 +1189,10 @@ in
         '';
     };
   };
-  options.hostEnv = {
-    FQDN = mkOption {
-      type = string;
-      description = ''
-        FQDN of the current host.
-        '';
-    };
+  options.hostEnv = mkOption {
+    readOnly = true;
+    type = hostEnv;
+    default = config.myEnv.servers."${name}";
+    description = "Host environment";
   };
 }
index a617934c4c09aed7b059cd621ca353ecf67eca61..b50e346a10495ed844ad15b2e2809a5f19795b1a 100644 (file)
@@ -1,23 +1,25 @@
-{ lib, pkgs, config,  ... }:
+{ lib, pkgs, config, ... }:
 {
   imports = [
     ./milters.nix
     ./postfix.nix
     ./dovecot.nix
+    ./relay.nix
     ./rspamd.nix
     ./opensmtpd.nix
   ];
   options.myServices.mail.enable = lib.mkEnableOption "enable Mail services";
   options.myServices.mailRelay.enable = lib.mkEnableOption "enable Mail relay services";
+  options.myServices.mailBackup.enable = lib.mkEnableOption "enable MX backup services";
 
   config = lib.mkIf config.myServices.mail.enable {
     security.acme.certs."mail" = config.myServices.certificates.certConfig // {
-      domain = "eldiron.immae.eu";
+      domain = config.hostEnv.fqdn;
       extraDomains = let
         zonesWithMx = builtins.filter (zone:
           lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0
         ) config.myEnv.dns.masterZones;
-        mxs = map (zone: "mx-1.${zone.name}") zonesWithMx;
+        mxs = map (zone: "${config.hostEnv.mx.subdomain}.${zone.name}") zonesWithMx;
       in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs);
     };
     services.duplyBackup.profiles = {
index 6b033e86102c4b684c115cf11cf31e220c0c3949..16c8a7a2891e4d69f807b13958fca09e36ba288a 100644 (file)
@@ -12,7 +12,7 @@
       milters sockets
       '';
   };
-  config = lib.mkIf config.myServices.mail.enable {
+  config = lib.mkIf (config.myServices.mail.enable || config.myServices.mailBackup.enable) {
     secrets.keys = [
       {
         dest = "opendkim/eldiron.private";
         user = config.services.opendmarc.user;
         group = config.services.opendmarc.group;
         permissions = "0400";
-        text = config.myEnv.mail.dmarc.ignore_hosts;
+        text = let
+          mxes = lib.attrsets.filterAttrs
+            (n: v: v.mx.enable)
+            config.myEnv.servers;
+          in
+            builtins.concatStringsSep "\n" ([
+              config.myEnv.mail.dmarc.ignore_hosts
+            ] ++ lib.mapAttrsToList (n: v: v.fqdn) mxes);
       }
     ];
     users.users."${config.services.opendkim.user}".extraGroups = [ "keys" ];
@@ -51,8 +58,9 @@
       keyPath = "${config.secrets.location}/opendkim";
       selector = "eldiron";
       configFile = pkgs.writeText "opendkim.conf" ''
-        SubDomains     yes
-        UMask          002
+        SubDomains        yes
+        UMask             002
+        AlwaysAddARHeader yes
         '';
       group = config.services.postfix.group;
     };
       configFile = pkgs.writeText "opendmarc.conf" ''
         AuthservID                  HOSTNAME
         FailureReports              false
-        FailureReportsBcc           postmaster@localhost.immae.eu
+        FailureReportsBcc           postmaster@immae.eu
         FailureReportsOnNone        true
         FailureReportsSentBy        postmaster@immae.eu
         IgnoreAuthenticatedClients  true
         IgnoreHosts                 ${config.secrets.fullPaths."opendmarc/ignore.hosts"}
         SoftwareHeader              true
+        SPFIgnoreResults            true
         SPFSelfValidate             true
-        TrustedAuthservIDs          HOSTNAME, immae.eu, nef2.ens.fr
         UMask                       002
         '';
       group = config.services.postfix.group;
index 7831ac0d587bcf352426d72962b2e33ce74c16c6..e4a6140c21014217ec2fccf15751020c8d03f05e 100644 (file)
@@ -8,7 +8,7 @@
         group = "smtpd";
         permissions = "0400";
         text = ''
-          eldiron    ${name}:${config.myEnv.servers."${name}".ldap.password}
+          eldiron    ${name}:${config.hostEnv.ldap.password}
           '';
       }
     ];
         # filter "fixfrom" \
         #   proc-exec "${pkgs.procmail}/bin/formail -i 'From: ${name}@immae.eu'"
         action "relay-rewrite-from" relay \
-          helo ${config.hostEnv.FQDN} \
+          helo ${config.hostEnv.fqdn} \
           host smtp+tls://eldiron@eldiron.immae.eu:587 \
           auth <creds> \
           mail-from ${name}@immae.eu
         action "relay" relay \
-          helo ${config.hostEnv.FQDN} \
+          helo ${config.hostEnv.fqdn} \
           host smtp+tls://eldiron@eldiron.immae.eu:587 \
           auth <creds>
         match for any !mail-from "@immae.eu" action "relay-rewrite-from"
index 6623735c2e35c46d13a07a820499fd2256fb6a13..bd284cbf1d3a4015b344ac7be7e5c6c35a2a2273 100644 (file)
@@ -1,4 +1,4 @@
-{ lib, pkgs, config, nodes, ... }:
+{ lib, pkgs, config, nodes, name, ... }:
 {
   config = lib.mkIf config.myServices.mail.enable {
     services.duplyBackup.profiles.mail.excludeFile = ''
           lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps
         ) config.myEnv.mail.postfix.backup_domains);
         smtpd_relay_restrictions = [
-          "permit_mynetworks"
-          "permit_sasl_authenticated"
           "defer_unauth_destination"
         ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v:
           if lib.attrsets.hasAttr "relay_restrictions" v
         smtp_tls_loglevel = "1";
 
         ### Force ip bind for smtp
-        smtp_bind_address  = config.myEnv.servers.eldiron.ips.main.ip4;
-        smtp_bind_address6 = builtins.head config.myEnv.servers.eldiron.ips.main.ip6;
+        smtp_bind_address  = config.hostEnv.ips.main.ip4;
+        smtp_bind_address6 = builtins.head config.hostEnv.ips.main.ip6;
 
         # Use some relays when authorized senders are not myself
         smtp_sasl_mechanism_filter = "plain,login"; # GSSAPI Not correctly supported by postfix
         ### opendkim, opendmarc, openarc milters
         non_smtpd_milters = [
           "unix:${config.myServices.mail.milters.sockets.opendkim}"
-          "unix:${config.myServices.mail.milters.sockets.opendmarc}"
-          "unix:${config.myServices.mail.milters.sockets.openarc}"
         ];
         smtpd_milters = [
           "unix:${config.myServices.mail.milters.sockets.opendkim}"
-          "unix:${config.myServices.mail.milters.sockets.opendmarc}"
           "unix:${config.myServices.mail.milters.sockets.openarc}"
+          "unix:${config.myServices.mail.milters.sockets.opendmarc}"
         ];
       };
       enable = true;
         smtpd_sasl_path = "private/auth";
         smtpd_reject_unlisted_recipient = "no";
         smtpd_client_restrictions = "permit_sasl_authenticated,reject";
+        smtpd_relay_restrictions = "permit_sasl_authenticated,reject";
         # Refuse to send e-mails with a From that is not handled
         smtpd_sender_restrictions =
           "reject_sender_login_mismatch,reject_unlisted_sender,permit_sasl_authenticated,reject";
         '';
       destination = ["localhost"];
       # This needs to reverse DNS
-      hostname = "eldiron.immae.eu";
+      hostname = config.hostEnv.fqdn;
       setSendmail = true;
       sslCert = "/var/lib/acme/mail/fullchain.pem";
       sslKey = "/var/lib/acme/mail/key.pem";
diff --git a/modules/private/mail/relay.nix b/modules/private/mail/relay.nix
new file mode 100644 (file)
index 0000000..9111350
--- /dev/null
@@ -0,0 +1,233 @@
+{ lib, pkgs, config, nodes, name, ... }:
+{
+  config = lib.mkIf config.myServices.mailBackup.enable {
+    security.acme.certs."mail" = config.myServices.certificates.certConfig // {
+      postRun = ''
+        systemctl restart postfix.service
+        '';
+      domain = config.hostEnv.fqdn;
+      extraDomains = let
+        zonesWithMx = builtins.filter (zone:
+          lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0
+        ) config.myEnv.dns.masterZones;
+        mxs = map (zone: "${config.myEnv.servers."${name}".mx.subdomain}.${zone.name}") zonesWithMx;
+      in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs);
+    };
+    secrets.keys = [
+      {
+        dest = "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_merge
+            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'
+          '';
+      }
+      {
+        dest = "postfix/mysql_mailbox_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 mailboxes
+            WHERE active = 1
+            AND (
+              (domain = '%d' AND user = '%u' AND regex = 0)
+              OR (
+                regex = 1
+                AND '%d' REGEXP CONCAT('^',domain,'$')
+                AND '%u' REGEXP CONCAT('^',user,'$')
+              )
+            )
+            LIMIT 1
+        '';
+      }
+      {
+        dest = "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 ];
+
+    nixpkgs.overlays = [ (self: super: {
+      postfix = super.postfix.override { withMySQL = true; };
+    }) ];
+    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/mysql_mailbox_maps"
+        config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"
+      ];
+    };
+    services.postfix = {
+      mapFiles = let
+        recipient_maps = let
+          name = n: i: "relay_${n}_${toString i}";
+          pair = n: i: m: lib.attrsets.nameValuePair (name n i) (
+            if m.type == "hash"
+            then pkgs.writeText (name n i) m.content
+            else null
+          );
+          pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps;
+        in lib.attrsets.filterAttrs (k: v: v != null) (
+          lib.attrsets.listToAttrs (lib.flatten (
+            lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains
+          ))
+        );
+        relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) (
+          lib.attrsets.mapAttrs' (n: v:
+            lib.attrsets.nameValuePair "recipient_access_${n}" (
+              if lib.attrsets.hasAttr "relay_restrictions" v
+              then pkgs.writeText "recipient_access_${n}" v.relay_restrictions
+              else null
+            )
+          ) config.myEnv.mail.postfix.backup_domains
+        );
+        virtual_map = {
+          virtual = pkgs.writeText "postfix-virtual" (
+            builtins.concatStringsSep "\n" (
+              lib.attrsets.mapAttrsToList (
+                n: v: lib.optionalString v.external ''
+                  script_${n}@mail.immae.eu 1
+                ''
+              ) config.myEnv.mail.scripts
+            )
+          );
+        };
+        sasl_access = {
+          host_dummy_mailboxes = pkgs.writeText "host-virtual-mailbox"
+            (builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: "${n}@immae.eu  1") nodes));
+        };
+      in
+        recipient_maps // relay_restrictions // virtual_map // sasl_access;
+      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 = let
+          backups = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains);
+          virtual_domains = config.myEnv.mail.postfix.additional_mailbox_domains
+            ++ lib.remove "localhost.immae.eu" (lib.remove null (lib.flatten (map
+                (zone: map
+                  (e: if e.receive
+                  then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}"
+                  else null
+                  )
+                  (zone.withEmail or [])
+                )
+                config.myEnv.dns.masterZones
+              )));
+        in
+          backups ++ virtual_domains;
+        relay_recipient_maps = let
+          backup_recipients = lib.flatten (lib.attrsets.mapAttrsToList (n: v:
+            lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps
+          ) config.myEnv.mail.postfix.backup_domains);
+          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 = [
+            "hash:/etc/postfix/host_dummy_mailboxes"
+            "mysql:${config.secrets.fullPaths."postfix/mysql_mailbox_maps"}"
+          ];
+        in
+          backup_recipients ++ virtual_alias_maps ++ virtual_mailbox_maps;
+        smtpd_relay_restrictions = [
+          "defer_unauth_destination"
+        ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v:
+          if lib.attrsets.hasAttr "relay_restrictions" v
+          then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ]
+          else []
+        ) config.myEnv.mail.postfix.backup_domains);
+
+        ### 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  = 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;
+      # FIXME: Mail adressed to localhost.immae.eu will still have mx-1 as
+      # prioritized MX, which provokes "mail for localhost.immae.eu loops
+      # back to myself" errors. This transport entry forces to push
+      # e-mails to its right destination.
+      transport = ''
+        localhost.immae.eu   smtp:[immae.eu]:25
+        '';
+      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 = "+";
+    };
+  };
+}
+
index a1f4b3f0c99a14ac32c14e6316a853c84b2af99b..2c2f693a9a0fd64dff62ba53cca937dd1b9d92b8 100644 (file)
@@ -85,7 +85,7 @@ let
   masterObjects = pkgs.callPackage ./objects_master.nix { inherit config; };
   commonObjects = pkgs.callPackage ./objects_common.nix ({
     master = cfg.master;
-    hostFQDN = config.hostEnv.FQDN;
+    hostFQDN = config.hostEnv.fqdn;
     hostName = name;
     sudo = "/run/wrappers/bin/sudo";
   } // builtins.getAttr name commonConfig);
@@ -97,7 +97,7 @@ let
         (builtins.pathExists specific_file)
         (pkgs.callPackage specific_file {
           inherit config;
-          hostFQDN = config.hostEnv.FQDN;
+          hostFQDN = config.hostEnv.fqdn;
           hostName = name;
         });
 in
index ed4d6812857eca914ef7d6213fe8185cd164525d..d25d9344247d35acc806cc7c6322d54d4a93ed44 100644 (file)
@@ -37,7 +37,7 @@
     security.acme.certs."${name}".extraDomains."status.immae.eu" = null;
 
     myServices.certificates.enable = true;
-    networking.firewall.allowedTCPPorts = [ 80 443 18000 ];
+    networking.firewall.allowedTCPPorts = [ 80 443 ];
     systemd.services.naemon-status = {
       description = "Naemon status";
       after = [ "network.target" ];
index 184add5ebece36e88a5d8083e6bc489b967bdc35..66208c4b316f2170e5322624f1208390afcffaca 100644 (file)
@@ -1,4 +1,4 @@
-{ pkgs, lib, ... }:
+{ pkgs, lib, config, name, ... }:
 {
   config = {
     services.duplyBackup.profiles.system = {
index ede5bc2e438af5a581affaf590c62e6109d57ad3..1d84667de9ba6d794abc28f4be5dda23f0b32c0a 100644 (file)
@@ -1,9 +1,8 @@
 { privateFiles }:
-{ config, pkgs, resources, name, ... }:
+{ config, pkgs, resources, ... }:
 {
   boot.kernelPackages = pkgs.linuxPackages_latest;
   myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; };
-  hostEnv.FQDN = "backup-2.v.immae.eu";
 
   imports = builtins.attrValues (import ../..);
 
     firewall.enable = true;
     interfaces."ens3".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList
       (n: ips: { address = ips.ip4; prefixLength = 32; })
-      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.myEnv.servers.backup-2.ips);
+      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
     interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
       (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
-      config.myEnv.servers.backup-2.ips);
+      config.hostEnv.ips);
     defaultGateway6 = { address = "fe80::1"; interface = "ens3"; };
   };
 
+  myServices.certificates.enable = true;
+  services.nginx = {
+    enable = true;
+    recommendedOptimisation = true;
+    recommendedGzipSettings = true;
+    recommendedProxySettings = true;
+  };
+  networking.firewall.allowedTCPPorts = [ 80 443 ];
+
   services.cron = {
     mailto = "cron@immae.eu";
     enable = true;
@@ -49,6 +57,7 @@
   };
 
   myServices.mailRelay.enable = true;
+  myServices.mailBackup.enable = true;
   myServices.monitoring.enable = true;
   myServices.databasesReplication = {
     postgresql = {
@@ -57,7 +66,7 @@
       hosts = {
         eldiron = {
           slot = "backup_2";
-          connection = "postgresql://backup-2:${config.myEnv.servers.backup-2.ldap.password}@eldiron.immae.eu";
+          connection = "postgresql://backup-2:${config.hostEnv.ldap.password}@eldiron.immae.eu";
         };
       };
     };
@@ -71,7 +80,7 @@
           host = config.myEnv.servers.eldiron.ips.main.ip4;
           port = "3306";
           user = "backup-2";
-          password = config.myEnv.servers.backup-2.ldap.password;
+          password = config.hostEnv.ldap.password;
           dumpUser = "root";
           dumpPassword = config.myEnv.databases.mysql.systemUsers.root;
         };
index bbe1345011b12d87a1b46b62f3e996ce1b95e09d..0490cfc61f455a62f931432e6be8d1cfdd3abe16 100644 (file)
@@ -3,17 +3,16 @@
 {
   boot.kernelPackages = pkgs.linuxPackages_latest;
   myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; };
-  hostEnv.FQDN = "eldiron.immae.eu";
 
   networking = {
     firewall.enable = true;
     # 176.9.151.89 declared in nixops -> infra / tools
     interfaces."eth0".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList
       (n: ips: { address = ips.ip4; prefixLength = 32; })
-      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.myEnv.servers.eldiron.ips);
+      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
     interfaces."eth0".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
       (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
-      config.myEnv.servers.eldiron.ips);
+      config.hostEnv.ips);
   };
 
   imports = builtins.attrValues (import ../..);
@@ -44,7 +43,7 @@
     hetzner = {
       robotUser = config.myEnv.hetzner.user;
       robotPass = config.myEnv.hetzner.pass;
-      mainIPv4 = config.myEnv.servers.eldiron.ips.main.ip4;
+      mainIPv4 = config.hostEnv.ips.main.ip4;
       partitions = ''
         clearpart --all --initlabel --drives=sda,sdb
 
index 14604780e51e50356882333815fa395991b791a0..20c12df8867a5729767a83994d80b8a1d393947c 100644 (file)
@@ -3,7 +3,6 @@
 {
   boot.kernelPackages = pkgs.linuxPackages_latest;
   myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; };
-  hostEnv.FQDN = "monitoring-1.v.immae.eu";
 
   imports = builtins.attrValues (import ../..);
 
     firewall.enable = true;
     interfaces."ens3".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList
       (n: ips: { address = ips.ip4; prefixLength = 32; })
-      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.myEnv.servers.monitoring-1.ips);
+      (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
     interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
       (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
-      config.myEnv.servers.monitoring-1.ips);
+      config.hostEnv.ips);
     defaultGateway6 = { address = "fe80::1"; interface = "ens3"; };
   };
   myServices.mailRelay.enable = true;
index d0d7a9887d7baaa5d42abcae0d413245edd17c72..8606819eb36dc1fc515fb6916c533b615c338759 100644 (file)
@@ -31,7 +31,7 @@ rec {
       $g_from_email            = 'mantisbt@tools.immae.eu';
       $g_return_path_email     = 'mantisbt@tools.immae.eu';
       $g_from_name             = 'Mantis Bug Tracker at git.immae.eu';
-      $g_email_receive_own     = OFF;
+      $g_email_receive_own     = ON;
       # --- LDAP ---
       $g_login_method = LDAP;
       $g_ldap_protocol_version = 3;
index a401b41fdf3f31c05ba99032caef3255c9546297..ed3fce8d6d6399b8b98a79e666f52753f78a9d0b 100644 (file)
@@ -13,13 +13,15 @@ let
     )
     config.myEnv.dns.masterZones
   )));
+  mxes = lib.mapAttrsToList
+    (n: v: v.mx.subdomain)
+    (lib.attrsets.filterAttrs (n: v: v.mx.enable) config.myEnv.servers);
   # FIXME: increase the id number in modules/private/dns.nix when this
   # file change (date -u +'%Y%m%d%H%M%S'Z)
   file = domain: pkgs.writeText "mta-sts-${domain.domain}.txt" ''
     version: STSv1
     mode: testing
-    mx: mx-1.${domain.mail}
-    mx: mx-2.${domain.mail}
+    ${builtins.concatStringsSep "\n" (map (v: "mx: ${v}.${domain.mail}") mxes)}
     max_age: 604800
     '';
   root = pkgs.runCommand "mta-sts_root" {} ''