Table A-2. Generic PgSQL backend capabilities
Native | Yes - but PostgreSQL does not replicate |
Master | Yes |
Slave | Yes |
Superslave | Yes |
Autoserial | Yes |
PostgreSQL backend with easily configurable SQL statements, allowing you to graft PDNS on any PostgreSQL database of your choosing. Because all database schemas will be different, a generic backend is needed to cover all needs.
The template queries are expanded using the C function 'snprintf' which implies that substitutions are performed on the basis of %-place holders. To place a a % in a query which will not be substituted, use %%.
The default setup conforms to the following schema:
create table domains ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, master VARCHAR(20) DEFAULT NULL, last_check INT DEFAULT NULL, type VARCHAR(6) NOT NULL, notified_serial INT DEFAULT NULL, account VARCHAR(40) DEFAULT NULL ); CREATE UNIQUE INDEX name_index ON domains(name); CREATE TABLE records ( id SERIAL PRIMARY KEY, 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_data INT DEFAULT NULL, CONSTRAINT domain_exists FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ); CREATE INDEX 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 domains_id_seq TO pdns; GRANT ALL ON records TO pdns; GRANT ALL ON records_id_seq TO pdns;
This schema contains all elements needed for master, slave and superslave operation. Depending on which features will be used, the 'GRANT' statements can be trimmed to make sure PDNS cannot subvert the contents of your database.
4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers.
The 4+4 regular queries must return the following 6 fields, in this exact order:
This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example.
TTL of this record, in seconds. Must be a real value, no checking is performed.
For MX records, this should be the priority of the mail exchanger specified.
The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this field returns an exact answer - PDNS won't recognise 'A ' as 'A'. This can be achieved by using a VARCHAR instead of a CHAR.
Each domain must have a unique domain_id. No two domains may share a domain_id, all records in a domain should have the same. A number.
Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain!
As said earlier, there are 8 SQL queries for regular lookups. If so called 'MBOXFW' fancy records are not used, four remain:
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' This is the most used query, needed for doing 1:1 lookups of qtype/name values. First %s is replaced by the ASCII representation of the qtype of the question, the second by the name.
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' and id=%d Used for doing lookups within a domain. First %s is replaced by the qtype, the %d which should appear after the %s by the numeric domain_id.
For doing ANY queries. Also used internally. Default: select content,ttl,prio,type,domain_id,name from records where name='%s' The %s is replaced by the qname of the question.
For doing ANY queries within a domain. Also used internally. Default: select content,ttl,prio,type,domain_id,name from records where name='%s' and domain_id=%d The %s is replaced by the name of the domain, the %d by the numerical domain id.
The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally:
To list an entire zone. Default: select content,ttl,prio,type,domain_id,name from records where domain_id=%d
If PDNS is used with so called 'Fancy Records', the 'MBOXFW' record exists which specifies an email address forwarding instruction, wildcard queries are sometimes needed. This is not enabled by default. A wildcard query is an internal concept - it has no relation to *.domain-type lookups. You can safely leave these queries blank.
Can be left blank. See above for an explanation. Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s'
Can be left blank. See above for an explanation. Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s' and domain_id=%d Used for doing lookups within a domain.
For doing wildcard ANY queries. Default: select content,ttl,prio,type,domain_id,name from records where name like '%s'
For doing wildcard ANY queries within a domain. Default: select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d
The queries above are specified in pdns.conf. For example, the basic-query would appear as:
gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'Queries can span multiple lines, like this:
gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \ where qtype='%s' and name='%s'Do not wrap statements in quotes as this will not work. Besides the query related settings, the following configuration options are available:
Database name to connect to
Database host to connect to. WARNING: When specified as a hostname a chicken/egg situation might arise where the database is needed to resolve the IP address of the database. It is best to supply an IP address of the database here.
Password to connect with
PgSQL user to connect as
For native operation, either drop the FOREIGN KEY on the domain_id field, or (recommended), make sure the domains table is filled properly. To add a domain, issue the following:
insert into domains (name,type) values ('powerdns.com','NATIVE');The records table can now be filled by with the domain_id set to the id of the domains table row just inserted.
The PostgreSQL backend is fully slave capable. To become a slave of the 'powerdns.com' domain, execute this:
insert into domains (name,master,type) values ('powerdns.com','213.244.168.217','SLAVE');And wait a while for PDNS to pick up the addition - which happens within one minute. Typical output is:
Apr 09 13:34:29 All slave domains are fresh Apr 09 13:35:29 1 slave domain needs checking Apr 09 13:35:29 Domain powerdns.com is stale, master serial 1, our serial 0 Apr 09 13:35:30 [gPgSQLBackend] Connected to database Apr 09 13:35:30 AXFR started for 'powerdns.com' Apr 09 13:35:30 AXFR done for 'powerdns.com' Apr 09 13:35:30 [gPgSQLBackend] Closing connection
From now on, PDNS is authoritative for the 'powerdns.com' zone and will respond accordingly for queries within that zone.
To configure a supermaster with IP address 10.0.0.11 which lists this installation as 'autoslave.powerdns.com', issue the following:
insert into supermasters ('10.0.0.11','autoslave.powerdns.com','internal');From now on, valid notifies from 10.0.0.11 that list a NS record containing 'autoslave.powerdns.com' will lead to the provisioning of a slave domain under the account 'internal'.
The PostgreSQL backend is fully master capable with automatic discovery of serial changes. Raising the serial number of a domain suffices to trigger PDNS to send out notifications. To configure a domain for master operation instead of the default native replication, issue:
insert into domains (name,type) values ('powerdns.com','SLAVE');Make sure that the assigned id in the domains table matches the domain_id field in the records table!