dns.scm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 Julien Lepiller <julien@lepiller.eu>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gnu services dns)
  19. #:use-module (gnu services)
  20. #:use-module (gnu services configuration)
  21. #:use-module (gnu services shepherd)
  22. #:use-module (gnu system shadow)
  23. #:use-module (gnu packages admin)
  24. #:use-module (gnu packages dns)
  25. #:use-module (guix packages)
  26. #:use-module (guix records)
  27. #:use-module (guix gexp)
  28. #:use-module (srfi srfi-1)
  29. #:use-module (srfi srfi-34)
  30. #:use-module (srfi srfi-35)
  31. #:use-module (ice-9 match)
  32. #:use-module (ice-9 regex)
  33. #:export (knot-service-type
  34. knot-acl-configuration
  35. knot-key-configuration
  36. knot-keystore-configuration
  37. knot-zone-configuration
  38. knot-remote-configuration
  39. knot-policy-configuration
  40. knot-configuration
  41. define-zone-entries
  42. zone-file
  43. zone-entry))
  44. ;;;
  45. ;;; Knot DNS.
  46. ;;;
  47. (define-record-type* <knot-key-configuration>
  48. knot-key-configuration make-knot-key-configuration
  49. knot-key-configuration?
  50. (id knot-key-configuration-id
  51. (default ""))
  52. (algorithm knot-key-configuration-algorithm
  53. (default #f)); one of #f, or an algorithm name
  54. (secret knot-key-configuration-secret
  55. (default "")))
  56. (define-record-type* <knot-acl-configuration>
  57. knot-acl-configuration make-knot-acl-configuration
  58. knot-acl-configuration?
  59. (id knot-acl-configuration-id
  60. (default ""))
  61. (address knot-acl-configuration-address
  62. (default '()))
  63. (key knot-acl-configuration-key
  64. (default '()))
  65. (action knot-acl-configuration-action
  66. (default '()))
  67. (deny? knot-acl-configuration-deny?
  68. (default #f)))
  69. (define-record-type* <zone-entry>
  70. zone-entry make-zone-entry
  71. zone-entry?
  72. (name zone-entry-name
  73. (default "@"))
  74. (ttl zone-entry-ttl
  75. (default ""))
  76. (class zone-entry-class
  77. (default "IN"))
  78. (type zone-entry-type
  79. (default "A"))
  80. (data zone-entry-data
  81. (default "")))
  82. (define-record-type* <zone-file>
  83. zone-file make-zone-file
  84. zone-file?
  85. (entries zone-file-entries
  86. (default '()))
  87. (origin zone-file-origin
  88. (default ""))
  89. (ns zone-file-ns
  90. (default "ns"))
  91. (mail zone-file-mail
  92. (default "hostmaster"))
  93. (serial zone-file-serial
  94. (default 1))
  95. (refresh zone-file-refresh
  96. (default (* 2 24 3600)))
  97. (retry zone-file-retry
  98. (default (* 15 60)))
  99. (expiry zone-file-expiry
  100. (default (* 2 7 24 3600)))
  101. (nx zone-file-nx
  102. (default 3600)))
  103. (define-record-type* <knot-keystore-configuration>
  104. knot-keystore-configuration make-knot-keystore-configuration
  105. knot-keystore-configuration?
  106. (id knot-keystore-configuration-id
  107. (default ""))
  108. (backend knot-keystore-configuration-backend
  109. (default 'pem))
  110. (config knot-keystore-configuration-config
  111. (default "/var/lib/knot/keys/keys")))
  112. (define-record-type* <knot-policy-configuration>
  113. knot-policy-configuration make-knot-policy-configuration
  114. knot-policy-configuration?
  115. (id knot-policy-configuration-id
  116. (default ""))
  117. (keystore knot-policy-configuration-keystore
  118. (default "default"))
  119. (manual? knot-policy-configuration-manual?
  120. (default #f))
  121. (single-type-signing? knot-policy-configuration-single-type-signing?
  122. (default #f))
  123. (algorithm knot-policy-configuration-algorithm
  124. (default "ecdsap256sha256"))
  125. (ksk-size knot-policy-configuration-ksk-size
  126. (default 256))
  127. (zsk-size knot-policy-configuration-zsk-size
  128. (default 256))
  129. (dnskey-ttl knot-policy-configuration-dnskey-ttl
  130. (default 'default))
  131. (zsk-lifetime knot-policy-configuration-zsk-lifetime
  132. (default (* 30 24 3600)))
  133. (propagation-delay knot-policy-configuration-propagation-delay
  134. (default (* 24 3600)))
  135. (rrsig-lifetime knot-policy-configuration-rrsig-lifetime
  136. (default (* 14 24 3600)))
  137. (rrsig-refresh knot-policy-configuration-rrsig-refresh
  138. (default (* 7 24 3600)))
  139. (nsec3? knot-policy-configuration-nsec3?
  140. (default #f))
  141. (nsec3-iterations knot-policy-configuration-nsec3-iterations
  142. (default 5))
  143. (nsec3-salt-length knot-policy-configuration-nsec3-salt-length
  144. (default 8))
  145. (nsec3-salt-lifetime knot-policy-configuration-nsec3-salt-lifetime
  146. (default (* 30 24 3600))))
  147. (define-record-type* <knot-zone-configuration>
  148. knot-zone-configuration make-knot-zone-configuration
  149. knot-zone-configuration?
  150. (domain knot-zone-configuration-domain
  151. (default ""))
  152. (file knot-zone-configuration-file
  153. (default "")) ; the file where this zone is saved.
  154. (zone knot-zone-configuration-zone
  155. (default (zone-file))) ; initial content of the zone file
  156. (master knot-zone-configuration-master
  157. (default '()))
  158. (ddns-master knot-zone-configuration-ddns-master
  159. (default #f))
  160. (notify knot-zone-configuration-notify
  161. (default '()))
  162. (acl knot-zone-configuration-acl
  163. (default '()))
  164. (semantic-checks? knot-zone-configuration-semantic-checks?
  165. (default #f))
  166. (disable-any? knot-zone-configuration-disable-any?
  167. (default #f))
  168. (zonefile-sync knot-zone-configuration-zonefile-sync
  169. (default 0))
  170. (dnssec-policy knot-zone-configuration-dnssec-policy
  171. (default #f))
  172. (serial-policy knot-zone-configuration-serial-policy
  173. (default 'increment)))
  174. (define-record-type* <knot-remote-configuration>
  175. knot-remote-configuration make-knot-remote-configuration
  176. knot-remote-configuration?
  177. (id knot-remote-configuration-id
  178. (default ""))
  179. (address knot-remote-configuration-address
  180. (default '()))
  181. (via knot-remote-configuration-via
  182. (default '()))
  183. (key knot-remote-configuration-key
  184. (default #f)))
  185. (define-record-type* <knot-configuration>
  186. knot-configuration make-knot-configuration
  187. knot-configuration?
  188. (knot knot-configuration-knot
  189. (default knot))
  190. (run-directory knot-configuration-run-directory
  191. (default "/var/run/knot"))
  192. (listen-v4 knot-configuration-listen-v4
  193. (default "0.0.0.0"))
  194. (listen-v6 knot-configuration-listen-v6
  195. (default "::"))
  196. (listen-port knot-configuration-listen-port
  197. (default 53))
  198. (keys knot-configuration-keys
  199. (default '()))
  200. (keystores knot-configuration-keystores
  201. (default '()))
  202. (acls knot-configuration-acls
  203. (default '()))
  204. (remotes knot-configuration-remotes
  205. (default '()))
  206. (policies knot-configuration-policies
  207. (default '()))
  208. (zones knot-configuration-zones
  209. (default '())))
  210. (define-syntax define-zone-entries
  211. (syntax-rules ()
  212. ((_ id (name ttl class type data) ...)
  213. (define id (list (make-zone-entry name ttl class type data) ...)))))
  214. (define (error-out msg)
  215. (raise (condition (&message (message msg)))))
  216. (define (verify-knot-key-configuration key)
  217. (unless (knot-key-configuration? key)
  218. (error-out "keys must be a list of only knot-key-configuration."))
  219. (let ((id (knot-key-configuration-id key)))
  220. (unless (and (string? id) (not (equal? id "")))
  221. (error-out "key id must be a non empty string.")))
  222. (unless (memq '(#f hmac-md5 hmac-sha1 hmac-sha224 hmac-sha256 hmac-sha384 hmac-sha512)
  223. (knot-key-configuration-algorithm key))
  224. (error-out "algorithm must be one of: #f, 'hmac-md5, 'hmac-sha1,
  225. 'hmac-sha224, 'hmac-sha256, 'hmac-sha384 or 'hmac-sha512")))
  226. (define (verify-knot-keystore-configuration keystore)
  227. (unless (knot-keystore-configuration? keystore)
  228. (error-out "keystores must be a list of only knot-keystore-configuration."))
  229. (let ((id (knot-keystore-configuration-id keystore)))
  230. (unless (and (string? id) (not (equal? id "")))
  231. (error-out "keystore id must be a non empty string.")))
  232. (unless (memq '(pem pkcs11)
  233. (knot-keystore-configuration-backend keystore))
  234. (error-out "backend must be one of: 'pem or 'pkcs11")))
  235. (define (verify-knot-policy-configuration policy)
  236. (unless (knot-policy-configuration? policy)
  237. (error-out "policies must be a list of only knot-policy-configuration."))
  238. (let ((id (knot-policy-configuration-id policy)))
  239. (unless (and (string? id) (not (equal? id "")))
  240. (error-out "policy id must be a non empty string."))))
  241. (define (verify-knot-acl-configuration acl)
  242. (unless (knot-acl-configuration? acl)
  243. (error-out "acls must be a list of only knot-acl-configuration."))
  244. (let ((id (knot-acl-configuration-id acl))
  245. (address (knot-acl-configuration-address acl))
  246. (key (knot-acl-configuration-key acl))
  247. (action (knot-acl-configuration-action acl)))
  248. (unless (and (string? id) (not (equal? id "")))
  249. (error-out "acl id must be a non empty string."))
  250. (unless (and (list? address)
  251. (fold (lambda (x1 x2) (and (string? x1) (string? x2))) "" address))
  252. (error-out "acl address must be a list of strings.")))
  253. (unless (boolean? (knot-acl-configuration-deny? acl))
  254. (error-out "deny? must be #t or #f.")))
  255. (define (verify-knot-zone-configuration zone)
  256. (unless (knot-zone-configuration? zone)
  257. (error-out "zones must be a list of only knot-zone-configuration."))
  258. (let ((domain (knot-zone-configuration-domain zone)))
  259. (unless (and (string? domain) (not (equal? domain "")))
  260. (error-out "zone domain must be a non empty string."))))
  261. (define (verify-knot-remote-configuration remote)
  262. (unless (knot-remote-configuration? remote)
  263. (error-out "remotes must be a list of only knot-remote-configuration."))
  264. (let ((id (knot-remote-configuration-id remote)))
  265. (unless (and (string? id) (not (equal? id "")))
  266. (error-out "remote id must be a non empty string."))))
  267. (define (verify-knot-configuration config)
  268. (unless (package? (knot-configuration-knot config))
  269. (error-out "knot configuration field must be a package."))
  270. (unless (string? (knot-configuration-run-directory config))
  271. (error-out "run-directory must be a string."))
  272. (unless (list? (knot-configuration-keys config))
  273. (error-out "keys must be a list of knot-key-configuration."))
  274. (for-each (lambda (key) (verify-knot-key-configuration key))
  275. (knot-configuration-keys config))
  276. (unless (list? (knot-configuration-keystores config))
  277. (error-out "keystores must be a list of knot-keystore-configuration."))
  278. (for-each (lambda (keystore) (verify-knot-keystore-configuration keystore))
  279. (knot-configuration-keystores config))
  280. (unless (list? (knot-configuration-acls config))
  281. (error-out "acls must be a list of knot-acl-configuration."))
  282. (for-each (lambda (acl) (verify-knot-acl-configuration acl))
  283. (knot-configuration-acls config))
  284. (unless (list? (knot-configuration-zones config))
  285. (error-out "zones must be a list of knot-zone-configuration."))
  286. (for-each (lambda (zone) (verify-knot-zone-configuration zone))
  287. (knot-configuration-zones config))
  288. (unless (list? (knot-configuration-policies config))
  289. (error-out "policies must be a list of knot-policy-configuration."))
  290. (for-each (lambda (policy) (verify-knot-policy-configuration policy))
  291. (knot-configuration-policies config))
  292. (unless (list? (knot-configuration-remotes config))
  293. (error-out "remotes must be a list of knot-remote-configuration."))
  294. (for-each (lambda (remote) (verify-knot-remote-configuration remote))
  295. (knot-configuration-remotes config))
  296. #t)
  297. (define (format-string-list l)
  298. "Formats a list of string in YAML"
  299. (if (eq? l '())
  300. ""
  301. (let ((l (reverse l)))
  302. (string-append
  303. "["
  304. (fold (lambda (x1 x2)
  305. (string-append (if (symbol? x1) (symbol->string x1) x1) ", "
  306. (if (symbol? x2) (symbol->string x2) x2)))
  307. (car l) (cdr l))
  308. "]"))))
  309. (define (knot-acl-config acls)
  310. (with-output-to-string
  311. (lambda ()
  312. (for-each
  313. (lambda (acl-config)
  314. (let ((id (knot-acl-configuration-id acl-config))
  315. (address (knot-acl-configuration-address acl-config))
  316. (key (knot-acl-configuration-key acl-config))
  317. (action (knot-acl-configuration-action acl-config))
  318. (deny? (knot-acl-configuration-deny? acl-config)))
  319. (format #t " - id: ~a\n" id)
  320. (unless (eq? address '())
  321. (format #t " address: ~a\n" (format-string-list address)))
  322. (unless (eq? key '())
  323. (format #t " key: ~a\n" (format-string-list key)))
  324. (unless (eq? action '())
  325. (format #t " action: ~a\n" (format-string-list action)))
  326. (format #t " deny: ~a\n" (if deny? "on" "off"))))
  327. acls))))
  328. (define (knot-key-config keys)
  329. (with-output-to-string
  330. (lambda ()
  331. (for-each
  332. (lambda (key-config)
  333. (let ((id (knot-key-configuration-id key-config))
  334. (algorithm (knot-key-configuration-algorithm key-config))
  335. (secret (knot-key-configuration-secret key-config)))
  336. (format #t " - id: ~a\n" id)
  337. (if algorithm
  338. (format #t " algorithm: ~a\n" (symbol->string algorithm)))
  339. (format #t " secret: ~a\n" secret)))
  340. keys))))
  341. (define (knot-keystore-config keystores)
  342. (with-output-to-string
  343. (lambda ()
  344. (for-each
  345. (lambda (keystore-config)
  346. (let ((id (knot-keystore-configuration-id keystore-config))
  347. (backend (knot-keystore-configuration-backend keystore-config))
  348. (config (knot-keystore-configuration-config keystore-config)))
  349. (format #t " - id: ~a\n" id)
  350. (format #t " backend: ~a\n" (symbol->string backend))
  351. (format #t " config: \"~a\"\n" config)))
  352. keystores))))
  353. (define (knot-policy-config policies)
  354. (with-output-to-string
  355. (lambda ()
  356. (for-each
  357. (lambda (policy-config)
  358. (let ((id (knot-policy-configuration-id policy-config))
  359. (keystore (knot-policy-configuration-keystore policy-config))
  360. (manual? (knot-policy-configuration-manual? policy-config))
  361. (single-type-signing? (knot-policy-configuration-single-type-signing?
  362. policy-config))
  363. (algorithm (knot-policy-configuration-algorithm policy-config))
  364. (ksk-size (knot-policy-configuration-ksk-size policy-config))
  365. (zsk-size (knot-policy-configuration-zsk-size policy-config))
  366. (dnskey-ttl (knot-policy-configuration-dnskey-ttl policy-config))
  367. (zsk-lifetime (knot-policy-configuration-zsk-lifetime policy-config))
  368. (propagation-delay (knot-policy-configuration-propagation-delay
  369. policy-config))
  370. (rrsig-lifetime (knot-policy-configuration-rrsig-lifetime
  371. policy-config))
  372. (nsec3? (knot-policy-configuration-nsec3? policy-config))
  373. (nsec3-iterations (knot-policy-configuration-nsec3-iterations
  374. policy-config))
  375. (nsec3-salt-length (knot-policy-configuration-nsec3-salt-length
  376. policy-config))
  377. (nsec3-salt-lifetime (knot-policy-configuration-nsec3-salt-lifetime
  378. policy-config)))
  379. (format #t " - id: ~a\n" id)
  380. (format #t " keystore: ~a\n" keystore)
  381. (format #t " manual: ~a\n" (if manual? "on" "off"))
  382. (format #t " single-type-signing: ~a\n" (if single-type-signing?
  383. "on" "off"))
  384. (format #t " algorithm: ~a\n" algorithm)
  385. (format #t " ksk-size: ~a\n" (number->string ksk-size))
  386. (format #t " zsk-size: ~a\n" (number->string zsk-size))
  387. (unless (eq? dnskey-ttl 'default)
  388. (format #t " dnskey-ttl: ~a\n" dnskey-ttl))
  389. (format #t " zsk-lifetime: ~a\n" zsk-lifetime)
  390. (format #t " propagation-delay: ~a\n" propagation-delay)
  391. (format #t " rrsig-lifetime: ~a\n" rrsig-lifetime)
  392. (format #t " nsec3: ~a\n" (if nsec3? "on" "off"))
  393. (format #t " nsec3-iterations: ~a\n"
  394. (number->string nsec3-iterations))
  395. (format #t " nsec3-salt-length: ~a\n"
  396. (number->string nsec3-salt-length))
  397. (format #t " nsec3-salt-lifetime: ~a\n" nsec3-salt-lifetime)))
  398. policies))))
  399. (define (knot-remote-config remotes)
  400. (with-output-to-string
  401. (lambda ()
  402. (for-each
  403. (lambda (remote-config)
  404. (let ((id (knot-remote-configuration-id remote-config))
  405. (address (knot-remote-configuration-address remote-config))
  406. (via (knot-remote-configuration-via remote-config))
  407. (key (knot-remote-configuration-key remote-config)))
  408. (format #t " - id: ~a\n" id)
  409. (unless (eq? address '())
  410. (format #t " address: ~a\n" (format-string-list address)))
  411. (unless (eq? via '())
  412. (format #t " via: ~a\n" (format-string-list via)))
  413. (if key
  414. (format #t " key: ~a\n" key))))
  415. remotes))))
  416. (define (serialize-zone-entries entries)
  417. (with-output-to-string
  418. (lambda ()
  419. (for-each
  420. (lambda (entry)
  421. (let ((name (zone-entry-name entry))
  422. (ttl (zone-entry-ttl entry))
  423. (class (zone-entry-class entry))
  424. (type (zone-entry-type entry))
  425. (data (zone-entry-data entry)))
  426. (format #t "~a ~a ~a ~a ~a\n" name ttl class type data)))
  427. entries))))
  428. (define (serialize-zone-file zone domain)
  429. (computed-file (string-append domain ".zone")
  430. #~(begin
  431. (call-with-output-file #$output
  432. (lambda (port)
  433. (format port "$ORIGIN ~a.\n"
  434. #$(zone-file-origin zone))
  435. (format port "@ IN SOA ~a ~a (~a ~a ~a ~a ~a)\n"
  436. #$(zone-file-ns zone)
  437. #$(zone-file-mail zone)
  438. #$(zone-file-serial zone)
  439. #$(zone-file-refresh zone)
  440. #$(zone-file-retry zone)
  441. #$(zone-file-expiry zone)
  442. #$(zone-file-nx zone))
  443. (format port "~a\n"
  444. #$(serialize-zone-entries (zone-file-entries zone))))))))
  445. (define (knot-zone-config zone)
  446. (let ((content (knot-zone-configuration-zone zone)))
  447. #~(with-output-to-string
  448. (lambda ()
  449. (let ((domain #$(knot-zone-configuration-domain zone))
  450. (file #$(knot-zone-configuration-file zone))
  451. (master (list #$@(knot-zone-configuration-master zone)))
  452. (ddns-master #$(knot-zone-configuration-ddns-master zone))
  453. (notify (list #$@(knot-zone-configuration-notify zone)))
  454. (acl (list #$@(knot-zone-configuration-acl zone)))
  455. (semantic-checks? #$(knot-zone-configuration-semantic-checks? zone))
  456. (disable-any? #$(knot-zone-configuration-disable-any? zone))
  457. (dnssec-policy #$(knot-zone-configuration-dnssec-policy zone))
  458. (serial-policy '#$(knot-zone-configuration-serial-policy zone)))
  459. (format #t " - domain: ~a\n" domain)
  460. (if (eq? master '())
  461. ;; This server is a master
  462. (if (equal? file "")
  463. (format #t " file: ~a\n"
  464. #$(serialize-zone-file content
  465. (knot-zone-configuration-domain zone)))
  466. (format #t " file: ~a\n" file))
  467. ;; This server is a slave (has masters)
  468. (begin
  469. (format #t " master: ~a\n"
  470. #$(format-string-list
  471. (knot-zone-configuration-master zone)))
  472. (if ddns-master (format #t " ddns-master ~a\n" ddns-master))))
  473. (unless (eq? notify '())
  474. (format #t " notify: ~a\n"
  475. #$(format-string-list
  476. (knot-zone-configuration-notify zone))))
  477. (unless (eq? acl '())
  478. (format #t " acl: ~a\n"
  479. #$(format-string-list
  480. (knot-zone-configuration-acl zone))))
  481. (format #t " semantic-checks: ~a\n" (if semantic-checks? "on" "off"))
  482. (format #t " disable-any: ~a\n" (if disable-any? "on" "off"))
  483. (if dnssec-policy
  484. (begin
  485. (format #t " dnssec-signing: on\n")
  486. (format #t " dnssec-policy: ~a\n" dnssec-policy)))
  487. (format #t " serial-policy: ~a\n"
  488. (symbol->string serial-policy)))))))
  489. (define (knot-config-file config)
  490. (verify-knot-configuration config)
  491. (computed-file "knot.conf"
  492. #~(begin
  493. (call-with-output-file #$output
  494. (lambda (port)
  495. (format port "server:\n")
  496. (format port " rundir: ~a\n" #$(knot-configuration-run-directory config))
  497. (format port " user: knot\n")
  498. (format port " listen: ~a@~a\n"
  499. #$(knot-configuration-listen-v4 config)
  500. #$(knot-configuration-listen-port config))
  501. (format port " listen: ~a@~a\n"
  502. #$(knot-configuration-listen-v6 config)
  503. #$(knot-configuration-listen-port config))
  504. (format port "\nkey:\n")
  505. (format port #$(knot-key-config (knot-configuration-keys config)))
  506. (format port "\nkeystore:\n")
  507. (format port #$(knot-keystore-config (knot-configuration-keystores config)))
  508. (format port "\nacl:\n")
  509. (format port #$(knot-acl-config (knot-configuration-acls config)))
  510. (format port "\nremote:\n")
  511. (format port #$(knot-remote-config (knot-configuration-remotes config)))
  512. (format port "\npolicy:\n")
  513. (format port #$(knot-policy-config (knot-configuration-policies config)))
  514. (unless #$(eq? (knot-configuration-zones config) '())
  515. (format port "\nzone:\n")
  516. (format port "~a\n"
  517. (string-concatenate
  518. (list #$@(map knot-zone-config
  519. (knot-configuration-zones config)))))))))))
  520. (define %knot-accounts
  521. (list (user-group (name "knot") (system? #t))
  522. (user-account
  523. (name "knot")
  524. (group "knot")
  525. (system? #t)
  526. (comment "knot dns server user")
  527. (home-directory "/var/empty")
  528. (shell (file-append shadow "/sbin/nologin")))))
  529. (define (knot-activation config)
  530. #~(begin
  531. (use-modules (guix build utils))
  532. (define (mkdir-p/perms directory owner perms)
  533. (mkdir-p directory)
  534. (chown directory (passwd:uid owner) (passwd:gid owner))
  535. (chmod directory perms))
  536. (mkdir-p/perms #$(knot-configuration-run-directory config)
  537. (getpwnam "knot") #o755)
  538. (mkdir-p/perms "/var/lib/knot" (getpwnam "knot") #o755)
  539. (mkdir-p/perms "/var/lib/knot/keys" (getpwnam "knot") #o755)
  540. (mkdir-p/perms "/var/lib/knot/keys/keys" (getpwnam "knot") #o755)))
  541. (define (knot-shepherd-service config)
  542. (let* ((config-file (knot-config-file config))
  543. (knot (knot-configuration-knot config)))
  544. (list (shepherd-service
  545. (documentation "Run the Knot DNS daemon.")
  546. (provision '(knot dns))
  547. (requirement '(networking))
  548. (start #~(make-forkexec-constructor
  549. (list (string-append #$knot "/sbin/knotd")
  550. "-c" #$config-file)))
  551. (stop #~(make-kill-destructor))))))
  552. (define knot-service-type
  553. (service-type (name 'knot)
  554. (extensions
  555. (list (service-extension shepherd-root-service-type
  556. knot-shepherd-service)
  557. (service-extension activation-service-type
  558. knot-activation)
  559. (service-extension account-service-type
  560. (const %knot-accounts))))))