about summary refs log tree commit diff stats
path: root/tests/by-name/em/email-dns
diff options
context:
space:
mode:
Diffstat (limited to 'tests/by-name/em/email-dns')
-rwxr-xr-xtests/by-name/em/email-dns/nodes/acme/certs/generate66
-rwxr-xr-xtests/by-name/em/email-dns/nodes/acme/certs/generate.ca38
-rwxr-xr-xtests/by-name/em/email-dns/nodes/acme/certs/generate.client44
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.cert.pem11
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.key.pem25
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.template5
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/ca.cert.pem10
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/ca.key.pem25
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/output/ca.template5
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/certs/snakeoil-certs.nix13
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/client.nix21
-rw-r--r--tests/by-name/em/email-dns/nodes/acme/default.nix114
-rw-r--r--tests/by-name/em/email-dns/nodes/mail_server.nix14
-rw-r--r--tests/by-name/em/email-dns/nodes/name_server.nix236
-rw-r--r--tests/by-name/em/email-dns/nodes/user.nix8
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/alice.com/private.age11
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/alice.com/public1
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/bob.com/private.age13
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/bob.com/public1
-rwxr-xr-xtests/by-name/em/email-dns/secrets/dkim/gen_key.sh33
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/private.age10
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/public1
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/private.age13
-rw-r--r--tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/public1
-rw-r--r--tests/by-name/em/email-dns/secrets/hostKey7
-rw-r--r--tests/by-name/em/email-dns/test.nix54
26 files changed, 120 insertions, 660 deletions
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/generate b/tests/by-name/em/email-dns/nodes/acme/certs/generate
deleted file mode 100755
index 0d6258e..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/generate
+++ /dev/null
@@ -1,66 +0,0 @@
-#! /usr/bin/env nix-shell
-#! nix-shell -p gnutls -p dash -i dash --impure
-# shellcheck shell=dash
-
-# For development and testing.
-# Create a CA key and cert, and use that to generate a server key and cert.
-# Creates:
-#   ca.key.pem
-#   ca.cert.pem
-#   server.key.pem
-#   server.cert.pem
-
-export SEC_PARAM=ultra
-export EXPIRATION_DAYS=123456
-export ORGANIZATION="Vhack.eu Test Keys"
-export COUNTRY=EU
-export SAN="acme.test"
-export KEY_TYPE="ed25519"
-
-BASEDIR="$(dirname "$0")"
-GENERATION_LOCATION="$BASEDIR/output"
-cd "$BASEDIR" || {
-    echo "(BUG?) No basedir ('$BASEDIR')" 1>&2
-    exit 1
-}
-
-ca=false
-clients=false
-
-usage() {
-    echo "Usage: $0 --ca|--clients"
-    exit 2
-}
-
-if [ "$#" -eq 0 ]; then
-    usage
-fi
-
-for arg in "$@"; do
-    case "$arg" in
-    "--ca")
-        ca=true
-        ;;
-    "--clients")
-        clients=true
-        ;;
-    *)
-        usage
-        ;;
-    esac
-done
-
-[ -d "$GENERATION_LOCATION" ] || mkdir --parents "$GENERATION_LOCATION"
-cd "$GENERATION_LOCATION" || echo "(BUG?) No generation location fould!" 1>&2
-
-[ "$ca" = true ] && ../generate.ca
-
-# Creates:
-#   <client_name>.key.pem
-#   <client_name>.cert.pem
-#
-[ "$clients" = true ] && ../generate.client "acme.test"
-
-echo "(INFO) Look for the keys at: $GENERATION_LOCATION"
-
-# vim: ft=sh
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/generate.ca b/tests/by-name/em/email-dns/nodes/acme/certs/generate.ca
deleted file mode 100755
index 92832c5..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/generate.ca
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /usr/bin/env sh
-
-# Take the correct binary to create the certificates
-CERTTOOL=$(command -v gnutls-certtool 2>/dev/null || command -v certtool 2>/dev/null)
-if [ -z "$CERTTOOL" ]; then
-    echo "ERROR: No certtool found" >&2
-    exit 1
-fi
-
-# Create a CA key.
-$CERTTOOL \
-    --generate-privkey \
-    --sec-param "$SEC_PARAM" \
-    --key-type "$KEY_TYPE" \
-    --outfile ca.key.pem
-
-chmod 600 ca.key.pem
-
-# Sign a CA cert.
-cat <<EOF >ca.template
-country = $COUNTRY
-dns_name = "$SAN"
-expiration_days = $EXPIRATION_DAYS
-organization = $ORGANIZATION
-ca
-EOF
-#state = $STATE
-#locality = $LOCALITY
-
-$CERTTOOL \
-    --generate-self-signed \
-    --load-privkey ca.key.pem \
-    --template ca.template \
-    --outfile ca.cert.pem
-
-chmod 600 ca.cert.pem
-
-# vim: ft=sh
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/generate.client b/tests/by-name/em/email-dns/nodes/acme/certs/generate.client
deleted file mode 100755
index 5930298..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/generate.client
+++ /dev/null
@@ -1,44 +0,0 @@
-#! /usr/bin/env sh
-
-# Take the correct binary to create the certificates
-CERTTOOL=$(command -v gnutls-certtool 2>/dev/null || command -v certtool 2>/dev/null)
-if [ -z "$CERTTOOL" ]; then
-    echo "ERROR: No certtool found" >&2
-    exit 1
-fi
-
-NAME=client
-if [ $# -gt 0 ]; then
-    NAME="$1"
-fi
-
-# Create a client key.
-$CERTTOOL \
-    --generate-privkey \
-    --sec-param "$SEC_PARAM" \
-    --key-type "$KEY_TYPE" \
-    --outfile "$NAME".key.pem
-
-chmod 600 "$NAME".key.pem
-
-# Sign a client cert with the key.
-cat <<EOF >"$NAME".template
-dns_name = "$NAME"
-dns_name = "$SAN"
-expiration_days = $EXPIRATION_DAYS
-organization = $ORGANIZATION
-encryption_key
-signing_key
-EOF
-
-$CERTTOOL \
-    --generate-certificate \
-    --load-privkey "$NAME".key.pem \
-    --load-ca-certificate ca.cert.pem \
-    --load-ca-privkey ca.key.pem \
-    --template "$NAME".template \
-    --outfile "$NAME".cert.pem
-
-chmod 600 "$NAME".cert.pem
-
-# vim: ft=sh
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.cert.pem b/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.cert.pem
deleted file mode 100644
index 687101d..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.cert.pem
+++ /dev/null
@@ -1,11 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIBjTCCAT+gAwIBAgIUfiDKld3eiPKuFhsaiHpPNmbMJU8wBQYDK2VwMCoxCzAJ
-BgNVBAYTAkVVMRswGQYDVQQKExJWaGFjay5ldSBUZXN0IEtleXMwIBcNMjUwMzAx
-MTEyNjU2WhgPMjM2MzAzMDYxMTI2NTZaMB0xGzAZBgNVBAoTElZoYWNrLmV1IFRl
-c3QgS2V5czAqMAUGAytlcAMhAHYq2cjrfrlslWxvcKjs2cD7THbpmtq+jf/dlrKW
-UEo8o4GBMH8wDAYDVR0TAQH/BAIwADAfBgNVHREEGDAWgglhY21lLnRlc3SCCWFj
-bWUudGVzdDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFN/1UyS0jnC3LoryMIL2
-/6cdsYBBMB8GA1UdIwQYMBaAFLUZcL/zguHlulHg5GYyYhXmVt/6MAUGAytlcANB
-ALz3u7lBreHeVZ0YXrwK3SDwlhWIH/SeUQwbxQlarzR47qu3cwQQ93Y1xjtOdu+h
-hOM/ig3nLGVOT6qL8IsZrQk=
------END CERTIFICATE-----
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.key.pem b/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.key.pem
deleted file mode 100644
index 06195b8..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.key.pem
+++ /dev/null
@@ -1,25 +0,0 @@
-Public Key Info:
-	Public Key Algorithm: EdDSA (Ed25519)
-	Key Security Level: High (256 bits)
-
-curve:	Ed25519
-private key:
-	9d:25:38:89:f2:37:d7:65:41:f5:24:ba:4c:19:fb:0f
-	86:c8:a3:cf:f7:08:57:69:cc:64:cf:55:2d:8e:99:3e
-	
-
-x:
-	76:2a:d9:c8:eb:7e:b9:6c:95:6c:6f:70:a8:ec:d9:c0
-	fb:4c:76:e9:9a:da:be:8d:ff:dd:96:b2:96:50:4a:3c
-	
-
-
-Public Key PIN:
-	pin-sha256:NPwZitkDv4isUmdiicSsM1t1OtYoxqhdvBUnqSc4bFQ=
-Public Key ID:
-	sha256:34fc198ad903bf88ac52676289c4ac335b753ad628c6a85dbc1527a927386c54
-	sha1:dff55324b48e70b72e8af23082f6ffa71db18041
-
------BEGIN PRIVATE KEY-----
-MC4CAQAwBQYDK2VwBCIEIJ0lOInyN9dlQfUkukwZ+w+GyKPP9whXacxkz1Utjpk+
------END PRIVATE KEY-----
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.template b/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.template
deleted file mode 100644
index 320a170..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/acme.test.template
+++ /dev/null
@@ -1,5 +0,0 @@
-dns_name = "acme.test"
-dns_name = "acme.test"
-expiration_days = 123456
-organization = Vhack.eu Test Keys
-encryption_key
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.cert.pem b/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.cert.pem
deleted file mode 100644
index 0fa9d14..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.cert.pem
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIBYDCCARKgAwIBAgIUdhVVcf+NgElqGuutU55FUDBtFVMwBQYDK2VwMCoxCzAJ
-BgNVBAYTAkVVMRswGQYDVQQKExJWaGFjay5ldSBUZXN0IEtleXMwIBcNMjUwMzAx
-MTEyNjU2WhgPMjM2MzAzMDYxMTI2NTZaMCoxCzAJBgNVBAYTAkVVMRswGQYDVQQK
-ExJWaGFjay5ldSBUZXN0IEtleXMwKjAFBgMrZXADIQCkO1LhHINvJjt41JD6UEc4
-ZKKUubB8lKPxSOyTkFBOgqNIMEYwDwYDVR0TAQH/BAUwAwEB/zAUBgNVHREEDTAL
-gglhY21lLnRlc3QwHQYDVR0OBBYEFLUZcL/zguHlulHg5GYyYhXmVt/6MAUGAytl
-cANBAFMFFy5tjuQtp5GVEN6qM50L4lteQuxfhlQqmOOfl06HV6153wJnrlKaTOYO
-t0dKlSqKROMYUYeU39xDp07MLAc=
------END CERTIFICATE-----
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.key.pem b/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.key.pem
deleted file mode 100644
index 64263bc..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.key.pem
+++ /dev/null
@@ -1,25 +0,0 @@
-Public Key Info:
-	Public Key Algorithm: EdDSA (Ed25519)
-	Key Security Level: High (256 bits)
-
-curve:	Ed25519
-private key:
-	82:0d:fc:f0:d6:82:89:63:e5:bc:23:78:ba:98:38:83
-	09:2d:e0:78:4c:53:92:e3:db:5b:2f:e4:39:ce:96:3d
-	
-
-x:
-	a4:3b:52:e1:1c:83:6f:26:3b:78:d4:90:fa:50:47:38
-	64:a2:94:b9:b0:7c:94:a3:f1:48:ec:93:90:50:4e:82
-	
-
-
-Public Key PIN:
-	pin-sha256:jpzYZMOHDPCeSXxfL+YUXgSPcbO9MAs8foGMP5CJiD8=
-Public Key ID:
-	sha256:8e9cd864c3870cf09e497c5f2fe6145e048f71b3bd300b3c7e818c3f9089883f
-	sha1:b51970bff382e1e5ba51e0e466326215e656dffa
-
------BEGIN PRIVATE KEY-----
-MC4CAQAwBQYDK2VwBCIEIIIN/PDWgolj5bwjeLqYOIMJLeB4TFOS49tbL+Q5zpY9
------END PRIVATE KEY-----
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.template b/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.template
deleted file mode 100644
index a2295d8..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/output/ca.template
+++ /dev/null
@@ -1,5 +0,0 @@
-country = EU
-dns_name = "acme.test"
-expiration_days = 123456
-organization = Vhack.eu Test Keys
-ca
diff --git a/tests/by-name/em/email-dns/nodes/acme/certs/snakeoil-certs.nix b/tests/by-name/em/email-dns/nodes/acme/certs/snakeoil-certs.nix
deleted file mode 100644
index aeb6dfc..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/certs/snakeoil-certs.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-let
-  domain = "acme.test";
-in {
-  inherit domain;
-  ca = {
-    cert = ./output/ca.cert.pem;
-    key = ./output/ca.key.pem;
-  };
-  "${domain}" = {
-    cert = ./output/. + "/${domain}.cert.pem";
-    key = ./output/. + "/${domain}.key.pem";
-  };
-}
diff --git a/tests/by-name/em/email-dns/nodes/acme/client.nix b/tests/by-name/em/email-dns/nodes/acme/client.nix
deleted file mode 100644
index 2b870e8..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/client.nix
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  nodes,
-  lib,
-  ...
-}: let
-  inherit (nodes.acme.test-support.acme) caCert;
-  inherit (nodes.acme.test-support.acme) caDomain;
-in {
-  security = {
-    acme = {
-      acceptTerms = true;
-      defaults = {
-        server = "https://${caDomain}/dir";
-      };
-    };
-
-    pki = {
-      certificateFiles = lib.mkForce [caCert];
-    };
-  };
-}
diff --git a/tests/by-name/em/email-dns/nodes/acme/default.nix b/tests/by-name/em/email-dns/nodes/acme/default.nix
deleted file mode 100644
index 236ba6a..0000000
--- a/tests/by-name/em/email-dns/nodes/acme/default.nix
+++ /dev/null
@@ -1,114 +0,0 @@
-# The certificate for the ACME service is exported as:
-#
-#   config.test-support.acme.caCert
-#
-# This value can be used inside the configuration of other test nodes to inject
-# the test certificate into security.pki.certificateFiles or into package
-# overlays.
-#
-# {
-#   acme = { nodes, lib, ... }: {
-#     imports = [ ./common/acme/server ];
-#     networking.nameservers = lib.mkForce [
-#       nodes.mydnsresolver.networking.primaryIPAddress
-#     ];
-#   };
-#
-#   dnsmyresolver = ...;
-# }
-#
-# Keep in mind, that currently only _one_ resolver is supported, if you have
-# more than one resolver in networking.nameservers only the first one will be
-# used.
-#
-# Also make sure that whenever you use a resolver from a different test node
-# that it has to be started _before_ the ACME service.
-{
-  config,
-  pkgs,
-  lib,
-  ...
-}: let
-  testCerts = import ./certs/snakeoil-certs.nix;
-  inherit (testCerts) domain;
-
-  pebbleConf.pebble = {
-    listenAddress = "0.0.0.0:443";
-    managementListenAddress = "0.0.0.0:15000";
-
-    # The cert and key are used only for the Web Front End (WFE)
-    certificate = testCerts.${domain}.cert;
-    privateKey = testCerts.${domain}.key;
-
-    httpPort = 80;
-    tlsPort = 443;
-    ocspResponderURL = "http://${domain}:4002";
-    strict = true;
-  };
-
-  pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf);
-in {
-  options.test-support.acme = {
-    caDomain = lib.mkOption {
-      type = lib.types.str;
-      default = domain;
-      readOnly = true;
-      description = ''
-        A domain name to use with the `nodes` attribute to
-        identify the CA server in the `client` config.
-      '';
-    };
-    caCert = lib.mkOption {
-      type = lib.types.path;
-      readOnly = true;
-      default = testCerts.ca.cert;
-      description = ''
-        A certificate file to use with the `nodes` attribute to
-        inject the test CA certificate used in the ACME server into
-        {option}`security.pki.certificateFiles`.
-      '';
-    };
-  };
-
-  config = {
-    networking = {
-      # This has priority 140, because modules/testing/test-instrumentation.nix
-      # already overrides this with priority 150.
-      nameservers = lib.mkOverride 140 ["127.0.0.1"];
-      firewall.allowedTCPPorts = [
-        80
-        443
-        15000
-        4002
-      ];
-
-      extraHosts = ''
-        127.0.0.1 ${domain}
-        ${config.networking.primaryIPAddress} ${domain}
-      '';
-    };
-
-    systemd.services = {
-      pebble = {
-        enable = true;
-        description = "Pebble ACME server";
-        wantedBy = ["network.target"];
-        environment = {
-          # We're not testing lego, we're just testing our configuration.
-          # No need to sleep.
-          PEBBLE_VA_NOSLEEP = "1";
-        };
-
-        serviceConfig = {
-          RuntimeDirectory = "pebble";
-          WorkingDirectory = "/run/pebble";
-
-          # Required to bind on privileged ports.
-          AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
-
-          ExecStart = "${pkgs.pebble}/bin/pebble -config ${pebbleConfFile}";
-        };
-      };
-    };
-  };
-}
diff --git a/tests/by-name/em/email-dns/nodes/mail_server.nix b/tests/by-name/em/email-dns/nodes/mail_server.nix
index a8c528a..279d289 100644
--- a/tests/by-name/em/email-dns/nodes/mail_server.nix
+++ b/tests/by-name/em/email-dns/nodes/mail_server.nix
@@ -13,7 +13,8 @@
       extraModules
       ++ [
         ../../../../../modules
-        ./acme/client.nix
+        ../../../../common/acme/client.nix
+        ../../../../common/dns/client.nix
       ];
 
     environment.systemPackages = [
@@ -21,12 +22,7 @@
       pkgs.openssl
     ];
 
-    networking.nameservers = lib.mkForce [
-      nodes.name_server.networking.primaryIPAddress
-      nodes.name_server.networking.primaryIPv6Address
-    ];
-
-    age.identityPaths = ["${../secrets/hostKey}"];
+    age.identityPaths = ["${../../../../common/email/hostKey}"];
 
     vhack = {
       stalwart-mail = {
@@ -36,8 +32,8 @@
         security = {
           dkimKeys = let
             loadKey = name: {
-              dkimPublicKey = builtins.readFile (../secrets/dkim + "/${name}/public");
-              dkimPrivateKeyPath = ../secrets/dkim + "/${name}/private.age";
+              dkimPublicKey = builtins.readFile (../../../../common/email/dkim + "/${name}/public");
+              dkimPrivateKeyPath = ../../../../common/email/dkim + "/${name}/private.age";
               keyAlgorithm = "ed25519-sha256";
             };
           in {
diff --git a/tests/by-name/em/email-dns/nodes/name_server.nix b/tests/by-name/em/email-dns/nodes/name_server.nix
index ef657f4..bde1a16 100644
--- a/tests/by-name/em/email-dns/nodes/name_server.nix
+++ b/tests/by-name/em/email-dns/nodes/name_server.nix
@@ -63,7 +63,7 @@
         adkim = "strict";
         aspf = "strict";
         fo = ["0" "1" "d" "s"];
-        p = "quarantine";
+        p = "reject";
         rua = cfg.admin;
         ruf = [cfg.admin];
       }
@@ -139,14 +139,10 @@ in {
     extraModules
     ++ [
       ../../../../../modules
-      ./acme/client.nix
+      ../../../../common/acme/client.nix
+      ../../../../common/dns/server.nix
     ];
 
-  networking.nameservers = lib.mkForce [
-    nodes.name_server.networking.primaryIPAddress
-    nodes.name_server.networking.primaryIPv6Address
-  ];
-
   services.nginx = {
     logError = "stderr debug";
     virtualHosts = let
@@ -175,145 +171,121 @@ in {
     nginx = {
       enable = true;
     };
-    dns = {
-      enable = true;
-      openFirewall = true;
-      interfaces = [
-        nodes.name_server.networking.primaryIPAddress
-        nodes.name_server.networking.primaryIPv6Address
-      ];
-
-      zones = let
-        stsZone = {
-          SOA = {
-            nameServer = "ns";
-            adminEmail = "admin@server.com";
-            serial = 2025012301;
-          };
+    dns.zones = let
+      stsZone = {
+        SOA = {
+          nameServer = "ns";
+          adminEmail = "admin@server.com";
+          serial = 2025012301;
+        };
 
-          useOrigin = false;
+        useOrigin = false;
 
-          A = [
-            nodes.name_server.networking.primaryIPAddress
-          ];
-          AAAA = [
-            nodes.name_server.networking.primaryIPv6Address
-          ];
+        A = [
+          nodes.name_server.networking.primaryIPAddress
+        ];
+        AAAA = [
+          nodes.name_server.networking.primaryIPv6Address
+        ];
+      };
+    in {
+      "arpa" = {
+        SOA = {
+          nameServer = "ns";
+          adminEmail = "admin@server.com";
+          serial = 2025012301;
         };
-      in {
-        "arpa" = {
-          SOA = {
-            nameServer = "ns";
-            adminEmail = "admin@server.com";
-            serial = 2025012301;
-          };
-          useOrigin = false;
-
-          PTR = [
-            {
-              name = "acme.test";
-              ip.v4 = nodes.acme.networking.primaryIPAddress;
-            }
-            {
-              name = "acme.test";
-              ip.v6 = nodes.acme.networking.primaryIPv6Address;
-            }
+        useOrigin = false;
 
-            {
-              name = "alice.com";
-              ip.v4 = nodes.alice.networking.primaryIPAddress;
-            }
-            {
-              name = "alice.com";
-              ip.v6 = nodes.alice.networking.primaryIPv6Address;
-            }
+        PTR = [
+          {
+            name = "acme.test";
+            ip.v4 = nodes.acme.networking.primaryIPAddress;
+          }
+          {
+            name = "acme.test";
+            ip.v6 = nodes.acme.networking.primaryIPv6Address;
+          }
 
-            {
-              name = "bob";
-              ip.v4 = nodes.bob.networking.primaryIPAddress;
-            }
-            {
-              name = "bob";
-              ip.v6 = nodes.bob.networking.primaryIPv6Address;
-            }
+          {
+            name = "alice.com";
+            ip.v4 = nodes.alice.networking.primaryIPAddress;
+          }
+          {
+            name = "alice.com";
+            ip.v6 = nodes.alice.networking.primaryIPv6Address;
+          }
 
-            {
-              name = "mail1.server.com";
-              ip.v4 = nodes.mail1_server.networking.primaryIPAddress;
-            }
-            {
-              name = "mail1.server.com";
-              ip.v6 = nodes.mail1_server.networking.primaryIPv6Address;
-            }
+          {
+            name = "bob";
+            ip.v4 = nodes.bob.networking.primaryIPAddress;
+          }
+          {
+            name = "bob";
+            ip.v6 = nodes.bob.networking.primaryIPv6Address;
+          }
 
-            {
-              name = "mail2.server.com";
-              ip.v4 = nodes.mail2_server.networking.primaryIPAddress;
-            }
-            {
-              name = "mail2.server.com";
-              ip.v6 = nodes.mail2_server.networking.primaryIPv6Address;
-            }
+          {
+            name = "mail1.server.com";
+            ip.v4 = nodes.mail1_server.networking.primaryIPAddress;
+          }
+          {
+            name = "mail1.server.com";
+            ip.v6 = nodes.mail1_server.networking.primaryIPv6Address;
+          }
 
-            {
-              name = "ns.server.com";
-              ip.v4 = nodes.name_server.networking.primaryIPAddress;
-            }
-            {
-              name = "ns.server.com";
-              ip.v6 = nodes.name_server.networking.primaryIPv6Address;
-            }
-          ];
-        };
+          {
+            name = "mail2.server.com";
+            ip.v4 = nodes.mail2_server.networking.primaryIPAddress;
+          }
+          {
+            name = "mail2.server.com";
+            ip.v6 = nodes.mail2_server.networking.primaryIPv6Address;
+          }
 
-        "alice.com" = mkZone "alice" nodes lib nodes.mail2_server.vhack.stalwart-mail;
-        "mta-sts.alice.com" = stsZone;
-        "bob.com" = mkZone "bob" nodes lib nodes.mail1_server.vhack.stalwart-mail;
-        "mta-sts.bob.com" = stsZone;
-        "mail1.server.com" = mkServerZone "mail1" nodes lib;
-        "mail2.server.com" = mkServerZone "mail2" nodes lib;
-        "ns.server.com" = {
-          SOA = {
-            nameServer = "ns";
-            adminEmail = "admin@server.com";
-            serial = 2025012301;
-          };
-          useOrigin = false;
+          {
+            name = "ns.server.com";
+            ip.v4 = nodes.name_server.networking.primaryIPAddress;
+          }
+          {
+            name = "ns.server.com";
+            ip.v6 = nodes.name_server.networking.primaryIPv6Address;
+          }
+        ];
+      };
 
-          A = [
-            nodes.name_server.networking.primaryIPAddress
-          ];
-          AAAA = [
-            nodes.name_server.networking.primaryIPv6Address
-          ];
+      "alice.com" = mkZone "alice" nodes lib nodes.mail2_server.vhack.stalwart-mail;
+      "mta-sts.alice.com" = stsZone;
+      "bob.com" = mkZone "bob" nodes lib nodes.mail1_server.vhack.stalwart-mail;
+      "mta-sts.bob.com" = stsZone;
+      "mail1.server.com" = mkServerZone "mail1" nodes lib;
+      "mail2.server.com" = mkServerZone "mail2" nodes lib;
+      "ns.server.com" = {
+        SOA = {
+          nameServer = "ns";
+          adminEmail = "admin@server.com";
+          serial = 2025012301;
         };
-        "acme.test" = {
-          SOA = {
-            nameServer = "ns";
-            adminEmail = "admin@server.com";
-            serial = 2025012301;
-          };
-          useOrigin = false;
+        useOrigin = false;
 
-          A = [
-            nodes.acme.networking.primaryIPAddress
-          ];
-          AAAA = [
-            nodes.acme.networking.primaryIPv6Address
-          ];
+        A = [
+          nodes.name_server.networking.primaryIPAddress
+        ];
+        AAAA = [
+          nodes.name_server.networking.primaryIPv6Address
+        ];
+      };
+      "server.com" = {
+        SOA = {
+          nameServer = "ns";
+          adminEmail = "admin@server.com";
+          serial = 2025012301;
         };
-        "server.com" = {
-          SOA = {
-            nameServer = "ns";
-            adminEmail = "admin@server.com";
-            serial = 2025012301;
-          };
 
-          useOrigin = false;
-          NS = [
-            "ns.server.com."
-          ];
-        };
+        useOrigin = false;
+        NS = [
+          "ns.server.com."
+        ];
       };
     };
   };
diff --git a/tests/by-name/em/email-dns/nodes/user.nix b/tests/by-name/em/email-dns/nodes/user.nix
index e4db347..fba02ce 100644
--- a/tests/by-name/em/email-dns/nodes/user.nix
+++ b/tests/by-name/em/email-dns/nodes/user.nix
@@ -8,7 +8,8 @@
     ...
   }: {
     imports = [
-      ./acme/client.nix
+      ../../../../common/acme/client.nix
+      ../../../../common/dns/client.nix
     ];
 
     environment.systemPackages = [
@@ -20,11 +21,6 @@
       pkgs.openssl
     ];
 
-    networking.nameservers = lib.mkForce [
-      nodes.name_server.networking.primaryIPAddress
-      nodes.name_server.networking.primaryIPv6Address
-    ];
-
     users.users."${user}" = {isNormalUser = true;};
 
     systemd.tmpfiles.rules = [
diff --git a/tests/by-name/em/email-dns/secrets/dkim/alice.com/private.age b/tests/by-name/em/email-dns/secrets/dkim/alice.com/private.age
deleted file mode 100644
index 97b9be7..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/alice.com/private.age
+++ /dev/null
@@ -1,11 +0,0 @@
------BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFJzZ1dwUSAxanpG
-VWxCYjF3aWFUUEM0b2Q2bGJUNEJZMGFlVkJpTFg3eUc1UGdyblF3CnlJVXY2Ti9z
-SmltMmIzM25jajl3WE5kMkVsY05NUkpDdzlJVHdJYXByZjQKLT4gU0t5SSxMLWdy
-ZWFzZSB6Tgova0Juc0x3RlFrR1NSVzBIMllYRmZiRXlzN2hSdHZQaFVDS3FPUFNr
-NzBiM0Q5dExOREgydFpKWm1MaGQ5QkxBCgotLS0gNC81ZHQ5eFBrUGJxWXF6dWF4
-Mlg0WHBXS2RqeW1uY1hGUVJXbHpUaDhlWQpih0QTGjejnwIQ2lvDFS1wbNiiOJ+c
-awJ2tX8chzWm+wOECaIZAqwW2NwVZj5Sj+Vzv6LQ1BVaQAiEN41GRvjyP/u3X+d+
-LKI3bPa8DWxQNd7/zAhFjSB1KEIBrqGb2GtW/Yv8Mu07V8IV/MaGUwpDOXgvFQVH
-UQ1qpM0R1r190IuV2Y7M558J42crH9/5mIvMH5rW++Ru
------END AGE ENCRYPTED FILE-----
diff --git a/tests/by-name/em/email-dns/secrets/dkim/alice.com/public b/tests/by-name/em/email-dns/secrets/dkim/alice.com/public
deleted file mode 100644
index 0f3c3b2..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/alice.com/public
+++ /dev/null
@@ -1 +0,0 @@
-cLWzd3zg51ITME1Fnu16/h07lXIUxfhdLivktUMoVQs=
\ No newline at end of file
diff --git a/tests/by-name/em/email-dns/secrets/dkim/bob.com/private.age b/tests/by-name/em/email-dns/secrets/dkim/bob.com/private.age
deleted file mode 100644
index 6bd9e28..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/bob.com/private.age
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFJzZ1dwUSBtQ1lC
-bmtXZWlqeE1SWmR2d1JTcEZMZFRKZW1jVnRGSHpUMEM1cnpvTkdFCkRVbmlNV0ZS
-SDdobTFFQUcyU3dMVXlTditvZXN0L0pPN1ZHaWtxOFZSL1EKLT4gfSM6JGpjOlot
-Z3JlYXNlICdRYiBLKlV6CmZmczdSa2U5cWl6OG5QL0VaUGsyNUlCVFJ1UjJxVnpV
-ZE1sN2lSRTgzVjI1S3pJVzdqN05WUVZmaTRYMXptb0kKczJEOG9EM2xtMFRHd3Vt
-TUpiK2RzZkRwZTZqb3lEOGpKNy80Vk9BVDlSNjhYSkROYlVGQ1ZESGhIV3ZJWVEK
-LS0tIEk0MXVEci9ITERYRzZFbTJJQWxSQzhFV3NqV2o3M0NvVlNhLzhhVkJYcTQK
-GJtIH4AxSSwZhnLn5IUhOihz9Ai2lLnf00uhvF6+i29TtyEgxgWhisBJtzShB/Aq
-Bct5em093jryJPNQBNDJpImEViP9WS/kTqQG0bnu2i/Nr5+vZyRcK8qv75guMxki
-p7sUirbzCNtA+5JGGJb30PqOAWpflBPL0fkC5L7JyAjhNRCOgIL+QQS3mosU1AYJ
-izFOdod2DA==
------END AGE ENCRYPTED FILE-----
diff --git a/tests/by-name/em/email-dns/secrets/dkim/bob.com/public b/tests/by-name/em/email-dns/secrets/dkim/bob.com/public
deleted file mode 100644
index ddea670..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/bob.com/public
+++ /dev/null
@@ -1 +0,0 @@
-3yrKD52yd5hBA6ue5uQVl7FXGK8UOlUE9Y+yCdBRfVQ=
\ No newline at end of file
diff --git a/tests/by-name/em/email-dns/secrets/dkim/gen_key.sh b/tests/by-name/em/email-dns/secrets/dkim/gen_key.sh
deleted file mode 100755
index 1e090f4..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/gen_key.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /usr/bin/env nix-shell
-#! nix-shell -p rage -p openssl -p dash -i dash --impure
-
-cd "$(dirname "$0")" || {
-    echo "No basedir?!"
-    exit 1
-}
-
-key_name="$1"
-[ -z "$key_name" ] && {
-    echo "Usage: $0 KEY_NAME"
-    exit 2
-}
-
-[ -d "$key_name" ] || mkdir "$key_name"
-cd "$key_name" || {
-    echo "Just created."
-    exit 1
-}
-
-openssl genpkey -algorithm ed25519 -out "private"
-openssl pkey -in "private" -pubout -out "public.tmp"
-
-openssl asn1parse -in "public.tmp" -offset 12 -noout -out /dev/stdout | base64 --wrap 0 >"public"
-rm "public.tmp"
-
-rage --encrypt \
-    --armor \
-    --recipient "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILxdvBk/PC9fC7B5vqe9TvygZKY6LgDQ2mXRdVrthBM/" \
-    "private" >"private.age"
-rm "private"
-
-# vim: ft=sh
diff --git a/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/private.age b/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/private.age
deleted file mode 100644
index 03bb0b1..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/private.age
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFJzZ1dwUSBiZmcz
-OVlacDhjS3pCWlZCYlpyVVFoQWxFN1Z0eTJIY2ovNVg2MjQ1SXpVClRZUnhkblFI
-c0VyelMxYzBsZ2NMUEVzWmtTSzJuVTdoVHFiZEc5cEd3aHMKLT4gJyctZ3JlYXNl
-IG1tIFt2YSAwCkQvY2VnMlBTSHhPbXJ2NE55ck0KLS0tIGkxWHdQb0NIVmZyaTdW
-bmorU2NLMjByakpTMlo1NUtFQ0NFd1YvOC9EaFEKtDNLHVtnsFiyhsREJOPq1xlk
-74MURNlYnlF1IMrUaA3oUQSR5M34Crg7rHtjF54OsRhm79Y1dGHWeeC3evVNVpY3
-1dn/q/12aWIzT/TgGcSi3bK5fPkv+nMs/WPKTREHJ1HcWLGDeH6e8uTV7lAwiSuP
-PjYhDbnNUCMMyaBsgbtCnMe8HuHdTwXQWuh0dApS5iL3z8qoSQ==
------END AGE ENCRYPTED FILE-----
diff --git a/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/public b/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/public
deleted file mode 100644
index 4941b85..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/mail1.server.com/public
+++ /dev/null
@@ -1 +0,0 @@
-quDd9+ogqiIUWybfegosFFkG7jAsblij2VrkuUXEzzY=
\ No newline at end of file
diff --git a/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/private.age b/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/private.age
deleted file mode 100644
index 6768973..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/private.age
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFJzZ1dwUSBBZ3Ex
-ZWNUU01JK0ZGOEhEWUpEM3JLdXpjc3doMVA2RUI5TVVpblQxS0JJCnlHRmdVVk05
-MW56cEt4M00raE1nU3JZaTMvTXdUQXdzbTYvVElqVjdvNWcKLT4gRnJFLWdyZWFz
-ZSA5bEhvWn4Kb01McHBBekVTalcwM0tob3VUd3NuVFlvZUpnSFQxbXVBaEJNMVlQ
-K1BiSjRCL1YrZDZoSnFBNU9aQkQyNjRoSwpqcnBnd2NJQlMxaHdoa0pPWGR0SEZO
-SU5DNjFxb3JQTTZITVZNRGF1VUR4Zm9laWhYd3lHZityRTNJVVF1bXdwCnhGYzMK
-LS0tIFFsN0Q3V1pxWUduSU9xd21uVEF2R0tJcURYa1FOTS9kMDh6RGkwNS9SMUEK
-Ni+1WbmAiavBCwLg8r1nvVipXQJ2/cItN1MgWlYe0+UrgLxRU5VLhoWi9BEulGEV
-KHkNWyMCK4Tl/NJt1PAQVJ6QBVHYYxIYQWY1QkNCqXe1YdaJ5jDcWGSZdhbCrzMN
-3tx3EPhigU2DiQZB6l4OOaHLjAw2a+POVwwsCavnRp7vEhs/5O2t5Lo2vCoDGCot
-6o+Sdr86mw==
------END AGE ENCRYPTED FILE-----
diff --git a/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/public b/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/public
deleted file mode 100644
index 5c4406d..0000000
--- a/tests/by-name/em/email-dns/secrets/dkim/mail2.server.com/public
+++ /dev/null
@@ -1 +0,0 @@
-th9exwaYvoAjxW1tAj3k/VNLl5jKzSC/dxKrxM2mTZE=
\ No newline at end of file
diff --git a/tests/by-name/em/email-dns/secrets/hostKey b/tests/by-name/em/email-dns/secrets/hostKey
deleted file mode 100644
index 79c9d6c..0000000
--- a/tests/by-name/em/email-dns/secrets/hostKey
+++ /dev/null
@@ -1,7 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
-QyNTUxOQAAACC8XbwZPzwvXwuweb6nvU78oGSmOi4A0Npl0XVa7YQTPwAAAJjFZPqHxWT6
-hwAAAAtzc2gtZWQyNTUxOQAAACC8XbwZPzwvXwuweb6nvU78oGSmOi4A0Npl0XVa7YQTPw
-AAAEA9D5AP+Uqhrg8rPx2DjgucjfnJknkk7lkeKHMV04ZZv7xdvBk/PC9fC7B5vqe9Tvyg
-ZKY6LgDQ2mXRdVrthBM/AAAAFSAnUHVibGljIHRlc3Rpbmcga2V5Jw==
------END OPENSSH PRIVATE KEY-----
diff --git a/tests/by-name/em/email-dns/test.nix b/tests/by-name/em/email-dns/test.nix
index 32447ae..c7ba3b3 100644
--- a/tests/by-name/em/email-dns/test.nix
+++ b/tests/by-name/em/email-dns/test.nix
@@ -31,9 +31,9 @@ in
         lib,
         ...
       }: {
-        imports = [./nodes/acme];
-        networking.nameservers = lib.mkForce [
-          nodes.name_server.networking.primaryIPAddress
+        imports = [
+          ../../../common/acme/server.nix
+          ../../../common/dns/client.nix
         ];
       };
 
@@ -44,7 +44,7 @@ in
         {
           class = "individual";
           name = "bob";
-          secret = "bob-password";
+          secret = "{PLAIN}bob-password";
           email = ["bob@bob.com"];
         };
 
@@ -53,7 +53,7 @@ in
         {
           class = "individual";
           name = "alice";
-          secret = "alice-password";
+          secret = "{PLAIN}alice-password";
           email = ["alice@alice.com"];
         };
 
@@ -89,23 +89,14 @@ in
           exit 1
         }
       '';
-      inherit (pkgs) lib;
+
+      acme = import ../../../common/acme {inherit pkgs;};
     in
-      /*
-      python
-      */
+      acme.prepare ["mail1_server" "mail2_server" "alice" "bob"]
+      # Python
       ''
         from time import sleep
 
-        # Start dependencies for the other services
-        acme.start()
-        acme.wait_for_unit("pebble.service")
-        name_server.start()
-        name_server.wait_for_unit("nsd.service")
-
-        # Start the actual testing machines
-        start_all()
-
         mail1_server.wait_for_unit("stalwart-mail.service")
         mail1_server.wait_for_open_port(993) # imap
         mail1_server.wait_for_open_port(465) # smtp
@@ -119,33 +110,6 @@ in
         name_server.wait_until_succeeds("stat /var/lib/acme/mta-sts.alice.com/cert.pem")
         name_server.wait_until_succeeds("stat /var/lib/acme/mta-sts.bob.com/cert.pem")
 
-        with subtest("Add pebble ca key to all services"):
-          for node in [name_server, mail1_server, mail2_server, alice, bob]:
-            node.succeed("${pkgs.writeShellScript "fetch-and-set-ca" ''
-          set -xe
-
-          # Fetch the randomly generated ca certificate
-          curl https://acme.test:15000/roots/0 > /tmp/ca.crt
-          curl https://acme.test:15000/intermediates/0 >> /tmp/ca.crt
-
-          # Append it to the various system stores
-          # The file paths are from <nixpgks>/modules/security/ca.nix
-          for cert_path in "ssl/certs/ca-certificates.crt" "ssl/certs/ca-bundle.crt" "pki/tls/certs/ca-bundle.crt"; do
-            cert_path="/etc/$cert_path"
-
-            mv "$cert_path" "$cert_path.old"
-            cat "$cert_path.old" > "$cert_path"
-            cat /tmp/ca.crt >> "$cert_path"
-          done
-
-          export NIX_SSL_CERT_FILE=/tmp/ca.crt
-          export SSL_CERT_FILE=/tmp/ca.crt
-
-          # TODO
-          # # P11-Kit trust source.
-          # environment.etc."ssl/trust-source".source = "$${cacertPackage.p11kit}/etc/ssl/trust-source";
-        ''}")
-
         with subtest("Both mailserver successfully started all services"):
           import json
           def all_services_running(host):