(define-module (arunisaac powerdns) #:use-module (ice-9 match) #:use-module (gnu packages admin) #:use-module (gnu packages boost) #:use-module (gnu packages lua) #:use-module (gnu packages pkg-config) #:use-module (gnu packages tls) #:use-module (gnu services) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (guix build-system gnu) #:use-module (guix download) #:use-module (guix gexp) #:use-module ((guix licenses) #:prefix license:) #:use-module (guix packages) #:use-module (guix records) #:export (powerdns-configuration powerdns-configuration? powerdns-configuration-package powerdns-configuration-backends powerdns-configuration-expand-alias? powerdns-configuration-local-address powerdns-configuration-local-port powerdns-configuration-socket-directory powerdns-configuration-resolver powerdns-configuration-zone-cache-refresh-interval powerdns-configuration-bind-config powerdns-configuration-bind-check-interval powerdns-configuration-pipe-abi-version powerdns-configuration-pipe-command powerdns-configuration-pipe-timeout powerdns-configuration-pipe-regex powerdns-service-type)) (define pdns (package (name "pdns") (version "4.6.2") (source (origin (method url-fetch) (uri (string-append "https://downloads.powerdns.com/releases/pdns-" version ".tar.bz2")) (sha256 (base32 "1f0r1gp64wx5rak1srzjxdzvbzq178xn2882hnsbn4dv8j4q8hzl")))) (build-system gnu-build-system) (arguments (list #:configure-flags #~(list "--disable-lua-records" "--with-modules=bind" (string-append "--sbindir=" (assoc-ref %outputs "out") "/bin")))) (inputs (list luajit openssl)) (native-inputs (list boost pkg-config)) (home-page "https://www.powerdns.com/index.html") (synopsis "Authoritative DNS name server") (description "The PowerDNS Authoritative Server is a versatile nameserver which supports a large number of backends. These backends can either be plain zone files or be more dynamic in nature. PowerDNS backends are datastores that the server will consult and contains DNS records (and some metadata). The backends range from database backends (MySQL, PostgreSQL) and BIND zone files to co-processes and JSON APIs. Multiple backends can be enabled in the configuration. Each backend can be configured separately.") (license (list license:gpl2 ; main license ;; ext/json11, ext/yahttp, src_js/d3.js, src_js/jquery.js, ;; src_js/moment.js, src_js/rickshaw.js license:expat ;; ext/luawrapper license:bsd-3)))) (define-record-type* powerdns-configuration make-powerdns-configuration powerdns-configuration? (package powerdns-configuration-package (default pdns)) (backends powerdns-configuration-backends (default (list))) (expand-alias? powerdns-configuration-expand-alias? (default 'unset)) (local-address powerdns-configuration-local-address (default #f)) (local-port powerdns-configuration-local-port (default #f)) ;; TODO: Reconsider unset for socket dir. (socket-directory powerdns-configuration-socket-directory (default "/var/run/powerdns")) (resolver powerdns-configuration-resolver (default #f)) (zone-cache-refresh-interval powerdns-configuration-zone-cache-refresh-interval (default #f)) ;; BIND backend configuration (bind-config powerdns-configuration-bind-config (default #f)) (bind-check-interval powerdns-configuration-bind-check-interval (default #f)) ;; Pipe backend configuration (pipe-abi-version powerdns-configuration-pipe-abi-version (default #f)) (pipe-command powerdns-configuration-pipe-command (default #f)) (pipe-timeout powerdns-configuration-pipe-timeout (default #f)) (pipe-regex powerdns-configuration-pipe-regex (default #f))) (define %powerdns-accounts (list (user-account (name "powerdns") (group "powerdns") (system? #t) (comment "PowerDNS daemon user") (home-directory "/var/empty") (shell (file-append shadow "/sbin/nologin"))) (user-group (name "powerdns") (system? #t)))) (define (pdns-conf-gexp config) (match config (($ package backends expand-alias? local-address local-port socket-directory resolver zone-cache-refresh-interval bind-config bind-check-interval pipe-abi-version pipe-command pipe-timeout pipe-regex) (when (and (not (eq? expand-alias? 'unset)) expand-alias? (not resolver)) (error "expand-alias? will be ignored without a resolver")) (when (and (member "pipe" backends) (not pipe-command)) (error "pipe-command is mandatory when pipe backend is used")) #~(begin (define (write-setting port key value) "Write KEY=VALUE to PORT when VALUE is not #f." (when value (format port "~a=~a~%" key value))) (call-with-output-file #$output (lambda (port) (write-setting port "setuid" "powerdns") (write-setting port "setgid" "powerdns") (write-setting port "launch" (and (not (null? '#$backends)) (string-join '#$backends ","))) (write-setting port "expand-alias" #$(cond ((eq? expand-alias? 'unset) #f) (expand-alias? "yes") (else "no"))) (write-setting port "local-port" #$local-address) (write-setting port "local-port" #$local-port) (write-setting port "socket-dir" #$socket-directory) (write-setting port "resolver" #$resolver) (write-setting port "zone-cache-refresh-interval" #$zone-cache-refresh-interval) ;; BIND backend configuration (write-setting port "bind-config" #$bind-config) (write-setting port "bind-check-interval" #$bind-check-interval) ;; Pipe backend configuration (write-setting port "pipe-abi-version" #$pipe-abi-version) (write-setting port "pipe-command" #$pipe-command) (write-setting port "pipe-timeout" #$pipe-timeout) (write-setting port "pipe-regex" #$pipe-regex))))))) (define (powerdns-activation config) (with-imported-modules '((guix build utils)) #~(begin (use-modules (guix build utils)) (let ((user (getpw "powerdns")) (socket-directory #$(powerdns-configuration-socket-directory config))) ;; Create socket directory. (mkdir-p socket-directory) (chown socket-directory (passwd:uid user) (passwd:gid user)))))) (define (powerdns-shepherd-service config) (shepherd-service (documentation "Run PowerDNS authoritative name server.") (provision '(powerdns)) (requirement '(networking)) (start #~(make-forkexec-constructor (list #$(file-append (powerdns-configuration-package config) "/bin/pdns_server") (string-append "--config-dir=" #$(file-union "powerdns" `(("pdns.conf" ,(computed-file "pdns.conf" (pdns-conf-gexp config))))))) #:log-file "/var/log/pdns.log")) (stop #~(make-kill-destructor)))) (define powerdns-service-type (service-type (name 'powerdns) (description "Run PowerDNS authoritative name server.") (extensions (list (service-extension account-service-type (const %powerdns-accounts)) (service-extension activation-service-type powerdns-activation) (service-extension shepherd-root-service-type (compose list powerdns-shepherd-service)))) (default-value (powerdns-configuration))))