;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
;;; Copyright © 2015, 2016 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
;;; Copyright © 2016 David Craven <david@craven.ch>
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
+;;; Copyright © 2019 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
(define-module (gnu services base)
#:use-module (guix store)
+ #:use-module (guix deprecation)
#:use-module (gnu services)
+ #:use-module (gnu services admin)
#:use-module (gnu services shepherd)
#:use-module (gnu system pam)
#:use-module (gnu system shadow) ; 'user-account', etc.
#:select (canonical-package glibc glibc-utf8-locales))
#:use-module (gnu packages bash)
#:use-module (gnu packages package-management)
+ #:use-module ((gnu packages gnupg) #:select (guile-gcrypt))
#:use-module (gnu packages linux)
#:use-module (gnu packages terminals)
#:use-module ((gnu build file-systems)
#:use-module (guix gexp)
#:use-module (guix records)
#:use-module (guix modules)
+ #:use-module ((guix self) #:select (make-config.scm))
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
guix-publish-configuration-guix
guix-publish-configuration-port
guix-publish-configuration-host
- guix-publish-configuration-compression-level
+ guix-publish-configuration-compression
+ guix-publish-configuration-compression-level ;deprecated
guix-publish-configuration-nar-path
guix-publish-configuration-cache
guix-publish-configuration-ttl
`(("fstab" ,(plain-file "fstab"
(string-append
"\
-# This file was generated from your GuixSD configuration. Any changes
+# This file was generated from your Guix configuration. Any changes
# will be lost upon reboot or reconfiguration.\n\n"
(string-join (map file-system->fstab-entry
file-systems)
(cons* sink user-unmount
(map file-system-shepherd-service file-systems))))
+(define (file-system-fstab-entries file-systems)
+ "Return the subset of @var{file-systems} that should have an entry in
+@file{/etc/fstab}."
+ ;; /etc/fstab is about telling fsck(8), mount(8), and umount(8) about
+ ;; relevant file systems they'll have to deal with. That excludes "pseudo"
+ ;; file systems.
+ ;;
+ ;; In particular, things like GIO (part of GLib) use it to determine the set
+ ;; of mounts, which is then used by graphical file managers and desktop
+ ;; environments to display "volume" icons. Thus, we really need to exclude
+ ;; those pseudo file systems from the list.
+ (remove (lambda (file-system)
+ (or (member (file-system-type file-system)
+ %pseudo-file-system-types)
+ (memq 'bind-mount (file-system-flags file-system))))
+ file-systems))
+
(define file-system-service-type
(service-type (name 'file-systems)
(extensions
(list (service-extension shepherd-root-service-type
file-system-shepherd-services)
(service-extension fstab-service-type
- identity)
+ file-system-fstab-entries)
;; Have 'user-processes' depend on 'file-systems'.
(service-extension user-processes-service-type
generator (RNG) with the value recorded when the system was last shut
down.")))
-(define (urandom-seed-service) ;deprecated
- (service urandom-seed-service-type #f))
+(define-deprecated (urandom-seed-service)
+ urandom-seed-service-type
+ (service urandom-seed-service-type))
;;;
#$@files))))
(respawn? #f)))))
-(define (console-keymap-service . files)
+(define-deprecated (console-keymap-service #:rest files)
+ #f
"Return a service to load console keymaps from @var{files}."
(service console-keymap-service-type files))
"Return the list of PAM service needed for CONF."
;; Let 'login' be known to PAM.
(list (unix-pam-service "login"
+ #:login-uid? #t
#:allow-empty-passwords?
(login-configuration-allow-empty-passwords? config)
#:motd
(service-type (name 'login)
(extensions (list (service-extension pam-root-service-type
login-pam-service)))
+ (default-value (login-configuration))
(description
"Provide a console log-in service as specified by its
configuration value, a @code{login-configuration} object.")))
(string-concatenate
(map cache->config caches)))))))
+(define (nscd-action-procedure nscd config option)
+ ;; XXX: This is duplicated from mcron; factorize.
+ #~(lambda (_ . args)
+ ;; Run 'nscd' in a pipe so we can explicitly redirect its output to
+ ;; 'current-output-port', which at this stage is bound to the client
+ ;; connection.
+ (let ((pipe (apply open-pipe* OPEN_READ #$nscd
+ "-f" #$config #$option args)))
+ (let loop ()
+ (match (read-line pipe 'concat)
+ ((? eof-object?)
+ (catch 'system-error
+ (lambda ()
+ (zero? (close-pipe pipe)))
+ (lambda args
+ ;; There's a race with the SIGCHLD handler, which could
+ ;; call 'waitpid' before 'close-pipe' above does. If we
+ ;; get ECHILD, that means we lost the race; in that case, we
+ ;; cannot tell what the exit code was (FIXME).
+ (or (= ECHILD (system-error-errno args))
+ (apply throw args)))))
+ (line
+ (display line)
+ (loop)))))))
+
+(define (nscd-actions nscd config)
+ "Return Shepherd actions for NSCD."
+ ;; Make this functionality available as actions because that's a simple way
+ ;; to run the right 'nscd' binary with the right config file.
+ (list (shepherd-action
+ (name 'statistics)
+ (documentation "Display statistics about nscd usage.")
+ (procedure (nscd-action-procedure nscd config "--statistics")))
+ (shepherd-action
+ (name 'invalidate)
+ (documentation
+ "Invalidate the given cache--e.g., 'hosts' for host name lookups.")
+ (procedure (nscd-action-procedure nscd config "--invalidate")))))
+
(define (nscd-shepherd-service config)
"Return a shepherd service for CONFIG, an <nscd-configuration> object."
- (let ((nscd.conf (nscd.conf-file config))
+ (let ((nscd (file-append (nscd-configuration-glibc config)
+ "/sbin/nscd"))
+ (nscd.conf (nscd.conf-file config))
(name-services (nscd-configuration-name-services config)))
(list (shepherd-service
(documentation "Run libc's name service cache daemon (nscd).")
(provision '(nscd))
(requirement '(user-processes))
(start #~(make-forkexec-constructor
- (list #$(file-append (nscd-configuration-glibc config)
- "/sbin/nscd")
- "-f" #$nscd.conf "--foreground")
+ (list #$nscd "-f" #$nscd.conf "--foreground")
;; Wait for the PID file. However, the PID file is
;; written before nscd is actually listening on its
(string-append dir "/lib"))
(list #$@name-services))
":")))))
- (stop #~(make-kill-destructor))))))
+ (stop #~(make-kill-destructor))
+ (modules `((ice-9 popen) ;for the actions
+ (ice-9 rdelim)
+ (ice-9 match)
+ ,@%default-modules))
+ (actions (nscd-actions nscd nscd.conf))))))
(define nscd-activation
;; Actions to take before starting nscd.
(name-services (append
(nscd-configuration-name-services config)
name-services)))))
+ (default-value %nscd-default-configuration)
(description
"Runs libc's @dfn{name service cache daemon} (nscd) with the
given configuration---an @code{<nscd-configuration>} object. @xref{Name
(define* (guix-build-accounts count #:key
(group "guixbuild")
- (first-uid 30001)
(shadow shadow))
- "Return a list of COUNT user accounts for Guix build users, with UIDs
-starting at FIRST-UID, and under GID."
+ "Return a list of COUNT user accounts for Guix build users with the given
+GID."
(unfold (cut > <> count)
(lambda (n)
(user-account
(name (format #f "guixbuilder~2,'0d" n))
(system? #t)
- (uid (+ first-uid n -1))
(group group)
;; guix-daemon expects GROUP to be listed as a
1+
1))
-(define (hydra-key-authorization key guix)
- "Return a gexp with code to register KEY, a file containing a 'guix archive'
-public key, with GUIX."
- #~(unless (file-exists? "/etc/guix/acl")
- (let ((pid (primitive-fork)))
- (case pid
- ((0)
- (let* ((key #$key)
- (port (open-file key "r0b")))
- (format #t "registering public key '~a'...~%" key)
- (close-port (current-input-port))
- (dup port 0)
- (execl #$(file-append guix "/bin/guix")
- "guix" "archive" "--authorize")
- (exit 1)))
- (else
- (let ((status (cdr (waitpid pid))))
- (unless (zero? status)
- (format (current-error-port) "warning: \
-failed to register hydra.gnu.org public key: ~a~%" status))))))))
+(define not-config?
+ ;; Select (guix …) and (gnu …) modules, except (guix config).
+ (match-lambda
+ (('guix 'config) #f)
+ (('guix rest ...) #t)
+ (('gnu rest ...) #t)
+ (rest #f)))
+
+(define (hydra-key-authorization keys guix)
+ "Return a gexp with code to register KEYS, a list of files containing 'guix
+archive' public keys, with GUIX."
+ (define default-acl
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules `(((guix config) => ,(make-config.scm))
+ ,@(source-module-closure '((guix pki))
+ #:select? not-config?))
+ (computed-file "acl"
+ #~(begin
+ (use-modules (guix pki)
+ (gcrypt pk-crypto)
+ (ice-9 rdelim))
+
+ (define keys
+ (map (lambda (file)
+ (call-with-input-file file
+ (compose string->canonical-sexp
+ read-string)))
+ '(#$@keys)))
+
+ (call-with-output-file #$output
+ (lambda (port)
+ (write-acl (public-keys->acl keys)
+ port))))))))
+
+ (with-imported-modules '((guix build utils))
+ #~(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)))))
(define %default-authorized-guix-keys
;; List of authorized substitute keys.
'())
#$@(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
+ ;; <https://bugs.gnu.org/32942>.
+ (string-append "GUIX_LOCPATH="
+ #$glibc-utf8-locales "/lib/locale")
+ "LC_ALL=en_US.utf8")
#:log-file #$log-file))
(stop #~(make-kill-destructor))))))
;; 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 hydra.gnu.org's key.
+ ;; Optionally authorize substitute server keys.
(if authorize-key?
- #~(begin
- #$@(map (cut hydra-key-authorization <> guix) keys))
+ (hydra-key-authorization keys guix)
#~#f))))
(define* (references-file item #:optional (name "references"))
(description
"Run the build daemon of GNU@tie{}Guix, aka. @command{guix-daemon}.")))
-(define* (guix-service #:optional (config %default-guix-configuration))
+(define-deprecated (guix-service #:optional
+ (config %default-guix-configuration))
+ guix-service-type
"Return a service that runs the Guix build daemon according to
@var{config}."
(service guix-service-type config))
(default 80))
(host guix-publish-configuration-host ;string
(default "localhost"))
- (compression-level guix-publish-configuration-compression-level ;integer
- (default 3))
+ (compression guix-publish-configuration-compression
+ (thunked)
+ (default (default-compression this-record
+ (current-source-location))))
+ (compression-level %guix-publish-configuration-compression-level ;deprecated
+ (default #f))
(nar-path guix-publish-configuration-nar-path ;string
(default "nar"))
(cache guix-publish-configuration-cache ;#f | string
(ttl guix-publish-configuration-ttl ;#f | integer
(default #f)))
-(define guix-publish-shepherd-service
- (match-lambda
- (($ <guix-publish-configuration> guix port host compression
- nar-path cache workers ttl)
- (list (shepherd-service
- (provision '(guix-publish))
- (requirement '(guix-daemon))
- (start #~(make-forkexec-constructor
- (list #$(file-append guix "/bin/guix")
- "publish" "-u" "guix-publish"
- "-p" #$(number->string port)
- "-C" #$(number->string compression)
- (string-append "--nar-path=" #$nar-path)
- (string-append "--listen=" #$host)
- #$@(if workers
- #~((string-append "--workers="
- #$(number->string
- workers)))
- #~())
- #$@(if ttl
- #~((string-append "--ttl="
- #$(number->string ttl)
- "s"))
- #~())
- #$@(if cache
- #~((string-append "--cache=" #$cache))
- #~()))
-
- ;; Make sure we run in a UTF-8 locale so we can produce
- ;; nars for packages that contain UTF-8 file names such
- ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
- #:environment-variables
- (list (string-append "GUIX_LOCPATH="
- #$glibc-utf8-locales "/lib/locale")
- "LC_ALL=en_US.utf8")))
- (stop #~(make-kill-destructor)))))))
+(define-deprecated (guix-publish-configuration-compression-level config)
+ "Return a compression level, the old way."
+ (match (guix-publish-configuration-compression config)
+ (((_ level) _ ...) level)))
+
+(define (default-compression config properties)
+ "Return the default 'guix publish' compression according to CONFIG, and
+raise a deprecation warning if the 'compression-level' field was used."
+ (match (%guix-publish-configuration-compression-level config)
+ (#f
+ '(("gzip" 3)))
+ (level
+ (warn-about-deprecation 'compression-level properties
+ #:replacement 'compression)
+ `(("gzip" ,level)))))
+
+(define (guix-publish-shepherd-service config)
+ (define (config->compression-options config)
+ (match (guix-publish-configuration-compression config)
+ (() ;empty list means "no compression"
+ '("-C0"))
+ (lst
+ (append-map (match-lambda
+ ((type level)
+ `("-C" ,(string-append type ":"
+ (number->string level)))))
+ lst))))
+
+ (match-record config <guix-publish-configuration>
+ (guix port host nar-path cache workers ttl)
+ (list (shepherd-service
+ (provision '(guix-publish))
+ (requirement '(guix-daemon))
+ (start #~(make-forkexec-constructor
+ (list #$(file-append guix "/bin/guix")
+ "publish" "-u" "guix-publish"
+ "-p" #$(number->string port)
+ #$@(config->compression-options config)
+ (string-append "--nar-path=" #$nar-path)
+ (string-append "--listen=" #$host)
+ #$@(if workers
+ #~((string-append "--workers="
+ #$(number->string
+ workers)))
+ #~())
+ #$@(if ttl
+ #~((string-append "--ttl="
+ #$(number->string ttl)
+ "s"))
+ #~())
+ #$@(if cache
+ #~((string-append "--cache=" #$cache))
+ #~()))
+
+ ;; Make sure we run in a UTF-8 locale so we can produce
+ ;; nars for packages that contain UTF-8 file names such
+ ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
+ #:environment-variables
+ (list (string-append "GUIX_LOCPATH="
+ #$glibc-utf8-locales "/lib/locale")
+ "LC_ALL=en_US.utf8")
+ #:log-file "/var/log/guix-publish.log"))
+ (stop #~(make-kill-destructor))))))
(define %guix-publish-accounts
(list (user-group (name "guix-publish") (system? #t))
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin")))))
+(define %guix-publish-log-rotations
+ (list (log-rotation
+ (files (list "/var/log/guix-publish.log")))))
+
(define (guix-publish-activation config)
(let ((cache (guix-publish-configuration-cache config)))
(if cache
guix-publish-shepherd-service)
(service-extension account-service-type
(const %guix-publish-accounts))
+ (service-extension rottlog-service-type
+ (const %guix-publish-log-rotations))
(service-extension activation-service-type
guix-publish-activation)))
(default-value (guix-publish-configuration))
"Add a Shepherd service running @command{guix publish}, a
command that allows you to share pre-built binaries with others over HTTP.")))
-(define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
+(define-deprecated (guix-publish-service #:key (guix guix)
+ (port 80) (host "localhost"))
+ guix-publish-service-type
"Return a service that runs @command{guix publish} listening on @var{host}
and @var{port} (@pxref{Invoking guix publish}).
udev-configuration make-udev-configuration
udev-configuration?
(udev udev-configuration-udev ;<package>
- (default udev))
+ (default eudev))
(rules udev-configuration-rules ;list of <package>
(default '())))
(respawn? #f)
;; We need additional modules.
(modules `((gnu build linux-boot)
- ,@%default-modules))))))))
+ ,@%default-modules))
+
+ (actions (list (shepherd-action
+ (name 'rules)
+ (documentation "Display the directory containing
+the udev rules in use.")
+ (procedure #~(lambda (_)
+ (display #$rules)
+ (newline))))))))))))
(define udev-service-type
(service-type (name 'udev)
(udev-configuration
(udev udev)
(rules (append initial-rules rules)))))))
+ (default-value (udev-configuration))
(description
"Run @command{udev}, which populates the @file{/dev}
directory dynamically. Get extra rules from the packages listed in the
notably to select, copy, and paste text. The default options use the
@code{ps2} protocol, which works for both USB and PS/2 mice.")))
-(define* (gpm-service #:key (gpm gpm) ;deprecated
- (options %default-gpm-options))
+(define-deprecated (gpm-service #:key (gpm gpm)
+ (options %default-gpm-options))
+ gpm-service-type
"Run @var{gpm}, the general-purpose mouse daemon, with the given
command-line @var{options}. GPM allows users to use the mouse in the console,
notably to select, copy, and paste text. The default value of @var{options}
(shepherd-service
(documentation "kmscon virtual terminal")
- (requirement '(user-processes udev dbus-system virtual-terminal))
+ (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)))))))
\f
(define %base-services
;; Convenience variable holding the basic services.
- (list (login-service)
+ (list (service login-service-type)
(service virtual-terminal-service-type)
(service console-font-service-type
(cons tty %default-console-font))
'("tty1" "tty2" "tty3" "tty4" "tty5" "tty6")))
- (agetty-service (agetty-configuration
- (extra-options '("-L")) ; no carrier detect
- (term "vt100")
- (tty #f))) ; automatic
-
- (mingetty-service (mingetty-configuration
- (tty "tty1")))
- (mingetty-service (mingetty-configuration
- (tty "tty2")))
- (mingetty-service (mingetty-configuration
- (tty "tty3")))
- (mingetty-service (mingetty-configuration
- (tty "tty4")))
- (mingetty-service (mingetty-configuration
- (tty "tty5")))
- (mingetty-service (mingetty-configuration
- (tty "tty6")))
+ (service agetty-service-type (agetty-configuration
+ (extra-options '("-L")) ; no carrier detect
+ (term "vt100")
+ (tty #f))) ; automatic
+
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty1")))
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty2")))
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty3")))
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty4")))
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty5")))
+ (service mingetty-service-type (mingetty-configuration
+ (tty "tty6")))
(service static-networking-service-type
(list (static-networking (interface "lo")
(provision '(loopback)))))
(syslog-service)
(service urandom-seed-service-type)
- (guix-service)
- (nscd-service)
+ (service guix-service-type)
+ (service nscd-service-type)
;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
;; used, so enable them by default. The FUSE and ALSA rules are
;; less critical, but handy.
- (udev-service #:rules (list lvm2 fuse alsa-utils crda))
+ (service udev-service-type
+ (udev-configuration
+ (rules (list lvm2 fuse alsa-utils crda))))
(service special-files-service-type
`(("/bin/sh" ,(file-append (canonical-package bash)