Migrating from Windows-based DNS servers to Linux often requires dynamic DNS updates without restarting BIND. The most efficient approach is using a database backend like MySQL with DLZ (Dynamically Loadable Zones) support. Here's a comprehensive guide to set it up correctly.
First, download and compile BIND with MySQL DLZ patches:
wget https://downloads.isc.org/isc/bind9/9.16.15/bind-9.16.15.tar.gz
tar xvf bind-9.16.15.tar.gz
cd bind-9.16.15
patch -p1 < bind-mysql.patch
./configure --prefix=/usr --sysconfdir=/etc/bind --localstatedir=/var \
--enable-threads --enable-largefile --with-libtool --enable-shared \
--enable-static --with-openssl --with-gssapi --with-libxml2 \
--with-dlz-mysql=/usr
make
sudo make install
Create the database schema for DNS records:
CREATE DATABASE bind;
USE bind;
CREATE TABLE dns_records (
zone VARCHAR(255) NOT NULL,
host VARCHAR(255) NOT NULL,
ttl INT DEFAULT NULL,
type VARCHAR(10) DEFAULT NULL,
mx_priority INT DEFAULT NULL,
data VARCHAR(255) DEFAULT NULL,
resp_person VARCHAR(255) DEFAULT NULL,
serial INT DEFAULT NULL,
refresh INT DEFAULT NULL,
expire INT DEFAULT NULL,
minimum INT DEFAULT NULL,
PRIMARY KEY (zone,host)
);
Configure /etc/named.conf
for MySQL backend:
options {
directory "/var/named";
allow-query { any; };
};
dlz "MySQL zone" {
database "mysql
{host=localhost dbname=bind user=bind_user pass=password}
{SELECT zone FROM dns_records WHERE zone = '$zone$'}
{SELECT ttl, type, mx_priority,
CASE WHEN type='TXT' THEN CONCAT('\"', data, '\"')
WHEN type='SOA' THEN CONCAT(data, ' ', resp_person, ' ',
serial, ' ', refresh, ' ', retry, ' ', expire, ' ', minimum)
ELSE data END
FROM dns_records
WHERE zone = '$zone$' AND host = '$record$'}";
};
Create a systemd service file at /etc/systemd/system/named.service
:
[Unit]
Description=BIND Domain Name Server
After=network.target
[Service]
ExecStart=/usr/sbin/named -f -4
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
Verify your setup with these commands:
named-checkconf /etc/named.conf
systemctl start named
dig @localhost my.cloud SOA
- Check
/var/log/messages
for BIND errors - Verify MySQL connection permissions
- Test SQL queries directly in MySQL client
- Ensure SELinux contexts are correct if enabled
Migrating from Windows DNS to Linux while maintaining dynamic zone updates requires a robust solution. The traditional zone file approach requires service restarts - a dealbreaker for production environments. Here's how to implement BIND with database backend properly:
For Amazon Linux/RHEL systems:
# MySQL version
sudo yum install -y bind bind-sdb bind-utils mysql mysql-server
# PostgreSQL alternative
sudo yum install -y bind bind-sdb bind-utils postgresql postgresql-server
First, compile BIND with MySQL support (if using custom build):
./configure --with-dlz-mysql
make
sudo make install
Then configure /etc/named.conf
:
dlz "mysql-zone" {
database "mysql
{host=localhost dbname=bind user=bind password=securepass}
{SELECT zone FROM dns_records WHERE zone = '$zone$'}
{SELECT ttl, type, mx_priority, data, resp_person,
serial, refresh, retry, expire, minimum
FROM dns_records
WHERE zone = '$zone$' AND host = '$record$'}";
};
Essential MySQL table structure:
CREATE TABLE dns_records (
zone VARCHAR(255) NOT NULL,
host VARCHAR(255) NOT NULL,
ttl INT DEFAULT 3600,
type VARCHAR(10) NOT NULL,
mx_priority INT DEFAULT NULL,
data VARCHAR(255) DEFAULT NULL,
resp_person VARCHAR(255) DEFAULT NULL,
serial BIGINT DEFAULT 1,
refresh INT DEFAULT 28800,
retry INT DEFAULT 7200,
expire INT DEFAULT 86400,
minimum INT DEFAULT 28800,
PRIMARY KEY (zone,host,type)
);
1. Service not starting: Check paths in systemd unit file or init script:
ExecStart=/usr/local/sbin/named -f -4 -c /etc/named.conf
2. Permission problems: Ensure DB user has proper grants:
GRANT SELECT ON bind.* TO 'bind'@'localhost' IDENTIFIED BY 'securepass';
3. Configuration validation: Always test with:
named-checkconf /etc/named.conf
For programmatic updates, create stored procedures:
DELIMITER //
CREATE PROCEDURE add_record(
IN p_zone VARCHAR(255),
IN p_host VARCHAR(255),
IN p_type VARCHAR(10),
IN p_data VARCHAR(255)
)
BEGIN
REPLACE INTO dns_records (zone, host, type, data)
VALUES (p_zone, p_host, p_type, p_data);
END //
DELIMITER ;
Then call from application code without restarting BIND.