X-Git-Url: http://git.hcoop.net/jackhill/guix/guix.git/blobdiff_plain/c6d02bcf1bcc06c70e440221e317274926c0fce3..95f72dcd7aece05e9252c93bef5a831f96cb5393:/gnu/services/base.scm diff --git a/gnu/services/base.scm b/gnu/services/base.scm index 08ab5970dc..f6a490f712 100644 --- a/gnu/services/base.scm +++ b/gnu/services/base.scm @@ -1,7 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès +;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès ;;; Copyright © 2015, 2016 Alex Kost -;;; Copyright © 2015, 2016 Mark H Weaver +;;; Copyright © 2015, 2016, 2020 Mark H Weaver ;;; Copyright © 2015 Sou Bunnbu ;;; Copyright © 2016, 2017 Leo Famulari ;;; Copyright © 2016 David Craven @@ -12,6 +12,7 @@ ;;; Copyright © 2019 John Soo ;;; Copyright © 2019 Jan (janneke) Nieuwenhuizen ;;; Copyright © 2020 Florian Pelz +;;; Copyright © 2020 Brice Waegeneire ;;; ;;; This file is part of GNU Guix. ;;; @@ -61,11 +62,12 @@ #:use-module (srfi srfi-26) #:use-module (ice-9 match) #:use-module (ice-9 format) + #:re-export (user-processes-service-type ;backwards compatibility + %default-substitute-urls) #:export (fstab-service-type root-file-system-service file-system-service-type swap-service - user-processes-service-type host-name-service console-keymap-service %default-console-font @@ -92,6 +94,7 @@ udev-service udev-rule file->udev-rule + udev-rules-service login-configuration login-configuration? @@ -104,6 +107,12 @@ agetty-service-type mingetty-configuration + mingetty-configuration-tty + mingetty-configuration-auto-login + mingetty-configuration-login-program + mingetty-configuration-login-pause? + mingetty-configuration-clear-on-logout? + mingetty-configuration-mingetty mingetty-configuration? mingetty-service mingetty-service-type @@ -175,6 +184,8 @@ pam-limits-service-type pam-limits-service + references-file + %base-services)) ;;; Commentary: @@ -186,128 +197,6 @@ -;;; -;;; User processes. -;;; - -(define %do-not-kill-file - ;; Name of the file listing PIDs of processes that must survive when halting - ;; the system. Typical example is user-space file systems. - "/etc/shepherd/do-not-kill") - -(define (user-processes-shepherd-service requirements) - "Return the 'user-processes' Shepherd service with dependencies on -REQUIREMENTS (a list of service names). - -This is a synchronization point used to make sure user processes and daemons -get started only after crucial initial services have been started---file -system mounts, etc. This is similar to the 'sysvinit' target in systemd." - (define grace-delay - ;; Delay after sending SIGTERM and before sending SIGKILL. - 4) - - (list (shepherd-service - (documentation "When stopped, terminate all user processes.") - (provision '(user-processes)) - (requirement requirements) - (start #~(const #t)) - (stop #~(lambda _ - (define (kill-except omit signal) - ;; Kill all the processes with SIGNAL except those listed - ;; in OMIT and the current process. - (let ((omit (cons (getpid) omit))) - (for-each (lambda (pid) - (unless (memv pid omit) - (false-if-exception - (kill pid signal)))) - (processes)))) - - (define omitted-pids - ;; List of PIDs that must not be killed. - (if (file-exists? #$%do-not-kill-file) - (map string->number - (call-with-input-file #$%do-not-kill-file - (compose string-tokenize - (@ (ice-9 rdelim) read-string)))) - '())) - - (define (now) - (car (gettimeofday))) - - (define (sleep* n) - ;; Really sleep N seconds. - ;; Work around . - (define start (now)) - (let loop ((elapsed 0)) - (when (> n elapsed) - (sleep (- n elapsed)) - (loop (- (now) start))))) - - (define lset= (@ (srfi srfi-1) lset=)) - - (display "sending all processes the TERM signal\n") - - (if (null? omitted-pids) - (begin - ;; Easy: terminate all of them. - (kill -1 SIGTERM) - (sleep* #$grace-delay) - (kill -1 SIGKILL)) - (begin - ;; Kill them all except OMITTED-PIDS. XXX: We would - ;; like to (kill -1 SIGSTOP) to get a fixed list of - ;; processes, like 'killall5' does, but that seems - ;; unreliable. - (kill-except omitted-pids SIGTERM) - (sleep* #$grace-delay) - (kill-except omitted-pids SIGKILL) - (delete-file #$%do-not-kill-file))) - - (let wait () - ;; Reap children, if any, so that we don't end up with - ;; zombies and enter an infinite loop. - (let reap-children () - (define result - (false-if-exception - (waitpid WAIT_ANY (if (null? omitted-pids) - 0 - WNOHANG)))) - - (when (and (pair? result) - (not (zero? (car result)))) - (reap-children))) - - (let ((pids (processes))) - (unless (lset= = pids (cons 1 omitted-pids)) - (format #t "waiting for process termination\ - (processes left: ~s)~%" - pids) - (sleep* 2) - (wait)))) - - (display "all processes have been terminated\n") - #f)) - (respawn? #f)))) - -(define user-processes-service-type - (service-type - (name 'user-processes) - (extensions (list (service-extension shepherd-root-service-type - user-processes-shepherd-service))) - (compose concatenate) - (extend append) - - ;; The value is the list of Shepherd services 'user-processes' depends on. - ;; Extensions can add new services to this list. - (default-value '()) - - (description "The @code{user-processes} service is responsible for -terminating all the processes so that the root file system can be re-mounted -read-only, just before rebooting/halting. Processes still running after a few -seconds after @code{SIGTERM} has been sent are terminated with -@code{SIGKILL}."))) - - ;;; ;;; File systems. ;;; @@ -390,7 +279,9 @@ system objects."))) (define root-file-system-service-type (shepherd-service-type 'root-file-system - (const %root-file-system-shepherd-service))) + (const %root-file-system-shepherd-service) + (description "Take care of syncing the root file +system and of remounting it read-only when the system shuts down."))) (define (root-file-system-service) "Return a service whose sole purpose is to re-mount read-only the root file @@ -409,7 +300,8 @@ FILE-SYSTEM." (define (mapped-device->shepherd-service-name md) "Return the symbol that denotes the shepherd service of MD, a ." (symbol-append 'device-mapping- - (string->symbol (mapped-device-target md)))) + (string->symbol (string-join + (mapped-device-targets md) "-")))) (define dependency->shepherd-service-name (match-lambda @@ -679,8 +571,10 @@ down."))) (documentation "Add TRNG to entropy pool.") (requirement '(udev)) (provision '(trng)) - (start #~(make-forkexec-constructor #$@rngd-command)) - (stop #~(make-kill-destructor)))))) + (start #~(make-forkexec-constructor '#$rngd-command)) + (stop #~(make-kill-destructor)))) + (description "Run the @command{rngd} random number generation daemon to +supply entropy to the kernel's pool."))) (define* (rngd-service #:key (rng-tools rng-tools) @@ -707,7 +601,8 @@ to add @var{device} to the kernel's entropy pool. The service will fail if (provision '(host-name)) (start #~(lambda _ (sethostname #$name))) - (one-shot? #t))))) + (one-shot? #t))) + (description "Initialize the machine's host name."))) (define (host-name-service name) "Return a service that sets the host name to @var{name}." @@ -736,7 +631,8 @@ to add @var{device} to the kernel's entropy pool. The service will fail if (display 1 port)))) #t)) (stop #~(const #f))))) - #t)) ;default to UTF-8 + #t ;default to UTF-8 + (description "Ensure the Linux virtual terminals run in UTF-8 mode."))) (define console-keymap-service-type (shepherd-service-type @@ -748,7 +644,10 @@ to add @var{device} to the kernel's entropy pool. The service will fail if (start #~(lambda _ (zero? (system* #$(file-append kbd "/bin/loadkeys") #$@files)))) - (respawn? #f))))) + (respawn? #f))) + (description "@emph{This service is deprecated in favor of the +@code{keyboard-layout} field of @code{operating-system}.} Load the given list +of console keymaps with @command{loadkeys}."))) (define-deprecated (console-keymap-service #:rest files) #f @@ -1142,20 +1041,22 @@ the tty to run, among other things." (define-record-type* mingetty-configuration make-mingetty-configuration mingetty-configuration? - (mingetty mingetty-configuration-mingetty ; - (default mingetty)) - (tty mingetty-configuration-tty) ;string - (auto-login mingetty-auto-login ;string | #f - (default #f)) - (login-program mingetty-login-program ;gexp - (default #f)) - (login-pause? mingetty-login-pause? ;Boolean - (default #f))) + (mingetty mingetty-configuration-mingetty ; + (default mingetty)) + (tty mingetty-configuration-tty) ;string + (auto-login mingetty-auto-login ;string | #f + (default #f)) + (login-program mingetty-login-program ;gexp + (default #f)) + (login-pause? mingetty-login-pause? ;Boolean + (default #f)) + (clear-on-logout? mingetty-clear-on-logout? ;Boolean + (default #t))) (define mingetty-shepherd-service (match-lambda (($ mingetty tty auto-login login-program - login-pause?) + login-pause? clear-on-logout?) (list (shepherd-service (documentation "Run mingetty on an tty.") @@ -1168,7 +1069,6 @@ the tty to run, among other things." (start #~(make-forkexec-constructor (list #$(file-append mingetty "/sbin/mingetty") - "--noclear" ;; Avoiding 'vhangup' allows us to avoid 'setfont' ;; errors down the path where various ioctls get @@ -1176,6 +1076,9 @@ the tty to run, among other things." ;; in Linux. "--nohangup" #$tty + #$@(if clear-on-logout? + #~() + #~("--noclear")) #$@(if auto-login #~("--autologin" #$auto-login) #~()) @@ -1447,7 +1350,9 @@ Service Switch}, for an example." (pid (spawn))) (umask mask) pid)))) - (stop #~(make-kill-destructor)))))) + (stop #~(make-kill-destructor)))) + (description "Run the syslog daemon, @command{syslogd}, which is +responsible for logging system messages."))) ;; Snippet adapted from the GNU inetutils manual. (define %default-syslog.conf @@ -1503,7 +1408,7 @@ information on the configuration file syntax." (module "pam_limits.so") (arguments '("conf=/etc/security/limits.conf"))))) (if (member (pam-service-name pam) - '("login" "su" "slim" "gdm-password")) + '("login" "su" "slim" "gdm-password" "sddm")) (pam-service (inherit pam) (session (cons pam-limits @@ -1594,14 +1499,22 @@ archive' public keys, with GUIX." #~(begin (use-modules (guix build utils)) - (unless (file-exists? "/etc/guix/acl") - (mkdir-p "/etc/guix") - (copy-file #+default-acl "/etc/guix/acl") - (chmod "/etc/guix/acl" #o600))))) + ;; If the ACL already exists, move it out of the way. Create a backup + ;; if it's a regular file: it's likely that the user manually updated + ;; it with 'guix archive --authorize'. + (if (file-exists? "/etc/guix/acl") + (if (and (symbolic-link? "/etc/guix/acl") + (store-file-name? (readlink "/etc/guix/acl"))) + (delete-file "/etc/guix/acl") + (rename-file "/etc/guix/acl" "/etc/guix/acl.bak")) + (mkdir-p "/etc/guix")) + + ;; Installed the declared ACL. + (symlink #+default-acl "/etc/guix/acl")))) (define %default-authorized-guix-keys ;; List of authorized substitute keys. - (list (file-append guix "/share/guix/berlin.guixsd.org.pub"))) + (list (file-append guix "/share/guix/berlin.guix.gnu.org.pub"))) (define-record-type* guix-configuration make-guix-configuration @@ -1628,6 +1541,8 @@ archive' public keys, with GUIX." (default 0)) (log-compression guix-configuration-log-compression (default 'bzip2)) + (discover? guix-configuration-discover? + (default #f)) (extra-options guix-configuration-extra-options ;list of strings (default '())) (log-file guix-configuration-log-file ;string @@ -1664,69 +1579,118 @@ proxy of 'guix-daemon'...~%") (environ environment) #t))))) +(define shepherd-discover-action + ;; Shepherd action to enable or disable substitute servers discovery. + (shepherd-action + (name 'discover) + (documentation + "Enable or disable substitute servers discovery and restart the +'guix-daemon'.") + (procedure #~(lambda* (_ status) + (let ((environment (environ))) + (if (and status + (string=? status "on")) + (begin + (format #t "enable substitute servers discovery~%") + (setenv "discover" "on")) + (begin + (format #t "disable substitute servers discovery~%") + (unsetenv "discover"))) + (action 'guix-daemon 'restart) + (environ environment) + #t))))) + (define (guix-shepherd-service config) "Return a for the Guix daemon service with CONFIG." (match-record config (guix build-group build-accounts authorize-key? authorized-keys use-substitutes? substitute-urls max-silent-time timeout - log-compression extra-options log-file http-proxy tmpdir - chroot-directories) + log-compression discover? extra-options log-file + http-proxy tmpdir chroot-directories) (list (shepherd-service (documentation "Run the Guix daemon.") (provision '(guix-daemon)) (requirement '(user-processes)) - (actions (list shepherd-set-http-proxy-action)) - (modules '((srfi srfi-1))) + (actions (list shepherd-set-http-proxy-action + shepherd-discover-action)) + (modules '((srfi srfi-1) + (ice-9 match) + (gnu build shepherd))) (start - #~(lambda _ - (define proxy - ;; HTTP/HTTPS proxy. The 'http_proxy' variable is set by - ;; the 'set-http-proxy' action. - (or (getenv "http_proxy") #$http-proxy)) - - (fork+exec-command - (cons* #$(file-append guix "/bin/guix-daemon") - "--build-users-group" #$build-group - "--max-silent-time" #$(number->string max-silent-time) - "--timeout" #$(number->string timeout) - "--log-compression" #$(symbol->string log-compression) - #$@(if use-substitutes? - '() - '("--no-substitutes")) - "--substitute-urls" #$(string-join substitute-urls) - #$@extra-options - - ;; Add CHROOT-DIRECTORIES and all their dependencies - ;; (if these are store items) to the chroot. - (append-map (lambda (file) - (append-map (lambda (directory) - (list "--chroot-directory" - directory)) - (call-with-input-file file - read))) - '#$(map references-file - chroot-directories))) - - #:environment-variables - (append (list #$@(if tmpdir - (list (string-append "TMPDIR=" tmpdir)) - '()) - - ;; Make sure we run in a UTF-8 locale so that - ;; 'guix offload' correctly restores nars that - ;; contain UTF-8 file names such as - ;; 'nss-certs'. See - ;; . - (string-append "GUIX_LOCPATH=" - #$glibc-utf8-locales - "/lib/locale") - "LC_ALL=en_US.utf8") - (if proxy - (list (string-append "http_proxy=" proxy) - (string-append "https_proxy=" proxy)) - '())) - - #:log-file #$log-file))) + (with-imported-modules `(((guix config) => ,(make-config.scm)) + ,@(source-module-closure + '((gnu build shepherd)) + #:select? not-config?)) + #~(lambda args + (define proxy + ;; HTTP/HTTPS proxy. The 'http_proxy' variable is set by + ;; the 'set-http-proxy' action. + (or (getenv "http_proxy") #$http-proxy)) + + (define discover? + (or (getenv "discover") #$discover?)) + + ;; Start the guix-daemon from a container, when supported, + ;; to solve an installation issue. See the comment below for + ;; more details. + (fork+exec-command/container + (cons* #$(file-append guix "/bin/guix-daemon") + "--build-users-group" #$build-group + "--max-silent-time" + #$(number->string max-silent-time) + "--timeout" #$(number->string timeout) + "--log-compression" + #$(symbol->string log-compression) + #$@(if use-substitutes? + '() + '("--no-substitutes")) + (string-append "--discover=" + (if discover? "yes" "no")) + "--substitute-urls" #$(string-join substitute-urls) + #$@extra-options + + ;; Add CHROOT-DIRECTORIES and all their dependencies + ;; (if these are store items) to the chroot. + (append-map + (lambda (file) + (append-map (lambda (directory) + (list "--chroot-directory" + directory)) + (call-with-input-file file + read))) + '#$(map references-file + chroot-directories))) + + ;; When running the installer, we need guix-daemon to + ;; operate from within the same MNT namespace as the + ;; installation container. In that case only, enter the + ;; namespace of the process PID passed as start argument. + ;; Otherwise, for symmetry purposes enter the caller + ;; namespaces which is a no-op. + #:pid (match args + ((pid) (string->number pid)) + (else (getpid))) + + #:environment-variables + (append (list #$@(if tmpdir + (list (string-append "TMPDIR=" tmpdir)) + '()) + + ;; Make sure we run in a UTF-8 locale so that + ;; 'guix offload' correctly restores nars + ;; that contain UTF-8 file names such as + ;; 'nss-certs'. See + ;; . + (string-append "GUIX_LOCPATH=" + #$glibc-utf8-locales + "/lib/locale") + "LC_ALL=en_US.utf8") + (if proxy + (list (string-append "http_proxy=" proxy) + (string-append "https_proxy=" proxy)) + '())) + + #:log-file #$log-file)))) (stop #~(make-kill-destructor)))))) (define (guix-accounts config) @@ -1751,26 +1715,32 @@ proxy of 'guix-daemon'...~%") ;; otherwise call 'chown' here, but the problem is that on a COW overlayfs, ;; chown leads to an entire copy of the tree, which is a bad idea. - ;; Optionally authorize substitute server keys. - (if authorize-key? - (substitute-key-authorization keys guix) - #~#f)))) + ;; Generate a key pair and optionally authorize substitute server keys. + #~(begin + (unless (file-exists? "/etc/guix/signing-key.pub") + (system* #$(file-append guix "/bin/guix") "archive" + "--generate-key")) + + #$(if authorize-key? + (substitute-key-authorization keys guix) + #~#f))))) (define* (references-file item #:optional (name "references")) "Return a file that contains the list of references of ITEM." (if (struct? item) ;lowerable object (computed-file name - (with-imported-modules (source-module-closure - '((guix build store-copy))) - #~(begin - (use-modules (guix build store-copy)) - - (call-with-output-file #$output - (lambda (port) - (write (map store-info-item - (call-with-input-file "graph" - read-reference-graph)) - port))))) + (with-extensions (list guile-gcrypt) ;for store-copy + (with-imported-modules (source-module-closure + '((guix build store-copy))) + #~(begin + (use-modules (guix build store-copy)) + + (call-with-output-file #$output + (lambda (port) + (write (map store-info-item + (call-with-input-file "graph" + read-reference-graph)) + port)))))) #:options `(#:local-build? #f #:references-graphs (("graph" ,item)))) (plain-file name "()"))) @@ -1815,6 +1785,8 @@ proxy of 'guix-daemon'...~%") (default 80)) (host guix-publish-configuration-host ;string (default "localhost")) + (advertise? guix-publish-advertise? ;boolean + (default #f)) (compression guix-publish-configuration-compression (thunked) (default (default-compression this-record @@ -1825,6 +1797,8 @@ proxy of 'guix-daemon'...~%") (default "nar")) (cache guix-publish-configuration-cache ;#f | string (default #f)) + (cache-bypass-threshold guix-publish-configuration-cache-bypass-threshold + (default (* 10 (expt 2 20)))) ;integer (workers guix-publish-configuration-workers ;#f | integer (default #f)) (ttl guix-publish-configuration-ttl ;#f | integer @@ -1859,10 +1833,13 @@ raise a deprecation warning if the 'compression-level' field was used." lst)))) (match-record config - (guix port host nar-path cache workers ttl) + (guix port host nar-path cache workers ttl cache-bypass-threshold + advertise?) (list (shepherd-service (provision '(guix-publish)) - (requirement '(guix-daemon)) + (requirement `(user-processes + guix-daemon + ,@(if advertise? '(avahi-daemon) '()))) (start #~(make-forkexec-constructor (list #$(file-append guix "/bin/guix") "publish" "-u" "guix-publish" @@ -1870,6 +1847,9 @@ raise a deprecation warning if the 'compression-level' field was used." #$@(config->compression-options config) (string-append "--nar-path=" #$nar-path) (string-append "--listen=" #$host) + #$@(if advertise? + #~("--advertise") + #~()) #$@(if workers #~((string-append "--workers=" #$(number->string @@ -1881,7 +1861,11 @@ raise a deprecation warning if the 'compression-level' field was used." "s")) #~()) #$@(if cache - #~((string-append "--cache=" #$cache)) + #~((string-append "--cache=" #$cache) + #$(string-append + "--cache-bypass-threshold=" + (number->string + cache-bypass-threshold))) #~())) ;; Make sure we run in a UTF-8 locale so we can produce @@ -2164,27 +2148,78 @@ extra rules from the packages listed in @var{rules}." (service udev-service-type (udev-configuration (udev udev) (rules rules)))) +(define* (udev-rules-service name rules #:key (groups '())) + "Return a service that extends udev-service-type with RULES and +account-service-type with GROUPS as system groups. This works by creating a +singleton service type NAME-udev-rules, of which the returned service is an +instance." + (let* ((name (symbol-append name '-udev-rules)) + (account-extension + (const (map (lambda (group) + (user-group (name group) (system? #t))) + groups))) + (udev-extension (const (list rules))) + (type (service-type + (name name) + (extensions (list + (service-extension + account-service-type account-extension) + (service-extension + udev-service-type udev-extension)))))) + (service type #f))) + (define swap-service-type (shepherd-service-type 'swap (lambda (device) (define requirement - (if (string-prefix? "/dev/mapper/" device) + (if (and (string? device) + (string-prefix? "/dev/mapper/" device)) (list (symbol-append 'device-mapping- (string->symbol (basename device)))) '())) - (shepherd-service - (provision (list (symbol-append 'swap- (string->symbol device)))) - (requirement `(udev ,@requirement)) - (documentation "Enable the given swap device.") - (start #~(lambda () - (restart-on-EINTR (swapon #$device)) - #t)) - (stop #~(lambda _ - (restart-on-EINTR (swapoff #$device)) - #f)) - (respawn? #f))))) + (define (device-lookup device) + ;; The generic 'find-partition' procedures could return a partition + ;; that's not swap space, but that's unlikely. + (cond ((uuid? device) + #~(find-partition-by-uuid #$(uuid-bytevector device))) + ((file-system-label? device) + #~(find-partition-by-label + #$(file-system-label->string device))) + (else + device))) + + (define service-name + (symbol-append 'swap- + (string->symbol + (cond ((uuid? device) + (string-take (uuid->string device) 6)) + ((file-system-label? device) + (file-system-label->string device)) + (else + device))))) + + (with-imported-modules (source-module-closure '((gnu build file-systems))) + (shepherd-service + (provision (list service-name)) + (requirement `(udev ,@requirement)) + (documentation "Enable the given swap device.") + (modules `((gnu build file-systems) + ,@%default-modules)) + (start #~(lambda () + (let ((device #$(device-lookup device))) + (and device + (begin + (restart-on-EINTR (swapon device)) + #t))))) + (stop #~(lambda _ + (let ((device #$(device-lookup device))) + (when device + (restart-on-EINTR (swapoff device))) + #f))) + (respawn? #f)))) + (description "Turn on the virtual memory swap area."))) (define (swap-service device) "Return a service that uses @var{device} as a swap device." @@ -2298,7 +2333,9 @@ This service is not part of @var{%base-services}." (requirement '(user-processes udev dbus-system)) (provision (list (symbol-append 'term- (string->symbol virtual-terminal)))) (start #~(make-forkexec-constructor #$kmscon-command)) - (stop #~(make-kill-destructor))))))) + (stop #~(make-kill-destructor))))) + (description "Start the @command{kmscon} virtual terminal emulator for the +Linux @dfn{kernel mode setting} (KMS)."))) (define-record-type* static-networking make-static-networking