Self-hosting a DNS server on a home lab

I run a small, boring DNS server at home. It sits on a low-power VM and quietly keeps things reachable. That calm service saves time when other projects break. This is the setup I use for a home lab, with the filenames, commands and checks I actually care about. Reliability matters more than novelty.

Pick simple hardware and a minimal install. For a tiny home lab, a Raspberry Pi 4 or a VM with 1–2 GB RAM and 8–16 GB disk is fine. On the software side, pick the right tool for the job: Unbound as a resolver, BIND9 for authoritative zones, or dnsmasq for lightweight local names. On Debian or Ubuntu, the packages are:

apt update
apt install unbound

or:

apt install bind9 dnsmasq

Give the server a static IP on your LAN and set DHCP to hand out that address as the primary DNS. In network configuration, use a fixed address in your router’s DHCP reservations or set the address in /etc/network/interfaces or netplan. For security, limit recursion to your subnet and block port 53 from the internet. Turn on DNSSEC validation in Unbound or BIND if you want validation of signed zones, and keep the machine patched.

The DNS setup I use is small and repeatable. For BIND, create /etc/bind/named.conf.local with a zone block for lab.local and a zone file at /etc/bind/db.lab. A minimal A record looks like this:

myhost IN A 192.168.1.10

For Unbound, run it as a caching resolver and forward unresolved queries to a trusted upstream or to root servers. After installing, run:

systemctl start bind9

or:

systemctl start unbound

Test from another machine with:

dig @192.168.1.5 myhost.lab A
dig @192.168.1.5 google.com

If dig returns the A record and a sensible response time, the DNS setup is working. If clients still use ISP DNS, check the DHCP settings or force a client to use the server by setting its DNS entry manually for testing.

Troubleshooting is usually one of three things: the server is firewalled, the zone file has a syntax error, or DHCP still points elsewhere. Check iptables or UFW for port 53 rules. Use:

named-checkzone
named-checkconf

for BIND to find file errors. For Unbound, check logs in /var/log/syslog or use:

unbound-control status

For maintenance, back up /etc/bind and /etc/unbound regularly and keep a copy off the device. Run a secondary read-only slave on another machine if uptime matters; BIND and many DNS servers support zone transfers to a slave. Add simple monitoring: a cron job that runs dig and alerts if the server fails to answer. For dynamic clients, set up RFC2136 updates so DHCP can update DNS automatically, or run a small script that posts updates with nsupdate.

If you want reliability, keep things small and predictable. Use a local resolver so name lookup does not depend on the internet. Give the server a static IP, lock recursion to the LAN, keep some logging, and run a secondary if you can. Keep configuration files in a git repo or a tarball and test restores on a spare VM. That leaves you with a service that is boring, but it just works. That is the point.

Tags:

Related posts

Agentic AI still needs domain judgement

Agentic AI can write the thing, but it still cannot tell you whether the thing is right. That is where domain expertise matters, because a clean config or neat bit of glue logic can still be wrong in...

Weekly Tech Digest | 06 Jul 2026

Stay updated with the latest in tech! This digest covers AI ethics, auto industry shifts, and the impact of politics on technology, exploring today's pressing issues.

wolfCOSE zero-allocation parsing in embedded C

wolfCOSE looks sensible only if you care about what your firmware actually has to carry. I like that, because on small targets the wrong crypto feature can cost more than the message itself, and there...