DNS Cheatsheet
Zone Files
Use this DNS reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
A complete commented zone
This is BIND master-file format, the same syntax named, NSD, Knot, and PowerDNS
all read, and what most providers export.
$TTL 3600 ; default TTL for records without one $ORIGIN example.com. ; @ and every unqualified name expand to this @ IN SOA ns1.example.com. hostmaster.example.com. ( 2026091501 ; serial, must increase on every change 7200 ; refresh, secondary re-checks after 2h 3600 ; retry, after a failed check, 1h 1209600 ; expire, secondary goes stale after 14d 300 ) ; minimum, the NEGATIVE caching TTL ; delegation: who is authoritative for this zone @ IN NS ns1.example.com. @ IN NS ns2.example.com. ; the nameservers' own addresses (glue, if they live in this zone) ns1 IN A 198.51.100.10 ns2 IN A 198.51.100.11 ; apex @ IN A 93.184.215.14 @ IN AAAA 2606:2800:21f:cb07::1 ; www as an alias, note the trailing dot on the target www IN CNAME example.com. ; mail @ IN MX 10 mx1.example.com. @ IN MX 20 mx2.example.com. mx1 IN A 198.51.100.20 mx2 IN A 198.51.100.21 ; mail policy @ IN TXT "v=spf1 mx include:_spf.google.com -all" _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com" sel1._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..." ; certificate authority authorization @ IN CAA 0 issue "letsencrypt.org" ; service discovery _sip._tcp IN SRV 10 60 5060 sip1.example.com. ; a subdomain delegated to someone else's nameservers dev IN NS ns1.dev-provider.net. dev IN NS ns2.dev-provider.net. ; short TTL on a record about to move api 300 IN A 198.51.100.30
Record syntax
Every line is the same five fields, and any of the first three may be omitted.
<name> [ttl] [class] <type> <rdata> www 3600 IN A 93.184.215.14
| Field | Omitted means | Notes |
|---|---|---|
name | Reuse the previous record's name | Leading whitespace is what signals this |
ttl | Use $TTL | Seconds, or 1h / 1d / 1w suffixes |
class | IN | CH and HS exist and you will never use them |
type | Required | Uppercase by convention, case insensitive |
rdata | Required | Format depends entirely on the type |
A name without a trailing dot gets $ORIGIN appended. This single rule
causes more zone-file bugs than everything else combined.
$ORIGIN example.com. www IN CNAME example.com ; WRONG -> example.com.example.com. www IN CNAME example.com. ; right, fully qualified www IN CNAME @ ; also right, @ is the origin
Directives
| Directive | Effect |
|---|---|
$TTL 3600 | Default TTL for the rest of the file. Required by RFC 2308 |
$ORIGIN sub.example.com. | Change what unqualified names expand to |
$INCLUDE /path/file | Splice in another file |
$GENERATE 1-254 host$ IN A 10.0.0.$ | Bulk generate a range of records |
$ORIGIN example.com. www IN A 93.184.215.14 ; www.example.com. $ORIGIN dev.example.com. www IN A 198.51.100.40 ; www.dev.example.com. $GENERATE 1-10 pool$ IN A 198.51.100.$ ; produces pool1 -> 198.51.100.1 through pool10 -> 198.51.100.10
Comments run from ; to end of line. Parentheses let a single record span
multiple lines, which is why the SOA is always written that way.
The SOA fields, one by one
| Field | Typical | What consumes it |
|---|---|---|
| MNAME | ns1.example.com. | The primary. Where dynamic updates and notify go |
| RNAME | hostmaster.example.com. | Contact email, first dot is the @ |
| SERIAL | 2026091501 | Secondaries compare it and transfer only if it grew |
| REFRESH | 7200 | How often a secondary polls the primary |
| RETRY | 3600 | How soon to retry after a failed poll |
| EXPIRE | 1209600 | Secondary stops answering after this long without contact |
| MINIMUM | 300 | The negative-caching TTL, nothing else |
MINIMUM has not meant "default TTL" since RFC 2308. It is how long resolvers cache an NXDOMAIN or NODATA answer for names in this zone. Set it low, 300 or below, or a typo fixed in seconds stays broken for its duration.
Serial conventions, pick one and never go backwards:
| Style | Example | Note |
|---|---|---|
| Date plus counter | 2026091501 | YYYYMMDDnn, readable, caps at 100 edits per day |
| Unix timestamp | 1789459200 | Never collides, unreadable |
| Plain counter | 47 | Fine if one tool owns the file |
Serial arithmetic is modulo 2³², so a serial that decreases stops all zone transfers until you push it past the old value or reload the secondaries.
Validating and loading
# syntax check without loading, BIND named-checkzone example.com /var/named/example.com.zone # check the server config too named-checkconf # reload one zone rndc reload example.com rndc notify example.com # nudge the secondaries # pull the live zone into a file, if AXFR is allowed to you dig @ns1.example.com example.com AXFR > example.com.zone
$ named-checkzone example.com db.example.com
zone example.com/IN: loaded serial 2026091501
OKnamed-checkzone catches missing trailing dots that produce a valid but wrong
name only when it makes the record structurally invalid, so it is a syntax check,
not a correctness check. Diff the dig output against what you meant.
Gotchas
- A missing trailing dot silently doubles the origin. dig shows
www.example.com.example.com. and everything looks fine in the file.
- A leading space means "same name as the line above". Indenting a record
for readability changes what it applies to.
- Forgetting to bump the serial means the primary is correct and every
secondary keeps serving the old data. Nothing errors.
- $TTL must be the first line or BIND warns and older versions refuse to
load the zone.
- A zone must have exactly one SOA and at least one NS at the apex. Two SOA
records is a load failure.
- Delegating a subdomain means NS records only. Adding an A record for dev
beside dev IN NS makes the zone ambiguous, and the delegation wins.
- Provider web UIs vary on whether you type www or www.example.com in the
name field. Enter one record and read it back with dig before doing fifty.