Remove traces of "GuixSD".
[jackhill/guix/guix.git] / gnu / services / base.scm
index 09a1ce9..04b123b 100644 (file)
@@ -1,11 +1,13 @@
 ;;; 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, 2017 Leo Famulari <leo@famulari.name>
 ;;; 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.
 ;;;
@@ -24,6 +26,7 @@
 
 (define-module (gnu services base)
   #:use-module (guix store)
+  #:use-module (guix deprecation)
   #:use-module (gnu services)
   #:use-module (gnu services shepherd)
   #:use-module (gnu system pam)
@@ -40,6 +43,7 @@
                 #: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)
@@ -47,6 +51,7 @@
   #: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)
@@ -306,7 +311,7 @@ seconds after @code{SIGTERM} has been sent are terminated with
   (string-append (match (file-system-device file-system)
                    ((? file-system-label? label)
                     (string-append "LABEL="
-                                   (file-system-label->string file-system)))
+                                   (file-system-label->string label)))
                    ((? uuid? uuid)
                     (string-append "UUID=" (uuid->string uuid)))
                    ((? string? device)
@@ -326,7 +331,7 @@ seconds after @code{SIGTERM} has been sent are terminated with
   `(("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)
@@ -419,7 +424,7 @@ FILE-SYSTEM."
                                  '((gnu build file-systems)))
            (shepherd-service
             (provision (list (file-system->shepherd-service-name file-system)))
-            (requirement `(root-file-system
+            (requirement `(root-file-system udev
                            ,@(map dependency->shepherd-service-name dependencies)))
             (documentation "Check, mount, and unmount the given file system.")
             (start #~(lambda args
@@ -613,8 +618,9 @@ file systems, as well as corresponding @file{/etc/fstab} entries.")))
 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))
 
 
 ;;;
@@ -685,17 +691,20 @@ to add @var{device} to the kernel's entropy pool.  The service will fail if
   (shepherd-service-type
    'virtual-terminal
    (lambda (utf8?)
-     (shepherd-service
-      (documentation "Set virtual terminals in UTF-8 module.")
-      (provision '(virtual-terminal))
-      (requirement '(root-file-system))
-      (start #~(lambda _
-                 (call-with-output-file
-                     "/sys/module/vt/parameters/default_utf8"
-                   (lambda (port)
-                     (display 1 port)))
-                 #t))
-      (stop #~(const #f))))
+     (let ((knob "/sys/module/vt/parameters/default_utf8"))
+       (shepherd-service
+        (documentation "Set virtual terminals in UTF-8 module.")
+        (provision '(virtual-terminal))
+        (requirement '(root-file-system))
+        (start #~(lambda _
+                   ;; In containers /sys is read-only so don't insist on
+                   ;; writing to this file.
+                   (unless (= 1 (call-with-input-file #$knob read))
+                     (call-with-output-file #$knob
+                       (lambda (port)
+                         (display 1 port))))
+                   #t))
+        (stop #~(const #f)))))
    #t))                                           ;default to UTF-8
 
 (define console-keymap-service-type
@@ -812,6 +821,7 @@ Return a service that sets up Unicode support in @var{tty} and loads
   (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.")))
@@ -1113,7 +1123,14 @@ the tty to run, among other things."
 
        (start  #~(make-forkexec-constructor
                   (list #$(file-append mingetty "/sbin/mingetty")
-                        "--noclear" #$tty
+                        "--noclear"
+
+                        ;; Avoiding 'vhangup' allows us to avoid 'setfont'
+                        ;; errors down the path where various ioctls get
+                        ;; EIO--see 'hung_up_tty_ioctl' in driver/tty/tty_io.c
+                        ;; in Linux.
+                        "--nohangup" #$tty
+
                         #$@(if auto-login
                                #~("--autologin" #$auto-login)
                                #~())
@@ -1241,18 +1258,57 @@ the tty to run, among other things."
                                 (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, but that's
+                 ;; fine.
+                 (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
@@ -1266,7 +1322,12 @@ the tty to run, among other things."
                                                   (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.
@@ -1301,6 +1362,7 @@ the tty to run, among other things."
                            (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
@@ -1421,16 +1483,14 @@ pam-limits-entry specified in LIMITS via pam_limits.so."
 
 (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
@@ -1444,26 +1504,58 @@ starting at FIRST-UID, and under GID."
           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 aaa
+    ;; XXX: Terrible hack to work around <https://bugs.gnu.org/15602>: this
+    ;; forces (guix config) and (guix utils) to be loaded upfront, so that
+    ;; their run-time symbols are defined.
+    (scheme-file "aaa.scm"
+                 #~(define-module (guix aaa)
+                     #:use-module (guix config)
+                     #:use-module (guix memoization))))
+
+  (define default-acl
+    (with-extensions (list guile-gcrypt)
+      (with-imported-modules `(((guix config) => ,(make-config.scm))
+                               ((guix aaa) => ,aaa)
+                               ,@(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.
@@ -1548,7 +1640,15 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
                             '())
                      #$@(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))))))
@@ -1575,10 +1675,9 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
      ;; 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"))
@@ -1592,8 +1691,9 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
 
                            (call-with-output-file #$output
                              (lambda (port)
-                               (write (call-with-input-file "graph"
-                                        read-reference-graph)
+                               (write (map store-info-item
+                                           (call-with-input-file "graph"
+                                             read-reference-graph))
                                       port)))))
                      #:options `(#:local-build? #f
                                  #:references-graphs (("graph" ,item))))
@@ -1622,7 +1722,9 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
    (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))
@@ -1723,7 +1825,9 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
                  "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}).
 
@@ -1743,7 +1847,7 @@ archive}).  If that is not the case, the service will fail to start."
   udev-configuration make-udev-configuration
   udev-configuration?
   (udev   udev-configuration-udev                 ;<package>
-          (default udev))
+          (default eudev))
   (rules  udev-configuration-rules                ;list of <package>
           (default '())))
 
@@ -1838,16 +1942,9 @@ item of @var{packages}."
 
          (documentation "Populate the /dev directory, dynamically.")
          (start #~(lambda ()
-                    (define find
-                      (@ (srfi srfi-1) find))
-
                     (define udevd
-                      ;; Choose the right 'udevd'.
-                      (find file-exists?
-                            (map (lambda (suffix)
-                                   (string-append #$udev suffix))
-                                 '("/libexec/udev/udevd" ;udev
-                                   "/sbin/udevd"))))     ;eudev
+                      ;; 'udevd' from eudev.
+                      #$(file-append udev "/sbin/udevd"))
 
                     (define (wait-for-udevd)
                       ;; Wait until someone's listening on udevd's control
@@ -1880,27 +1977,28 @@ item of @var{packages}."
                             (string-append linux-module-directory "/"
                                            kernel-release))
                            (old-umask (umask #o022)))
-                      (make-static-device-nodes directory)
+                      ;; If we're in a container, DIRECTORY might not exist,
+                      ;; for instance because the host runs a different
+                      ;; kernel.  In that case, skip it; we'll just miss a few
+                      ;; nodes like /dev/fuse.
+                      (when (file-exists? directory)
+                        (make-static-device-nodes directory))
                       (umask old-umask))
 
-                    (let ((pid (primitive-fork)))
-                      (case pid
-                        ((0)
-                         (exec-command (list udevd)))
-                        (else
-                         ;; Wait until udevd is up and running.  This
-                         ;; appears to be needed so that the events
-                         ;; triggered below are actually handled.
-                         (wait-for-udevd)
-
-                         ;; Trigger device node creation.
-                         (system* #$(file-append udev "/bin/udevadm")
-                                  "trigger" "--action=add")
-
-                         ;; Wait for things to settle down.
-                         (system* #$(file-append udev "/bin/udevadm")
-                                  "settle")
-                         pid)))))
+                    (let ((pid (fork+exec-command (list udevd))))
+                      ;; Wait until udevd is up and running.  This appears to
+                      ;; be needed so that the events triggered below are
+                      ;; actually handled.
+                      (wait-for-udevd)
+
+                      ;; Trigger device node creation.
+                      (system* #$(file-append udev "/bin/udevadm")
+                               "trigger" "--action=add")
+
+                      ;; Wait for things to settle down.
+                      (system* #$(file-append udev "/bin/udevadm")
+                               "settle")
+                      pid)))
          (stop #~(make-kill-destructor))
 
          ;; When halting the system, 'udev' is actually killed by
@@ -1909,7 +2007,15 @@ item of @var{packages}."
          (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)
@@ -1924,6 +2030,7 @@ item of @var{packages}."
                              (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
@@ -2012,8 +2119,9 @@ command-line options.  GPM allows users to use the mouse in the console,
 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}
@@ -2035,6 +2143,8 @@ This service is not part of @var{%base-services}."
                            (default (file-append shadow "/bin/login")))
   (login-arguments         kmscon-configuration-login-arguments
                            (default '("-p")))
+  (auto-login              kmscon-configuration-auto-login
+                           (default #f))
   (hardware-acceleration?  kmscon-configuration-hardware-acceleration?
                            (default #f))) ; #t causes failure
 
@@ -2046,18 +2156,24 @@ This service is not part of @var{%base-services}."
            (virtual-terminal (kmscon-configuration-virtual-terminal config))
            (login-program (kmscon-configuration-login-program config))
            (login-arguments (kmscon-configuration-login-arguments config))
+           (auto-login (kmscon-configuration-auto-login config))
            (hardware-acceleration? (kmscon-configuration-hardware-acceleration? config)))
 
        (define kmscon-command
          #~(list
             #$(file-append kmscon "/bin/kmscon") "--login"
             "--vt" #$virtual-terminal
+            "--no-switchvt" ;Prevent a switch to the virtual terminal.
             #$@(if hardware-acceleration? '("--hwaccel") '())
-            "--" #$login-program #$@login-arguments))
+            "--login" "--"
+            #$login-program #$@login-arguments
+            #$@(if auto-login
+                   #~(#$auto-login)
+                   #~())))
 
        (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)))))))
@@ -2125,7 +2241,7 @@ This service is not part of @var{%base-services}."
                                              AF_INET INADDR_ANY 0)))
                     (set-network-interface-flags sock #$interface 0)
                     (close-port sock)
-:                    #f)))
+                    #f)))
         (respawn? #f))))))
 
 (define (static-networking-etc-files interfaces)
@@ -2212,7 +2328,7 @@ to handle."
 \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
@@ -2220,23 +2336,23 @@ to handle."
                         (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")
@@ -2245,13 +2361,15 @@ to handle."
                                           (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)