Server — DNS — DANE
TLS has a trust problem that is easy to overlook until you think about it directly. When your browser connects to a site over HTTPS, it trusts the certificate because it was signed by one of the roughly 150 root Certificate Authorities your OS ships with. Any one of those CAs can issue a certificate for any domain. Most of them will not do so fraudulently. Some have, historically, either through compromise or negligence. The CA system works because it is good enough, not because it is watertight.
For public-facing services, Certificate Transparency logs help catch misissuance after the fact. For internal services, they do not apply at all: internal hostnames do not appear in CT logs, and the certificates securing them are self-signed or issued by your own CA, which no public trust store knows about. The only thing preventing a rogue cert from silently working against an internal service is whether the client bothers to validate the chain at all.
DANE is the alternative model. Instead of delegating trust to external CAs, you publish the certificate fingerprint directly in DNS, protected by DNSSEC. A client that supports DANE can verify the certificate cryptographically using the same chain of trust that validates your zone. No external authority required.
What a TLSA record contains
DANE uses a record type called TLSA. It lives at a name that encodes the port and protocol of the service it covers, in the form _PORT._PROTOCOL.hostname. For HTTPS on port 443:
_443._tcp.february.home.arpa. IN TLSA 3 1 1 <hex fingerprint>
For SMTP on port 25:
_25._tcp.mail.home.arpa. IN TLSA 3 1 1 <hex fingerprint>
The three numbers after TLSA are the usage field, the selector field, and the matching type field. They are not obvious and they matter.
Usage (first number) defines what the record is certifying:
0— PKIX-TA: the record matches a CA cert; the full chain to a trusted root must also be valid.1— PKIX-EE: the record matches the end-entity cert; full chain validation still required.2— DANE-TA: the record matches a CA cert; no requirement for a publicly trusted root.3— DANE-EE: the record matches the end-entity cert; no CA chain validation required.
For internal services with self-signed or internal-CA-issued certificates, 3 is the right choice. It says: trust this specific certificate, regardless of who signed it or whether the chain leads anywhere publicly trusted. For public services with Let’s Encrypt certificates, 1 or 3 both work; 3 is simpler since it sidesteps chain validation entirely.
Selector (second number) defines what part of the certificate is hashed:
0— the entire certificate1— just the public key
Use 1. Hashing only the public key means the record remains valid if the certificate is reissued with the same key but a new expiry date, which is how Let’s Encrypt renewals typically work. If you hash the full certificate, every renewal requires a TLSA update.
Matching type (third number) defines the hash algorithm:
1— SHA-2562— SHA-512
Use 1. SHA-256 is standard and sufficient.
So for most cases in this network, the right prefix is 3 1 1: domain-issued certificate, public key only, SHA-256. That is the combination used throughout this article.
Generating the fingerprint
The fingerprint is the SHA-256 hash of the certificate’s public key in DER encoding. OpenSSL produces it in one command. Given a certificate file at /etc/ssl/certs/service.crt:
openssl x509 -in /etc/ssl/certs/service.crt -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256 | awk '{print $2}'
The output is the hex string that goes in the TLSA record. Do not add any separators; it should be a continuous lowercase hex string.
If you only have a private key and want to generate the fingerprint without the certificate (useful during provisioning):
openssl pkey -in /etc/ssl/private/service.key -pubout -outform DER | openssl dgst -sha256 | awk '{print $2}'
The result is the same as long as the public key embedded in the certificate matches the private key, which it always should.
Adding TLSA records to PowerDNS
Use pdnsutil add-record. The name is the underscore-prefixed port and protocol combination, not a standalone hostname:
# HTTPS on port 443 for february.home.arpa
sudo pdnsutil add-record home.arpa _443._tcp.february TLSA "3 1 1 <hex fingerprint>"
# Rectify the zone after adding records
sudo pdnsutil zone rectify home.arpa
Verify the record is present and signed:
dig TLSA _443._tcp.february.home.arpa @127.0.0.1 +dnssec
The response should include the TLSA record and its RRSIG, and the ad flag should be set confirming DNSSEC validation. Without ad, the record exists but is not authenticated, and DANE-capable clients will not trust it.
For each additional service, repeat with the appropriate port:
# PowerDNS Admin on port 9191
sudo pdnsutil add-record home.arpa _9191._tcp.february TLSA "3 1 1 <hex fingerprint>"
# SMTP on port 25 for a mail server
sudo pdnsutil add-record home.arpa _25._tcp.mail TLSA "3 1 1 <hex fingerprint>"
sudo pdnsutil zone rectify home.arpa
Internal services with self-signed certificates
For services running with self-signed certificates, the TLSA record with usage 3 effectively replaces the CA system entirely for that service. The fingerprint in the record is the only trust anchor; no chain validation occurs. This is correct and intentional for a DNSSEC-secured internal network.
The implication is that the TLSA record itself is what a client trusts. If the record is wrong, or the certificate changes without the record being updated, clients that enforce DANE will refuse to connect. This is the same behaviour as a certificate mismatch in the traditional CA model, just with a different trust anchor.
A practical workflow for issuing internal certificates that includes TLSA generation upfront:
# Generate key and self-signed certificate
openssl req -x509 -newkey ed25519 -keyout /etc/ssl/private/service.key -out /etc/ssl/certs/service.crt -days 825 -nodes -subj "/CN=service.home.arpa"
# Generate the TLSA fingerprint
FINGERPRINT=$(openssl x509 -in /etc/ssl/certs/service.crt -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256 | awk '{print $2}')
# Add to PowerDNS
sudo pdnsutil add-record home.arpa _443._tcp.service TLSA "3 1 1 $FINGERPRINT"
sudo pdnsutil zone rectify home.arpa
echo "TLSA record added: 3 1 1 $FINGERPRINT"
Run this once when provisioning a service and the TLSA record is in place before the service is ever accessed.
Public services with Let’s Encrypt certificates
For services with Let’s Encrypt certificates, the approach is the same but with a renewal consideration. Because the selector is 1 (public key only), the TLSA record remains valid as long as the private key does not change between renewals. Certbot and most ACME clients keep the private key stable across renewals by default, so a single TLSA record can cover multiple certificate lifetimes.
If you ever rotate the private key (which is good practice periodically, or when a key is compromised), the TLSA record must be updated before the new certificate is deployed. The safe procedure is:
- Generate the new key and get a new certificate.
- Add a TLSA record for the new key fingerprint, leaving the old one in place.
- Wait for DNS TTL to expire so both records are cached by clients.
- Deploy the new certificate.
- Remove the old TLSA record.
This rollover window prevents any client from encountering a certificate whose TLSA record has already been removed. It mirrors the same care required for SSHFP records when rotating SSH host keys, just with an additional step to account for caching.
For automated Let’s Encrypt renewal with TLSA updates, a deploy hook script is the right approach. The hook runs after a successful renewal, regenerates the fingerprint from the new certificate, updates the PowerDNS record via pdnsutil, and rectifies the zone. That is worth its own article when the reverse proxy setup is covered.
SMTP and DANE
DANE for email works on the same TLSA mechanism but at port 25 and with one important difference in semantics. Email clients and mail transfer agents that support DANE-SMTP use the TLSA record to verify the receiving server’s certificate before delivering mail. Unlike HTTPS in browsers, SMTP with DANE is well-supported by major mail servers including Postfix, Exim, and most modern MTAs.
For an internal mail server:
sudo pdnsutil add-record home.arpa _25._tcp.mail TLSA "3 1 1 <fingerprint>"
sudo pdnsutil zone rectify home.arpa
For a public-facing mail server where the zone is signed and the DS record is published at the registrar, this enables authenticated delivery from other DANE-capable MTAs without any CA involvement. That is one of the strongest practical arguments for deploying DANE: email with DANE and DNSSEC is significantly more resistant to downgrade attacks and certificate misissuance than email relying on the CA trust store alone.
Browser support caveat
It is worth being direct about this: mainstream browsers do not natively support DANE for HTTPS as of mid-2026. Firefox and Chrome do not validate TLSA records for web browsing. This is a deliberate policy choice by browser vendors who have invested heavily in the WebPKI and CA/Browser Forum infrastructure.
DANE for HTTPS in browsers requires either a plugin, a custom build, or an alternative browser. For internal networks where you control the client environment, this is manageable: you can deploy a browser extension or configure clients appropriately. For public-facing web services, DANE currently offers no browser-visible benefit.
Where DANE delivers unambiguous value today, regardless of browser support, is in server-to-server communication: SMTP, APIs, internal services accessed by non-browser clients, and tooling that explicitly supports DANE validation. Publish the records now; the value compounds as client support improves.
A note on record maintenance
TLSA records require ongoing maintenance in a way that A records and MX records do not. Every time a certificate changes in a way that affects the fingerprint, the TLSA record must be updated in step. A stale TLSA record that points to a no-longer-valid fingerprint will cause DANE-capable clients to refuse to connect.
Keep a record of which TLSA records exist and which certificates they correspond to. The borgmatic backup includes /etc/ssl and the PowerDNS database, so the state is recoverable, but the operational habit of updating DNS alongside certificate changes is worth building from the start.