diff --git a/default.nix b/default.nix index 60dbceb..88e1829 100644 --- a/default.nix +++ b/default.nix @@ -41,7 +41,15 @@ in type = types.listOf types.str; example = [ "example.com" ]; default = []; - description = "The domains that this mail server serves."; + description = "The domains that this mail server serves and provides a mailbox for."; + }; + + relayDomains = mkOption { + type = types.listOf types.str; + example = [ "lists.example.com" ]; + default = []; + defaultText = lib.literalExpression "config.mailserver.domains"; + description = "The domains that this mail server relays, in addition to those in {option}`domains`."; }; certificateDomains = mkOption { @@ -1319,4 +1327,8 @@ in ./mail-server/nginx.nix ./mail-server/kresd.nix ]; + + config = { + mailserver.relayDomains = cfg.domains; + }; } diff --git a/flake.nix b/flake.nix index 6fb5637..2b9a497 100644 --- a/flake.nix +++ b/flake.nix @@ -34,12 +34,13 @@ "clamav" "multiple" "ldap" + "relay" ]; genTest = testName: release: { "name"= "${testName}-${builtins.replaceStrings ["."] ["_"] release.name}"; "value"= import (./tests/. + "/${testName}.nix") { pkgs = release.pkgs; - inherit blobs; + inherit blobs lib; }; }; # Generate an attribute set such as diff --git a/mail-server/opendkim.nix b/mail-server/opendkim.nix index cdb283c..5fd096d 100644 --- a/mail-server/opendkim.nix +++ b/mail-server/opendkim.nix @@ -41,13 +41,13 @@ let echo "Generated key for domain ${dom} selector ${cfg.dkimSelector}" fi ''; - createAllCerts = lib.concatStringsSep "\n" (map createDomainDkimCert cfg.domains); + createAllCerts = lib.concatStringsSep "\n" (map createDomainDkimCert cfg.relayDomains); keyTable = pkgs.writeText "opendkim-KeyTable" - (lib.concatStringsSep "\n" (lib.flip map cfg.domains + (lib.concatStringsSep "\n" (lib.flip map cfg.relayDomains (dom: "${dom} ${dom}:${cfg.dkimSelector}:${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.key"))); signingTable = pkgs.writeText "opendkim-SigningTable" - (lib.concatStringsSep "\n" (lib.flip map cfg.domains (dom: "${dom} ${dom}"))); + (lib.concatStringsSep "\n" (lib.flip map cfg.relayDomains (dom: "${dom} ${dom}"))); dkim = config.services.opendkim; args = [ "-f" "-l" ] ++ lib.optionals (dkim.configFile != null) [ "-x" dkim.configFile ]; @@ -58,7 +58,7 @@ in enable = true; selector = cfg.dkimSelector; keyPath = cfg.dkimKeyDirectory; - domains = "csl:${builtins.concatStringsSep "," cfg.domains}"; + domains = "csl:${builtins.concatStringsSep "," cfg.relayDomains}"; configFile = pkgs.writeText "opendkim.conf" ('' Canonicalization ${cfg.dkimHeaderCanonicalization}/${cfg.dkimBodyCanonicalization} UMask 0002 diff --git a/mail-server/postfix.nix b/mail-server/postfix.nix index 6ba6ec6..964ba71 100644 --- a/mail-server/postfix.nix +++ b/mail-server/postfix.nix @@ -157,6 +157,7 @@ let tls_ca_cert_file = ${cfg.ldap.tlsCAFile} tls_require_cert = yes + domain = ${lib.concatStringsSep ", " cfg.domains} search_base = ${cfg.ldap.searchBase} scope = ${cfg.ldap.searchScope} diff --git a/mail-server/rspamd.nix b/mail-server/rspamd.nix index 8fb9b00..42e4d43 100644 --- a/mail-server/rspamd.nix +++ b/mail-server/rspamd.nix @@ -73,7 +73,7 @@ in domain = "${cfg.dmarcReporting.domain}"; org_name = "${cfg.dmarcReporting.organizationName}"; from_name = "${cfg.dmarcReporting.fromName}"; - msgid_from = "dmarc-rua"; + msgid_from = "${cfg.dmarcReporting.domain}"; }''} ''; }; }; diff --git a/tests/clamav.nix b/tests/clamav.nix index ae186df..3828a72 100644 --- a/tests/clamav.nix +++ b/tests/clamav.nix @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ pkgs ? import {}, blobs}: +{ pkgs ? import {}, blobs, ...}: pkgs.nixosTest { name = "clamav"; diff --git a/tests/relay.nix b/tests/relay.nix new file mode 100644 index 0000000..3088cc3 --- /dev/null +++ b/tests/relay.nix @@ -0,0 +1,78 @@ +# This tests is used to test features requiring several mail domains. + +{ lib, pkgs ? import { }, ... }: + +let + hashPassword = password: pkgs.runCommand + "password-${password}-hashed" + { buildInputs = [ pkgs.mkpasswd ]; inherit password; } + '' + mkpasswd -sm bcrypt <<<"$password" > $out + ''; + + password = pkgs.writeText "password" "password"; + + domainGenerator = domain: { + imports = [ ../default.nix ]; + virtualisation.memorySize = 1024; + mailserver = { + enable = true; + fqdn = "mail.${domain}"; + domains = [ domain ]; + localDnsResolver = false; + loginAccounts = { + "user@${domain}" = { + hashedPasswordFile = hashPassword "password"; + }; + }; + enableImap = true; + enableImapSsl = true; + }; + services = { + dnsmasq = { + enable = true; + settings.mx-host = [ "domain1.com,domain1,10" "domain2.com,domain2,10" ]; + }; + # disable rspamd because of graylisting + postfix.config.smtpd_milters = lib.mkForce [ ]; + rspamd.enable = lib.mkForce false; + redis.servers.rspamd.enable = false; + }; + systemd.services.postfix.requires = lib.mkForce [ "postfix-setup.service" ]; + }; + +in + +pkgs.nixosTest { + name = "relay"; + nodes = { + domain1 = { + imports = [ + ../default.nix + (domainGenerator "domain1.com") + ]; + mailserver.relayDomains = [ "replay.domain1.com" ]; + # ip of itself + services.postfix.networks = [ "[2001:db8:1::1]/128" ]; + }; + domain2 = domainGenerator "domain2.com"; + client = { pkgs, ... }: { + environment.systemPackages = [ + (pkgs.writeScriptBin "mail-check" '' + ${pkgs.python3}/bin/python ${../scripts/mail-check.py} $@ + '') + ]; + }; + }; + testScript = '' + start_all() + + domain1.wait_for_unit("multi-user.target") + domain2.wait_for_unit("multi-user.target") + + # user@domain1.com sends a mail to user@domain2.com + client.succeed( + "mail-check send-and-read --smtp-port 25 --smtp-starttls --smtp-host domain1 --from-addr user@relay.domain1.com --imap-host domain2 --to-addr user@domain2.com --dst-password-file ${password} --ignore-dkim-spf" + ) + ''; +}