1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
4 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
5 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
7 ;;; This file is part of GNU Guix.
9 ;;; GNU Guix is free software; you can redistribute it and/or modify it
10 ;;; under the terms of the GNU General Public License as published by
11 ;;; the Free Software Foundation; either version 3 of the License, or (at
12 ;;; your option) any later version.
14 ;;; GNU Guix is distributed in the hope that it will be useful, but
15 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;;; GNU General Public License for more details.
19 ;;; You should have received a copy of the GNU General Public License
20 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22 (define-module (gnu services base)
23 #:use-module (guix store)
24 #:use-module (gnu services)
25 #:use-module (gnu services dmd)
26 #:use-module (gnu services networking)
27 #:use-module (gnu system pam)
28 #:use-module (gnu system shadow) ; 'user-account', etc.
29 #:use-module (gnu system file-systems) ; 'file-system', etc.
30 #:use-module (gnu packages admin)
31 #:use-module ((gnu packages linux)
32 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda gpm))
33 #:use-module ((gnu packages base)
34 #:select (canonical-package glibc))
35 #:use-module (gnu packages package-management)
36 #:use-module (gnu packages lsh)
37 #:use-module (gnu packages lsof)
38 #:use-module ((gnu build file-systems)
39 #:select (mount-flags->bit-mask))
40 #:use-module (guix gexp)
41 #:use-module (guix records)
42 #:use-module (srfi srfi-1)
43 #:use-module (srfi srfi-26)
44 #:use-module (ice-9 match)
45 #:use-module (ice-9 format)
46 #:export (fstab-service-type
47 root-file-system-service
50 device-mapping-service
52 user-processes-service
53 session-environment-service
54 session-environment-service-type
56 console-keymap-service
61 udev-configuration-rules
66 mingetty-configuration
67 mingetty-configuration?
72 %nscd-default-configuration
88 guix-publish-configuration
89 guix-publish-configuration?
91 guix-publish-service-type
99 ;;; Base system services---i.e., services that 99% of the users will want to
109 (define (file-system->fstab-entry file-system)
110 "Return a @file{/etc/fstab} entry for @var{file-system}."
111 (string-append (case (file-system-title file-system)
113 (string-append "LABEL=" (file-system-device file-system)))
117 (uuid->string (file-system-device file-system))))
119 (file-system-device file-system)))
121 (file-system-mount-point file-system) "\t"
122 (file-system-type file-system) "\t"
123 (or (file-system-options file-system) "defaults") "\t"
125 ;; XXX: Omit the 'fs_freq' and 'fs_passno' fields because we
126 ;; don't have anything sensible to put in there.
129 (define (file-systems->fstab file-systems)
130 "Return a @file{/etc} entry for an @file{fstab} describing
132 `(("fstab" ,(plain-file "fstab"
135 # This file was generated from your GuixSD configuration. Any changes
136 # will be lost upon reboot or reconfiguration.\n\n"
137 (string-join (map file-system->fstab-entry
142 (define fstab-service-type
143 ;; The /etc/fstab service.
144 (service-type (name 'fstab)
146 (list (service-extension etc-service-type
147 file-systems->fstab)))
151 (define %root-file-system-dmd-service
153 (documentation "Take care of the root file system.")
154 (provision '(root-file-system))
157 ;; Return #f if successfully stopped.
160 (call-with-blocked-asyncs
162 (let ((null (%make-void-port "w")))
164 (display "closing log\n")
165 ;; XXX: Ideally we'd use 'stop-logging', but that one
166 ;; doesn't actually close the port as of dmd 0.1.
167 (close-port (@@ (dmd comm) log-output-port))
168 (set! (@@ (dmd comm) log-output-port) null)
170 ;; Redirect the default output ports..
171 (set-current-output-port null)
172 (set-current-error-port null)
174 ;; Close /dev/console.
175 (for-each close-fdes '(0 1 2))
177 ;; At this point, there are no open files left, so the
178 ;; root file system can be re-mounted read-only.
180 (logior MS_REMOUNT MS_RDONLY)
186 (define root-file-system-service-type
187 (dmd-service-type 'root-file-system
188 (const %root-file-system-dmd-service)))
190 (define (root-file-system-service)
191 "Return a service whose sole purpose is to re-mount read-only the root file
192 system upon shutdown (aka. cleanly \"umounting\" root.)
194 This service must be the root of the service dependency graph so that its
195 'stop' action is invoked when dmd is the only process left."
196 (service root-file-system-service-type #f))
198 (define (file-system->dmd-service-name file-system)
199 "Return the symbol that denotes the service mounting and unmounting
201 (symbol-append 'file-system-
202 (string->symbol (file-system-mount-point file-system))))
204 (define (mapped-device->dmd-service-name md)
205 "Return the symbol that denotes the dmd service of MD, a <mapped-device>."
206 (symbol-append 'device-mapping-
207 (string->symbol (mapped-device-target md))))
209 (define dependency->dmd-service-name
211 ((? mapped-device? md)
212 (mapped-device->dmd-service-name md))
214 (file-system->dmd-service-name fs))))
216 (define (file-system-dmd-service file-system)
217 "Return a list containing the dmd service for @var{file-system}."
218 (let ((target (file-system-mount-point file-system))
219 (device (file-system-device file-system))
220 (type (file-system-type file-system))
221 (title (file-system-title file-system))
222 (check? (file-system-check? file-system))
223 (create? (file-system-create-mount-point? file-system))
224 (dependencies (file-system-dependencies file-system)))
225 (if (file-system-mount? file-system)
228 (provision (list (file-system->dmd-service-name file-system)))
229 (requirement `(root-file-system
230 ,@(map dependency->dmd-service-name dependencies)))
231 (documentation "Check, mount, and unmount the given file system.")
232 (start #~(lambda args
233 ;; FIXME: Use or factorize with 'mount-file-system'.
234 (let ((device (canonicalize-device-spec #$device '#$title))
235 (flags #$(mount-flags->bit-mask
236 (file-system-flags file-system))))
242 ;; Make sure fsck.ext2 & co. can be found.
246 "/run/current-system/profile/sbin:"
248 (check-file-system device #$type))
251 (mount device #$target #$type flags
252 #$(file-system-options file-system))
254 ;; For read-only bind mounts, an extra remount is
255 ;; needed, as per <http://lwn.net/Articles/281157/>,
256 ;; which still applies to Linux 4.0.
257 (when (and (= MS_BIND (logand flags MS_BIND))
258 (= MS_RDONLY (logand flags MS_RDONLY)))
259 (mount device #$target #$type
260 (logior MS_BIND MS_REMOUNT MS_RDONLY))))
263 ;; Normally there are no processes left at this point, so
264 ;; TARGET can be safely unmounted.
266 ;; Make sure PID 1 doesn't keep TARGET busy.
272 ;; We need an additional module.
273 (modules `(((gnu build file-systems)
274 #:select (check-file-system canonicalize-device-spec))
276 (imported-modules `((gnu build file-systems)
277 ,@%default-imported-modules))))
280 (define file-system-service-type
281 ;; TODO(?): Make this an extensible service that takes <file-system> objects
282 ;; and returns a list of <dmd-service>.
283 (service-type (name 'file-system)
285 (list (service-extension dmd-root-service-type
286 file-system-dmd-service)
287 (service-extension fstab-service-type
290 (define* (file-system-service file-system)
291 "Return a service that mounts @var{file-system}, a @code{<file-system>}
293 (service file-system-service-type file-system))
295 (define user-unmount-service-type
298 (lambda (known-mount-points)
300 (documentation "Unmount manually-mounted file systems.")
301 (provision '(user-file-systems))
304 (define (known? mount-point)
306 (cons* "/proc" "/sys" '#$known-mount-points)))
308 ;; Make sure we don't keep the user's mount points busy.
311 (for-each (lambda (mount-point)
312 (format #t "unmounting '~a'...~%" mount-point)
315 (umount mount-point))
317 (let ((errno (system-error-errno args)))
318 (format #t "failed to unmount '~a': ~a~%"
319 mount-point (strerror errno))))))
320 (filter (negate known?) (mount-points)))
323 (define (user-unmount-service known-mount-points)
324 "Return a service whose sole purpose is to unmount file systems not listed
325 in KNOWN-MOUNT-POINTS when it is stopped."
326 (service user-unmount-service-type known-mount-points))
328 (define %do-not-kill-file
329 ;; Name of the file listing PIDs of processes that must survive when halting
330 ;; the system. Typical example is user-space file systems.
331 "/etc/dmd/do-not-kill")
333 (define user-processes-service-type
337 ((requirements grace-delay)
339 (documentation "When stopped, terminate all user processes.")
340 (provision '(user-processes))
341 (requirement (cons* 'root-file-system 'user-file-systems
342 (map file-system->dmd-service-name
346 (define (kill-except omit signal)
347 ;; Kill all the processes with SIGNAL except those listed
348 ;; in OMIT and the current process.
349 (let ((omit (cons (getpid) omit)))
350 (for-each (lambda (pid)
351 (unless (memv pid omit)
357 ;; List of PIDs that must not be killed.
358 (if (file-exists? #$%do-not-kill-file)
360 (call-with-input-file #$%do-not-kill-file
361 (compose string-tokenize
362 (@ (ice-9 rdelim) read-string))))
366 (car (gettimeofday)))
369 ;; Really sleep N seconds.
370 ;; Work around <http://bugs.gnu.org/19581>.
372 (let loop ((elapsed 0))
374 (sleep (- n elapsed))
375 (loop (- (now) start)))))
377 (define lset= (@ (srfi srfi-1) lset=))
379 (display "sending all processes the TERM signal\n")
381 (if (null? omitted-pids)
383 ;; Easy: terminate all of them.
385 (sleep* #$grace-delay)
388 ;; Kill them all except OMITTED-PIDS. XXX: We would
389 ;; like to (kill -1 SIGSTOP) to get a fixed list of
390 ;; processes, like 'killall5' does, but that seems
392 (kill-except omitted-pids SIGTERM)
393 (sleep* #$grace-delay)
394 (kill-except omitted-pids SIGKILL)
395 (delete-file #$%do-not-kill-file)))
398 (let ((pids (processes)))
399 (unless (lset= = pids (cons 1 omitted-pids))
400 (format #t "waiting for process termination\
401 (processes left: ~s)~%"
406 (display "all processes have been terminated\n")
410 (define* (user-processes-service file-systems #:key (grace-delay 4))
411 "Return the service that is responsible for terminating all the processes so
412 that the root file system can be re-mounted read-only, just before
413 rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
414 has been sent are terminated with SIGKILL.
416 The returned service will depend on 'root-file-system' and on all the dmd
417 services corresponding to FILE-SYSTEMS.
419 All the services that spawn processes must depend on this one so that they are
420 stopped before 'kill' is called."
421 (service user-processes-service-type
422 (list (filter file-system-mount? file-systems) grace-delay)))
426 ;;; System-wide environment variables.
429 (define (environment-variables->environment-file vars)
430 "Return a file for pam_env(8) that contains environment variables VARS."
431 (apply mixed-text-file "environment"
432 (append-map (match-lambda
434 (list key "=" value "\n")))
437 (define session-environment-service-type
439 (name 'session-environment)
441 (list (service-extension
444 (list `("environment"
445 ,(environment-variables->environment-file vars)))))))
446 (compose concatenate)
449 (define (session-environment-service vars)
450 "Return a service that builds the @file{/etc/environment}, which can be read
451 by PAM-aware applications to set environment variables for sessions.
453 VARS should be an association list in which both the keys and the values are
454 strings or string-valued gexps."
455 (service session-environment-service-type vars))
462 (define host-name-service-type
467 (documentation "Initialize the machine's host name.")
468 (provision '(host-name))
470 (sethostname #$name)))
473 (define (host-name-service name)
474 "Return a service that sets the host name to @var{name}."
475 (service host-name-service-type name))
477 (define (unicode-start tty)
478 "Return a gexp to start Unicode support on @var{tty}."
480 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
481 ;; 'tty' command, that command returns TTY.
483 (let ((pid (primitive-fork)))
487 (dup2 (open-fdes #$tty O_RDONLY) 0)
489 (dup2 (open-fdes #$tty O_WRONLY) 1)
490 (execl (string-append #$kbd "/bin/unicode_start")
493 (zero? (cdr (waitpid pid))))))))
495 (define console-keymap-service-type
500 (documentation (string-append "Load console keymap (loadkeys)."))
501 (provision '(console-keymap))
503 (zero? (system* (string-append #$kbd "/bin/loadkeys")
507 (define (console-keymap-service file)
508 "Return a service to load console keymap from @var{file}."
509 (service console-keymap-service-type file))
511 (define console-font-service-type
516 (let ((device (string-append "/dev/" tty)))
518 (documentation "Load a Unicode console font.")
519 (provision (list (symbol-append 'console-font-
520 (string->symbol tty))))
522 ;; Start after mingetty has been started on TTY, otherwise the settings
524 (requirement (list (symbol-append 'term-
525 (string->symbol tty))))
528 (and #$(unicode-start device)
530 (system* (string-append #$kbd "/bin/setfont")
531 "-C" #$device #$font)))))
535 (define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
536 "Return a service that sets up Unicode support in @var{tty} and loads
537 @var{font} for that tty (fonts are per virtual console in Linux.)"
538 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
539 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
540 ;; codepoints notably found in the UTF-8 manual.
541 (service console-font-service-type (list tty font)))
543 (define-record-type* <mingetty-configuration>
544 mingetty-configuration make-mingetty-configuration
545 mingetty-configuration?
546 (mingetty mingetty-configuration-mingetty ;<package>
548 (tty mingetty-configuration-tty) ;string
549 (motd mingetty-configuration-motd ;file-like
550 (default (plain-file "motd" "Welcome.\n")))
551 (auto-login mingetty-auto-login ;string | #f
553 (login-program mingetty-login-program ;gexp
555 (login-pause? mingetty-login-pause? ;Boolean
558 ;; Allow empty passwords by default so that first-time users can log in when
559 ;; the 'root' account has just been created.
560 (allow-empty-passwords? mingetty-configuration-allow-empty-passwords?
561 (default #t))) ;Boolean
563 (define (mingetty-pam-service conf)
564 "Return the list of PAM service needed for CONF."
565 ;; Let 'login' be known to PAM. All the mingetty services will have that
566 ;; PAM service, but that's fine because they're all identical and duplicates
568 (list (unix-pam-service "login"
569 #:allow-empty-passwords?
570 (mingetty-configuration-allow-empty-passwords? conf)
572 (mingetty-configuration-motd conf))))
574 (define mingetty-dmd-service
576 (($ <mingetty-configuration> mingetty tty motd auto-login login-program
577 login-pause? allow-empty-passwords?)
580 (documentation "Run mingetty on an tty.")
581 (provision (list (symbol-append 'term- (string->symbol tty))))
583 ;; Since the login prompt shows the host name, wait for the 'host-name'
584 ;; service to be done. Also wait for udev essentially so that the tty
585 ;; text is not lost in the middle of kernel messages (XXX).
586 (requirement '(user-processes host-name udev))
588 (start #~(make-forkexec-constructor
589 (list (string-append #$mingetty "/sbin/mingetty")
592 #~("--autologin" #$auto-login)
595 #~("--loginprog" #$login-program)
600 (stop #~(make-kill-destructor)))))))
602 (define mingetty-service-type
603 (service-type (name 'mingetty)
604 (extensions (list (service-extension dmd-root-service-type
605 mingetty-dmd-service)
606 (service-extension pam-root-service-type
607 mingetty-pam-service)))))
609 (define* (mingetty-service config)
610 "Return a service to run mingetty according to @var{config}, which specifies
611 the tty to run, among other things."
612 (service mingetty-service-type config))
614 (define-record-type* <nscd-configuration> nscd-configuration
615 make-nscd-configuration
617 (log-file nscd-configuration-log-file ;string
618 (default "/var/log/nscd.log"))
619 (debug-level nscd-debug-level ;integer
621 ;; TODO: See nscd.conf in glibc for other options to add.
622 (caches nscd-configuration-caches ;list of <nscd-cache>
623 (default %nscd-default-caches))
624 (name-services nscd-configuration-name-services ;list of <packages>
626 (glibc nscd-configuration-glibc ;<package>
627 (default (canonical-package glibc))))
629 (define-record-type* <nscd-cache> nscd-cache make-nscd-cache
631 (database nscd-cache-database) ;symbol
632 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
633 (negative-time-to-live nscd-cache-negative-time-to-live
634 (default 20)) ;integer
635 (suggested-size nscd-cache-suggested-size ;integer ("default module
638 (check-files? nscd-cache-check-files? ;Boolean
640 (persistent? nscd-cache-persistent? ;Boolean
642 (shared? nscd-cache-shared? ;Boolean
644 (max-database-size nscd-cache-max-database-size ;integer
645 (default (* 32 (expt 2 20))))
646 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
649 (define %nscd-default-caches
650 ;; Caches that we want to enable by default. Note that when providing an
651 ;; empty nscd.conf, all caches are disabled.
652 (list (nscd-cache (database 'hosts)
654 ;; Aggressively cache the host name cache to improve
655 ;; privacy and resilience.
656 (positive-time-to-live (* 3600 12))
657 (negative-time-to-live 20)
660 (nscd-cache (database 'services)
662 ;; Services are unlikely to change, so we can be even more
664 (positive-time-to-live (* 3600 24))
665 (negative-time-to-live 3600)
666 (check-files? #t) ;check /etc/services changes
669 (define %nscd-default-configuration
670 ;; Default nscd configuration.
671 (nscd-configuration))
673 (define (nscd.conf-file config)
674 "Return the @file{nscd.conf} configuration file for @var{config}, an
675 @code{<nscd-configuration>} object."
676 (define cache->config
678 (($ <nscd-cache> (= symbol->string database)
679 positive-ttl negative-ttl size check-files?
680 persistent? shared? max-size propagate?)
681 (string-append "\nenable-cache\t" database "\tyes\n"
683 "positive-time-to-live\t" database "\t"
684 (number->string positive-ttl) "\n"
685 "negative-time-to-live\t" database "\t"
686 (number->string negative-ttl) "\n"
687 "suggested-size\t" database "\t"
688 (number->string size) "\n"
689 "check-files\t" database "\t"
690 (if check-files? "yes\n" "no\n")
691 "persistent\t" database "\t"
692 (if persistent? "yes\n" "no\n")
693 "shared\t" database "\t"
694 (if shared? "yes\n" "no\n")
695 "max-db-size\t" database "\t"
696 (number->string max-size) "\n"
697 "auto-propagate\t" database "\t"
698 (if propagate? "yes\n" "no\n")))))
701 (($ <nscd-configuration> log-file debug-level caches)
702 (plain-file "nscd.conf"
704 # Configuration of libc's name service cache daemon (nscd).\n\n"
706 (string-append "logfile\t" log-file)
710 (string-append "debug-level\t"
711 (number->string debug-level))
715 (map cache->config caches)))))))
717 (define (nscd-dmd-service config)
718 "Return a dmd service for CONFIG, an <nscd-configuration> object."
719 (let ((nscd.conf (nscd.conf-file config))
720 (name-services (nscd-configuration-name-services config)))
722 (documentation "Run libc's name service cache daemon (nscd).")
724 (requirement '(user-processes))
725 (start #~(make-forkexec-constructor
726 (list (string-append #$(nscd-configuration-glibc config)
728 "-f" #$nscd.conf "--foreground")
730 #:environment-variables
731 (list (string-append "LD_LIBRARY_PATH="
734 (string-append dir "/lib"))
735 (list #$@name-services))
737 (stop #~(make-kill-destructor))
741 (define nscd-activation
742 ;; Actions to take before starting nscd.
744 (use-modules (guix build utils))
745 (mkdir-p "/var/run/nscd")
746 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
748 (define nscd-service-type
749 (service-type (name 'nscd)
751 (list (service-extension activation-service-type
752 (const nscd-activation))
753 (service-extension dmd-root-service-type
756 ;; This can be extended by providing additional name services
758 (compose concatenate)
759 (extend (lambda (config name-services)
762 (name-services (append
763 (nscd-configuration-name-services config)
766 (define* (nscd-service #:optional (config %nscd-default-configuration))
767 "Return a service that runs libc's name service cache daemon (nscd) with the
768 given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
769 Service Switch}, for an example."
770 (service nscd-service-type config))
772 (define syslog-service-type
775 (lambda (config-file)
777 (documentation "Run the syslog daemon (syslogd).")
778 (provision '(syslogd))
779 (requirement '(user-processes))
780 (start #~(make-forkexec-constructor
781 (list (string-append #$inetutils "/libexec/syslogd")
782 "--no-detach" "--rcfile" #$config-file)))
783 (stop #~(make-kill-destructor))))))
785 ;; Snippet adapted from the GNU inetutils manual.
786 (define %default-syslog.conf
787 (plain-file "syslog.conf" "
788 # Log all error messages, authentication messages of
789 # level notice or higher and anything of level err or
790 # higher to the console.
791 # Don't log private authentication messages!
792 *.alert;auth.notice;authpriv.none /dev/console
794 # Log anything (except mail) of level info or higher.
795 # Don't log private authentication messages!
796 *.info;mail.none;authpriv.none /var/log/messages
798 # Same, in a different place.
799 *.info;mail.none;authpriv.none /dev/tty12
801 # The authpriv file has restricted access.
802 authpriv.* /var/log/secure
804 # Log all the mail messages in one place.
805 mail.* /var/log/maillog
808 (define* (syslog-service #:key (config-file %default-syslog.conf))
809 "Return a service that runs @code{syslogd}.
810 If configuration file name @var{config-file} is not specified, use some
811 reasonable default settings."
812 (service syslog-service-type config-file))
819 (define* (guix-build-accounts count #:key
823 "Return a list of COUNT user accounts for Guix build users, with UIDs
824 starting at FIRST-UID, and under GID."
825 (unfold (cut > <> count)
828 (name (format #f "guixbuilder~2,'0d" n))
830 (uid (+ first-uid n -1))
833 ;; guix-daemon expects GROUP to be listed as a
834 ;; supplementary group too:
835 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
836 (supplementary-groups (list group "kvm"))
838 (comment (format #f "Guix Build User ~2d" n))
839 (home-directory "/var/empty")
840 (shell #~(string-append #$shadow "/sbin/nologin"))))
844 (define (hydra-key-authorization guix)
845 "Return a gexp with code to register the hydra.gnu.org public key with
847 #~(unless (file-exists? "/etc/guix/acl")
848 (let ((pid (primitive-fork)))
851 (let* ((key (string-append #$guix
852 "/share/guix/hydra.gnu.org.pub"))
853 (port (open-file key "r0b")))
854 (format #t "registering public key '~a'...~%" key)
855 (close-port (current-input-port))
857 (execl (string-append #$guix "/bin/guix")
858 "guix" "archive" "--authorize")
861 (let ((status (cdr (waitpid pid))))
862 (unless (zero? status)
863 (format (current-error-port) "warning: \
864 failed to register hydra.gnu.org public key: ~a~%" status))))))))
866 (define-record-type* <guix-configuration>
867 guix-configuration make-guix-configuration
869 (guix guix-configuration-guix ;<package>
871 (build-group guix-configuration-build-group ;string
872 (default "guixbuild"))
873 (build-accounts guix-configuration-build-accounts ;integer
875 (authorize-key? guix-configuration-authorize-key? ;Boolean
877 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
879 (substitute-urls guix-configuration-substitute-urls ;list of strings
880 (default %default-substitute-urls))
881 (extra-options guix-configuration-extra-options ;list of strings
883 (lsof guix-configuration-lsof ;<package>
885 (lsh guix-configuration-lsh ;<package>
888 (define %default-guix-configuration
889 (guix-configuration))
891 (define (guix-dmd-service config)
892 "Return a <dmd-service> for the Guix daemon service with CONFIG."
894 (($ <guix-configuration> guix build-group build-accounts authorize-key?
895 use-substitutes? substitute-urls extra-options
898 (documentation "Run the Guix daemon.")
899 (provision '(guix-daemon))
900 (requirement '(user-processes))
902 #~(make-forkexec-constructor
903 (list (string-append #$guix "/bin/guix-daemon")
904 "--build-users-group" #$build-group
905 #$@(if use-substitutes?
907 '("--no-substitutes"))
908 "--substitute-urls" #$(string-join substitute-urls)
911 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
913 #:environment-variables
914 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
915 (stop #~(make-kill-destructor)))))))
917 (define (guix-accounts config)
918 "Return the user accounts and user groups for CONFIG."
920 (($ <guix-configuration> _ build-group build-accounts)
925 ;; Use a fixed GID so that we can create the store with the right
928 (guix-build-accounts build-accounts
929 #:group build-group)))))
931 (define (guix-activation config)
932 "Return the activation gexp for CONFIG."
934 (($ <guix-configuration> guix build-group build-accounts authorize-key?)
935 ;; Assume that the store has BUILD-GROUP as its group. We could
936 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
937 ;; chown leads to an entire copy of the tree, which is a bad idea.
939 ;; Optionally authorize hydra.gnu.org's key.
941 (hydra-key-authorization guix)))))
943 (define guix-service-type
947 (list (service-extension dmd-root-service-type guix-dmd-service)
948 (service-extension account-service-type guix-accounts)
949 (service-extension activation-service-type guix-activation)))))
951 (define* (guix-service #:optional (config %default-guix-configuration))
952 "Return a service that runs the Guix build daemon according to
954 (service guix-service-type config))
957 (define-record-type* <guix-publish-configuration>
958 guix-publish-configuration make-guix-publish-configuration
959 guix-publish-configuration?
960 (guix guix-publish-configuration-guix ;package
962 (port guix-publish-configuration-port ;number
964 (host guix-publish-configuration-host ;string
965 (default "localhost")))
967 (define guix-publish-dmd-service
969 (($ <guix-publish-configuration> guix port host)
971 (provision '(guix-publish))
972 (requirement '(guix-daemon))
973 (start #~(make-forkexec-constructor
974 (list (string-append #$guix "/bin/guix")
975 "publish" "-u" "guix-publish"
976 "-p" #$(number->string port)
977 (string-append "--listen=" #$host))))
978 (stop #~(make-kill-destructor)))))))
980 (define %guix-publish-accounts
981 (list (user-group (name "guix-publish") (system? #t))
983 (name "guix-publish")
984 (group "guix-publish")
986 (comment "guix publish user")
987 (home-directory "/var/empty")
988 (shell #~(string-append #$shadow "/sbin/nologin")))))
990 (define guix-publish-service-type
991 (service-type (name 'guix-publish)
993 (list (service-extension dmd-root-service-type
994 guix-publish-dmd-service)
995 (service-extension account-service-type
996 (const %guix-publish-accounts))))))
998 (define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
999 "Return a service that runs @command{guix publish} listening on @var{host}
1000 and @var{port} (@pxref{Invoking guix publish}).
1002 This assumes that @file{/etc/guix} already contains a signing key pair as
1003 created by @command{guix archive --generate-key} (@pxref{Invoking guix
1004 archive}). If that is not the case, the service will fail to start."
1005 (service guix-publish-service-type
1006 (guix-publish-configuration (guix guix) (port port) (host host))))
1013 (define-record-type* <udev-configuration>
1014 udev-configuration make-udev-configuration
1016 (udev udev-configuration-udev ;<package>
1018 (rules udev-configuration-rules ;list of <package>
1021 (define (udev-rules-union packages)
1022 "Return the union of the @code{lib/udev/rules.d} directories found in each
1023 item of @var{packages}."
1026 (use-modules (guix build union)
1031 (define %standard-locations
1032 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
1034 (define (rules-sub-directory directory)
1035 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1036 ;; #f if none was found.
1037 (find directory-exists?
1038 (map (cut string-append directory <>) %standard-locations)))
1040 (mkdir-p (string-append #$output "/lib/udev"))
1041 (union-build (string-append #$output "/lib/udev/rules.d")
1042 (filter-map rules-sub-directory '#$packages))))
1044 (computed-file "udev-rules" build
1045 #:modules '((guix build union)
1046 (guix build utils))))
1048 (define (udev-rule file-name contents)
1049 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1050 (computed-file file-name
1052 (use-modules (guix build utils))
1055 (string-append #$output "/lib/udev/rules.d"))
1058 (call-with-output-file
1059 (string-append rules.d "/" #$file-name)
1061 (display #$contents port))))
1062 #:modules '((guix build utils))))
1064 (define kvm-udev-rule
1065 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1066 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1067 ;; but now we have to add it by ourselves.
1069 ;; Build users are part of the "kvm" group, so we can fearlessly make
1070 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1071 (udev-rule "90-kvm.rules"
1072 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1074 (define udev-dmd-service
1075 ;; Return a <dmd-service> for UDEV with RULES.
1077 (($ <udev-configuration> udev rules)
1078 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
1079 (udev.conf (computed-file "udev.conf"
1080 #~(call-with-output-file #$output
1083 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1089 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1091 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1092 (requirement '(root-file-system))
1094 (documentation "Populate the /dev directory, dynamically.")
1097 (@ (srfi srfi-1) find))
1100 ;; Choose the right 'udevd'.
1102 (map (lambda (suffix)
1103 (string-append #$udev suffix))
1104 '("/libexec/udev/udevd" ;udev
1105 "/sbin/udevd")))) ;eudev
1107 (define (wait-for-udevd)
1108 ;; Wait until someone's listening on udevd's control
1110 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1112 (catch 'system-error
1114 (connect sock PF_UNIX "/run/udev/control")
1117 (format #t "waiting for udevd...~%")
1121 ;; Allow udev to find the modules.
1122 (setenv "LINUX_MODULE_DIRECTORY"
1123 "/run/booted-system/kernel/lib/modules")
1125 ;; The first one is for udev, the second one for eudev.
1126 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1127 (setenv "EUDEV_RULES_DIRECTORY"
1128 (string-append #$rules "/lib/udev/rules.d"))
1130 (let ((pid (primitive-fork)))
1133 (exec-command (list udevd)))
1135 ;; Wait until udevd is up and running. This
1136 ;; appears to be needed so that the events
1137 ;; triggered below are actually handled.
1140 ;; Trigger device node creation.
1141 (system* (string-append #$udev "/bin/udevadm")
1142 "trigger" "--action=add")
1144 ;; Wait for things to settle down.
1145 (system* (string-append #$udev "/bin/udevadm")
1148 (stop #~(make-kill-destructor))
1150 ;; When halting the system, 'udev' is actually killed by
1151 ;; 'user-processes', i.e., before its own 'stop' method was called.
1152 ;; Thus, make sure it is not respawned.
1155 (define udev-service-type
1156 (service-type (name 'udev)
1158 (list (service-extension dmd-root-service-type
1161 (compose concatenate) ;concatenate the list of rules
1162 (extend (lambda (config rules)
1164 (($ <udev-configuration> udev initial-rules)
1167 (rules (append initial-rules rules)))))))))
1169 (define* (udev-service #:key (udev eudev) (rules '()))
1170 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
1171 extra rules from the packages listed in @var{rules}."
1172 (service udev-service-type
1173 (udev-configuration (udev udev) (rules rules))))
1175 (define device-mapping-service-type
1179 ((target open close)
1181 (provision (list (symbol-append 'device-mapping- (string->symbol target))))
1182 (requirement '(udev))
1183 (documentation "Map a device node using Linux's device mapper.")
1184 (start #~(lambda () #$open))
1185 (stop #~(lambda _ (not #$close)))
1188 (define (device-mapping-service target open close)
1189 "Return a service that maps device @var{target}, a string such as
1190 @code{\"home\"} (meaning @code{/dev/mapper/home}). Evaluate @var{open}, a
1191 gexp, to open it, and evaluate @var{close} to close it."
1192 (service device-mapping-service-type
1193 (list target open close)))
1195 (define swap-service-type
1200 (if (string-prefix? "/dev/mapper/" device)
1201 (list (symbol-append 'device-mapping-
1202 (string->symbol (basename device))))
1206 (provision (list (symbol-append 'swap- (string->symbol device))))
1207 (requirement `(udev ,@requirement))
1208 (documentation "Enable the given swap device.")
1210 (restart-on-EINTR (swapon #$device))
1213 (restart-on-EINTR (swapoff #$device))
1217 (define (swap-service device)
1218 "Return a service that uses @var{device} as a swap device."
1219 (service swap-service-type device))
1222 (define-record-type* <gpm-configuration>
1223 gpm-configuration make-gpm-configuration gpm-configuration?
1224 (gpm gpm-configuration-gpm) ;package
1225 (options gpm-configuration-options)) ;list of strings
1227 (define gpm-dmd-service
1229 (($ <gpm-configuration> gpm options)
1231 (requirement '(udev))
1234 ;; 'gpm' runs in the background and sets a PID file.
1235 ;; Note that it requires running as "root".
1236 (false-if-exception (delete-file "/var/run/gpm.pid"))
1237 (fork+exec-command (list (string-append #$gpm "/sbin/gpm")
1240 ;; Wait for the PID file to appear; declare failure if
1241 ;; it doesn't show up.
1243 (or (file-exists? "/var/run/gpm.pid")
1251 ;; Return #f if successfully stopped.
1252 (not (zero? (system* (string-append #$gpm "/sbin/gpm")
1255 (define gpm-service-type
1256 (service-type (name 'gpm)
1258 (list (service-extension dmd-root-service-type
1259 gpm-dmd-service)))))
1261 (define* (gpm-service #:key (gpm gpm)
1262 (options '("-m" "/dev/input/mice" "-t" "ps2")))
1263 "Run @var{gpm}, the general-purpose mouse daemon, with the given
1264 command-line @var{options}. GPM allows users to use the mouse in the console,
1265 notably to select, copy, and paste text. The default value of @var{options}
1266 uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
1268 This service is not part of @var{%base-services}."
1269 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
1270 ;; "info mice" and "mouse_set X" to use the right mouse.
1271 (service gpm-service-type
1272 (gpm-configuration (gpm gpm) (options options))))
1275 (define %base-services
1276 ;; Convenience variable holding the basic services.
1277 (let ((motd (plain-file "motd" "
1278 This is the GNU operating system, welcome!\n\n")))
1279 (list (console-font-service "tty1")
1280 (console-font-service "tty2")
1281 (console-font-service "tty3")
1282 (console-font-service "tty4")
1283 (console-font-service "tty5")
1284 (console-font-service "tty6")
1286 (mingetty-service (mingetty-configuration
1287 (tty "tty1") (motd motd)))
1288 (mingetty-service (mingetty-configuration
1289 (tty "tty2") (motd motd)))
1290 (mingetty-service (mingetty-configuration
1291 (tty "tty3") (motd motd)))
1292 (mingetty-service (mingetty-configuration
1293 (tty "tty4") (motd motd)))
1294 (mingetty-service (mingetty-configuration
1295 (tty "tty5") (motd motd)))
1296 (mingetty-service (mingetty-configuration
1297 (tty "tty6") (motd motd)))
1299 (static-networking-service "lo" "127.0.0.1"
1300 #:provision '(loopback))
1305 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
1306 ;; used, so enable them by default. The FUSE and ALSA rules are
1307 ;; less critical, but handy.
1308 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
1310 ;;; base.scm ends here