gnu: services: Fix the NFS service.
[jackhill/guix/guix.git] / gnu / services / dns.scm
index 1ef754b..b339eb0 100644 (file)
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2017 Julien Lepiller <julien@lepiller.eu>
 ;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;; Copyright © 2020 Pierre Langlois <pierre.langlois@gmx.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -45,6 +46,9 @@
             zone-file
             zone-entry
 
+            knot-resolver-service-type
+            knot-resolver-configuration
+
             dnsmasq-service-type
             dnsmasq-configuration
 
 (define-record-type* <knot-zone-configuration>
   knot-zone-configuration make-knot-zone-configuration
   knot-zone-configuration?
-  (domain           knot-zone-configuration-domain
-                    (default ""))
-  (file             knot-zone-configuration-file
-                    (default "")) ; the file where this zone is saved.
-  (zone             knot-zone-configuration-zone
-                    (default (zone-file))) ; initial content of the zone file
-  (master           knot-zone-configuration-master
-                    (default '()))
-  (ddns-master      knot-zone-configuration-ddns-master
-                    (default #f))
-  (notify           knot-zone-configuration-notify
-                    (default '()))
-  (acl              knot-zone-configuration-acl
-                    (default '()))
-  (semantic-checks? knot-zone-configuration-semantic-checks?
-                    (default #f))
-  (disable-any?     knot-zone-configuration-disable-any?
-                    (default #f))
-  (zonefile-sync    knot-zone-configuration-zonefile-sync
-                    (default 0))
-  (dnssec-policy    knot-zone-configuration-dnssec-policy
-                    (default #f))
-  (serial-policy    knot-zone-configuration-serial-policy
-                    (default 'increment)))
+  (domain            knot-zone-configuration-domain
+                     (default ""))
+  (file              knot-zone-configuration-file
+                     (default "")) ; the file where this zone is saved.
+  (zone              knot-zone-configuration-zone
+                     (default (zone-file))) ; initial content of the zone file
+  (master            knot-zone-configuration-master
+                     (default '()))
+  (ddns-master       knot-zone-configuration-ddns-master
+                     (default #f))
+  (notify            knot-zone-configuration-notify
+                     (default '()))
+  (acl               knot-zone-configuration-acl
+                     (default '()))
+  (semantic-checks?  knot-zone-configuration-semantic-checks?
+                     (default #f))
+  (disable-any?      knot-zone-configuration-disable-any?
+                     (default #f))
+  (zonefile-sync     knot-zone-configuration-zonefile-sync
+                     (default 0))
+  (zonefile-load     knot-zone-configuration-zonefile-load
+                     (default #f))
+  (journal-content   knot-zone-configuration-journal-content
+                     (default #f))
+  (max-journal-usage knot-zone-configuration-max-journal-usage
+                     (default #f))
+  (max-journal-depth knot-zone-configuration-max-journal-depth
+                     (default #f))
+  (max-zone-size     knot-zone-configuration-max-zone-size
+                     (default #f))
+  (dnssec-policy     knot-zone-configuration-dnssec-policy
+                     (default #f))
+  (serial-policy     knot-zone-configuration-serial-policy
+                     (default 'increment)))
 
 (define-record-type* <knot-remote-configuration>
   knot-remote-configuration make-knot-remote-configuration
                  (default knot))
   (run-directory knot-configuration-run-directory
                  (default "/var/run/knot"))
+  (includes      knot-configuration-includes
+                 (default '()))
   (listen-v4     knot-configuration-listen-v4
                  (default "0.0.0.0"))
   (listen-v6     knot-configuration-listen-v6
     (error-out "knot configuration field must be a package."))
   (unless (string? (knot-configuration-run-directory config))
     (error-out "run-directory must be a string."))
+  (unless (list? (knot-configuration-includes config))
+    (error-out "includes must be a list of strings or file-like objects."))
   (unless (list? (knot-configuration-keys config))
     (error-out "keys must be a list of knot-key-configuration."))
   (for-each (lambda (key) (verify-knot-key-configuration key))
           (fold (lambda (x1 x2)
                   (string-append (if (symbol? x1) (symbol->string x1) x1) ", "
                                  (if (symbol? x2) (symbol->string x2) x2)))
-                (car l) (cdr l))
+                (if (symbol? (car l)) (symbol->string (car l)) (car l)) (cdr l))
           "]"))))
 
 (define (knot-acl-config acls)
                 (acl (list #$@(knot-zone-configuration-acl zone)))
                 (semantic-checks? #$(knot-zone-configuration-semantic-checks? zone))
                 (disable-any? #$(knot-zone-configuration-disable-any? zone))
+                (zonefile-sync #$(knot-zone-configuration-zonefile-sync zone))
+                (zonefile-load '#$(knot-zone-configuration-zonefile-load zone))
+                (journal-content #$(knot-zone-configuration-journal-content zone))
+                (max-journal-usage #$(knot-zone-configuration-max-journal-usage zone))
+                (max-journal-depth #$(knot-zone-configuration-max-journal-depth zone))
+                (max-zone-size #$(knot-zone-configuration-max-zone-size zone))
                 (dnssec-policy #$(knot-zone-configuration-dnssec-policy zone))
                 (serial-policy '#$(knot-zone-configuration-serial-policy zone)))
             (format #t "    - domain: ~a\n" domain)
                           (knot-zone-configuration-acl zone))))
             (format #t "      semantic-checks: ~a\n" (if semantic-checks? "on" "off"))
             (format #t "      disable-any: ~a\n" (if disable-any? "on" "off"))
+            (if zonefile-sync
+              (format #t "      zonefile-sync: ~a\n" zonefile-sync))
+            (if zonefile-load
+              (format #t "      zonefile-load: ~a\n"
+                      (symbol->string zonefile-load)))
+            (if journal-content
+              (format #t "      journal-content: ~a\n"
+                      (symbol->string journal-content)))
+            (if max-journal-usage
+              (format #t "      max-journal-usage: ~a\n" max-journal-usage))
+            (if max-journal-depth
+              (format #t "      max-journal-depth: ~a\n" max-journal-depth))
+            (if max-zone-size
+              (format #t "      max-zone-size: ~a\n" max-zone-size))
             (if dnssec-policy
                 (begin
                   (format #t "      dnssec-signing: on\n")
     #~(begin
         (call-with-output-file #$output
           (lambda (port)
+            (for-each (lambda (inc)
+                        (format port "include: ~a\n" inc))
+                      '#$(knot-configuration-includes config))
             (format port "server:\n")
             (format port "    rundir: ~a\n" #$(knot-configuration-run-directory config))
             (format port "    user: knot\n")
                         (service-extension activation-service-type
                                            knot-activation)
                         (service-extension account-service-type
-                                           (const %knot-accounts))))))
+                                           (const %knot-accounts))))
+                (description
+                 "Run @uref{https://www.knot-dns.cz/, Knot}, an authoritative
+name server for the @acronym{DNS, Domain Name System}.")))
+
+\f
+;;;
+;;; Knot Resolver.
+;;;
+
+(define-record-type* <knot-resolver-configuration>
+  knot-resolver-configuration
+  make-knot-resolver-configuration
+  knot-resolver-configuration?
+  (package knot-resolver-configuration-package
+           (default knot-resolver))
+  (kresd-config-file knot-resolver-kresd-config-file
+                     (default %kresd.conf))
+  (garbage-collection-interval knot-resolver-garbage-collection-interval
+                               (default 1000)))
+
+(define %kresd.conf
+  (plain-file "kresd.conf" "-- -*- mode: lua -*-
+trust_anchors.add_file('/var/cache/knot-resolver/root.keys')
+net = { '127.0.0.1', '::1' }
+user('knot-resolver', 'knot-resolver')
+modules = { 'hints > iterate', 'stats', 'predict' }
+cache.size = 100 * MB
+"))
+
+(define %knot-resolver-accounts
+  (list (user-group
+         (name "knot-resolver")
+         (system? #t))
+        (user-account
+         (name "knot-resolver")
+         (group "knot-resolver")
+         (system? #t)
+         (home-directory "/var/cache/knot-resolver")
+         (shell (file-append shadow "/sbin/nologin")))))
+
+(define (knot-resolver-activation config)
+  #~(begin
+      (use-modules (guix build utils))
+      (let ((rundir "/var/cache/knot-resolver")
+            (owner (getpwnam "knot-resolver")))
+        (mkdir-p rundir)
+        (chown rundir (passwd:uid owner) (passwd:gid owner)))))
+
+(define knot-resolver-shepherd-services
+  (match-lambda
+    (($ <knot-resolver-configuration> package
+                                      kresd-config-file
+                                      garbage-collection-interval)
+     (list
+      (shepherd-service
+       (provision '(kresd))
+       (requirement '(networking))
+       (documentation "Run the Knot Resolver daemon.")
+       (start #~(make-forkexec-constructor
+                 '(#$(file-append package "/sbin/kresd")
+                   "-c" #$kresd-config-file "-n"
+                   "/var/cache/knot-resolver")))
+       (stop #~(make-kill-destructor)))
+      (shepherd-service
+       (provision '(kres-cache-gc))
+       (requirement '(user-processes))
+       (documentation "Run the Knot Resolver Garbage Collector daemon.")
+       (start #~(make-forkexec-constructor
+                 '(#$(file-append package "/sbin/kres-cache-gc")
+                   "-d" #$(number->string garbage-collection-interval)
+                   "-c" "/var/cache/knot-resolver")
+                 #:user "knot-resolver"
+                 #:group "knot-resolver"))
+       (stop #~(make-kill-destructor)))))))
+
+(define knot-resolver-service-type
+  (service-type
+   (name 'knot-resolver)
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             knot-resolver-shepherd-services)
+          (service-extension activation-service-type
+                             knot-resolver-activation)
+          (service-extension account-service-type
+                             (const %knot-resolver-accounts))))
+   (default-value (knot-resolver-configuration))
+   (description "Run the Knot DNS Resolver.")))
 
 \f
 ;;;
                     (default #f))       ;boolean
   (servers          dnsmasq-configuration-servers
                     (default '()))      ;list of string
+  (addresses        dnsmasq-configuration-addresses
+                    (default '()))      ;list of string
   (cache-size       dnsmasq-configuration-cache-size
                     (default 150))      ;integer
   (negative-cache?  dnsmasq-configuration-negative-cache?
-                    (default #t)))      ;boolean
+                    (default #t))      ;boolean
+  (tftp-enable?     dnsmasq-configuration-tftp-enable?
+                    (default #f))       ;boolean
+  (tftp-no-fail?    dnsmasq-configuration-tftp-no-fail?
+                    (default #f))       ;boolean
+  (tftp-single-port? dnsmasq-configuration-tftp-single-port?
+                    (default #f))       ;boolean
+  (tftp-secure?     dnsmasq-tftp-secure?
+                    (default #f))       ;boolean
+  (tftp-max         dnsmasq-tftp-max
+                    (default #f))       ;integer
+  (tftp-mtu         dnsmasq-tftp-mtu
+                    (default #f))       ;integer
+  (tftp-no-blocksize? dnsmasq-tftp-no-blocksize?
+                      (default #f))     ;boolean
+  (tftp-lowercase?  dnsmasq-tftp-lowercase?
+                    (default #f))       ;boolean
+  (tftp-port-range  dnsmasq-tftp-port-range
+                    (default #f))       ;string
+  (tftp-root        dnsmasq-tftp-root
+                    (default "/var/empty,lo")) ;string
+  (tftp-unique-root dnsmasq-tftp-unique-root
+                    (default #f)))      ;"" or "ip" or "mac"
 
 (define dnsmasq-shepherd-service
   (match-lambda
                                 no-hosts?
                                 port local-service? listen-addresses
                                 resolv-file no-resolv? servers
-                                cache-size negative-cache?)
+                                addresses cache-size negative-cache?
+                                tftp-enable? tftp-no-fail?
+                                tftp-single-port? tftp-secure?
+                                tftp-max tftp-mtu tftp-no-blocksize?
+                                tftp-lowercase? tftp-port-range
+                                tftp-root tftp-unique-root)
      (shepherd-service
       (provision '(dnsmasq))
       (requirement '(networking))
                          '())
                   #$@(map (cut format #f "--server=~a" <>)
                           servers)
+                  #$@(map (cut format #f "--address=~a" <>)
+                          addresses)
                   #$(format #f "--cache-size=~a" cache-size)
                   #$@(if negative-cache?
                          '()
-                         '("--no-negcache")))
+                         '("--no-negcache"))
+                  #$@(if tftp-enable?
+                         '("--enable-tftp")
+                         '())
+                  #$@(if tftp-no-fail?
+                         '("--tftp-no-fail")
+                         '())
+                  #$@(if tftp-single-port?
+                         '("--tftp-single-port")
+                         '())
+                  #$@(if tftp-secure?
+                         '("--tftp-secure?")
+                         '())
+                  #$@(if tftp-max
+                         (list (format #f "--tftp-max=~a" tftp-max))
+                         '())
+                  #$@(if tftp-mtu
+                         (list (format #f "--tftp-mtu=~a" tftp-mtu))
+                         '())
+                  #$@(if tftp-no-blocksize?
+                         '("--tftp-no-blocksize")
+                         '())
+                  #$@(if tftp-lowercase?
+                         '("--tftp-lowercase")
+                         '())
+                  #$@(if tftp-port-range
+                         (list (format #f "--tftp-port-range=~a"
+                                          tftp-port-range))
+                         '())
+                  #$@(if tftp-root
+                         (list (format #f "--tftp-root=~a" tftp-root))
+                         '())
+                  #$@(if tftp-unique-root
+                         (list
+                          (if (> (length tftp-unique-root) 0)
+                              (format #f "--tftp-unique-root=~a" tftp-unique-root)
+                              (format #f "--tftp-unique-root")))
+                         '()))
                 #:pid-file "/run/dnsmasq.pid"))
       (stop #~(make-kill-destructor))))))