From 44392c04045965ed0cf041ac582a310ed5de1216 Mon Sep 17 00:00:00 2001 From: Christoph Wiechert Date: Sun, 15 Jan 2017 22:41:17 +0100 Subject: [PATCH] init --- .gitignore | 2 + Dockerfile | 32 ++++++++ README.md | 56 ++++++++++++++ entrypoint.sh | 52 +++++++++++++ pdns.conf | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++ schema.sql | 90 ++++++++++++++++++++++ 6 files changed, 437 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100755 entrypoint.sh create mode 100644 pdns.conf create mode 100644 schema.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6ef218 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd17f60 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM alpine +MAINTAINER Christoph Wiechert + +ENV REFRESHED_AT="2017-01-17" \ + POWERDNS_VERSION=4.0.2 \ + MYSQL_AUTOCONF=true \ + MYSQL_HOST="mysql" \ + MYSQL_PORT="3306" \ + MYSQL_USER="root" \ + MYSQL_PASS="root" \ + MYSQL_DB="pdns" + +RUN apk --update add mysql-client mariadb-client-libs libpq sqlite-libs libstdc++ libgcc && \ + apk add --virtual build-deps \ + g++ make mariadb-dev postgresql-dev sqlite-dev curl boost-dev && \ + curl -sSL https://downloads.powerdns.com/releases/pdns-$POWERDNS_VERSION.tar.bz2 | tar xj -C /tmp && \ + cd /tmp/pdns-$POWERDNS_VERSION && \ + ./configure --prefix="" --exec-prefix=/usr --sysconfdir=/etc/pdns \ + --with-modules="bind gmysql gpgsql gsqlite3" --without-lua && \ + make && make install && cd / && \ + mkdir -p /etc/pdns/conf.d && \ + addgroup -S pdns 2>/dev/null && \ + adduser -S -D -H -h /var/empty -s /bin/false -G pdns -g pdns pdns 2>/dev/null && \ + apk del --purge build-deps && \ + rm -rf /tmp/pdns-$POWERDNS_VERSION /var/cache/apk/* + +ADD schema.sql pdns.conf /etc/pdns/ +ADD entrypoint.sh / + +EXPOSE 53/tcp 53/udp + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2a58aa --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# PowerDNS Docker Container + +[![Docker Stars](https://img.shields.io/docker/stars/psitrax/powerdns.svg)]() +[![Docker Pulls](https://img.shields.io/docker/pulls/psitrax/powerdns.svg)]() +[![Docker Automated buil](https://img.shields.io/docker/automated/psitrax/powerdns.svg)]() +[![ImageLayers Size](https://img.shields.io/imagelayers/image-size/psitrax/powerdns/latest.svg)]() + +* Small Alpine based Image +* MySQL (default), Postgres, SQLight and Bind backend included +* Automatic MySQL database initialization +* Latest PowerDNS version (if not pls file an issue) +* Guardian process enabled +* Graceful shutdown using pdns_control + +## Usage + +```shell +# Start a MySQL Container +$ docker run -d \ + --name pdns-mysql \ + -e MYSQL_ROOT_PASSWORD=supersecret \ + -v $PWD/mysql-data:/var/lib/mysql \ + mariadb:10.1 + +$ docker run --name pdns \ + --link pdns-mysql:mysql \ + -p 53:53 \ + -p 53:53/udp \ + -e MYSQL_USER=root \ + -e MYSQL_PASS=supersecret \ + psitrax/powerdns \ + --cache-ttl=120 \ + --allow-axfr-ips=127.0.0.1 123.1.2.3 +``` + +## Configuration + +**Environment Configuration:** + +* MySQL connection settings + * `MYSQL_HOST=mysql` + * `MYSQL_USER=root` + * `MYSQL_PASS=root` + * `MYSQL_DB=pdns` +* Want to disable mysql initialization? Use `MYSQL_AUTOCONF=false` +* Want to use own config files? Mount a Volume to `/etc/pdns/conf.d` or simply overwrite `/etc/pdns/pdns.conf` + +**PowerDNS Configuration:** + +Append the PowerDNS setting to the command as shown in the example above. +See `docker run --rm psitrax/powerdns --help` + + +## Maintainer + +* Christoph Wiechert diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..c688156 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,52 @@ +#!/bin/sh +set -e + +# --help, --version +[ "$1" = "--help" ] || [ "$1" = "--version" ] && exec pdns_server $1 +# treat everything expect -- as exec cmd +[ "${1:0:2}" != "--" ] && exec "$@" + +# Set MySQL Credentials in pdns.conf +if $MYSQL_AUTOCONF ; then + sed -r -i "s/^[# ]*gmysql-host=.*/gmysql-host=${MYSQL_HOST}/g" /etc/pdns/pdns.conf + sed -r -i "s/^[# ]*gmysql-port=.*/gmysql-port=${MYSQL_PORT}/g" /etc/pdns/pdns.conf + sed -r -i "s/^[# ]*gmysql-user=.*/gmysql-user=${MYSQL_USER}/g" /etc/pdns/pdns.conf + sed -r -i "s/^[# ]*gmysql-password=.*/gmysql-password=${MYSQL_PASS}/g" /etc/pdns/pdns.conf + sed -r -i "s/^[# ]*gmysql-dbname=.*/gmysql-dbname=${MYSQL_DB}/g" /etc/pdns/pdns.conf +fi + + +MYSQLCMD="mysql -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASS -r -N" + +# wait for Database come ready +isDBup () { + echo "SHOW STATUS" | $MYSQLCMD 1>/dev/null + echo $? +} + +RETRY=10 +until [ `isDBup` -eq 0 ] || [ $RETRY -le 0 ] ; do + echo "Waiting for database to come up" + sleep 5 + RETRY=$(expr $RETRY - 1) +done +if [ $RETRY -le 0 ]; then + >&2 echo Error: Could not connect to Database on $MYSQL_HOST:$MYSQL_PORT + exit 1 +fi + +# init database if necessary +echo "CREATE DATABASE IF NOT EXISTS $MYSQL_DB;" | $MYSQLCMD +MYSQLCMD="$MYSQLCMD $MYSQL_DB" + +if [ "$(echo "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = \"$MYSQL_DB\";" | $MYSQLCMD)" -le 1 ]; then + echo Initializing Database + cat /etc/pdns/schema.sql | $MYSQLCMD +fi + +trap "pdns_control quit" SIGHUP SIGINT SIGTERM + +pdns_server "$@" & + +wait + diff --git a/pdns.conf b/pdns.conf new file mode 100644 index 0000000..6871f94 --- /dev/null +++ b/pdns.conf @@ -0,0 +1,205 @@ +# allow-axfr-ips Allow zonetransfers only to these subnets +# allow-axfr-ips=0.0.0.0/0 + +# allow-recursion List of subnets that are allowed to recurse +################################# +allow-recursion=127.0.0.1 + +# allow-recursion-override Set this so that local data fully overrides the recursor +# allow-recursion-override=no + +# cache-ttl Seconds to store packets in the PacketCache +cache-ttl=60 + +# chroot If set, chroot to this directory for more security +# chroot=/var/empty + +# config-dir Location of configuration directory (pdns.conf) +config-dir=/etc/pdns + +include-dir=/etc/pdns/conf.d + +# config-name Name of this virtual configuration - will rename the binary image +# config-name= + +# control-console Debugging switch - don't use +# control-console=no + +# daemon Operate as a daemon +daemon=no + +# default-soa-name name to insert in the SOA record if none set in the backend +# default-soa-name=a.misconfigured.powerdns.server + +# default-ttl Seconds a result is valid if not set otherwise +# default-ttl=3600 + +# disable-axfr Disable zonetransfers but do allow TCP queries +disable-axfr=no + +# disable-tcp Do not listen to TCP queries +# disable-tcp=no + +# distributor-threads Default number of Distributor (backend) threads to start +distributor-threads=1 + +# do-ipv6-additional-processing Do AAAA additional processing +# do-ipv6-additional-processing=no + +# fancy-records Process URL and MBOXFW records +# fancy-records=no + +# guardian Run within a guardian process +guardian=yes + +# launch Which backends to launch and order to query them in +launch=gmysql +#gmysql-host=mysql +#gmysql-port=3306 +#gmysql-dbname=pdns +#gmysql-user=root +#gmysql-password=root +#gmysql-dnssec=no + +# lazy-recursion Only recurse if question cannot be answered locally +# lazy-recursion=yes + +# load-modules Load this module - supply absolute or relative path +# load-modules= + +# local-address Local IP addresses to which we bind +local-address=0.0.0.0 + +# local-ipv6 Local IP address to which we bind +# local-ipv6= + +# local-port The port on which we listen +local-port=53 + +# log-dns-details If PDNS should log DNS non-erroneous details +# log-dns-details= + +# log-failed-updates If PDNS should log failed update requests +# log-failed-updates= + +# logfile Logfile to use (Windows only) +# logfile=pdns.log + +# logging-facility Log under a specific facility +# logging-facility= + +# loglevel Amount of logging. Higher is more. Do not set below 3 +loglevel=3 + + +# master Act as a master +master=yes + +# max-queue-length Maximum queuelength before considering situation lost +# max-queue-length=5000 + +# max-tcp-connections Maximum number of TCP connections +# max-tcp-connections=10 + +# module-dir Default directory for modules +# module-dir=/usr/lib/pdns + +# negquery-cache-ttl Seconds to store packets in the PacketCache +negquery-cache-ttl=60 + +# no-shuffle Set this to prevent random shuffling of answers - for regression testing +# no-shuffle=off + +# out-of-zone-additional-processing Do out of zone additional processing +# out-of-zone-additional-processing=yes + +# pipebackend-abi-version Version of the pipe backend ABI +# pipebackend-abi-version=1 + +# query-cache-ttl Seconds to store packets in the PacketCache +# query-cache-ttl=20 + +# query-local-address Source IP address for sending queries +# query-local-address= + +# query-logging Hint backends that queries should be logged +# query-logging=no + +# queue-limit Maximum number of milliseconds to queue a query +# queue-limit=1500 + +# recursive-cache-ttl Seconds to store packets in the PacketCache +# recursive-cache-ttl=10 + +# recursor If recursion is desired, IP address of a recursing nameserver +# recursor=no + +# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority +# send-root-referral=no + +# setgid If set, change group id to this gid for more security +setgid=pdns + +# setuid If set, change user id to this uid for more security +setuid=pdns + +# skip-cname Do not perform CNAME indirection for each query +# skip-cname=no + +# slave Act as a slave +# slave=no + +# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds +# slave-cycle-interval=60 + +# smtpredirector Our smtpredir MX host +# smtpredirector=a.misconfigured.powerdns.smtp.server + +# soa-expire-default Default SOA expire +# soa-expire-default=604800 + +# soa-minimum-ttl Default SOA mininum ttl +# soa-minimum-ttl=3600 + +# soa-refresh-default Default SOA refresh +# soa-refresh-default=10800 + +# soa-retry-default Default SOA retry +# soa-retry-default=3600 + +# soa-serial-offset Make sure that no SOA serial is less than this number +# soa-serial-offset=0 + +# socket-dir Where the controlsocket will live +socket-dir=/var/run + +# strict-rfc-axfrs Perform strictly rfc compliant axfrs (very slow) +# strict-rfc-axfrs=no + +# trusted-notification-proxy IP address of incoming notification proxy +# trusted-notification-proxy= + +# urlredirector Where we send hosts to that need to be url redirected +# urlredirector=127.0.0.1 + +# version-string PowerDNS version in packets - full, anonymous, powerdns or custom +version-string=powerdns + +# webserver Start a webserver for monitoring +webserver=no + +# webserver-address IP Address of webserver to listen on +# webserver-address=127.0.0.1 + +# webserver-password Password required for accessing the webserver +# webserver-password= + +# webserver-port Port of webserver to listen on +# webserver-port=8081 + +# webserver-print-arguments If the webserver should print arguments +# webserver-print-arguments=no + +# wildcard-url Process URL and MBOXFW records +# wildcard-url=no + diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..002fe92 --- /dev/null +++ b/schema.sql @@ -0,0 +1,90 @@ +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) +) Engine=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(10) DEFAULT NULL, + content VARCHAR(64000) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + change_date INT DEFAULT NULL, + disabled TINYINT(1) DEFAULT 0, + ordername VARCHAR(255) BINARY DEFAULT NULL, + auth TINYINT(1) DEFAULT 1, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) NOT NULL, + PRIMARY KEY (ip, nameserver) +) Engine=InnoDB; + + +CREATE TABLE comments ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) NOT NULL, + comment VARCHAR(64000) NOT NULL, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + kind VARCHAR(32), + content TEXT, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); + + +CREATE TABLE cryptokeys ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT, + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INT AUTO_INCREMENT, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);