In my homelab I historically used a couple of MS Windows Server machines to run DNS and authentication services. They did their job perfectly, but I realized that lately no single machine in my network was joined to their Active Directory domain, and so basically I was using them as just DNS servers. To simplify my lab I decided to switch them to two Linux servers, using Bind as the dns service and Webmin to have a comfortable user interface. This is how I did.
Deploy the servers and the software
Firs, I installed two Ubuntu Linux 24.04 LTS virtual machines, I configured them to connect to my lab network and to use the same IP addresses of the previous Windows DNS servers. In a production environment you should plan to replace one server at the time to keep all the clients connected to the DNS service, so I did the same even if in my lab I could have sustained a short downtime.
Then, I needed Webmin. This software has its own repository, so I had to configure it. Thankfully they offer an easy script to do the entire setup:
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh sudo sh webmin-setup-repo.sh sudo apt-get install webmin --install-recommends
I don’t need to install Bind, since this can be done directly from Webmin.
Configuration
Webmin can be reached at https://<IP Address>:10000. In the Un-used Modules there is a section named Bind DNS Server, and here I can ask Webmin to install it for me:

Webmin integrates nicely with Ubuntu and its package manager, so it asks to confirm that also some needed dependencies will be installed:

Once Bind is installed, I recreated my lab dns zones in the primary server:

One additional configuration I need to properly use the first DNS server is recursion. By default, Bind will only answer to queries related to the zones it hosts. In my lab however I also use my DNS servers to allow all the other machines to resolve DNS names.
Replication between master and slave
In the second DNS server I configured the same zones, this time as Slave zones. This is pretty easy to achieve, I only need to tell DNS2 to retrieve zone data from DNS1:

However, upon the first synchronization, the zone in the slave server was still empty, even if the Test Zone Transfer command was completing successfully.

A quick search in the syslog for the messages registered by the named service gave me the answer to what was happening:
2025-12-05T14:02:45.884469+00:00 dns1 named[14730]: zone cloudconnect.local/IN: transfer: could not set file modification time of '/var/lib/bind/cloudconnect.local.hosts': permission denied 2025-12-05T14:02:46.384370+00:00 dns1 named[14730]: zone virtualtothecore.com/IN: transfer: could not set file modification time of '/var/lib/bind/virtualtothecore.com.hosts': permission denied 2025-12-05T14:02:46.384499+00:00 dns1 named[14730]: zone virtualtothecore.local/IN: transfer: could not set file modification time of '/var/lib/bind/virtualtothecore.local.hosts': permission denied
the slave DNS server was indeed grabbing the zones from the master, but it couldn’t write them in the specified folder. Seemed like some permissions were wrong, and a quick look in the folder confirmed my suspect:

The files are owned by root, so bind (the user of the named/Bind service) cannot write them to update the records. Also, note their size is 0KB, which means they are totally empty.
The fix is pretty easy, I change the permissions on the files with a quick:
chown bind:bind *
I check again the files and now their permissions are correct:

I can then force a resync of the zones by restarting the service, and afterwards the size of the files are correct:

and in Webmin I see that the slave zones now have all the records that also exist in the master zone:

