Self-Hosted DNS: NSD, DNSSEC and DANE

Gavin Phratsachack · operator, AS218248 · Minnesota, USA - hosted in Düsseldorf, Germany

I run my own authoritative DNS for gnpk.zip on the same VPS as the rest of AS218248. NSD serves the zone, Hurricane Electric runs the secondary, and the zone is signed with DNSSEC, with DANE and MTA-STS on top. It is a small zone — a handful of records — but every record is there on purpose, and the whole setup is verifiable from the outside.

Why this exists

I run DNS to learn about DNS. Reading the RFCs is one thing; operating a signed zone — generating keys, re-signing, watching validators reject a bad record — is how the details actually stick. It is also, almost, a role model for what a secure website and DNS server looks like: DNSSEC, DANE, strict transport security, and a clean bill from the public testers, all running on one small box. If you are setting up your own zone, this page is a working example you can look at.

The setup

AuthoritativeNSD on the VPS (gnpk-as)
Secondaryns1.he.net (Hurricane Electric), via AXFR
Public NSns1.gnpk.zip + ns1.he.net
Fallbackns2 Namecheap glue left as a revert option

NSD serves the unsigned zone from /etc/nsd/gnpk.zip.zone and the signed zone from /etc/nsd/gnpk.zip.zone.signed. HE pulls the signed zone by AXFR. The zone is small and hand-edited — every record in it was added deliberately.

DNSSEC

DNSSEC went live on Nov 8, 2026, at about 23:19 CST. DNSViz shows the zone all Secure.

KSK38585
ZSK35382
AlgorithmECDSAP256SHA256 (alg 13)
NSEC3Yes, salt 9b2436ee12ed48bb
DS recordgnpk.zip. 3600 IN DS 38585 13 2 e3d34c2afa05b02a97ff798f1cc1bfe9f6f0534c7d273bd4a68d27eb0ce8ec8c
RRSIGs expireDec 7, 2026

Re-signing is scripted: /usr/local/bin/resign.sh bumps the SOA serial in the unsigned zone, signs it, and restarts NSD. A root cron runs it every Sunday at 03:00 UTC. Every unsigned zone edit should be followed by a re-sign; HTML-only changes do not need one. Do not generate a new KSK — the DS record in the parent is tied to the current one.

DANE and TLSA

Three TLSA records pin the site and mail certificates to the DNS:

_443._tcp.gnpk.zip3 1 1 (web)
_25._tcp.mail.gnpk.zip3 1 1 (mail)
_25._tcp.mail.gnpk.zip2 1 1 (mail)

The Postfix certificate is a Let’s Encrypt ECDSA (secp384r1) certificate for mail.gnpk.zip. A certbot renewal hook (/etc/letsencrypt/renewal-hooks/deploy/update-tlsa.sh) recomputes the TLSA records from the renewed certificate, appends them to the zone only if not already present, re-signs, and reloads Postfix and nginx — so a renewal cannot silently break DANE.

MTA-STS and TLS-RPT

Mail transport security is published too: an _mta-sts TXT record (v=STSv1; id=20261113), a _smtp._tls TXT record (v=TLSRPTv1; rua=mailto:me@gnpk.zip), and a policy at mta-sts.gnpk.zip in enforce mode with max_age 604800 and mx: mail.gnpk.zip. The flip happened Nov 13, 2026, ahead of the planned Nov 16–17 date, after two clean TLS-RPT reports from Google (Nov 9: 5 sessions, 0 failures; Nov 10: 2 sessions, 0 failures).

HTTPS record and DNS over TLS

Two more DNS standards went live Nov 13, 2026:

DNS over HTTPS (DoH) and DNS over QUIC (DoQ) do not apply here: both are stub-to-recursive protocols, and NSD is authoritative-only. DoT is the encrypted transport for an authoritative server, and it is the one in use.

ZONEMD: tried and removed

ZONEMD (TYPE63, RFC 8976) was added Nov 13, 2026, and removed the same day. The record itself worked — the primary served it, DNSSEC-validated — but Hurricane Electric’s secondary could not handle it: ns1.he.net returned SERVFAIL for every query (SOA, A, DNSKEY) whenever the zone contained a ZONEMD record, and served normally whenever it did not. An A/B test across three re-signs proved it (serial 2026110821 without ZONEMD: NOERROR; serial 2026110822 with ZONEMD: SERVFAIL on everything; serial 2026110823 without ZONEMD: NOERROR again). HE’s NSD cannot serve a zone containing TYPE63. So ZONEMD stays off while HE is the secondary — the re-sign script no longer passes the -z flag to ldns-signzone. If the secondary ever changes, it is worth retrying.

The same incident showed the value of a secondary: while HE was SERVFAILing, the primary kept answering, and the fix was a fresh zone pull from HE’s panel (Validate!) followed by the ZONEMD removal.

Extras in the zone

How it scores

internet.nl website100% — Hall of Fame
internet.nl email100% — Hall of Fame
Mozilla ObservatoryA+, 155/100
HE IPv6 CertificationGuru, earned Nov 2, 2026