How to Configure a DNS Server
Set up BIND9 as an authoritative DNS server on your GoZen VPS. Covers zone files, A/AAAA/MX/TXT records, reverse DNS, and DNSSEC.
Running your own DNS server gives you full control over your domain’s records, TTLs, and resolution behavior. This is useful if you’re a reseller managing many domains, need split-horizon DNS, or just want to stop depending on third-party DNS panels.
This guide uses BIND9, the most widely used DNS server on the internet.
Most people don’t need to run their own DNS. GoZen Host’s nameservers and the Enhance control panel handle DNS for you. Run your own only if you have a specific reason - reselling, custom configurations, or learning.
Install BIND9
Check that it’s running:
sudo systemctl status named # Rocky/Alma
sudo systemctl status bind9 # Ubuntu/Debian
# Test with a query
dig @localhost version.bind txt chaos
How DNS Works (Quick Version)
When someone visits yourdomain.com:
- Their browser asks a recursive resolver (like 1.1.1.1 or 8.8.8.8) for the IP
- The resolver asks the .com TLD servers “who handles yourdomain.com?”
- The TLD server says “ask ns1.yourdomain.com” (your authoritative server)
- The resolver asks your BIND server for the A record
- Your server returns the IP, the resolver caches it, the browser connects
You’re setting up step 4 - the authoritative server that answers queries about your domain.
Configure BIND as an Authoritative Server
Main Configuration
recursion no; is critical - an open recursive DNS server will get abused for amplification attacks within hours.
Add Your Zone
Create a Zone File
This is where your actual DNS records live.
$TTL 3600
@ IN SOA ns1.yourdomain.com. admin.yourdomain.com. (
2026041301 ; Serial (YYYYMMDDNN - increment on every change)
3600 ; Refresh (1 hour)
900 ; Retry (15 minutes)
1209600 ; Expire (2 weeks)
300 ; Negative cache TTL (5 minutes)
)
; Nameservers
@ IN NS ns1.yourdomain.com.
@ IN NS ns2.yourdomain.com.
; Nameserver A records (glue records)
ns1 IN A 203.0.113.10
ns2 IN A 198.51.100.10
; Main domain
@ IN A 203.0.113.10
@ IN AAAA 2001:db8::1
; Subdomains
www IN A 203.0.113.10
www IN AAAA 2001:db8::1
mail IN A 203.0.113.10
staging IN A 203.0.113.20
api IN A 203.0.113.30
; Mail
@ IN MX 10 mail.yourdomain.com.
; SPF - allow only your mail server to send
@ IN TXT "v=spf1 mx ip4:203.0.113.10 -all"
; DKIM (paste your DKIM key here)
default._domainkey IN TXT "v=DKIM1; k=rsa; p=YOUR_DKIM_PUBLIC_KEY"
; DMARC
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:admin@yourdomain.com"
; CAA - only Let's Encrypt can issue certs for this domain
@ IN CAA 0 issue "letsencrypt.org"
Record Types Explained
| Type | Purpose | Example |
|---|---|---|
A | Maps name to IPv4 address | @ IN A 203.0.113.10 |
AAAA | Maps name to IPv6 address | @ IN AAAA 2001:db8::1 |
CNAME | Alias to another name | blog IN CNAME yourdomain.com. |
MX | Mail server (with priority) | @ IN MX 10 mail.yourdomain.com. |
TXT | Text data (SPF, DKIM, verification) | @ IN TXT "v=spf1 mx -all" |
NS | Nameserver for this zone | @ IN NS ns1.yourdomain.com. |
SOA | Start of Authority (zone metadata) | Required, one per zone |
CAA | Which CAs can issue SSL certs | @ IN CAA 0 issue "letsencrypt.org" |
SRV | Service discovery | Used by some apps, VoIP, etc. |
The Serial Number Matters
The SOA serial number tells secondary DNS servers whether the zone has changed. You must increment it every time you edit the zone file. The convention is YYYYMMDDNN where NN starts at 01 and increments for each change that day.
Check and Apply
# Validate your zone file
named-checkzone yourdomain.com /etc/bind/zones/db.yourdomain.com # Ubuntu/Debian
named-checkzone yourdomain.com /var/named/db.yourdomain.com # Rocky/Alma
# Validate the main config
named-checkconf
# Reload BIND
sudo systemctl reload bind9 # Ubuntu/Debian
sudo systemctl reload named # Rocky/Alma
If named-checkzone shows errors, fix them before reloading. A syntax error can take down DNS for all your domains.
Test Your DNS
# Query your server directly
dig @localhost yourdomain.com A
dig @localhost yourdomain.com MX
dig @localhost yourdomain.com TXT
# From another machine (replace with your server's IP)
dig @203.0.113.10 yourdomain.com A
# Check all record types
dig yourdomain.com ANY @localhost
Set Up a Secondary (Slave) DNS
You need at least two nameservers for most domain registrars. Set up a secondary on a different server:
On the secondary server, install BIND and add:
zone "yourdomain.com" {
type slave;
file "/var/cache/bind/db.yourdomain.com";
masters { 203.0.113.10; }; // primary DNS IP
};
On the primary server, update allow-transfer in the zone config:
allow-transfer { 198.51.100.10; }; // secondary DNS IP
Reload both:
sudo systemctl reload bind9 # or named
The secondary pulls zone data from the primary automatically and stays in sync based on the SOA refresh interval.
Reverse DNS (PTR Records)
Reverse DNS maps an IP back to a hostname. Mail servers check this - if your PTR record doesn’t match, your emails may get flagged as spam.
For GoZen Host VPS customers: Reverse DNS (PTR) records are configured through the client area or by opening a support ticket. You typically can’t run your own reverse DNS zone because the IP block is managed by the hosting provider.
If you do manage your own IP block, here’s the reverse zone:
sudo nano /etc/bind/zones/db.113.0.203
$TTL 3600
@ IN SOA ns1.yourdomain.com. admin.yourdomain.com. (
2026041301
3600
900
1209600
300
)
@ IN NS ns1.yourdomain.com.
@ IN NS ns2.yourdomain.com.
10 IN PTR yourdomain.com.
10 IN PTR mail.yourdomain.com.
Open the Firewall
DNS uses port 53 on both TCP and UDP:
# UFW
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# firewalld
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
Troubleshooting
| Problem | Fix |
|---|---|
named-checkzone shows “file not found” | Check the file path in your zone declaration. Ubuntu uses /etc/bind/zones/, Rocky uses /var/named/. |
| BIND won’t start - “permission denied” | On Rocky/AlmaLinux, SELinux may block access. Check: sudo ausearch -m avc -ts recent. Fix: sudo restorecon -Rv /var/named/. |
| Zone transfers fail | Check allow-transfer on primary and masters on secondary. Firewall must allow port 53. |
| Changes don’t propagate | Did you increment the serial number? Secondary servers only pull updates when the serial increases. |
dig works locally but not remotely | Firewall is blocking port 53. Check with sudo ufw status or sudo firewall-cmd --list-all. |
| “SERVFAIL” responses | Syntax error in zone file. Run named-checkzone to find it. |
| High CPU from BIND | You may have recursion yes and the internet is hammering you with queries. Set recursion no for authoritative-only servers. |
Related Articles
Last updated 21 Apr 2026, 08:08 +0300.