Every time you type a website address like example.com into your browser, something has to translate that human-readable name into a numeric IP address the network can actually route to. That translation service is provided by DNS (Domain Name System), and the primary name server (also called the master server) is the authoritative source of truth for a domain’s DNS records.
In this article, we walk through what a primary name server is, how DNS authority works, and how to configure your own primary name server on Linux using BIND9, the most widely used open-source DNS server software, complete with practical examples and troubleshooting.
Table of Contents
- What Is DNS and Why Do We Need Name Servers?
- Primary vs. Secondary Name Servers
- What Is BIND9?
- Prerequisites
- Step-by-Step: Installing BIND9
- Understanding BIND9 Configuration Files
- Step-by-Step: Configuring a Primary Zone
- Creating the Zone File
- Starting and Testing the Name Server
- Configuring Clients to Use Your Name Server
- Real-World Example
- Cisco Router DNS Configuration
- Python Example: Querying Your New Name Server
- Comparison Table: Primary vs. Secondary vs. Caching Name Servers
- Best Practices
- Troubleshooting Common Issues
- Conclusion
1. What Is DNS and Why Do We Need Name Servers?
DNS (Domain Name System) is often described as the “phone book of the internet.” It maps human-friendly domain names (like example.com) to machine-friendly IP addresses (like 203.0.113.10). Without DNS, you would need to memorize numeric IP addresses for every website you wanted to visit.
A name server is a server that stores DNS records and answers queries about a domain. When your browser needs to find example.com, it sends a query to a name server, which responds with the correct IP address.
2. Primary vs. Secondary Name Servers
DNS infrastructure for a domain typically involves at least two types of authoritative name servers:
- Primary (Master) Name Server: This is the original, authoritative source of a domain’s DNS records. Zone files are created and edited directly on this server. Also historically called the “master.”
- Secondary (Slave) Name Server: This server holds a read-only copy of the zone data, automatically synchronized (via a process called a zone transfer) from the primary server. It provides redundancy — if the primary goes down, the secondary can still answer queries.
graph LR
P[Primary Name Server - holds original zone file] -->|Zone Transfer AXFR/IXFR| S[Secondary Name Server - read-only copy]
C[DNS Client / Resolver] --> P
C --> SThis article focuses specifically on setting up the primary name server, since that is where zone data is authored and managed.
3. What Is BIND9?
BIND (Berkeley Internet Name Domain), version 9, is the most widely deployed DNS server software in the world, used by ISPs, universities, and enterprises to run authoritative and caching name servers. It is open-source, highly configurable, and the de facto standard for Linux-based DNS infrastructure.
4. Prerequisites
- A Linux server (Ubuntu, Debian, CentOS, or RHEL) with a static IP address.
- Root or
sudoaccess. - A registered domain name (or a private/internal domain for lab/testing purposes).
- Basic understanding of DNS record types (A, CNAME, MX, NS, SOA — covered in more depth in the next article on zone files).
5. Step-by-Step: Installing BIND9
On Ubuntu/Debian:
sudo apt update
sudo apt install bind9 bind9utils bind9-doc -yOn CentOS/RHEL/Fedora:
sudo dnf install bind bind-utils -yEnable and start the service:
sudo systemctl enable named # CentOS/RHEL service name
sudo systemctl enable bind9 # Ubuntu/Debian service name
sudo systemctl start bind9
sudo systemctl status bind96. Understanding BIND9 Configuration Files
BIND9’s configuration is split across a few key files, typically located in /etc/bind/ (Ubuntu/Debian) or /etc/named.conf and /var/named/ (CentOS/RHEL):
| File | Purpose |
|---|---|
named.conf | Main configuration file, defines global options and includes other files |
named.conf.local | Where you define your custom zones (Ubuntu/Debian convention) |
named.conf.options | Global server options (forwarders, recursion settings) |
Zone files (e.g., db.example.com) | Contain the actual DNS records for a specific domain |
7. Step-by-Step: Configuring a Primary Zone
Step 1: Define the zone in named.conf.local (Ubuntu/Debian) or the zone section of named.conf (RHEL/CentOS).
sudo nano /etc/bind/named.conf.localAdd the following:
zone "example.com" {
type master;
file "/etc/bind/zones/db.example.com";
allow-transfer { 203.0.113.20; }; // IP of the secondary name server
};Here, type master; explicitly declares this server as the primary name server for the example.com zone. The allow-transfer directive restricts zone transfers to only trusted secondary servers, an important security measure.
Step 2: Create the zones directory (if it doesn’t already exist).
sudo mkdir -p /etc/bind/zones8. Creating the Zone File
Copy the default local zone template as a starting point:
sudo cp /etc/bind/db.local /etc/bind/zones/db.example.comEdit the zone file:
sudo nano /etc/bind/zones/db.example.comExample zone file content:
$TTL 604800
@ IN SOA ns1.example.com. admin.example.com. (
2026072401 ; Serial (increment on every change)
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; Name servers
@ IN NS ns1.example.com.
; A records
ns1 IN A 203.0.113.10
www IN A 203.0.113.10
mail IN A 203.0.113.11
; MX record
@ IN MX 10 mail.example.com.
We will explore each of these record types (SOA, NS, A, MX) in much greater depth in the next article on zone file formats and resource records.
Check the zone file for syntax errors:
sudo named-checkzone example.com /etc/bind/zones/db.example.comCheck the overall BIND configuration for errors:
sudo named-checkconf9. Starting and Testing the Name Server
Restart BIND9 to apply the new zone:
sudo systemctl restart bind9Query your new name server locally using dig:
dig @localhost example.comQuery a specific record type:
dig @localhost www.example.com ASample output (truncated):
;; ANSWER SECTION:
www.example.com. 604800 IN A 203.0.113.10If you see the correct IP address returned, your primary name server is successfully answering authoritative queries for your zone.
10. Configuring Clients to Use Your Name Server
To make devices on your network actually use your new primary name server for DNS resolution, point their DNS settings to your server’s IP address.
On a Linux client, edit /etc/resolv.conf (or use systemd-resolved/NetworkManager depending on your distro):
nameserver 203.0.113.10Or configure it via nmcli (NetworkManager):
sudo nmcli con mod "Wired connection 1" ipv4.dns "203.0.113.10"
sudo nmcli con up "Wired connection 1"11. Real-World Example
A small hosting company runs its own internal domain internal.company.local for managing hundreds of internal servers by hostname instead of by IP address. They configure one Linux server as the primary name server, holding the authoritative zone file, and a second Linux server elsewhere in the data center as a secondary name server for redundancy. Every internal server and workstation is configured to use these two name servers, allowing engineers to reach db-primary.internal.company.local instead of memorizing 10.20.30.5.
graph TD
Admin[Admin edits zone file] --> Primary[Primary Name Server: ns1.internal.company.local]
Primary -->|Zone Transfer| Secondary[Secondary Name Server: ns2.internal.company.local]
Client1[Server A] --> Primary
Client2[Server B] --> Secondary12. Cisco Router DNS Configuration
Network administrators often configure Cisco routers to use a specific internal DNS server (like the primary name server just configured) for their own name resolution needs, and sometimes to act as a simple DNS relay for connected clients.
Configure a Cisco router to use your new primary name server:
Router(config)# ip domain-lookup
Router(config)# ip name-server 203.0.113.10
Router(config)# ip domain-name example.comVerify DNS resolution from the router itself:
Router# ping www.example.comIf configured correctly, the router will resolve www.example.com using your primary name server before sending the ICMP ping.
13. Python Example: Querying Your New Name Server
The following Python script uses the dnspython library to send a DNS query directly to your newly configured primary name server, bypassing your system’s default resolver — useful for testing and automation.
import dns.resolver
def query_custom_dns(domain, record_type, dns_server_ip):
resolver = dns.resolver.Resolver()
resolver.nameservers = [dns_server_ip]
try:
answers = resolver.resolve(domain, record_type)
for answer in answers:
print(f"{domain} ({record_type}) -> {answer}")
except dns.resolver.NXDOMAIN:
print(f"{domain} does not exist on this name server.")
except dns.exception.Timeout:
print(f"Query to {dns_server_ip} timed out.")
# Query the primary name server directly
query_custom_dns("www.example.com", "A", "203.0.113.10")
query_custom_dns("example.com", "MX", "203.0.113.10")Sample Output:
www.example.com (A) -> 203.0.113.10
example.com (MX) -> 10 mail.example.com.Install the required library first:
pip install dnspython --break-system-packages14. Comparison Table: Primary vs. Secondary vs. Caching Name Servers
| Server Type | Zone Data Source | Purpose | Editable? |
|---|---|---|---|
| Primary (Master) | Original zone file, hand-edited | Authoritative source of truth | Yes, directly editable |
| Secondary (Slave) | Synced via zone transfer from primary | Redundancy, load distribution | No, read-only copy |
| Caching/Resolver | No authoritative zones; caches answers from other servers | Speeds up repeated queries for clients | N/A (not authoritative) |
15. Best Practices
- Always increment the Serial number in the SOA record every time you edit a zone file — secondary servers use this to detect changes.
- Restrict zone transfers (
allow-transfer) to only known, trusted secondary server IPs to prevent zone data leakage (a security practice called preventing “zone transfer attacks”). - Run at least one secondary name server for redundancy — never rely on a single primary name server in production.
- Use
named-checkzoneandnamed-checkconfbefore every restart to catch syntax errors proactively. - Set reasonable TTL values — shorter TTLs (like 300 seconds) during planned migrations for faster propagation, longer TTLs (like 86400 seconds) for stable records to reduce query load.
- Enable DNSSEC where possible to protect against DNS spoofing and cache poisoning attacks.
16. Troubleshooting Common Issues
| Issue | Cause | Fix |
|---|---|---|
dig returns no answer | BIND9 not running, or zone not loaded | Check systemctl status bind9, check /var/log/syslog for zone errors |
| “zone example.com/IN: loading from master file failed” | Syntax error in zone file | Run named-checkzone example.com /path/to/zonefile to locate the error |
| Secondary server not syncing | allow-transfer misconfigured, or firewall blocking port 53 TCP | Verify allow-transfer IP, check firewall rules for TCP/53 |
| Clients still resolving old IP after a change | High TTL causing caching | Lower TTL before planned changes, or wait for the TTL to expire |
| “REFUSED” response from name server | Query doesn’t match any configured zone, or ACL restrictions | Check named.conf zone definitions and allow-query settings |
Quick diagnostic sequence:
sudo named-checkconf # Check main config syntax
sudo named-checkzone example.com /etc/bind/zones/db.example.com # Check zone file syntax
sudo systemctl restart bind9 # Restart after fixes
dig @localhost example.com # Test resolution
tail -f /var/log/syslog | grep named # Watch live logs (Debian/Ubuntu)17. Conclusion
Configuring a primary name server on Linux using BIND9 gives you full control over your domain’s DNS infrastructure — whether for a public-facing website, an internal corporate network, or a lab environment. The key steps are installing BIND9, declaring your zone as type master, carefully crafting your zone file with accurate records, validating your configuration with named-checkconf and named-checkzone, and testing thoroughly with dig. In the next article, we’ll go much deeper into zone file formats and the various resource record types (SOA, A, AAAA, CNAME, MX, TXT, NS) that make DNS work.