;;; 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.
;;;
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
(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)
- (if (knot-configuration-includes config)
- (for-each (lambda (inc)
- (format port "include: ~a\n" inc))
- (knot-configuration-includes config)))
+ (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))))))