Type something to search...
What is a DNS zone and a zone file?

What is a DNS zone and a zone file?

A DNS zone is a portion of the DNS namespace that's managed as a single unit by one administrator and served by the same set of authoritative name servers. For most people, the zone for example.com contains every record for example.com and its subdomains, such as www, mail and api. A zone file is a plain text file that defines that zone: it lists every record in a standard format first set out in RFC 1035, starting with an SOA record and the zone's NS records. Authoritative DNS servers such as BIND, NSD and Knot DNS load zone files to know what to answer, and most managed DNS providers let you import and export zones in the same format.

Even if you only ever edit DNS in a web dashboard, understanding the zone file format pays off. It's the common language of DNS: providers use it for imports and exports, documentation uses it for examples, and dig prints records in it. In this article you'll learn what a zone contains, how a zone file is laid out line by line, what the directives and shorthand mean, the mistakes that catch people out, and how to check a zone file before you load it.

What a DNS Zone Is

DNS is a tree of names. A zone is a connected section of that tree that someone manages as one unit.

  • The top of a zone is called the zone apex, or sometimes the root of the zone. For the example.com zone, the apex is example.com itself. In zone files and dashboards the apex is often written as @.
  • A zone contains the apex and every name beneath it, except any part that has been delegated to a separate zone with its own NS records.
  • Each zone has exactly one SOA (Start of Authority) record at its apex, and at least one NS record listing its authoritative servers.

For example, if example.com delegates dev.example.com to a different set of name servers, there are two zones: example.com (containing www.example.com, mail.example.com and so on) and dev.example.com (containing app.dev.example.com, db.dev.example.com and so on). The point where one zone ends and another begins is called a zone cut.

Most small and medium websites have just one zone per domain, so in everyday conversation "my domain's DNS" and "my zone" mean the same thing.

What a Zone File Looks Like

Here's a complete, realistic zone file for example.com. The rest of this article explains each part.

; Zone file for example.com
$ORIGIN example.com.
$TTL 3600

; Start of Authority
@       IN  SOA  ns1.example.com. hostmaster.example.com. (
                 2026101101  ; serial (YYYYMMDDnn)
                 7200        ; refresh
                 3600        ; retry
                 1209600     ; expire
                 3600 )      ; negative caching TTL

; Name servers for the zone
        IN  NS   ns1.example.com.
        IN  NS   ns2.example.net.

; Glue for the in-zone name server
ns1     IN  A    192.0.2.53
        IN  AAAA 2001:db8::53

; Website
@       IN  A     203.0.113.10
@       IN  AAAA  2001:db8:10::1
www     IN  CNAME example.com.

; Email
@       IN  MX   10 mail
@       IN  MX   20 mail-backup.example.net.
mail    IN  A    203.0.113.20
@       IN  TXT  "v=spf1 mx -all"

; Services with a shorter TTL
api 300 IN  A    203.0.113.30

; Delegated subzone
dev     IN  NS   ns1.dev.example.com.
ns1.dev IN  A    198.51.100.10

It looks dense at first, but it follows a small set of rules.

The Anatomy of a Resource Record

Each record line has up to five fields:

<owner name>  <TTL>  <class>  <type>  <data>
FieldExampleMeaning
Owner namewww or www.example.com.The name the record belongs to
TTL300How many seconds resolvers may cache it (optional if $TTL is set)
ClassINThe protocol family. Almost always IN for internet
TypeA, MX, TXTWhat kind of record it is
Data (RDATA)203.0.113.10The value, whose format depends on the type

The TTL and class can appear in either order, and both can be left out, in which case the defaults apply. So these three lines mean the same thing in the zone above:

www.example.com.  3600  IN  CNAME  example.com.
www               3600  IN  CNAME  example.com.
www                         CNAME  example.com.

Directives

Lines starting with $ are directives. They aren't records; they control how the rest of the file is read.

$ORIGIN

$ORIGIN sets the domain that's appended to any name that doesn't end in a dot. With $ORIGIN example.com., the name mail means mail.example.com., and @ means example.com. itself.

If you don't include $ORIGIN, most servers use the zone name from their configuration as the origin. Including it explicitly makes the file self-describing.

You can change the origin part-way through a file, which is handy for groups of records under a subdomain:

$ORIGIN eu.example.com.
web     IN  A  203.0.113.40   ; web.eu.example.com.
db      IN  A  203.0.113.41   ; db.eu.example.com.
$ORIGIN example.com.

$TTL

$TTL sets the default TTL for records that don't specify their own. RFC 2308 introduced it, and every modern server expects it. In the example, every record gets 3,600 seconds (one hour) except api, which overrides it with 300 seconds.

Many servers also accept unit suffixes, such as $TTL 1h or 1d, but plain seconds are the most portable.

$INCLUDE

$INCLUDE pulls another file into the zone at that point:

$INCLUDE /etc/bind/zones/example.com.dkim

It's useful for keeping generated records, such as DKIM keys, separate from hand-edited ones. Some managed providers don't support it on import, so expand includes before uploading a zone.

$GENERATE (BIND)

BIND, and some other servers that copy its syntax, support $GENERATE for creating a series of similar records:

$GENERATE 1-4 host$ A 192.0.2.$

That single line produces host1 to host4 pointing at 192.0.2.1 to 192.0.2.4. It isn't part of the RFC standard, so don't rely on it if your zone needs to move between different software.

Shorthand and Formatting Rules

The Trailing Dot

This is the single most important rule in zone files. A name ending in a dot is fully qualified and used exactly as written. A name without a trailing dot is relative, and the origin is appended to it.

www     IN  CNAME  example.net.   ; points to example.net
www     IN  CNAME  example.net    ; points to example.net.example.com. (wrong!)

The second line is a classic mistake. Most DNS dashboards add the dot for you, but in a raw zone file you have to get it right yourself.

@ for the Apex

@ is shorthand for the current origin. @ IN A 203.0.113.10 sets the address of example.com itself.

Blank Owner Names

If a line starts with whitespace, the record belongs to the same owner as the previous record. In the example, the two NS lines inherit the apex from the SOA line above them, and the AAAA record under ns1 also belongs to ns1. This is convenient but easy to misread, so indent consistently.

Comments and Parentheses

Everything after a semicolon (;) on a line is a comment. Parentheses let one record span several lines, which is why the SOA record above is readable. Quoted strings in TXT records can contain spaces and semicolons without being treated as comments.

Long TXT Records

A single string inside a TXT record can be at most 255 characters. Longer values, such as 2048-bit DKIM keys, are split into several quoted strings that are joined together when read:

sel1._domainkey  IN  TXT  ( "v=DKIM1; k=rsa; "
                            "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." )

The Records Every Zone Needs

SOA

Every zone has exactly one SOA record at its apex. It names the primary name server, gives a contact address (with the @ replaced by a dot, so hostmaster.example.com. means hostmaster@example.com), and sets several timers used by secondary servers and negative caching.

The most important field for day-to-day work is the serial number. Secondary servers only pick up changes when the serial increases, so you must raise it every time you edit the zone by hand. The YYYYMMDDnn convention (date plus a two-digit change counter, like 2026101101) is popular because it's readable and always increases.

NS

The apex NS records list the authoritative servers for the zone. They should match the name servers registered at your registrar. If a name server's name sits inside the zone, such as ns1.example.com, you also need an address record for it, and the same address must be registered at the registrar as glue.

Validating a Zone File

Always check a zone file before loading it. One stray character can cause a server to reject the whole zone, or worse, load it with a wrong record.

With BIND's named-checkzone

named-checkzone example.com /etc/bind/zones/example.com.zone
zone example.com/IN: loaded serial 2026101101
OK

If there's a problem, it tells you the line number:

/etc/bind/zones/example.com.zone:24: unknown RR type 'CNMAE'
zone example.com/IN: loading from master file /etc/bind/zones/example.com.zone failed: unknown class/type
zone example.com/IN: not loaded due to errors.

named-checkzone is in the bind9-utils package on Debian and Ubuntu, and in bind-utils on RHEL-based systems.

With NSD or Knot DNS

nsd-checkzone example.com /etc/nsd/zones/example.com.zone
kzonecheck -o example.com /var/lib/knot/example.com.zone

With Python

If you don't have a DNS server installed, the dnspython library can parse a zone and print every record in its fully expanded form, which is a good way to see how relative names and defaults were interpreted:

import sys

import dns.zone

zone = dns.zone.from_file(sys.argv[1], origin=sys.argv[2], relativize=False)
for name, node in sorted(zone.nodes.items()):
    for rdataset in node.rdatasets:
        print(rdataset.to_text(name))
python3 -m pip install dnspython
python3 checkzone.py example.com.zone example.com
example.com. 3600 IN SOA ns1.example.com. hostmaster.example.com. 2026101101 7200 3600 1209600 3600
example.com. 3600 IN NS ns1.example.com.
example.com. 3600 IN NS ns2.example.net.
example.com. 3600 IN A 203.0.113.10
example.com. 3600 IN AAAA 2001:db8:10::1
example.com. 3600 IN MX 10 mail.example.com.
example.com. 3600 IN MX 20 mail-backup.example.net.
example.com. 3600 IN TXT "v=spf1 mx -all"
api.example.com. 300 IN A 203.0.113.30
dev.example.com. 3600 IN NS ns1.dev.example.com.
ns1.dev.example.com. 3600 IN A 198.51.100.10
mail.example.com. 3600 IN A 203.0.113.20
ns1.example.com. 3600 IN A 192.0.2.53
ns1.example.com. 3600 IN AAAA 2001:db8::53
www.example.com. 3600 IN CNAME example.com.

Notice how 10 mail became 10 mail.example.com., and how api kept its 300-second TTL while everything else inherited 3,600 seconds.

Loading a Zone in BIND

Once a zone file validates, you tell the server about it. In BIND, add a zone block to named.conf (or named.conf.local on Debian and Ubuntu):

zone "example.com" {
    type primary;
    file "/etc/bind/zones/example.com.zone";
    allow-transfer { 198.51.100.53; };
    notify yes;
};

Check the configuration and reload just that zone:

sudo named-checkconf
sudo rndc reload example.com
zone reload queued

type primary is the modern spelling; older configurations use type master, which BIND still accepts.

Zone Files and Managed DNS Providers

Managed providers store your records in their own databases rather than as files, but nearly all of them speak the zone file format:

  • Import: Most dashboards let you upload or paste a BIND-style zone file to create many records at once, which is the easiest way to move providers.
  • Export: You can usually download your zone as a file for backup or migration.
  • Differences: Providers handle the SOA and apex NS records themselves, so they often ignore or rewrite those lines on import. Provider-specific features, such as proxied records, ALIAS records or traffic policies, may not survive an export.

You can also see much of a zone from the outside by asking for records directly. dig prints answers in zone file format, so its output can be pasted straight into a zone file:

dig example.com MX +noall +answer
example.com.            3600    IN      MX      10 mail.example.com.
example.com.            3600    IN      MX      20 mail-backup.example.net.

Common Zone File Mistakes

  1. Missing trailing dot: example.net instead of example.net. silently creates the wrong target.
  2. Forgetting to raise the serial: Secondaries keep serving the old version.
  3. A CNAME at the apex or alongside other records: A name with a CNAME can't have any other records, and the apex always has SOA and NS records, so @ IN CNAME is invalid.
  4. Accidental owner inheritance: A line that starts with a space attaches the record to the previous name, not the apex.
  5. Unquoted TXT values with spaces or semicolons: The semicolon starts a comment and truncates the value.
  6. Missing glue for in-zone name servers: The zone lists ns1.example.com but has no address for it.
  7. Mixing tabs and spaces carelessly: It's valid, but it makes inherited owner names hard to spot.

FAQ: DNS Zones and Zone Files

Often, but not always. A domain is a name in the DNS tree and everything under it. A zone is the part of that tree managed as one unit. If a domain delegates a subdomain to other name servers, the domain spans more than one zone.

On self-hosted servers they're plain text files, commonly under /etc/bind, /var/lib/bind, /etc/nsd or /var/lib/knot depending on the software. Managed DNS providers store records in their own databases but can import and export zone files.

It's shorthand for the current origin, which is usually the zone apex. A record written as @ IN A 203.0.113.10 applies to example.com itself in the example.com zone.

A trailing dot marks a name as fully qualified. Without it, the origin is appended, so example.net in the example.com zone becomes example.net.example.com. Always end external names with a dot.

Yes, if you edit a zone file by hand and have secondary servers. Secondaries compare serials and only transfer the zone when the number increases. Many managed providers and DNS servers with dynamic updates manage the serial automatically.

Yes. Edit the file, raise the serial, validate it with a checker such as named-checkzone, then tell the server to reload the zone, for example with rndc reload example.com. Servers that accept dynamic updates may need to be frozen first so they don't overwrite your edits.

The apex is the top name of a zone, such as example.com for the example.com zone. It holds the SOA and NS records, which is why a CNAME can't be placed there.


Conclusion

A DNS zone is the slice of the namespace you're responsible for, and a zone file is its definition in plain text. Once you know the five fields of a record, the $ORIGIN and $TTL directives, the role of @, and the all-important trailing dot, any zone file becomes easy to read, whether it's on your own server, in a provider's export or in an example online.

Treat zone files like code: keep them in version control, raise the serial on every change, and run them through named-checkzone, nsd-checkzone or a quick dnspython script before they go live. A minute of validation is far cheaper than a broken MX record or a missing dot discovered by your users.

Tags :
Share :

Related Posts

What is the difference between an A record and a CNAME record?

What is the difference between an A record and a CNAME record?

The difference between an A record and a CNAME record is what they point to. An A record points a hostname directly at an IPv4 address, such

Dive Deeper
What are the best DNS providers for websites?

What are the best DNS providers for websites?

The best DNS providers for most websites are Cloudflare for a fast, free, easy starting point, Amazon Route 53 if you already run on AWS, **G

Dive Deeper
What are the best public DNS resolvers?

What are the best public DNS resolvers?

The best public DNS resolvers for most people are Cloudflare (1.1.1.1) for speed and privacy, Google Public DNS (8.8.8.8) for reliability and

Dive Deeper