I run a small, boring DNS Server at home. It sits on a low-power VM and quietly keeps everything reachable. That quiet service saves time when other projects break. This guide shows how I set one up for a home lab, with real filenames, commands and checks you can copy. I focus on reliability over 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 choose the right tool for the job: Unbound as a resolver, BIND9 for authoritative zones, or dnsmasq for lightweight local names. On Debian/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 the DHCP server to hand out that IP 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 practical 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: 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 and dig @192.168.1.5 google.com. If dig returns the A record and a reasonable 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 tiny 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, perform basic 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 gives a service that is boring, but it just works, and that is the point of good self-hosting.





