Certificates for domains already in use

Your question

I have domains, both apex and subdomains which have websites published on them. These websites already have certificates issued and renewed by a reverse proxy with ACME Let’s Encrypt.

I want to receive and send emails from these domains e.g. “[email protected]”. If I have Stalwart to automatically generate the TLS certificates, does it generate separate certificates for its own use (JMAP, IMAP etc.) that won’t interfere with the website certificates managed by the proxy? Or do I have to manually add the existing certificates? The latter will make renewal complicated.

Thanks

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

In automatic mode Stalwart obtains and renews its own certificates for the hostnames it serves (typically mail.example.com and the mail service subdomains), entirely separate from the certs your reverse proxy manages for the websites. Let’s Encrypt allows multiple concurrent valid certificates for the same name, so Stalwart issuing its own doesn’t interfere with the proxy’s, and you don’t have to import anything. Manual import is possible but, as you say, it makes renewal a chore, so automatic is the way to go here.

The one thing to watch is the ACME challenge. TLS-ALPN-01 and HTTP-01 need ports 443/80 for the challenged names reachable by Stalwart, which conflicts if your proxy already terminates those same names on those ports. Two clean options: keep the mail hostname distinct from the website hostname (e.g. mail.example.com for mail, example.com/www for the site), or use the DNS-01 challenge, which avoids the port conflict entirely (it needs automatic DNS management configured). Docs: TLS certificates | Stalwart. If you tell me whether the mail hostnames are the same names the proxy already serves, I can be more specific.

Thank you, yes, I do need the DNS-01 challenge. I looked into it, tried to set it up in Stalwart but the DNS provider is not supported (I do not see it in the list) and the provider does not support RFC2136 either. In any case I do not want to pass the DNS credentials to Stalwart - even though it would be acceptable for my case to pass them temporarily and then change them. The DNS provider is Dynadot.

I read that the ACME client in such cases can request from the ACME provider the token used as the value in the DNS records, then once per domain you can set up the DNS records manually. I don’t see how this is done in Stalwart, is that supported?

There is no mode that hands you the per-order DNS-01 token to publish by hand; DNS-01 needs a configured provider and fails outright without one. It would not be a once-per-domain job either, since that token changes on every issuance.

What you are describing does exist though, under a different name: set the challenge type to DNS-PERSIST-01. With that, Stalwart never touches DNS at all, and the record you create once by hand is a _validation-persist.yourdomain TXT containing the CA’s domain and your account URI. It shows up in the domain’s DNS records list alongside everything else, so it is copy and paste into Dynadot (you need CAA enabled under Record Types for it to appear there). Wildcards still work.

The catch is that DNS-PERSIST-01 is a draft ACME extension and the CA has to implement it. Let’s Encrypt does not today, so check with whichever CA you are using before committing to it. If they do not support it, the cleanest alternative that keeps your Dynadot credentials out of Stalwart is to CNAME _acme-challenge.yourdomain to a zone hosted somewhere supported (deSEC and Cloudflare both have usable free tiers) and let Stalwart write the challenge there. Docs for the challenge types are at stalw.art/docs/server/tls/acme/challenges.

Ok thank you, I’ll be looking into deSec, but I also found this tool acme-dns-client that seems like it’s for this job specifically? If I regularly run this via linux cron, then pass the certificate location to Stalwart would that work? I remember seeing somewhere in the docs or UI that Stalwart will have to be restarted if the certificates change? Any other problems I may encounter?

The main strategy is risk mitigation. If my hosting of Stalwart (Stalwart itself or the host) is compromised, then the attacker would have full access to Dynadot or deSec with fairly dire consequences. A tool like this, if works as advertised, seems to have the best damage limitation. There’s also AcmeX

That works, and it meets the goal you’re actually after. A Certificate object can point at files on disk for both the chain and the key, so the external client owns renewal entirely and Stalwart just reads what it wrote.

On the restart question: no restart, but the reload isn’t automatic either, since nothing watches the files for changes. Your cron job needs to trigger the reload after writing them, either from the UI or with stalwart-cli create action/reloadtlscertificates. In a cluster that reload is broadcast to the other nodes for you. The one trap is ordering: write both files to a temp path and rename them into place before triggering the reload, otherwise it can pick up a half-written pair.

Otherwise: PEM for both, full chain in the certificate file, keep the domain’s certificate management on Manual for those names so we don’t also try to issue, and make sure the key file is readable by the stalwart user. There’s nothing to map per hostname, since the SANs and validity are parsed out of the certificate itself; clients that send no SNI get whatever the default certificate points at.

Worth knowing that acme-dns-client is acme-dns underneath, so it’s the same CNAME delegation of _acme-challenge I suggested with deSEC, just with the delegated zone self-hosted. That’s a reasonable trade if you’d rather run it yourself, and it does keep the Dynadot credentials off the mail host either way.