diff --git a/gnu/packages/dns.scm b/gnu/packages/dns.scm
index 9cc707e5b4..b929f8b426 100644
--- a/gnu/packages/dns.scm
+++ b/gnu/packages/dns.scm
@@ -32,9 +32,11 @@
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages base)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages boost)
   #:use-module (gnu packages databases)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages crypto)
+  #:use-module (gnu packages curl)
   #:use-module (gnu packages datastructures)
   #:use-module (gnu packages flex)
   #:use-module (gnu packages glib)
@@ -44,6 +46,7 @@
   #:use-module (gnu packages libevent)
   #:use-module (gnu packages libidn)
   #:use-module (gnu packages linux)
+  #:use-module (gnu packages lua)
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages nettle)
   #:use-module (gnu packages networking)
@@ -51,6 +54,8 @@
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages protobuf)
   #:use-module (gnu packages python)
+  #:use-module (gnu packages ruby)
+  #:use-module (gnu packages sqlite)
   #:use-module (gnu packages swig)
   #:use-module (gnu packages tls)
   #:use-module (gnu packages web)
@@ -403,6 +408,177 @@ run in a @code{chroot} jail, thus making any security flaws in NSD less likely
 to result in system-wide compromise.")
     (license (list license:bsd-3))))
 
+(define-public pdns
+  (package
+    (name "pdns")
+    (version "4.1.6")
+    (source
+     (origin
+       (method url-fetch)
+       (uri
+        (string-append "https://downloads.powerdns.com/releases/pdns-"
+                       version ".tar.bz2"))
+       (sha256
+        (base32 "0ggpcvzj90a31qf71m8788ql0hbxnkb9y6c3wgqr9l0qwv8dsgpm"))
+       (modules '((guix build utils)))
+       (snippet
+        '(begin
+           ;; Delete (free) back ends for a non-free database.  This also
+           ;; side-steps some licence confusion where modules/oraclebackend's
+           ;; README says ‘MIT’ but the actual file headers state GPL2 [only].
+           (for-each
+            (lambda (back-end)
+              (with-directory-excursion "modules"
+                (delete-file-recursively back-end))
+              (substitute* "configure"
+                (((format " modules/~a/Makefile" back-end))
+                 ""))
+              (substitute* "modules/Makefile.in"
+                (((format ".*~a.*" back-end)) ; delete the whole line
+                 "")))
+            (list "goraclebackend"
+                  "oraclebackend"))
+           #t))))
+    (build-system gnu-build-system)
+    ;; Keep the extra tools from littering the user's profile unless desired.
+    ;; There's no make target or other way to cleanly separate the tools from
+    ;; the core.  We have to rely on a hard-coded list (below), which needs to
+    ;; be double-checked when changing the package version or configuration.
+    (outputs (list "out" "tools"))
+    (arguments
+     `(#:configure-flags
+       (list "--enable-libsodium"       ; ed25519 (DNSSEC algorithm 15)
+             ;; "--enable-libdecaf"     ; ed25519 & Ed448 (XXX unpackaged)
+             "--enable-reproducible"
+             "--enable-tools"
+             "--enable-unit-tests"
+
+             ;; XXX The 'core' (sbin/pdns_server) retains references to some
+             ;; dependencies (e.g. luajit, sqlite) but not all of them (e.g.
+             ;; postgresql). Moving backend modules to their own output (or
+             ;; package?) might reduce the closure size significantly and/or
+             ;; allow us to build more (all?) of them. Something to consider.
+             (string-append
+              "--with-dynmodules="      ; build dynamic modules...
+              (string-join
+               (list "bind"             ; BIND-style zone files
+                     "gpgsql"           ; generic PostgreSQL
+                     "gsqlite3"         ; generic Sqlite
+                     "lua"              ; Lua scripting
+                     "pipe"             ; simple stdin/stdout pipe
+                     "remote")          ; generic JSON/RPC connector
+               " "))
+             "--with-modules="          ; ...and no static modules
+
+             "--with-luajit"            ; use JIT variant for Lua backend
+             "--with-protobuf"          ; for logging DNS query information
+             "--with-sqlite3"           ; include the sqlite3 driver
+
+             (string-append "--docdir=" (assoc-ref %outputs "out") "/share/doc/"
+                            ,name "-" ,version)
+             "--sysconfdir=/etc/powerdns"
+             "--with-socketdir=/run")
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'use-packaged-yahttp
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let ((yahttp (assoc-ref inputs "yahttp")))
+               (delete-file-recursively "ext/yahttp")
+               (substitute* "configure"
+                 (("\\$\\(top_builddir\\)/ext/yahttp/yahttp")
+                  (string-append yahttp "/lib"))
+                 (("ext/(yahttp/)+Makefile") ""))
+               (substitute* "ext/Makefile.in"
+                 (("yahttp ") ""))
+               #t)))
+         (add-after 'unpack 'omit-PDNS_CONFIG_ARGS
+           ;; Avoid ‘pdns_server --version’ printing build-time details, like
+           ;; PKG_CONFIG_PATH, which embed references to almost every input.
+           (lambda _
+             (substitute* "configure"
+               (("#define PDNS_CONFIG_ARGS.*") ""))
+             #t))
+         (replace 'install
+           ;; Don't try to install configuration files to /etc.
+           (lambda* (#:key make-flags #:allow-other-keys)
+             (apply invoke "make" "sysconfdir=$(docdir)/examples" "install"
+                    make-flags)))
+         (add-after 'install 'move-tools
+           ;; Move tools (and their documentation) to a separate output.
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out   (assoc-ref outputs "out"))
+                    (tools (assoc-ref outputs "tools"))
+                    (move  (lambda (file)
+                             (let ((target (string-append tools "/" file)))
+                               (mkdir-p (dirname target))
+                               (rename-file file target)))))
+               (with-directory-excursion out
+                 (for-each (lambda (tool)
+                             (move (string-append "bin/" tool))
+                             (move (string-append "share/man/man1/"
+                                                  tool ".1")))
+                           (list "calidns"
+                                 "dnsbulktest"
+                                 "dnsgram"
+                                 "dnsreplay"
+                                 "dnsscan"
+                                 "dnsscope"
+                                 "dnstcpbench"
+                                 "dnswasher"
+                                 "dumresp"
+                                 "ixplore"
+                                 "nproxy"
+                                 "nsec3dig"
+                                 "pdns_notify"
+                                 "saxfr"
+                                 "sdig"))
+
+                 ;; This one weird tool doesn't have a man page.
+                 (move "bin/stubquery")
+                 #t)))))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+
+       ;; For tests.
+       ("curl" ,curl)
+       ("perl" ,perl)
+       ("ruby" ,ruby)))
+    (inputs
+     `(("boost" ,boost)
+       ("libsodium" ,libsodium)
+       ("luajit" ,luajit)
+       ("openssl" ,openssl)
+       ("postgresql" ,postgresql)
+       ("protobuf" ,protobuf)
+       ("sqlite" ,sqlite)
+       ("yahttp" ,yahttp)
+       ("zlib" ,zlib)))
+    (home-page "https://www.powerdns.com/")
+    (synopsis "Authoritative DNS name server with dynamic back-ends")
+    (description
+     "This is the PowerDNS Authoritative Server, a versatile name server for the
+@acronym{DNS, Domain Name System} that supports a wide variety of storage back
+ends.
+
+The core server (@command{pdns_server}) handles all packet processing and DNS
+intelligence, while retrieving and updating the actual DNS records (and any
+additional metadata) through one or more of numerous loadable backends.
+
+Included back ends range from simple BIND-style zone files and relational
+databases to (geographical) load-balancing, JSON APIs, and entire scripting
+languages.  Records can be transparently signed for use with @acronym{DNSSEC,
+Domain Name System Security Extensions}.  Automated key management is available.
+
+Real-time statistics can be exported to different formats, or through an optional
+built-in Web server and API that allow for basic remote administration.")
+    (license
+     (list license:bsd-3                ; ext/luawrapper/include/LuaContext.*
+           license:expat                ; ext/{json11,yahttp}
+           ;; pdns/{ssqlite3,tcpreceiver,test-tsig,zone2ldap}.* and
+           ;; modules/ldapbackend are GPL2-only.
+           license:gpl2
+           license:gpl3+))))            ; the rest is GPL[23]+
+
 (define-public unbound
   (package
     (name "unbound")
