Skip to content
InteractiveZone files

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

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.

BIND zone file explainer

Resolve owner names, inherited TTLs, record meanings, and individual RDATA fields in your browser.

BIND parsing runs locally; pasted zone data is not uploaded.

9 records explained for example.com..

9 records parsed for example.com.

Select any record to inspect its absolute owner name, effective TTL, purpose, and fields.

Record-by-record explanation

9 total
  1. SOAexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Defines the zone's primary server, serial, timers, and negative-cache TTL.

    Fields

    Primary nameserver
    ns1.example.net.
    Responsible mailbox
    hostmaster.example.com.
    Serial
    2026092701
    Refresh
    7200
    Retry
    3600
    Expire
    1209600
    Negative cache TTL
    300
  2. NSexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Delegates the zone or name to an authoritative nameserver.

    Fields

    Nameserver
    ns1.example.net.
  3. NSexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Delegates the zone or name to an authoritative nameserver.

    Fields

    Nameserver
    ns2.example.net.
  4. MXexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Selects a mail server, with lower preference values tried first.

    Fields

    Preference
    10
    Mail server
    mail.example.com.
  5. TXTexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Stores text used by verification, email policy, and other protocols.

    Fields

    Text
    v=spf1 -all
  6. CAAexample.com.1 hour · 3,600 seconds
    Absolute name
    example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Controls which certificate authorities may issue certificates.

    Fields

    Flags
    0
    Tag
    issue
    Value
    "letsencrypt.org"
  7. SRV_sip._tcp.example.com.1 hour · 3,600 seconds
    Absolute name
    _sip._tcp.example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Locates a service by priority, weight, port, and target.

    Fields

    Priority
    10
    Weight
    20
    Port
    5060
    Target
    sip.example.net.
  8. Amail.example.com.5 minutes · 300 seconds
    Absolute name
    mail.example.com.
    Effective TTL
    5 minutes (300 seconds)
    Type meaning
    Maps a name to an IPv4 address.

    Fields

    IP address
    192.0.2.25
  9. CNAMEwww.example.com.1 hour · 3,600 seconds
    Absolute name
    www.example.com.
    Effective TTL
    1 hour (3,600 seconds)
    Type meaning
    Aliases this name to another canonical name.

    Fields

    Target
    example.com.

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:

text
owner  [ttl]  [class]  type  rdata

The 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:

text
www    300    IN       A     192.0.2.10
  • www is the owner. Under $ORIGIN example.com., it means www.example.com.
  • 300 is the TTL in seconds: a resolver may cache this RRset for five minutes.
  • IN is the Internet class. Almost every public DNS zone uses it.
  • A is the record type.
  • 192.0.2.10 is 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#

text
$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#

text
$TTL 1h

RFC 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#

text
$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#

text
$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.

text
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:

text
@       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:

text
@ 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:

  1. MNAME — the primary source server for the zone, here ns1.example.net.
  2. RNAME — the responsible mailbox encoded as a DNS name. hostmaster.example.com. means hostmaster@example.com. A literal dot in the mailbox local part must be escaped.
  3. SERIAL — the zone version used by secondary servers.
  4. REFRESH — how soon a secondary checks for a newer serial.
  5. RETRY — how soon it retries a failed refresh.
  6. EXPIRE — how long a secondary can keep serving without refreshing.
  7. 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#

text
@       3600 IN NS    ns1.example.net.
www      300 IN A     192.0.2.10
www      300 IN AAAA  2001:db8::10

NS 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#

text
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#

text
@ 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#

text
@ 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#

text
_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#

text
@ 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#

example.com.zone
$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.net silently 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?
A DNS zone file is a text master file containing resource records for one authoritative DNS zone. It stores names, TTLs, classes, record types, and type-specific data, plus directives that control how relative text is interpreted.
What is the BIND zone file format?
It is the RFC 1035 master-file format as implemented by BIND, with later additions such as RFC 2308's $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?
A trailing dot makes a domain name absolute. Without it, the current $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?
A TXT RR can contain multiple character-strings, but each string is limited to 255 octets in wire format. Split a long logical value into adjacent quoted strings and verify that the consuming application concatenates them as expected.
How do I check a zone file before importing it?
Paste a copy into the zone file validator, inspect every relative name, then translate it for the destination provider. For a production BIND server, also run named-checkzone because it performs BIND-specific loading and integrity checks.