Adding new zones to an existing Bind master/slave setup can be a bit tedious, since NOTIFYs are ignored for zoned not already configured on the slave. PowerDNS solves this problem by introducing something called supermasters. When a supermaster sends a NOTIFY to a slave for a zone that doesn’t already exist, the slave server simply ads it to the database and fetches the data.
As a side note, I’ve previously written about how to sync djbdns zones with rsync.
For this example I’ll be using two Ubuntu 10.10 servers. ns1.example.com with ip address 10.0.0.10 and ns2.example.com with address 10.0.0.20. Start by installing MySQL and PowerDNS on them:
# aptitude install mysql-server pdns-backend-mysql
Create a database named pdns and populate it with the tables described in the documentation.
CREATE TABLE domains (
id INT auto_increment,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
primary key (id)
)type=InnoDB;
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id INT auto_increment,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(6) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
primary key(id)
)type=InnoDB;
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE TABLE supermasters (
ip VARCHAR(25) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) DEFAULT NULL
);
GRANT SELECT ON supermasters TO pdns;
GRANT ALL ON domains TO pdns;
GRANT ALL ON records TO pdns;
GRANT SELECT ON supermasters TO pdns;
GRANT ALL ON domains TO pdns;
GRANT ALL ON records TO pdns;
Then edit /etc/powerdns/pdns.d/pdns.local on both servers to configure the backend and enable master/slave operation.
For ns1:
allow-axfr-ips=10.0.0.20
disable-axfr=no
master=yes
launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=pdns
gmysql-dbname=pdns
gmysql-password=<password>
For ns2:
slave=yes
gmysql-host=127.0.0.1
gmysql-user=pdns
gmysql-dbname=pdns
gmysql-password=<password>
Make sure the new configuration is loaded, on both servers run:
# /etc/init.d/pdns restart
Now, add the supermaster to the database on ns2:
INSERT INTO supermasters (ip, nameserver, account) VALUES ('10.0.0.10', 'ns2.example.com', 'admin');
On ns1, create a domain:
INSERT INTO domains (name, type) VALUES ('example.com', 'MASTER');
INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.com', 'ns1.example.com hostmaster.example.com 1', 'SOA', 86400, NULL);
INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.com', 'ns1.example.com', 'NS', 86400, NULL);
INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.com', 'ns2.example.com', 'NS', 86400, NULL);
INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'ns1.example.com', '10.0.0.10', 'A', 86400, NULL);
INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'ns2.example.com', '10.0.0.20', 'A', 86400, NULL);
Now try if it works on ns1:
# dig @10.0.0.10 ns example.com
...
;; QUESTION SECTION:
;example.com. IN NS
;; ANSWER SECTION:
example.com. 86400 IN NS ns2.example.com.
example.com. 86400 IN NS ns1.example.com.
;; ADDITIONAL SECTION:
ns2.example.com. 86400 IN A 10.0.0.10
ns1.example.com. 86400 IN A 10.0.0.20
...
The tables on ns2 haven’t been populated yet, but if we update the serial on ns1 and trigger a NOTIFY, it will sync up.
UPDATE records SET content = 'ns1.example.com hostmaster.example.com 2' WHERE id = '1';
The zone is now synchronized, try it out.
Also, consider using a web interface for the management, such as Poweradmin.