The BIND zone file format, explained with examples
BIND zone file examples explained line by line: $ORIGIN, $TTL, SOA, NS, A, MX, TXT and CNAME. Paste your own file into the browser-based explainer.
8 min readDNSMigrator team
On this page
What is a zone file?#
A zone file is a master-file representation of one DNS zone: the authoritative records at and below a zone apex, stopping at delegated child zones. RFC 1035 section 5 defines the core text format. BIND implements that format and adds a few conveniences.
Paste a DNS zone file into the explainer. It resolves relative names, translates TTLs into readable durations, and identifies each record's fields. Nothing is sent to a DNS provider.
A file that parses is not automatically a complete or portable zone. Provider aliases, proxy switches, redirects, routing policies, and comments may not survive a BIND round trip. If you are moving providers, read the per-provider export guide before treating a file as the source of truth.
Zone file format: one record at a time#
A normal resource-record line has this shape:
owner [ttl] [class] type rdataThe TTL and class are optional, and BIND accepts them in either order before the type. Whitespace separates fields; it is alignment, not syntax. For example:
www 300 IN A 192.0.2.10wwwis the owner. Under$ORIGIN example.com., it meanswww.example.com.300is the TTL in seconds: a resolver may cache this RRset for five minutes.INis the Internet class. Almost every public DNS zone uses it.Ais the record type.192.0.2.10is the type-specific RDATA, here one IPv4 address.
RFC 1035 section 5.1 calls the file line-oriented, but parentheses can continue one logical record across lines. A semicolon begins a comment outside a quoted string.
Directives: $ORIGIN, $TTL, $INCLUDE, and $GENERATE#
Directives affect how later lines are read; they are not DNS records.
$ORIGIN sets the base name#
$ORIGIN example.com.Any domain name without a final dot is relative to the current origin. api becomes api.example.com.. The standalone @ is shorthand for the current origin itself. BIND begins with an implicit origin supplied by the zone configuration, but an explicit absolute $ORIGIN makes a portable file easier to audit.
$TTL supplies the default cache time#
$TTL 1hRFC 2308 section 4 added $TTL to the master-file format. It applies to following records without an explicit TTL. BIND accepts duration suffixes such as 1h, 30m, and combinations such as 1h30m; plain numbers are seconds. The SOA's final field is now the negative-cache TTL, not the default for ordinary records.
$INCLUDE inserts another file#
$INCLUDE keys/dkim.zone example.com.$INCLUDE is part of RFC 1035. Its optional second argument sets the included file's origin; after the include ends, the parent file's origin is restored. It is filesystem behavior, so browser tools and managed-provider importers often reject it. Inline the included records before migration and preserve their effective origin.
$GENERATE is BIND-specific#
$GENERATE 1-3 host-$ 300 IN A 192.0.2.$BIND expands that into host-1, host-2, and host-3. The BIND 9 zone-file documentation defines ranges, steps, offsets, widths, and number bases. $GENERATE is not standardized master-file syntax, so expand it before sending a zone to software that does not explicitly support it.
Owner names and the trailing dot#
The final dot means “this name already reaches the DNS root.” Without it, the parser appends the current origin.
www IN CNAME app.example.net.
www.example.com. IN CNAME app.example.net.With origin example.com., those owners are equivalent. The target app.example.net. must also be absolute. If it were app.example.net without the dot, it would become app.example.net.example.com..
The same rule applies to domain names inside SOA, NS, CNAME, MX, PTR, and SRV RDATA. It does not apply to arbitrary text inside a quoted TXT record. A missing trailing dot is the most dangerous valid syntax error because the resulting name can parse cleanly and still be wrong.
A line beginning with whitespace can omit its owner and inherit the previous owner:
@ IN NS ns1.example.net.
IN NS ns2.example.net.That is valid, but explicit owners are safer during review. Reformatters may make leading whitespace hard to see.
SOA record fields, line by line#
Every zone needs one Start of Authority record at its apex. A common DNS zone file template is:
@ IN SOA ns1.example.net. hostmaster.example.com. (
2026092701 ; serial
7200 ; refresh: 2 hours
3600 ; retry: 1 hour
1209600 ; expire: 14 days
300 ; negative cache: 5 minutes
)RFC 1035 section 3.3.13 defines the seven RDATA fields:
- MNAME — the primary source server for the zone, here
ns1.example.net. - RNAME — the responsible mailbox encoded as a DNS name.
hostmaster.example.com.meanshostmaster@example.com. A literal dot in the mailbox local part must be escaped. - SERIAL — the zone version used by secondary servers.
- REFRESH — how soon a secondary checks for a newer serial.
- RETRY — how soon it retries a failed refresh.
- EXPIRE — how long a secondary can keep serving without refreshing.
- MINIMUM — under RFC 2308, the negative-cache TTL used with the SOA TTL to bound cached NXDOMAIN or NODATA answers.
YYYYMMDDnn is a readable serial convention, not a protocol requirement. The serial is an unsigned 32-bit value. It must advance after a change and be compared using RFC 1982 serial arithmetic, including wraparound; setting an apparently “larger” decimal value is not always a safe repair.
BIND zone file examples by record type#
NS, A, and AAAA#
@ 3600 IN NS ns1.example.net.
www 300 IN A 192.0.2.10
www 300 IN AAAA 2001:db8::10NS RDATA is an authoritative server name, not an IP address. A stores one IPv4 address; AAAA stores one IPv6 address. Multiple values are separate lines with the same owner, TTL, class, and type, forming one RRset.
Apex NS records describe this zone's authorities. NS records at a lower owner can delegate a child zone. During a provider import, do not delete every NS record just because the destination creates its own apex NS set.
CNAME#
docs 300 IN CNAME docs-host.example.net.A CNAME says its owner is an alias for the target. RFC 1034 section 3.6.2 says no other data should exist at a CNAME owner. That rules out an ordinary CNAME at the zone apex, where SOA and NS already exist, and rules out placing an A, MX, or TXT beside docs above.
Provider ALIAS, ANAME, or flattened-apex features are not ordinary CNAME records. Translate them using the apex alias migration rules, not by forcing an apex CNAME into the file.
MX#
@ 3600 IN MX 10 mail1.example.net.
@ 3600 IN MX 20 mail2.example.net.The first RDATA field is preference; lower values are tried first. The second is an absolute mail-exchanger hostname. RFC 2181 section 10.3 requires that target to have address records and not be a CNAME. A target of . is the RFC 7505 null MX, which explicitly says the domain accepts no mail.
TXT and long strings#
@ IN TXT "v=spf1 include:_spf.example.net -all"
selector._domainkey IN TXT (
"v=DKIM1; k=rsa; p=first-part"
"second-part"
)RFC 1035 defines TXT RDATA as one or more character-strings. Each wire-format string can carry at most 255 octets; a long logical value is split into adjacent quoted strings. Applications commonly concatenate them, but the string boundaries still exist in DNS. Parentheses continue the record; they do not create a new value.
Quotes protect spaces and semicolons. Escape an embedded quote or backslash. Do not add quote characters to the intended SPF, DKIM, or verification value: the quotes delimit zone-file syntax and are not part of the text returned to an application.
SRV#
_sip._tcp 3600 IN SRV 10 20 5060 sip.example.net.RFC 2782 orders SRV RDATA as priority, weight, port, and target. Lower priority is preferred; weight distributes choices among equal-priority records; port is numeric; target is an absolute hostname with address records and must not be an alias. A target of . means the service is unavailable.
CAA#
@ IN CAA 0 issue "letsencrypt.org"
@ IN CAA 0 iodef "mailto:security@example.com"RFC 8659 section 4.1 defines flags, tag, and value. 0 clears the critical flag; common tags are issue, issuewild, and iodef. The value is quoted when it contains punctuation or spaces. CAA controls certificate-authority authorization; it does not install or validate a certificate.
A complete annotated BIND zone file example#
$ORIGIN example.com.
$TTL 3600
@ IN SOA ns1.example.net. hostmaster.example.com. (
2026092701 ; serial
2h ; refresh
1h ; retry
2w ; expire
5m ; negative-cache TTL
)
; Authority for this zone
@ IN NS ns1.example.net.
@ IN NS ns2.example.net.
; Web and mail
@ 300 IN A 192.0.2.10
@ 300 IN AAAA 2001:db8::10
www 300 IN CNAME @
mail 300 IN A 192.0.2.25
@ IN MX 10 mail.example.com.
@ IN TXT "v=spf1 mx -all"
_dmarc IN TXT "v=DMARC1; p=reject"
; Service discovery and certificate policy
_sip._tcp IN SRV 10 20 5060 sip.example.net.
@ IN CAA 0 issue "letsencrypt.org"
; Intentional child-zone delegation
status IN NS ns1.status-host.example.
status IN NS ns2.status-host.example.This example uses documentation-only address ranges. The @ CNAME target is relative shorthand for example.com. and is valid because the CNAME owner is www, not the apex. status is a delegation and therefore marks a boundary: authoritative data below it belongs in the child zone, apart from required glue when the delegated server name is below that child.
Common zone file mistakes to review#
- Relative target by accident:
MX 10 mail.other.netsilently gains the current origin. - CNAME collision: the same owner has CNAME plus A, TXT, MX, or other ordinary data.
- Wrong apex representation: a provider ALIAS was rewritten as a literal apex CNAME.
- Missing or duplicate SOA: a zone needs exactly one SOA at its top.
- Serial moved backward: secondaries can keep the older copy even though the file loaded.
- TXT split incorrectly: a long value exceeds one character-string or gains unintended spaces or quotes.
- Unclosed parentheses or quotes: following lines become part of one logical record or fail to parse.
- Blind apex NS import: old provider nameservers overwrite or conflict with destination-managed authority records.
- Unexpanded include: the importer cannot access the local file named by
$INCLUDE.
Use the free zone file checker to catch parser errors and inspect its normalized, fully qualified output before import. Review the semantic mistakes above separately. If you operate BIND itself, also run its authoritative named-checkzone tool; a migration parser is not a replacement for server-specific integrity checks.
Where DNSMigrator's parser differs from BIND#
DNSMigrator's current parser accepts $ORIGIN, $TTL, comments, multiline parentheses, owner inheritance, and duration suffixes. It limits input to 2 MB. It does not implement BIND’s $GENERATE expansion.
It deliberately rejects $INCLUDE, $GENERATE, and other unsupported directives; paste included content and expand generated records first. It ignores generated signing records such as RRSIG, NSEC, NSEC3, CDS, and CDNSKEY because the destination signs its own zone. It recognizes a broad explicit type list, including HTTPS, SVCB, TLSA, SSHFP, NAPTR, LOC, URI, and others, but rejects unknown generic TYPE#### records rather than implementing every BIND extension.
The parser normalizes names and RRsets for migration. It is designed to expose errors and provider translation issues, not to reproduce BIND's full loading environment, filesystem, views, dynamic-update journal, or every semantic integrity check. The BIND zone-file migration documentation lists the supported source workflow.
Validate, translate, then verify DNS#
Parse a copy
Keep the original export unchanged and paste a copy into the zone file validator. Resolve every line-numbered error.
Inspect absolute names
Expand every owner and domain-valued target mentally or with the explainer. Pay special attention to trailing dots on off-zone CNAME, MX, NS, PTR, and SRV targets.
Translate provider behavior
Use the zone translator to identify aliases, unsupported types, TTL constraints, and metadata that a destination cannot represent.
Query the destination authority
After apply, use the dig migration commands or the DNS record diff to compare authoritative answers before changing nameservers.
What is a DNS zone file?
What is the BIND zone file format?
$TTL and BIND's nonstandard $GENERATE. A typical record is owner ttl IN type rdata, with TTL and class optionally inherited.Why does a trailing dot matter in a zone file?
$ORIGIN is appended, so mail.other.net inside the example.com. zone becomes mail.other.net.example.com..Can a TXT record be longer than 255 characters?
How do I check a zone file before importing it?
named-checkzone because it performs BIND-specific loading and integrity checks.