Add mail.cnx.email client alias as a cert SAN

A mail.cnx.email CNAME (-> mx1.cnx.email) lets clients (Thunderbird etc.)
use a friendly hostname for submission/IMAP. To avoid a TLS name
mismatch the cert now carries mail.cnx.email as a SAN, so the acme_mx1
key is authorized to write _acme-challenge.mail too. The MX still points
at mx1.cnx.email and --reuse-key keeps the DANE TLSA digest valid across
the re-issue.
This commit is contained in:
Berwn
2026-06-18 15:01:03 +07:00
parent dc21348727
commit 1dd3aadb97
3 changed files with 14 additions and 3 deletions
+3 -2
View File
@@ -58,8 +58,8 @@ in
# ACME DNS-01, dedicated mx1 key. A *separate* TSIG key (acme_mx1) that only # ACME DNS-01, dedicated mx1 key. A *separate* TSIG key (acme_mx1) that only
# mx1 holds, rendered from the shared secret (generator dns-acme-mx1-secret, # mx1 holds, rendered from the shared secret (generator dns-acme-mx1-secret,
# imported above). acl_acme_mx1 scopes it to TXT updates at exactly # imported above). acl_acme_mx1 scopes it to TXT updates at exactly
# _acme-challenge.mx1 and _acme-challenge.mta-sts (the mail cert and its # _acme-challenge.{mx1,mta-sts,mail} (the mail cert and its MTA-STS + client-
# MTA-STS SAN), and it is attached only to the cnx.email zone below — so this # alias SANs), and it is attached only to the cnx.email zone below — so this
# credential can write nothing but mx1's own cert challenges. # credential can write nothing but mx1's own cert challenges.
clan.core.vars.generators.dns-acme-mx1-knot = { clan.core.vars.generators.dns-acme-mx1-knot = {
files."acme.conf" = { files."acme.conf" = {
@@ -99,6 +99,7 @@ in
"update-owner-name" = [ "update-owner-name" = [
"_acme-challenge.mx1" "_acme-challenge.mx1"
"_acme-challenge.mta-sts" "_acme-challenge.mta-sts"
"_acme-challenge.mail"
]; ];
} }
]; ];
+4
View File
@@ -14,6 +14,10 @@ $TTL 3600
; ---- Mail ---- ; ---- Mail ----
mx1 IN A 5.223.65.38 mx1 IN A 5.223.65.38
mx1 IN AAAA 2a01:4ff:2f0:1963::1 mx1 IN AAAA 2a01:4ff:2f0:1963::1
; Client-facing alias for IMAP/submission (Thunderbird etc.); the cert carries
; mail.cnx.email as a SAN. The MX must never point here (CNAMEs are illegal MX
; targets) — server-to-server delivery and DANE stay on mx1.cnx.email.
mail IN CNAME mx1.cnx.email.
@ IN MX 10 mx1.cnx.email. @ IN MX 10 mx1.cnx.email.
@ IN TXT "v=spf1 mx -all" @ IN TXT "v=spf1 mx -all"
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:postmaster@cnx.email" _dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:postmaster@cnx.email"
+7 -1
View File
@@ -19,6 +19,9 @@ let
hosts = import ./hosts.nix; hosts = import ./hosts.nix;
fqdn = "mx1.cnx.email"; fqdn = "mx1.cnx.email";
mtaStsHost = "mta-sts.cnx.email"; mtaStsHost = "mta-sts.cnx.email";
# Client-facing alias (CNAME -> mx1) so Thunderbird etc. can use mail.cnx.email
# for submission/IMAP; added as a cert SAN so TLS validates against that name.
clientHost = "mail.cnx.email";
# MTA-STS policy served at https://mta-sts.cnx.email/.well-known/mta-sts.txt. # MTA-STS policy served at https://mta-sts.cnx.email/.well-known/mta-sts.txt.
# enforce = a sending MTA that fetched this must use a valid, MX-matching TLS # enforce = a sending MTA that fetched this must use a valid, MX-matching TLS
@@ -94,7 +97,10 @@ in
# web server and no inbound HTTP needed, so port 80 stays closed. Add the # web server and no inbound HTTP needed, so port 80 stays closed. Add the
# MTA-STS host as a SAN so the one cert also covers the policy endpoint. # MTA-STS host as a SAN so the one cert also covers the policy endpoint.
certificateScheme = "acme"; certificateScheme = "acme";
certificateDomains = [ mtaStsHost ]; certificateDomains = [
mtaStsHost
clientHost
];
dkimSelector = "mail"; dkimSelector = "mail";
}; };