From 20c51c1d2ce8fd4b32203343c3afbfe2622a22d7 Mon Sep 17 00:00:00 2001 From: Felix Lechner Date: Fri, 12 May 2023 11:52:48 -0700 Subject: services: pam-limits: Keep 'limits.conf' in the store. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/base.scm (pam-limits-service-type)[pam-extension]: Wrap into a 'lambda' that takes 'limits-file'. Pass that in the 'arguments' field. Define 'make-limits-file' and use it. Remove ETC-SERVICE-TYPE extension. Signed-off-by: Ludovic Courtès --- gnu/services/base.scm | 63 ++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'gnu/services') diff --git a/gnu/services/base.scm b/gnu/services/base.scm index 492cf8a693..b557af24af 100644 --- a/gnu/services/base.scm +++ b/gnu/services/base.scm @@ -1603,38 +1603,36 @@ information on the configuration file syntax." (define pam-limits-service-type (let ((pam-extension - (pam-extension - (transformer - (lambda (pam) - (let ((pam-limits (pam-entry - (control "required") - (module "pam_limits.so") - (arguments - '("conf=/etc/security/limits.conf"))))) - (if (member (pam-service-name pam) - '("login" "greetd" "su" "slim" "gdm-password" - "sddm" "sudo" "sshd" "lightdm")) - (pam-service - (inherit pam) - (session (cons pam-limits - (pam-service-session pam)))) - pam)))))) - - ;; XXX: Using file-like objects is deprecated, use lists instead. - ;; This is to be reduced into the list? case when the deprecated - ;; code gets removed. - ;; Create /etc/security containing the provided "limits.conf" file. - (security-limits + (lambda (limits-file) + (pam-extension + (transformer + (lambda (pam) + (let ((pam-limits (pam-entry + (control "required") + (module "pam_limits.so") + (arguments + (list #~(string-append "conf=" #$limits-file)))))) + (if (member (pam-service-name pam) + '("login" "greetd" "su" "slim" "gdm-password" + "sddm" "lightdm" "sudo" "sshd")) + (pam-service + (inherit pam) + (session (cons pam-limits + (pam-service-session pam)))) + pam))))))) + (make-limits-file (match-lambda + ;; XXX: Using file-like objects is deprecated, use lists instead. + ;; This is to be reduced into the list? case when the deprecated + ;; code gets removed. ((? file-like? obj) (warning (G_ "Using file-like value for \ 'pam-limits-service-type' is deprecated~%")) - `(("security/limits.conf" ,obj))) + obj) ((? list? lst) - `(("security/limits.conf" - ,(plain-file "limits.conf" - (string-join (map pam-limits-entry->string lst) - "\n" 'suffix))))) + (plain-file "limits.conf" + (string-join (map pam-limits-entry->string lst) + "\n" 'suffix))) (_ (raise (formatted-message (G_ "invalid input for 'pam-limits-service-type'~%"))))))) @@ -1642,13 +1640,12 @@ information on the configuration file syntax." (service-type (name 'limits) (extensions - (list (service-extension etc-service-type security-limits) - (service-extension pam-root-service-type - (lambda _ (list pam-extension))))) + (list (service-extension pam-root-service-type + (lambda (config) + (list (pam-extension (make-limits-file config))))))) (description - "Install the specified resource usage limits by populating -@file{/etc/security/limits.conf} and using the @code{pam_limits} -authentication module.") + "Use the @code{pam_limits} authentication module to set the specified +resource usage limits.") (default-value '())))) (define-deprecated (pam-limits-service #:optional (limits '())) -- cgit 1.4.1 From 48d06aee7b39c8e72644d665bd1995cb1ae1b094 Mon Sep 17 00:00:00 2001 From: Felix Lechner Date: Fri, 12 May 2023 11:52:50 -0700 Subject: services: Use more 'file-append'. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/authentication.scm (pam-ldap-pam-service): Use 'file-append' instead of #~(string-append ...). * gnu/services/base.scm (greetd-pam-service): Likewise. * gnu/services/kerberos.scm (pam-krb5-pam-service): Likewise. * gnu/services/pam-mount.scm (pam-mount-pam-service): Likewise. Signed-off-by: Ludovic Courtès --- gnu/services/authentication.scm | 2 +- gnu/services/base.scm | 2 +- gnu/services/kerberos.scm | 4 ++-- gnu/services/pam-mount.scm | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'gnu/services') diff --git a/gnu/services/authentication.scm b/gnu/services/authentication.scm index f1ad1b1afe..fbfef2d3d0 100644 --- a/gnu/services/authentication.scm +++ b/gnu/services/authentication.scm @@ -504,7 +504,7 @@ password.") (define (pam-ldap-pam-service config) "Return a PAM service for LDAP authentication." (define pam-ldap-module - #~(string-append #$(nslcd-configuration-nss-pam-ldapd config) + (file-append (nslcd-configuration-nss-pam-ldapd config) "/lib/security/pam_ldap.so")) (pam-extension (transformer diff --git a/gnu/services/base.scm b/gnu/services/base.scm index b557af24af..b3f2d2e8b8 100644 --- a/gnu/services/base.scm +++ b/gnu/services/base.scm @@ -3263,7 +3263,7 @@ to handle." (define optional-pam-mount (pam-entry (control "optional") - (module #~(string-append #$greetd-pam-mount "/lib/security/pam_mount.so")) + (module (file-append greetd-pam-mount "/lib/security/pam_mount.so")) (arguments '("disable_interactive")))) (list diff --git a/gnu/services/kerberos.scm b/gnu/services/kerberos.scm index 1a1b37f890..a6f540a9b6 100644 --- a/gnu/services/kerberos.scm +++ b/gnu/services/kerberos.scm @@ -432,8 +432,8 @@ generates such a file. It does not cause any daemon to be started."))) (transformer (lambda (pam) (define pam-krb5-module - #~(string-append #$(pam-krb5-configuration-pam-krb5 config) - "/lib/security/pam_krb5.so")) + (file-append (pam-krb5-configuration-pam-krb5 config) + "/lib/security/pam_krb5.so")) (let ((pam-krb5-sufficient (pam-entry diff --git a/gnu/services/pam-mount.scm b/gnu/services/pam-mount.scm index dbb9d0285f..b3a02e82e9 100644 --- a/gnu/services/pam-mount.scm +++ b/gnu/services/pam-mount.scm @@ -94,7 +94,7 @@ (define optional-pam-mount (pam-entry (control "optional") - (module #~(string-append #$pam-mount "/lib/security/pam_mount.so")))) + (module (file-append pam-mount "/lib/security/pam_mount.so")))) (list (pam-extension (transformer -- cgit 1.4.1 From b8ee6b8a59bf02f47a6668e016905308b441523e Mon Sep 17 00:00:00 2001 From: Felix Lechner Date: Sun, 28 May 2023 16:36:31 -0700 Subject: services: Add cachefilesd service. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Bruno Victal "mirai" for cooperating on this patch and for generously sharing a wealth of insights about Guix services. Thanks to Jean-Baptiste Note for an early version of this service! * doc/guix.texi (Linux Services)[Cachefilesd Service]: New heading. * gnu/services/linux.scm (serialize-string, non-negative-integer?) (serialize-non-negative-integer, string, non-negative-integer) (make-option-serializer, make-percentage-threshold-serializer): New procedures. (cachefilesd-configuration): New record type. (cachefilesd-service-type): New variable. * gnu/tests/cachefilesd.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. Co-authored-by: Bruno Victal Signed-off-by: Ludovic Courtès --- doc/guix.texi | 89 +++++++++++++++++++++ gnu/local.mk | 1 + gnu/services/linux.scm | 199 +++++++++++++++++++++++++++++++++++++++++++++- gnu/tests/cachefilesd.scm | 71 +++++++++++++++++ 4 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 gnu/tests/cachefilesd.scm (limited to 'gnu/services') diff --git a/doc/guix.texi b/doc/guix.texi index b50feed4c4..22590b4f9c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -117,6 +117,7 @@ Copyright @copyright{} 2023 Karl Hallsby@* Copyright @copyright{} 2023 Nathaniel Nicandro@* Copyright @copyright{} 2023 Tanguy Le Carrour@* Copyright @copyright{} 2023 Brian Cully@* +Copyright @copyright{} 2023 Felix Lechner@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -38659,6 +38660,94 @@ parameters, can be done as follow: @end lisp @end defvar +@subsubheading Cachefilesd Service + +@cindex cachefilesd +@cindex fscache, file system caching (Linux) +The Cachefilesd service starts a daemon that caches network file system +data locally. It is especially useful for NFS and AFS shares, where it +reduces latencies for repeated access when reading files. + +The daemon can be configured as follows: + +@lisp +(service cachefilesd-service-type + (cachefilesd-configuration + (cache-directory "/var/cache/fscache"))) +@end lisp + +@defvar cachefilesd-service-type +The service type for starting @command{cachefilesd}. The value for this +service type is a @code{cachefilesd-configuration}, whose only required +field is @var{cache-directory}. + +@end defvar + +@c %start of fragment +@deftp {Data Type} cachefilesd-configuration +Available @code{cachefilesd-configuration} fields are: + +@table @asis +@item @code{cachefilesd} (default: @code{cachefilesd}) (type: file-like) +The cachefilesd package to use. + +@item @code{debug-output?} (default: @code{#f}) (type: boolean) +Print debugging output to stderr. + +@item @code{use-syslog?} (default: @code{#t}) (type: boolean) +Log to syslog facility instead of stdout. + +@item @code{scan?} (default: @code{#t}) (type: boolean) +Scan for cachable objects. + +@item @code{cache-directory} (type: maybe-string) +Location of the cache directory. + +@item @code{cache-name} (default: @code{"CacheFiles"}) (type: maybe-string) +Name of cache (keep unique). + +@item @code{security-context} (type: maybe-string) +SELinux security context. + +@item @code{pause-culling-for-block-percentage} (default: @code{7}) (type: maybe-non-negative-integer) +Pause culling when available blocks exceed this percentage. + +@item @code{pause-culling-for-file-percentage} (default: @code{7}) (type: maybe-non-negative-integer) +Pause culling when available files exceed this percentage. + +@item @code{resume-culling-for-block-percentage} (default: @code{5}) (type: maybe-non-negative-integer) +Start culling when available blocks drop below this percentage. + +@item @code{resume-culling-for-file-percentage} (default: @code{5}) (type: maybe-non-negative-integer) +Start culling when available files drop below this percentage. + +@item @code{pause-caching-for-block-percentage} (default: @code{1}) (type: maybe-non-negative-integer) +Pause further allocations when available blocks drop below this +percentage. + +@item @code{pause-caching-for-file-percentage} (default: @code{1}) (type: maybe-non-negative-integer) +Pause further allocations when available files drop below this +percentage. + +@item @code{log2-table-size} (default: @code{12}) (type: maybe-non-negative-integer) +Size of tables holding cullable objects in logarithm of base 2. + +@item @code{cull?} (default: @code{#t}) (type: boolean) +Create free space by culling (consumes system load). + +@item @code{trace-function-entry-in-kernel-module?} (default: @code{#f}) (type: boolean) +Trace function entry in the kernel module (for debugging). + +@item @code{trace-function-exit-in-kernel-module?} (default: @code{#f}) (type: boolean) +Trace function exit in the kernel module (for debugging). + +@item @code{trace-internal-checkpoints-in-kernel-module?} (default: @code{#f}) (type: boolean) +Trace internal checkpoints in the kernel module (for debugging). + +@end table +@end deftp +@c %end of fragment + @cindex rasdaemon @cindex Platform Reliability, Availability and Serviceability daemon @subsubheading Rasdaemon Service diff --git a/gnu/local.mk b/gnu/local.mk index 1bf33377a4..5ed399adb0 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -770,6 +770,7 @@ GNU_SYSTEM_MODULES = \ %D%/tests.scm \ %D%/tests/audio.scm \ %D%/tests/base.scm \ + %D%/tests/cachefilesd.scm \ %D%/tests/ci.scm \ %D%/tests/cups.scm \ %D%/tests/databases.scm \ diff --git a/gnu/services/linux.scm b/gnu/services/linux.scm index d105c42850..d17f492e15 100644 --- a/gnu/services/linux.scm +++ b/gnu/services/linux.scm @@ -6,6 +6,7 @@ ;;; Copyright © 2021 B. Wilson ;;; Copyright © 2022 Josselin Poiret ;;; Copyright © 2023 Bruno Victal +;;; Copyright © 2023 Felix Lechner ;;; ;;; This file is part of GNU Guix. ;;; @@ -67,6 +68,28 @@ kernel-module-loader-service-type + cachefilesd-configuration + cachefilesd-configuration? + cachefilesd-configuration-cachefilesd + cachefilesd-configuration-debug-output? + cachefilesd-configuration-use-syslog? + cachefilesd-configuration-scan? + cachefilesd-configuration-cache-directory + cachefilesd-configuration-cache-name + cachefilesd-configuration-security-context + cachefilesd-configuration-pause-culling-for-block-percentage + cachefilesd-configuration-pause-culling-for-file-percentage + cachefilesd-configuration-resume-culling-for-block-percentage + cachefilesd-configuration-resume-culling-for-file-percentage + cachefilesd-configuration-pause-caching-for-block-percentage + cachefilesd-configuration-pause-caching-for-file-percentage + cachefilesd-configuration-log2-table-size + cachefilesd-configuration-cull? + cachefilesd-configuration-trace-function-entry-in-kernel-module + cachefilesd-configuration-trace-function-exit-in-kernel-module + cachefilesd-configuration-trace-internal-checkpoints-in-kernel-module + cachefilesd-service-type + rasdaemon-configuration rasdaemon-configuration? rasdaemon-configuration-record? @@ -306,6 +329,180 @@ more information)." (extend append) (default-value '()))) + +;;; +;;; Cachefilesd, an FS-Cache daemon +;;; + +(define (serialize-string variable-symbol value) + #~(format #f "~a ~a~%" #$(symbol->string variable-symbol) #$value)) + +(define-maybe string) + +(define (non-negative-integer? val) + (and (exact-integer? val) (not (negative? val)))) + +(define (serialize-non-negative-integer variable-symbol value) + #~(format #f "~a ~d~%" #$(symbol->string variable-symbol) #$value)) + +(define-maybe non-negative-integer) + +(define (make-option-serializer option-symbol) + (lambda (variable-symbol text) + (if (maybe-value-set? text) + #~(format #f "~a ~a~%" #$(symbol->string option-symbol) #$text) + ""))) + +(define (make-percentage-threshold-serializer threshold-symbol) + (lambda (variable-symbol percentage) + (if (maybe-value-set? percentage) + #~(format #f "~a ~a%~%" #$(symbol->string threshold-symbol) #$percentage) + ""))) + +(define-configuration cachefilesd-configuration + (cachefilesd + (file-like cachefilesd) + "The cachefilesd package to use." + (serializer empty-serializer)) + + ;; command-line options + (debug-output? + (boolean #f) + "Print debugging output to stderr." + (serializer empty-serializer)) + + (use-syslog? + (boolean #t) + "Log to syslog facility instead of stdout." + (serializer empty-serializer)) + + ;; culling is part of the configuration file + ;; despite the name of the command-line option + (scan? + (boolean #t) + "Scan for cachable objects." + (serializer empty-serializer)) + + ;; sole required field in the configuration file + (cache-directory + maybe-string + "Location of the cache directory." + (serializer (make-option-serializer 'dir))) + + (cache-name + (maybe-string "CacheFiles") + "Name of cache (keep unique)." + (serializer (make-option-serializer 'tag))) + + (security-context + maybe-string + "SELinux security context." + (serializer (make-option-serializer 'secctx))) + + ;; percentage thresholds in the configuration file + (pause-culling-for-block-percentage + (maybe-non-negative-integer 7) + "Pause culling when available blocks exceed this percentage." + (serializer (make-percentage-threshold-serializer 'brun))) + + (pause-culling-for-file-percentage + (maybe-non-negative-integer 7) + "Pause culling when available files exceed this percentage." + (serializer (make-percentage-threshold-serializer 'frun))) + + (resume-culling-for-block-percentage + (maybe-non-negative-integer 5) + "Start culling when available blocks drop below this percentage." + (serializer (make-percentage-threshold-serializer 'bcull))) + + (resume-culling-for-file-percentage + (maybe-non-negative-integer 5) + "Start culling when available files drop below this percentage." + (serializer (make-percentage-threshold-serializer 'fcull))) + + (pause-caching-for-block-percentage + (maybe-non-negative-integer 1) + "Pause further allocations when available blocks drop below this percentage." + (serializer (make-percentage-threshold-serializer 'bstop))) + + (pause-caching-for-file-percentage + (maybe-non-negative-integer 1) + "Pause further allocations when available files drop below this percentage." + (serializer (make-percentage-threshold-serializer 'fstop))) + + ;; run time optimizations in the configuration file + (log2-table-size + (maybe-non-negative-integer 12) + "Size of tables holding cullable objects in logarithm of base 2." + (serializer (make-option-serializer 'culltable))) + + (cull? + (boolean #t) + "Create free space by culling (consumes system load)." + (serializer + (lambda (variable-symbol value) + (if value "" "nocull\n")))) + + ;; kernel module debugging in the configuration file + (trace-function-entry-in-kernel-module? + (boolean #f) + "Trace function entry in the kernel module (for debugging)." + (serializer empty-serializer)) + + (trace-function-exit-in-kernel-module? + (boolean #f) + "Trace function exit in the kernel module (for debugging)." + (serializer empty-serializer)) + + (trace-internal-checkpoints-in-kernel-module? + (boolean #f) + "Trace internal checkpoints in the kernel module (for debugging)." + (serializer empty-serializer))) + +(define (serialize-cachefilesd-configuration configuration) + (mixed-text-file + "cachefilesd.conf" + (serialize-configuration configuration cachefilesd-configuration-fields))) + +(define (cachefilesd-shepherd-service config) + "Return a list of for cachefilesd for CONFIG." + (match-record + config (cachefilesd + debug-output? + use-syslog? + scan? + cache-directory) + (let ((configuration-file (serialize-cachefilesd-configuration config))) + (shepherd-service + (documentation "Run the cachefilesd daemon for FS-Cache.") + (provision '(cachefilesd)) + (requirement (append '(file-systems) + (if use-syslog? '(syslogd) '()))) + (start #~(begin + (and=> #$(maybe-value cache-directory) mkdir-p) + (make-forkexec-constructor + `(#$(file-append cachefilesd "/sbin/cachefilesd") + ;; do not detach + "-n" + #$@(if debug-output? '("-d") '()) + #$@(if use-syslog? '() '("-s")) + #$@(if scan? '() '("-N")) + "-f" #$configuration-file)))) + (stop #~(make-kill-destructor)))))) + +(define cachefilesd-service-type + (service-type + (name 'cachefilesd) + (description + "Run the file system cache daemon @command{cachefilesd}, which relies on +the Linux @code{cachefiles} module.") + (extensions + (list (service-extension kernel-module-loader-service-type + (const '("cachefiles"))) + (service-extension shepherd-root-service-type + (compose list cachefilesd-shepherd-service)))) + (default-value (cachefilesd-configuration)))) + ;;; ;;; Reliability, Availability, and Serviceability (RAS) daemon @@ -351,7 +548,7 @@ more information)." ;;; -;;; Kernel module loader. +;;; Zram device ;;; (define-record-type* diff --git a/gnu/tests/cachefilesd.scm b/gnu/tests/cachefilesd.scm new file mode 100644 index 0000000000..7f5d513067 --- /dev/null +++ b/gnu/tests/cachefilesd.scm @@ -0,0 +1,71 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2017 Peter Mikkelsen +;;; Copyright © 2022 Bruno Victal +;;; Copyright © 2023 Felix Lechner +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu tests cachefilesd) + #:use-module (gnu tests) + #:use-module (gnu system) + #:use-module (gnu system vm) + #:use-module (gnu services) + #:use-module (gnu services linux) + #:use-module (guix gexp) + #:export (%test-cachefilesd)) + +(define %cachefilesd-os + (simple-operating-system + (service cachefilesd-service-type + (cachefilesd-configuration + (cache-directory "/var/cache/fscache"))))) + +(define (run-cachefilesd-test) + "Run tests in %cachefilesd-os, which has cachefilesd running." + (define os + (marionette-operating-system + %cachefilesd-os + #:imported-modules '((gnu services herd)))) + + (define vm + (virtual-machine os)) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (srfi srfi-64) + (gnu build marionette)) + (define marionette + (make-marionette (list #$vm))) + + (test-runner-current (system-test-runner #$output)) + (test-begin "cachefilesd") + + (test-assert "service is running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (start-service 'cachefilesd)) + marionette)) + + (test-end)))) + (gexp->derivation "cachefilesd-test" test)) + +(define %test-cachefilesd + (system-test + (name "cachefilesd") + (description "Test that the cachefilesd runs when started.") + (value (run-cachefilesd-test)))) -- cgit 1.4.1 From 132ddca5a4fb6d789f98866b5bf85be95306c969 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Thu, 27 Jul 2023 12:49:30 -0400 Subject: gnu: elogind: Update to 252.9. * gnu/packages/freedesktop.scm (elogind): Update to 252.9. [source]: Replace elogind-revert-polkit-detection.patch with elogind-fix-rpath.patch in patches. [configure-flags]: Add the dbussystemservicedir, dbussessionservicedir, dbussystemservicedir and dbus-interfaces-dir flags. [phases] Update list of patched files. Update substitutions, and skip the copy_holes test. [native-inputs]: Add python-jinja2. [inputs]: Add util-linux:lib. * gnu/services/desktop.scm (elogind-dbus-service) : Add a symlink to elogind's share/dbus-1/system.d to expose D-Bus policy configurations. * gnu/tests/desktop.scm (run-elogind-test): Adjust expected result for the new "linger" value. * gnu/packages/patches/elogind-revert-polkit-detection.patch: Delete file. * gnu/packages/patches/elogind-fix-rpath.patch: New file. * gnu/local.mk (dist_patch_DATA): Update. Series-to: 64938@debbugs.gnu.org Series-prefix: elogind-updates Series-version: 2 Series-changes: 2 - Fix elogind system test - Install D-Bus policy files in elogind-dbus-service-wrapper - Remove duplicate 'dbussystemservicedir' configure flag --- gnu/local.mk | 2 +- gnu/packages/freedesktop.scm | 53 +++++++++++-------- gnu/packages/patches/elogind-fix-rpath.patch | 60 ++++++++++++++++++++++ .../patches/elogind-revert-polkit-detection.patch | 41 --------------- gnu/services/desktop.scm | 4 ++ gnu/tests/desktop.scm | 2 +- 6 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 gnu/packages/patches/elogind-fix-rpath.patch delete mode 100644 gnu/packages/patches/elogind-revert-polkit-detection.patch (limited to 'gnu/services') diff --git a/gnu/local.mk b/gnu/local.mk index 5f0f373054..1be15b4200 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1089,7 +1089,7 @@ dist_patch_DATA = \ %D%/packages/patches/elm-ghc9.2.patch \ %D%/packages/patches/elm-offline-package-registry.patch \ %D%/packages/patches/elm-reactor-static-files.patch \ - %D%/packages/patches/elogind-revert-polkit-detection.patch \ + %D%/packages/patches/elogind-fix-rpath.patch \ %D%/packages/patches/emacs-deferred-fix-number-of-arguments.patch \ %D%/packages/patches/emacs-exec-path.patch \ %D%/packages/patches/emacs-ess-fix-obsolete-function-alias.patch \ diff --git a/gnu/packages/freedesktop.scm b/gnu/packages/freedesktop.scm index 60d8dfe9fd..7eba464036 100644 --- a/gnu/packages/freedesktop.scm +++ b/gnu/packages/freedesktop.scm @@ -643,7 +643,7 @@ the freedesktop.org XDG Base Directory specification.") (define-public elogind (package (name "elogind") - (version "246.10") + (version "252.9") (source (origin (method git-fetch) (uri (git-reference @@ -652,16 +652,21 @@ the freedesktop.org XDG Base Directory specification.") (file-name (git-file-name name version)) (sha256 (base32 - "16045bhpwjq2nqgswln67ipg1zrz2djxlgkfngqng3jqpwagmnzq")) - (patches (search-patches - "elogind-revert-polkit-detection.patch")))) + "049cfv97975x700s7lx4p9i22nv6v7j046iwkspxba7kr5qq7akw")) + (patches (search-patches "elogind-fix-rpath.patch")))) (build-system meson-build-system) (arguments `(#:configure-flags ,#~(let* ((out #$output) (sysconf (string-append out "/etc")) (libexec (string-append out "/libexec/elogind")) - (dbuspolicy (string-append out "/etc/dbus-1/system.d")) + (dbus-data (string-append out "/share/dbus-1")) + (dbuspolicy (string-append dbus-data "/system.d")) + (dbussessionservice (string-append dbus-data "/services")) + (dbussystemservice (string-append dbus-data + "/system-services")) + (dbusinterfaces (string-append dbus-data "/interfaces")) + #$@(if (not (target-riscv64?)) #~((kexec-tools #$(this-package-input "kexec-tools"))) #~()) @@ -679,6 +684,9 @@ the freedesktop.org XDG Base Directory specification.") (string-append "-Dsysconfdir=" sysconf) (string-append "-Drootlibexecdir=" libexec) (string-append "-Ddbuspolicydir=" dbuspolicy) + (string-append "-Ddbussessionservicedir=" dbussessionservice) + (string-append "-Ddbussystemservicedir=" dbussystemservice) + (string-append "-Ddbus-interfaces-dir=" dbusinterfaces) (string-append "-Dc_link_args=-Wl,-rpath=" libexec) (string-append "-Dcpp_link_args=-Wl,-rpath=" libexec) (string-append "-Dhalt-path=" halt-path) @@ -703,21 +711,28 @@ the freedesktop.org XDG Base Directory specification.") ;; XXX There is no run-time setting to set this per-process, only a ;; build-time, hard-coded list of global directories. (lambda _ - (substitute* (list "src/login/elogind-dbus.c" - "src/sleep/sleep.c") + (substitute* (list "src/login/logind-core.c" + "src/login/logind-dbus.c" + "src/sleep/sleep.c" + "src/shared/sleep-config.c") (("PKGSYSCONFDIR") "\"/etc/elogind\"")))) (add-after 'unpack 'adjust-tests (lambda _ - ;; Skip the following test, which depends on users such as 'root' - ;; existing in the build environment. - (invoke "sed" "/src\\/test\\/test-user-util.c/,+2s/^/#/g" - "-i" "src/test/meson.build") + ;; Skip the user-util tests, which depends on users such as + ;; 'root' existing in the build environment. + (substitute* "src/test/meson.build" + ((".*'test-user-util.c'.*") "") + ((".*'test-cgroup.c'.*") "")) ;; This test tries to copy some bytes from /usr/lib/os-release, ;; which does not exist in the build container. Choose something ;; more likely to be available. (substitute* "src/test/test-copy.c" (("/usr/lib/os-release") - "/etc/passwd")) + "/etc/passwd") + ;; Skip the copy_holes test, which fails for unknown reasons + ;; (see: https://github.com/elogind/elogind/issues/261). + (("TEST_RET\\(copy_holes).*" all) + (string-append all " return 77;\n"))) ;; Use a shebang that works in the build container. (substitute* "src/test/test-exec-util.c" (("#!/bin/sh") @@ -742,12 +757,6 @@ the freedesktop.org XDG Base Directory specification.") ;; loopback device, but that fails because /sys is unavailable. (substitute* "src/libelogind/sd-device/test-sd-device-thread.c" ((".*sd_device_new_from_syspath.*/sys/class/net/lo.*") - "return 77;")) - ;; Most of these tests require cgroups or an actual live - ;; logind system so that it can flicker the monitor, etc. - ;; Just skip it until a more narrow selection can be made. - (substitute* "src/libelogind/sd-login/test-login.c" - (("test_login\\(\\);") "return 77;")))) (add-after 'unpack 'change-pid-file-path (lambda _ @@ -763,6 +772,7 @@ the freedesktop.org XDG Base Directory specification.") m4 pkg-config python + python-jinja2 libxslt)) (inputs (append @@ -771,9 +781,10 @@ the freedesktop.org XDG Base Directory specification.") '()) (list linux-pam libcap - shadow ; for 'nologin' - shepherd ; for 'halt' and 'reboot', invoked - ; when pressing the power button + `(,util-linux "lib") ;for 'libmount' + shadow ;for 'nologin' + shepherd ;for 'halt' and 'reboot', invoked + ;when pressing the power button dbus eudev acl))) ; to add individual users to ACLs on /dev nodes diff --git a/gnu/packages/patches/elogind-fix-rpath.patch b/gnu/packages/patches/elogind-fix-rpath.patch new file mode 100644 index 0000000000..2a76cc467f --- /dev/null +++ b/gnu/packages/patches/elogind-fix-rpath.patch @@ -0,0 +1,60 @@ +Retrieved from https://github.com/elogind/elogind/issues/258 + +From: Mark Hindley +Date: Wed, 24 May 2023 10:39:41 +0100 +Subject: Fixup_executable_rpath + +./meson.build sets + + install_rpath : rootlibexecdir + +however src/shared/meson.build sets + +libshared = shared_library( + [snip] + install_dir : rootpkglibdir + ) +--- + meson.build | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/meson.build b/meson.build +index 694a2fd..a575f69 100644 +--- a/meson.build ++++ b/meson.build +@@ -2903,7 +2903,7 @@ executable('elogind', + dependencies : [threads, + libacl, + libudev], +- install_rpath : rootlibexecdir, ++ install_rpath : rootpkglibdir, + install : true, + install_dir : rootlibexecdir) + +@@ -2913,7 +2913,7 @@ exe = executable('loginctl', + link_with : [libshared], + dependencies : [threads, + libudev], +- install_rpath : rootlibexecdir, ++ install_rpath : rootpkglibdir, + install : true, + install_dir : rootbindir) + public_programs += [exe] +@@ -2923,7 +2923,7 @@ exe = executable('elogind-inhibit', + include_directories : includes, + link_with : [libshared], + dependencies : [threads], +- install_rpath : rootlibexecdir, ++ install_rpath : rootpkglibdir, + install : true, + install_dir : rootbindir) + public_programs += [exe] +@@ -4283,7 +4283,7 @@ executable('elogind-uaccess-command', + libshared], + dependencies: [libacl, + libudev], +- install_rpath : rootlibexecdir, ++ install_rpath : rootpkglibdir, + install : true, + install_dir : rootlibexecdir) + #endif // 0 diff --git a/gnu/packages/patches/elogind-revert-polkit-detection.patch b/gnu/packages/patches/elogind-revert-polkit-detection.patch deleted file mode 100644 index 43dd1684b6..0000000000 --- a/gnu/packages/patches/elogind-revert-polkit-detection.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 715ce0a6459e418f92e74c7ce52df3244c18f383 Mon Sep 17 00:00:00 2001 -From: Sven Eden -Date: Mon, 8 Mar 2021 08:40:08 +0100 -Subject: [PATCH] Revert "Disable polkit support if libpolkit is not installed" - -This reverts commit 1194dec4f8f2d1b8bd14e1625f34418ecfce817e. - -Removing polkit support with -Dpolkit=auto when libpolkit is not -installed, removes the whole interface. This makes it impossible to -add polkit support as a runtime dependency. - -Bug: #167 -Closes: #206 -Signed-off-by: Sven Eden ---- - meson.build | 9 --------- - 1 file changed, 9 deletions(-) - -diff --git a/meson.build b/meson.build -index 2dd05db3c..f38551f55 100644 ---- a/meson.build -+++ b/meson.build -@@ -1157,15 +1157,6 @@ if want_polkit != 'false' and not skip_deps - message('Old polkit detected, will install pkla files') - install_polkit_pkla = true - endif --#if 1 /// Disable polkit completely if libpolkit is not there. See elogind issue #167 -- if not libpolkit.found() -- if want_polkit != 'auto' -- error('Polkit requested but libpolkit was not found.') -- endif -- install_polkit = false -- want_polkit = false -- endif --#endif // 1 - endif - conf.set10('ENABLE_POLKIT', install_polkit) - --- -2.33.1 - diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm index 01aec64bee..4996d1a3d9 100644 --- a/gnu/services/desktop.scm +++ b/gnu/services/desktop.scm @@ -1165,6 +1165,10 @@ started~%") (string-append #$output service-directory)) (symlink (string-append #$elogind "/etc") ;for etc/dbus-1 (string-append #$output "/etc")) + ;; Also expose the D-Bus policy configurations (.conf) files, now + ;; installed under '/share' instead of the legacy '/etc' prefix. + (symlink (string-append #$elogind "/share/dbus-1/system.d") + (string-append #$output "/share/dbus-1/system.d")) ;; Replace the "Exec=" line of the 'org.freedesktop.login1.service' ;; file with one that refers to WRAPPER instead of elogind. diff --git a/gnu/tests/desktop.scm b/gnu/tests/desktop.scm index 137260ea93..ef30442886 100644 --- a/gnu/tests/desktop.scm +++ b/gnu/tests/desktop.scm @@ -55,7 +55,7 @@ (test-equal "login on tty1" '(("c1" "0" "root" "seat0" "tty1") ;session ("seat0") ;seat - ("0" "root")) ;user + ("0" "root" "no")) ;user (begin ;; Wait for tty1. -- cgit 1.4.1 From 9dda7479755ba709bb9bb96614ea09ded566b6d3 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Mon, 17 Jul 2023 18:13:42 -0400 Subject: services: posgresql: Add option to specify UID/GID for postgres user. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 'createAccount?', 'uid' and 'gid' to . Unlike other system daemons, the PostgreSQL data directory is typically meant to persist across 'guix system reconfigure' and once created, you don't want it's UID or GID to change anymore. Furthermore, if you want to place the data directory on a network share and use NFSv4 with idmap, then the 'postgres' user must exist when the 'rpc.idmapd' daemon is launched; prior to mounting the share. And it needs to be possible to mount the share without configuring PostgreSQL. With NFSv3, the UID and GID typically needs to match those on the server. The added options allow for both of these scenarios: You can either create the user in (operating-system (users)) completely independently of the 'postgresql-service-type' (for instance to get your NFS setup working first prior to configuring your databases) - or "pin" it's UID / GID values. * gnu/services/databases.scm ()[create-account?] [uid, gid]: New fields. (%postgresql-accounts): Remove. (create-postgresql-account): New procedure. (postgresql-service-type)[extensions]: Use it. * doc/guix.texi (Database Services): Update accordingly. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 14 ++++++++++++++ gnu/services/databases.scm | 37 +++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) (limited to 'gnu/services') diff --git a/doc/guix.texi b/doc/guix.texi index 22590b4f9c..e2e61f0f2d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -25179,6 +25179,20 @@ There is no need to add this field for contrib extensions such as hstore or dblink as they are already loadable by postgresql. This field is only required to add extensions provided by other packages. +@item @code{create-account?} (default: @code{#t}) +Whether or not the @code{postgres} user and group should be created. + +@item @code{uid} (default: @code{#f}) +Explicitly specify the UID of the @code{postgres} daemon account. +You normally do not need to specify this, in which case a free UID will +be automatically assigned. + +One situation where this option might be useful is if the @var{data-directory} +is located on a mounted network share. + +@item @code{gid} (default: @code{#f}) +Explicitly specify the GID of the @code{postgres} group. + @end table @end deftp diff --git a/gnu/services/databases.scm b/gnu/services/databases.scm index 7148971c1d..d3fee2a8ef 100644 --- a/gnu/services/databases.scm +++ b/gnu/services/databases.scm @@ -180,17 +180,30 @@ host all all ::1/128 md5")) (data-directory postgresql-configuration-data-directory (default "/var/lib/postgresql/data")) (extension-packages postgresql-configuration-extension-packages - (default '()))) - -(define %postgresql-accounts - (list (user-group (name "postgres") (system? #t)) - (user-account - (name "postgres") - (group "postgres") - (system? #t) - (comment "PostgreSQL server user") - (home-directory "/var/empty") - (shell (file-append shadow "/sbin/nologin"))))) + (default '())) + (create-account? postgresql-configuration-create-account? + (default #t)) + (uid postgresql-configuration-uid + (default #f)) + (gid postgresql-configuration-gid + (default #f))) + +(define (create-postgresql-account config) + (match-record config + (create-account? uid gid) + (if (not create-account?) '() + (list (user-group + (name "postgres") + (id gid) + (system? #t)) + (user-account + (name "postgres") + (group "postgres") + (system? #t) + (uid uid) + (comment "PostgreSQL server user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))))))) (define (final-postgresql postgresql extension-packages) (if (null? extension-packages) @@ -327,7 +340,7 @@ host all all ::1/128 md5")) (service-extension activation-service-type postgresql-activation) (service-extension account-service-type - (const %postgresql-accounts)) + create-postgresql-account) (service-extension profile-service-type (compose list postgresql-configuration-postgresql)))) -- cgit 1.4.1 From 2b031ca4b2daa1d429e79b08e28fcd26e395bdf2 Mon Sep 17 00:00:00 2001 From: Bruno Victal Date: Sun, 16 Jul 2023 19:47:47 +0100 Subject: Revert "services: Add ddclient service." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ddclient is unmaintained as of 2023-07-04 [1] and this service has been broken for a while [2]. Remove it rather than shipping a broken service for an unmaintained program that's unlikely to be fixed. [1]: [2]: This reverts commit 8490a8346b5c8207f5798be55bea1de865b0bd42. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 107 -------------------------------- gnu/services/dns.scm | 168 +-------------------------------------------------- 2 files changed, 1 insertion(+), 274 deletions(-) (limited to 'gnu/services') diff --git a/doc/guix.texi b/doc/guix.texi index e2e61f0f2d..633d62bd98 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -32563,113 +32563,6 @@ network or obtained a DHCP lease from dnsmasq. @end table @end deftp -@subsubheading ddclient Service - -@cindex ddclient -The ddclient service described below runs the ddclient daemon, which takes -care of automatically updating DNS entries for service providers such as -@uref{https://dyn.com/dns/, Dyn}. - -The following example show instantiates the service with its default -configuration: - -@lisp -(service ddclient-service-type) -@end lisp - -Note that ddclient needs to access credentials that are stored in a -@dfn{secret file}, by default @file{/etc/ddclient/secrets} (see -@code{secret-file} below). You are expected to create this file manually, in -an ``out-of-band'' fashion (you @emph{could} make this file part of the -service configuration, for instance by using @code{plain-file}, but it will be -world-readable @i{via} @file{/gnu/store}). See the examples in the -@file{share/ddclient} directory of the @code{ddclient} package. - -@c %start of fragment - -Available @code{ddclient-configuration} fields are: - -@deftypevr {@code{ddclient-configuration} parameter} package ddclient -The ddclient package. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} integer daemon -The period after which ddclient will retry to check IP and domain name. - -Defaults to @samp{300}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} boolean syslog -Use syslog for the output. - -Defaults to @samp{#t}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string mail -Mail to user. - -Defaults to @samp{"root"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string mail-failure -Mail failed update to user. - -Defaults to @samp{"root"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string pid -The ddclient PID file. - -Defaults to @samp{"/var/run/ddclient/ddclient.pid"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} boolean ssl -Enable SSL support. - -Defaults to @samp{#t}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string user -Specifies the user name or ID that is used when running ddclient -program. - -Defaults to @samp{"ddclient"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string group -Group of the user who will run the ddclient program. - -Defaults to @samp{"ddclient"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} string secret-file -Secret file which will be appended to @file{ddclient.conf} file. This -file contains credentials for use by ddclient. You are expected to -create it manually. - -Defaults to @samp{"/etc/ddclient/secrets.conf"}. - -@end deftypevr - -@deftypevr {@code{ddclient-configuration} parameter} list extra-options -Extra options will be appended to @file{ddclient.conf} file. - -Defaults to @samp{'()}. - -@end deftypevr - - -@c %end of fragment - @node VNC Services @subsection VNC Services @cindex VNC (virtual network computing) diff --git a/gnu/services/dns.scm b/gnu/services/dns.scm index f45fc99c69..6608046909 100644 --- a/gnu/services/dns.scm +++ b/gnu/services/dns.scm @@ -1,6 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 Julien Lepiller -;;; Copyright © 2018 Oleg Pykhalov ;;; Copyright © 2020 Pierre Langlois ;;; Copyright © 2021 Maxime Devos ;;; Copyright © 2022 Remco van 't Veer @@ -53,10 +52,7 @@ knot-resolver-configuration dnsmasq-service-type - dnsmasq-configuration - - ddclient-service-type - ddclient-configuration)) + dnsmasq-configuration)) ;;; ;;; Knot DNS. @@ -901,165 +897,3 @@ cache.size = 100 * MB dnsmasq-activation))) (default-value (dnsmasq-configuration)) (description "Run the dnsmasq DNS server."))) - - -;;; -;;; ddclient -;;; - -(define (uglify-field-name field-name) - (string-delete #\? (symbol->string field-name))) - -(define (serialize-field field-name val) - (when (not (member field-name '(group secret-file user))) - (format #t "~a=~a\n" (uglify-field-name field-name) val))) - -(define (serialize-boolean field-name val) - (serialize-field field-name (if val "yes" "no"))) - -(define (serialize-integer field-name val) - (serialize-field field-name (number->string val))) - -(define (serialize-string field-name val) - (if (and (string? val) (string=? val "")) - "" - (serialize-field field-name val))) - -(define (serialize-list field-name val) - (if (null? val) "" (serialize-field field-name (string-join val)))) - -(define (serialize-extra-options extra-options) - (string-join extra-options "\n" 'suffix)) - -(define-configuration ddclient-configuration - (ddclient - (file-like ddclient) - "The ddclient package.") - (daemon - (integer 300) - "The period after which ddclient will retry to check IP and domain name.") - (syslog - (boolean #t) - "Use syslog for the output.") - (mail - (string "root") - "Mail to user.") - (mail-failure - (string "root") - "Mail failed update to user.") - (pid - (string "/var/run/ddclient/ddclient.pid") - "The ddclient PID file.") - (ssl - (boolean #t) - "Enable SSL support.") - (user - (string "ddclient") - "Specifies the user name or ID that is used when running ddclient -program.") - (group - (string "ddclient") - "Group of the user who will run the ddclient program.") - (secret-file - (string "/etc/ddclient/secrets.conf") - "Secret file which will be appended to @file{ddclient.conf} file. This -file contains credentials for use by ddclient. You are expected to create it -manually.") - (extra-options - (list '()) - "Extra options will be appended to @file{ddclient.conf} file.")) - -(define (ddclient-account config) - "Return the user accounts and user groups for CONFIG." - (let ((ddclient-user (ddclient-configuration-user config)) - (ddclient-group (ddclient-configuration-group config))) - (list (user-group - (name ddclient-group) - (system? #t)) - (user-account - (name ddclient-user) - (system? #t) - (group ddclient-group) - (comment "ddclientd privilege separation user") - (home-directory (string-append "/var/run/" ddclient-user)))))) - -(define (ddclient-activation config) - "Return the activation GEXP for CONFIG." - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils) - (ice-9 rdelim)) - (let ((ddclient-user - (passwd:uid (getpw #$(ddclient-configuration-user config)))) - (ddclient-group - (passwd:gid (getpw #$(ddclient-configuration-group config)))) - (ddclient-secret-file - #$(ddclient-configuration-secret-file config))) - ;; 'ddclient' complains about ddclient.conf file permissions, which - ;; rules out /gnu/store. Thus we copy the ddclient.conf to /etc. - (for-each (lambda (dir) - (mkdir-p dir) - (chmod dir #o700) - (chown dir ddclient-user ddclient-group)) - '("/var/cache/ddclient" "/var/run/ddclient" - "/etc/ddclient")) - (with-output-to-file "/etc/ddclient/ddclient.conf" - (lambda () - (display - (string-append - "# Generated by 'ddclient-service'.\n\n" - #$(with-output-to-string - (lambda () - (serialize-configuration config - ddclient-configuration-fields))) - (if (string-null? ddclient-secret-file) - "" - (format #f "\n\n# Appended from '~a'.\n\n~a" - ddclient-secret-file - (with-input-from-file ddclient-secret-file - read-string))))))) - (chmod "/etc/ddclient/ddclient.conf" #o600) - (chown "/etc/ddclient/ddclient.conf" - ddclient-user ddclient-group))))) - -(define (ddclient-shepherd-service config) - "Return a for ddclient with CONFIG." - (let ((ddclient (ddclient-configuration-ddclient config)) - (ddclient-pid (ddclient-configuration-pid config)) - (ddclient-user (ddclient-configuration-user config)) - (ddclient-group (ddclient-configuration-group config))) - (list (shepherd-service - (provision '(ddclient)) - (documentation "Run ddclient daemon.") - (start #~(make-forkexec-constructor - (list #$(file-append ddclient "/bin/ddclient") - "-foreground" - "-file" "/etc/ddclient/ddclient.conf") - #:pid-file #$ddclient-pid - #:environment-variables - (list "SSL_CERT_DIR=/run/current-system/profile\ -/etc/ssl/certs" - "SSL_CERT_FILE=/run/current-system/profile\ -/etc/ssl/certs/ca-certificates.crt") - #:user #$ddclient-user - #:group #$ddclient-group)) - (stop #~(make-kill-destructor)))))) - -(define ddclient-service-type - (service-type - (name 'ddclient) - (extensions - (list (service-extension account-service-type - ddclient-account) - (service-extension shepherd-root-service-type - ddclient-shepherd-service) - (service-extension activation-service-type - ddclient-activation))) - (default-value (ddclient-configuration)) - (description "Configure address updating utility for dynamic DNS services, -ddclient."))) - -(define (generate-ddclient-documentation) - (generate-documentation - `((ddclient-configuration ,ddclient-configuration-fields)) - 'ddclient-configuration)) -- cgit 1.4.1