Setting up DANE and DNSSEC for Mailcow

DANE for Mailcow: sign with DNSSEC, generate TLSA from the MX certificate (3 1 1), publish under _25._tcp — and keep it in sync on every certificate renewal.

Last updated: July 2026

In short: After this guide your Mailcow server's zone is DNSSEC-signed and publishes a TLSA record that pins your MX certificate — the strongest transport protection you can self-host.

⚠️ Delivery risk: a wrong TLSA record or a broken DNSSEC chain makes DANE-validating servers hard-fail delivery to your domain. Enable DNSSEC first, verify every step, and plan for certificate renewal before publishing TLSA.

Being self-hosted is an advantage here: DANE is the one security mechanism you can fully exploit on your own infrastructure — unlike at most shared hosts.

Prerequisites

What is DANE with DNSSEC?

DANE (DNS-based Authentication of Named Entities) stores a TLSA record in DNS that pins your mail server's certificate. A sending server checks before delivery whether the presented TLS certificate matches the TLSA record — resistant to downgrade and MITM attacks. For this to be trustworthy, the zone must be DNSSEC-signed; TLSA without DNSSEC is worthless.

DANE + DNSSEC secure the transport path. The sender identity is secured by SPF, DKIM, and DMARC.

Step-by-step guide

1. Check PTR and the basics

DANE stands and falls with clean basics: the PTR record of your server IP must match the MAILCOW_HOSTNAME — for IPv4 and IPv6. You set these at the IP provider (Hetzner, Netcup …).

dig -x 203.0.113.25 +short    # must return mail.example.com.

2. Enable DNSSEC for the zone

Enable DNSSEC at your DNS provider. At many providers this is a toggle in the DNS settings; you then store the DS record at the domain's registrar. Check the chain afterwards, e.g. with a DNSSEC analyzer. Don't publish a TLSA record without DNSSEC — it brings no protection and can cause delivery problems with some resolvers.

3. Generate the TLSA record from the MX certificate

The recommended and widely used TLSA type in practice is 3 1 1 (certificate usage 3 = direct certificate association, selector 1 = public key, matching type 1 = SHA-256). This is what a real record looks like (live example from a DANE operator):

_25._tcp.mail.beispiel.de.  IN TLSA  3 1 1 <sha256-hash-of-the-public-key>

You generate the hash directly from your mail server's certificate:

openssl x509 -in /path/to/cert.pem -noout -pubkey \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256 -binary \
  | xxd -p -c 256

The result is the 3 1 1 hash. Publish the TLSA record for each of your MX hostnames under _25._tcp.<mx-hostname>.

4. The critical point: certificate renewal

This is where most self-hosters fail. Mailcow renews the Let's Encrypt certificate automatically — and with 3 1 1 over the public key, the hash only stays stable if the key stays the same. By default, Let's Encrypt generates a new key pair on every renewal → the TLSA hash no longer matches → deliveries from DANE-checking senders (e.g. Microsoft 365, many German providers) fail.

Two clean solutions:

Automate this. A manually maintained TLSA record is a ticking delivery bomb.

5. Wait and check

DNS changes take time; DNSSEC signing sometimes longer.

Verify the result

Check your configuration with the free Kuveris scanner — it shows DNSSEC status, TLSA/DANE, PTR, and the interplay with SPF, DKIM, and DMARC.

Common mistakes

TLSA without DNSSEC. Without a signed zone, the TLSA record is worthless and potentially harmful. DNSSEC first.

Certificate renewal breaks DANE. The most common self-hoster mistake: after the Let's Encrypt renewal the 3 1 1 hash no longer matches. Automate the rollover or keep the key.

Only covered one MX host. Every MX hostname needs its own _25._tcp.<host> TLSA record.

PTR missing or wrong. Reverse DNS must match the MAILCOW_HOSTNAME — for IPv4 and IPv6.

Further reading

Related finding: What does this finding mean?