“Running a DNS server” can mean two different things:
- A recursive (caching) resolver looks up names for your own servers or network — like the DNS server your ISP gives you.
- An authoritative server answers for your own domains — it’s where your
A,MXandTXTrecords live.
This guide covers both, with the tools most commonly used on Linux: Unbound for resolving and BIND for authoritative DNS.
Part 1: A local caching resolver with Unbound
A local resolver speeds up servers that do many DNS lookups (mail servers, crawlers, applications calling APIs) and removes dependence on an external resolver.
apt install -y unbound
/etc/unbound/unbound.conf.d/local.conf:
server:
interface: 127.0.0.1
access-control: 127.0.0.0/8 allow
hide-identity: yes
hide-version: yes
prefetch: yes
qname-minimisation: yes
unbound-checkconf
systemctl restart unbound
dig @127.0.0.1 debian.org +short
Point the system at it — in /etc/resolv.conf set nameserver 127.0.0.1 (or configure systemd-resolved / your network config to use it).
Never let a resolver answer queries from the whole internet. Open resolvers are abused for DNS amplification attacks. Keep interface on localhost or a private network, and firewall port 53.
Part 2: Authoritative DNS with BIND
Install
apt install -y bind9 bind9-utils
Declare the zone
/etc/bind/named.conf.local:
zone "example.com" {
type primary;
file "/etc/bind/zones/db.example.com";
allow-transfer { 198.51.100.53; }; // secondary server
notify yes;
};
Write the zone file
/etc/bind/zones/db.example.com:
$TTL 3600
@ IN SOA ns1.example.com. hostmaster.example.com. (
2026110401 ; serial (YYYYMMDDnn) — increase on every change
3600 ; refresh
900 ; retry
1209600 ; expire
300 ) ; negative cache TTL
IN NS ns1.example.com.
IN NS ns2.example.com.
ns1 IN A 203.0.113.53
ns2 IN A 198.51.100.53
@ IN A 203.0.113.20
www IN CNAME example.com.
@ IN MX 10 mail.example.com.
mail IN A 203.0.113.25
@ IN TXT "v=spf1 mx -all"
Disable recursion on the authoritative server
In /etc/bind/named.conf.options:
options {
directory "/var/cache/bind";
recursion no;
allow-query { any; };
dnssec-validation auto;
};
Check and load
named-checkconf
named-checkzone example.com /etc/bind/zones/db.example.com
systemctl restart named
ufw allow 53
dig @127.0.0.1 example.com A +short
Delegate the domain
At your domain registrar, register glue records for ns1/ns2.example.com with their IPs, then set the domain’s nameservers to them. DNS changes can take up to the old records’ TTL (and up to 48 hours for delegation) to propagate.
Run a secondary
You need at least two nameservers on different servers, ideally in different locations. On the secondary:
zone "example.com" {
type secondary;
primaries { 203.0.113.53; };
file "/var/cache/bind/db.example.com";
};
Testing with dig
dig example.com A # what your resolver returns
dig @ns1.example.com example.com A +norecurse # ask the authoritative server directly
dig example.com MX +short
dig -x 203.0.113.25 # reverse DNS (PTR)
dig +trace example.com # follow delegation from the root
Reverse DNS
PTR records for your server IPs are controlled by whoever owns the IP block — your hosting provider. On our USA VPS you can set rDNS in the client area; it’s important for mail servers. See Email VPS.
Should you self-host authoritative DNS?
Self-hosting gives full control, but DNS is critical: if it’s down, your site and email are unreachable. Many people run authoritative DNS with a managed provider (often free with a CDN like Cloudflare, or with their registrar) and use their own servers for resolvers and internal zones. If you self-host, run two servers in different locations and monitor them.
Related: Debian network configuration and VPS + Cloudflare.