Installing PowerDNS

Installing PowerDNS

PowerDNS Logo
There are notes on installing PowerDNS on a CentOS 5 server. This is generic enough that it aught to work on any RPM based Linux distro with yum installed.

2009-01-20 Update: Fixed the section on local-address in the configuration file which prevented outside machines from accessing the name server.

2010-04-21 Update: Fixed error caught by Matt. Thanks, Matt!

Preliminary Setup

  • Ensure BIND is not installed.


    $ sudo yum erase bind

  • Create a user to run as.


    $ sudo useradd -c "PowerDNS" -M -r -s /sbin/nologin pdns

  • Install MySQL

  • $ sudo yum install mysql-server
    $ sudo /sbin/service mysqld start
    $ sudo /sbin/chkconfig --level 35 mysqld on

  • Set MySQL root password. Please use different passwords.


    $ /usr/bin/mysqladmin -u root password 'new password'
    $ /usr/bin/mysqladmin -u root -h localhost password 'new password'

  • Run the following MySQL commands. Please change the passwords in the file first.


    $ mysql --user=root mysql -p
    Enter password:
    mysql> source database-install.sql;


    The database-install.sql is something I created. It has the following:


    ################################################################################
    #
    # Adjust users.
    #
    # !!! WARNING !!! Change the two passwords below!
    #
    ################################################################################

    # Change the root password here.
    UPDATE mysql.user SET password = PASSWORD('password') WHERE user = 'root';

    # Change the PowerDNS password here.
    CREATE USER 'powerdns'@'localhost' IDENTIFIED BY 'password';

    DROP USER '';

    FLUSH PRIVILEGES;

    ################################################################################
    #
    # Create database and tables.
    #
    ################################################################################
    CREATE DATABASE powerdns;

    USE powerdns;

    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
    ) type=InnoDB;

    GRANT ALL ON domains TO powerdns;
    GRANT ALL ON records TO powerdns;
    GRANT SELECT ON supermasters TO powerdns;

PowerDNS Setup

  • Download PowerDNS RPM.
  • Install RPM.
  • Change the permissions on the PowerDNS config file since it holds passwords in plain text.


    sudo chmod 440 /etc/powerdns/pdns.conf

  • Edit the PowerDNS config file.


    sudo vim /etc/powerdns/pdns.conf

  • Find the setgid and setuid lines. Add the appropriate lines


    setgid=pdns
    setuid=pdns

  • Find the launch line. Add information for the MySQL database.


    launch=gmysql
    gmysql-host=localhost
    gmysql-user=powerdns
    gmysql-password=password
    gmysql-dbname=powerdns
    gmysql-socket=/var/lib/mysql/mysql.sock

  • Find the local-address line and add the IP address of the publicly-facing NIC. See Chapter 15 of the documentation.


    local-address=xxx.xxx.xxx.xxx

  • Find the log-dns-details line and add the following:


    log-dns-details=off

Testing

  • Test the setup by running PowerDNS in monitor mode:


    $ sudo /etc/init.d/pdns monitor

    Jan 04 22:46:34 This is a standalone pdns
    Jan 04 22:46:34 UDP server bound to 127.0.0.1:53
    Jan 04 22:46:34 TCP server bound to 127.0.0.1:53
    Jan 04 22:46:34 PowerDNS 2.9.21.2 (C) 2001-2008 PowerDNS.COM BV (Nov 16 2008, 14:07:43, gcc 4.2.3 (Ubuntu 4.2.3-2ubuntu7)) starting up
    Jan 04 22:46:34 PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
    Jan 04 22:46:34 Set effective group id to 105
    Jan 04 22:46:34 Set effective user id to 102
    Jan 04 22:46:34 Creating backend connection for TCP
    Jan 04 22:46:34 gmysql Connection succesful
    Jan 04 22:46:34 About to create 3 backend threads for UDP
    Jan 04 22:46:34 gmysql Connection succesful
    Jan 04 22:46:34 gmysql Connection succesful
    Jan 04 22:46:34 gmysql Connection succesful
    Jan 04 22:46:34 Done launching threads, ready to distribute questions

  • If there are problems, see Chapter 4 of the documentation.
  • Test the operation. Leave the monitor (previous item) running. Pull up a new shell. Execute the following host command and look for a similar response.


    $ host www.test.com 127.0.0.1
    Using domain server:
    Name: 127.0.0.1
    Address: 127.0.0.1#53
    Aliases:

    Host www.test.com not found: 2(SERVFAIL)


    In the monitor you should see the following message:


    Not authoritative for 'www.test.com', sending servfail to 127.0.0.1 (recursion was desired)

  • Add some test records to the database:


    $ mysql --user=root -p
    mysql> source database-test.sql;


    That file has the following commands, which I copied from the InterNet:


    USE powerdns;

    INSERT INTO domains (name, type) values ('test.com', 'NATIVE');
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'test.com','localhost ahu@ds9a.nl 1','SOA',86400,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'test.com','dns-us1.powerdns.net','NS',86400,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'test.com','dns-eu1.powerdns.net','NS',86400,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'www.test.com','199.198.197.196','A',120,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'mail.test.com','195.194.193.192','A',120,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'localhost.test.com','127.0.0.1','A',120,NULL);
    INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'test.com','mail.test.com','MX',120,25);

  • Run the test again:


    $ host www.test.com 127.0.0.1
    Using domain server:
    Name: 127.0.0.1
    Address: 127.0.0.1#53
    Aliases:

    www.test.com has address 199.198.197.196

  • Try another test.


    $ host -v -t mx www.test.com 127.0.0.1
    Trying "www.test.com"
    Using domain server:
    Name: 127.0.0.1
    Address: 127.0.0.1#53
    Aliases:

    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27585
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

    ;; QUESTION SECTION:
    ;www.test.com. IN MX

    ;; AUTHORITY SECTION:
    test.com. 86400 IN SOA localhost. ahu.ds9a.nl. 1 10800 3600 604800 3600

    Received 86 bytes from 127.0.0.1#53 in 21 ms

  • If you are receiving the following in the monitor:


    Authoritative empty NO ERROR to 127.0.0.1 for 'www.test.com' (AAAA), other types do exist.


    Then you did not put the log-dns-details=off in the configuration file. See the documentation, which says

    As the name implies, this is not an error. It tells you there are questions for a domain which exists in your database, but for which no record of the requested type exists. To get rid of this error, add log-dns-details=off to your configuration.

  • Remove the test records.


    $ mysql --user=root -p
    mysql> USE powerdns;
    mysql> DELETE FROM domains;
    mysql> DELETE FROM records;

  • Add pdns to chkconfig and ensure that it’s set to run at boot time. I prefer to use system-config-services, but it’s just a graphical wrapper around chkconfig.
  • Start the services as a dæmon and you’re done.


    $ sudo /etc/init.d/pdns start

  1. Setting Up Public Name Servers | James Reuben Knowles Says:

    [...] This article talks about setting up your own public name server, allowing you to have complete control over DNS for your domains. It will cover the steps I went through to achieve this. Where I encountered difficulty will have greater amounts of detail. The actual installation of a name server is covered in my article Installing PowerDNS. [...]

  2. Mike Says:

    anyluck setting up toplevel domains? I recently joined a vpn network, and i have tried to add a domain like .brd and well it doesn’t see it as a top level domain and refuses to add it.

    any ideas?

  3. James Reuben Knowles Says:

    Hey Mike,

    I’ve not tried to set up a TLD. I think this would be a perfect question for the PowerDNS mailing list. Have you tried the elist yet?

  4. Matt Says:

    Nice article, very useful for a PowerDNS first timer! Worked right away on CentOS 5… Thanks!

    BTW, small error on the line : sudo yum /sbin/service mysqld start (yum?)

    Thanks!
    Matt.

  5. James Reuben Knowles Says:

    Matt,

    Thank you very much for catching that error! I’ve used these notes a couple of times and blew right past it.

    Glad you found it useful, and thanks again for the bug catch.
    James

Leave a Reply