Subject: [bug#77204] [PATCH v4 2/3] services: dnsmasq: Add pid-file, conf-file and conf-dir configuration fields.

From: Alexey Abramov <[email-masked]>
Date: Thu, 8 May 2025 19:47:42 +0200

* gnu/services/dns.scm (<dnsmasq-configuration>)[pid-file]: New field
to specify alternate path for dnsmasq PID.
[conf-file]: New field to specify one or more configuration files.
[conf-dir]: New field to read configuration files from a directory.
[extra-options]: Move to the end of the definition as a last resort option.
(dnsmasq-shepherd-service): Use new fields instead of hardcoded values.

* gnu/services/dns.scm: Export all record accessors.

* doc/guix.texi: Document new configuration options.
---
 doc/guix.texi        | 15 ++++++++++++
 gnu/services/dns.scm | 58 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 279bbda9ac4..ec096643eaa 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -36095,6 +36095,9 @@ DNS Services
 Likewise, @code{shepherd-requirement} is a list of Shepherd service names
 (symbols) that this service will depend on.
 
+@item @code{pid-file} (default: @code{"/run/dnsmasq.pid"})
+Specify an alternate path for dnsmasq to record its process-id in.
+
 @item @code{no-hosts?} (default: @code{#f})
 When true, don't read the hostnames in /etc/hosts.
 
@@ -36215,6 +36218,18 @@ DNS Services
 resolving MAC addresses is only possible if the client is in the local
 network or obtained a DHCP lease from dnsmasq.
 
+@item @code{conf-file} (default: @code{'()})
+Specify a configuration file or multiple.  The given value should be a
+list of string paths to the configuration files.  File-like objects are
+also supported.
+
+@item @code{conf-dir} (default: @code{#f})
+Read all the files in the given directory as configuration files.
+@command{dnsmasq} also supports extensions for the field, but here it is
+not implemented.  It is more convenient to make @code{computed-file}
+directory in the store and use that.  Files are loaded in alphabetical
+order of filename.
+
 @item @code{extra-options} (default: @code{'()})
 This option provides an ``escape hatch'' for the user to provide arbitrary
 command-line arguments to @command{dnsmasq} as a list of strings.
diff --git a/gnu/services/dns.scm b/gnu/services/dns.scm
index fd849d08e89..d55ee3e4fcb 100644
--- a/gnu/services/dns.scm
+++ b/gnu/services/dns.scm
@@ -55,6 +55,38 @@ (define-module (gnu services dns)
 
             dnsmasq-service-type
             dnsmasq-configuration
+            dnsmasq-configuration-package
+            dnsmasq-configuration-shepherd-provision
+            dnsmasq-configuration-shepherd-requirement
+            dnsmasq-configuration-pid-file
+            dnsmasq-configuration-no-hosts?
+            dnsmasq-configuration-port
+            dnsmasq-configuration-local-service?
+            dnsmasq-configuration-listen-address
+            dnsmasq-configuration-resolv-file
+            dnsmasq-configuration-no-resolv?
+            dnsmasq-configuration-forward-private-reverse-lookup?
+            dnsmasq-configuration-query-servers-in-order?
+            dnsmasq-configuration-servers
+            dnsmasq-configuration-servers-file
+            dnsmasq-configuration-addresses
+            dnsmasq-configuration-cache-size
+            dnsmasq-configuration-negative-cache?
+            dnsmasq-configuration-cpe-id
+            dnsmasq-configuration-tftp-enable?
+            dnsmasq-configuration-tftp-no-fail?
+            dnsmasq-configuration-tftp-single-port?
+            dnsmasq-tftp-secure?
+            dnsmasq-tftp-max
+            dnsmasq-tftp-mtu
+            dnsmasq-tftp-no-blocksize?
+            dnsmasq-tftp-lowercase?
+            dnsmasq-tftp-port-range
+            dnsmasq-tftp-root
+            dnsmasq-tftp-unique-root
+            dnsmasq-configuration-conf-file
+            dnsmasq-configuration-conf-dir
+            dnsmasq-configuration-extra-options
 
             unbound-service-type
             unbound-configuration
@@ -752,14 +784,14 @@ (define-record-type* <dnsmasq-configuration>
                                 (default '(user-processes networking)))
   (no-hosts?        dnsmasq-configuration-no-hosts?
                     (default #f))       ;boolean
+  (pid-file         dnsmasq-configuration-pid-file
+                    (default "/run/dnsmasq.pid")) ;string
   (port             dnsmasq-configuration-port
                     (default 53))       ;integer
   (local-service?   dnsmasq-configuration-local-service?
                     (default #t))       ;boolean
   (listen-addresses dnsmasq-configuration-listen-address
                     (default '()))      ;list of string
-  (extra-options    dnsmasq-configuration-extra-options
-                    (default '()))      ;list of string
   (resolv-file      dnsmasq-configuration-resolv-file
                     (default "/etc/resolv.conf")) ;string
   (no-resolv?       dnsmasq-configuration-no-resolv?
@@ -803,7 +835,13 @@ (define-record-type* <dnsmasq-configuration>
   (tftp-root        dnsmasq-tftp-root
                     (default "/var/empty,lo")) ;string
   (tftp-unique-root dnsmasq-tftp-unique-root
-                    (default #f)))      ;"" or "ip" or "mac"
+                    (default #f))       ;"" or "ip" or "mac"
+  (conf-file        dnsmasq-configuration-conf-file
+                    (default '()))      ;list of string|file-like
+  (conf-dir         dnsmasq-configuration-conf-dir
+                    (default #f))       ;string|file-like
+  (extra-options    dnsmasq-configuration-extra-options
+                    (default '())))     ;list of string
 
 (define (warn-deprecated-dnsmasq-configuration-provision value)
   (when (pair? value)
@@ -818,6 +856,7 @@ (define (dnsmasq-shepherd-service config)
      provision
      shepherd-provision
      shepherd-requirement
+     pid-file
      no-hosts?
      port local-service? listen-addresses
      resolv-file no-resolv?
@@ -829,7 +868,8 @@ (define (dnsmasq-shepherd-service config)
      tftp-single-port? tftp-secure?
      tftp-max tftp-mtu tftp-no-blocksize?
      tftp-lowercase? tftp-port-range
-     tftp-root tftp-unique-root extra-options)
+     tftp-root tftp-unique-root
+     conf-file conf-dir extra-options)
     (shepherd-service
      (provision (or provision shepherd-provision))
      (requirement shepherd-requirement)
@@ -838,7 +878,7 @@ (define (dnsmasq-shepherd-service config)
                (list
                 #$(file-append package "/sbin/dnsmasq")
                 "--keep-in-foreground"
-                "--pid-file=/run/dnsmasq.pid"
+                (string-append "--pid-file=" #$pid-file)
                 #$@(if no-hosts?
                        '("--no-hosts")
                         '())
@@ -909,8 +949,14 @@ (define (dnsmasq-shepherd-service config)
                             (format #f "--tftp-unique-root=~a" tftp-unique-root)
                             (format #f "--tftp-unique-root")))
                        '())
+                #$@(map (lambda (conf-file)
+                          #~(string-append "--conf-file=" #$conf-file))
+                        conf-file)
+                #$@(if conf-dir
+                       (list #~(string-append "--conf-dir=" #$conf-dir))
+                       '())
                 #$@extra-options)
-               #:pid-file "/run/dnsmasq.pid"))
+               #:pid-file #$pid-file))
      (stop #~(make-kill-destructor)))))
 
 (define (dnsmasq-activation config)
-- 
2.49.0