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>
6 ;;; This file is part of GNU Guix.
8 ;;; GNU Guix is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; GNU Guix is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 (define-module (gnu services base)
22 #:use-module (guix store)
23 #:use-module (gnu services)
24 #:use-module (gnu services dmd)
25 #:use-module (gnu services networking)
26 #:use-module (gnu system shadow) ; 'user-account', etc.
27 #:use-module (gnu system linux) ; 'pam-service', etc.
28 #:use-module (gnu system file-systems) ; 'file-system', etc.
29 #:use-module (gnu packages admin)
30 #:use-module ((gnu packages linux)
31 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda))
32 #:use-module ((gnu packages base)
33 #:select (canonical-package glibc))
34 #:use-module (gnu packages package-management)
35 #:use-module (gnu packages lsh)
36 #:use-module (gnu packages lsof)
37 #:use-module ((gnu build file-systems)
38 #:select (mount-flags->bit-mask))
39 #:use-module (guix gexp)
40 #:use-module (guix records)
41 #:use-module (srfi srfi-1)
42 #:use-module (srfi srfi-26)
43 #:use-module (ice-9 match)
44 #:use-module (ice-9 format)
45 #:export (root-file-system-service
48 device-mapping-service
50 user-processes-service
52 console-keymap-service
57 mingetty-configuration
58 mingetty-configuration?
62 %nscd-default-configuration
82 ;;; Base system services---i.e., services that 99% of the users will want to
92 (define %root-file-system-dmd-service
94 (documentation "Take care of the root file system.")
95 (provision '(root-file-system))
98 ;; Return #f if successfully stopped.
101 (call-with-blocked-asyncs
103 (let ((null (%make-void-port "w")))
105 (display "closing log\n")
106 ;; XXX: Ideally we'd use 'stop-logging', but that one
107 ;; doesn't actually close the port as of dmd 0.1.
108 (close-port (@@ (dmd comm) log-output-port))
109 (set! (@@ (dmd comm) log-output-port) null)
111 ;; Redirect the default output ports..
112 (set-current-output-port null)
113 (set-current-error-port null)
115 ;; Close /dev/console.
116 (for-each close-fdes '(0 1 2))
118 ;; At this point, there are no open files left, so the
119 ;; root file system can be re-mounted read-only.
121 (logior MS_REMOUNT MS_RDONLY)
127 (define root-file-system-service-type
128 (dmd-service-type 'root-file-system
129 (const %root-file-system-dmd-service)))
131 (define (root-file-system-service)
132 "Return a service whose sole purpose is to re-mount read-only the root file
133 system upon shutdown (aka. cleanly \"umounting\" root.)
135 This service must be the root of the service dependency graph so that its
136 'stop' action is invoked when dmd is the only process left."
137 (service root-file-system-service-type #f))
139 (define (file-system->dmd-service-name file-system)
140 "Return the symbol that denotes the service mounting and unmounting
142 (symbol-append 'file-system-
143 (string->symbol (file-system-mount-point file-system))))
145 (define file-system-service-type
146 ;; TODO(?): Make this an extensible service that takes <file-system> objects
147 ;; and returns a list of <dmd-service>.
150 (lambda (file-system)
151 (let ((target (file-system-mount-point file-system))
152 (device (file-system-device file-system))
153 (type (file-system-type file-system))
154 (title (file-system-title file-system))
155 (check? (file-system-check? file-system))
156 (create? (file-system-create-mount-point? file-system))
157 (dependencies (file-system-dependencies file-system)))
159 (provision (list (file-system->dmd-service-name file-system)))
160 (requirement `(root-file-system
161 ,@(map file-system->dmd-service-name dependencies)))
162 (documentation "Check, mount, and unmount the given file system.")
163 (start #~(lambda args
164 ;; FIXME: Use or factorize with 'mount-file-system'.
165 (let ((device (canonicalize-device-spec #$device '#$title))
166 (flags #$(mount-flags->bit-mask
167 (file-system-flags file-system))))
173 ;; Make sure fsck.ext2 & co. can be found.
177 "/run/current-system/profile/sbin:"
179 (check-file-system device #$type))
182 (mount device #$target #$type flags
183 #$(file-system-options file-system))
185 ;; For read-only bind mounts, an extra remount is needed,
186 ;; as per <http://lwn.net/Articles/281157/>, which still
187 ;; applies to Linux 4.0.
188 (when (and (= MS_BIND (logand flags MS_BIND))
189 (= MS_RDONLY (logand flags MS_RDONLY)))
190 (mount device #$target #$type
191 (logior MS_BIND MS_REMOUNT MS_RDONLY))))
194 ;; Normally there are no processes left at this point, so
195 ;; TARGET can be safely unmounted.
197 ;; Make sure PID 1 doesn't keep TARGET busy.
203 (define* (file-system-service file-system)
204 "Return a service that mounts @var{file-system}, a @code{<file-system>}
206 (service file-system-service-type file-system))
208 (define user-unmount-service-type
211 (lambda (known-mount-points)
213 (documentation "Unmount manually-mounted file systems.")
214 (provision '(user-file-systems))
217 (define (known? mount-point)
219 (cons* "/proc" "/sys" '#$known-mount-points)))
221 ;; Make sure we don't keep the user's mount points busy.
224 (for-each (lambda (mount-point)
225 (format #t "unmounting '~a'...~%" mount-point)
228 (umount mount-point))
230 (let ((errno (system-error-errno args)))
231 (format #t "failed to unmount '~a': ~a~%"
232 mount-point (strerror errno))))))
233 (filter (negate known?) (mount-points)))
236 (define (user-unmount-service known-mount-points)
237 "Return a service whose sole purpose is to unmount file systems not listed
238 in KNOWN-MOUNT-POINTS when it is stopped."
239 (service user-unmount-service-type known-mount-points))
241 (define %do-not-kill-file
242 ;; Name of the file listing PIDs of processes that must survive when halting
243 ;; the system. Typical example is user-space file systems.
244 "/etc/dmd/do-not-kill")
246 (define user-processes-service-type
250 ((requirements grace-delay)
252 (documentation "When stopped, terminate all user processes.")
253 (provision '(user-processes))
254 (requirement (cons* 'root-file-system 'user-file-systems
255 (map file-system->dmd-service-name
259 (define (kill-except omit signal)
260 ;; Kill all the processes with SIGNAL except those listed
261 ;; in OMIT and the current process.
262 (let ((omit (cons (getpid) omit)))
263 (for-each (lambda (pid)
264 (unless (memv pid omit)
270 ;; List of PIDs that must not be killed.
271 (if (file-exists? #$%do-not-kill-file)
273 (call-with-input-file #$%do-not-kill-file
274 (compose string-tokenize
275 (@ (ice-9 rdelim) read-string))))
279 (car (gettimeofday)))
282 ;; Really sleep N seconds.
283 ;; Work around <http://bugs.gnu.org/19581>.
285 (let loop ((elapsed 0))
287 (sleep (- n elapsed))
288 (loop (- (now) start)))))
290 (define lset= (@ (srfi srfi-1) lset=))
292 (display "sending all processes the TERM signal\n")
294 (if (null? omitted-pids)
296 ;; Easy: terminate all of them.
298 (sleep* #$grace-delay)
301 ;; Kill them all except OMITTED-PIDS. XXX: We would
302 ;; like to (kill -1 SIGSTOP) to get a fixed list of
303 ;; processes, like 'killall5' does, but that seems
305 (kill-except omitted-pids SIGTERM)
306 (sleep* #$grace-delay)
307 (kill-except omitted-pids SIGKILL)
308 (delete-file #$%do-not-kill-file)))
311 (let ((pids (processes)))
312 (unless (lset= = pids (cons 1 omitted-pids))
313 (format #t "waiting for process termination\
314 (processes left: ~s)~%"
319 (display "all processes have been terminated\n")
323 (define* (user-processes-service file-systems #:key (grace-delay 4))
324 "Return the service that is responsible for terminating all the processes so
325 that the root file system can be re-mounted read-only, just before
326 rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
327 has been sent are terminated with SIGKILL.
329 The returned service will depend on 'root-file-system' and on all the dmd
330 services corresponding to FILE-SYSTEMS.
332 All the services that spawn processes must depend on this one so that they are
333 stopped before 'kill' is called."
334 (service user-processes-service-type
335 (list file-systems grace-delay)))
342 (define host-name-service-type
347 (documentation "Initialize the machine's host name.")
348 (provision '(host-name))
350 (sethostname #$name)))
353 (define (host-name-service name)
354 "Return a service that sets the host name to @var{name}."
355 (service host-name-service-type name))
357 (define (unicode-start tty)
358 "Return a gexp to start Unicode support on @var{tty}."
360 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
361 ;; 'tty' command, that command returns TTY.
363 (let ((pid (primitive-fork)))
367 (dup2 (open-fdes #$tty O_RDONLY) 0)
369 (dup2 (open-fdes #$tty O_WRONLY) 1)
370 (execl (string-append #$kbd "/bin/unicode_start")
373 (zero? (cdr (waitpid pid))))))))
375 (define console-keymap-service-type
380 (documentation (string-append "Load console keymap (loadkeys)."))
381 (provision '(console-keymap))
383 (zero? (system* (string-append #$kbd "/bin/loadkeys")
387 (define (console-keymap-service file)
388 "Return a service to load console keymap from @var{file}."
389 (service console-keymap-service-type file))
391 (define console-font-service-type
396 (let ((device (string-append "/dev/" tty)))
398 (documentation "Load a Unicode console font.")
399 (provision (list (symbol-append 'console-font-
400 (string->symbol tty))))
402 ;; Start after mingetty has been started on TTY, otherwise the settings
404 (requirement (list (symbol-append 'term-
405 (string->symbol tty))))
408 (and #$(unicode-start device)
410 (system* (string-append #$kbd "/bin/setfont")
411 "-C" #$device #$font)))))
415 (define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
416 "Return a service that sets up Unicode support in @var{tty} and loads
417 @var{font} for that tty (fonts are per virtual console in Linux.)"
418 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
419 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
420 ;; codepoints notably found in the UTF-8 manual.
421 (service console-font-service-type (list tty font)))
423 (define-record-type* <mingetty-configuration>
424 mingetty-configuration make-mingetty-configuration
425 mingetty-configuration?
426 (mingetty mingetty-configuration-mingetty ;<package>
428 (tty mingetty-configuration-tty) ;string
429 (motd mingetty-configuration-motd ;file-like
430 (default (plain-file "motd" "Welcome.\n")))
431 (auto-login mingetty-auto-login ;string | #f
433 (login-program mingetty-login-program ;gexp
435 (login-pause? mingetty-login-pause? ;Boolean
438 ;; Allow empty passwords by default so that first-time users can log in when
439 ;; the 'root' account has just been created.
440 (allow-empty-passwords? mingetty-configuration-allow-empty-passwords?
441 (default #t))) ;Boolean
443 (define (mingetty-pam-service conf)
444 "Return the list of PAM service needed for CONF."
445 ;; Let 'login' be known to PAM. All the mingetty services will have that
446 ;; PAM service, but that's fine because they're all identical and duplicates
448 (list (unix-pam-service "login"
449 #:allow-empty-passwords?
450 (mingetty-configuration-allow-empty-passwords? conf)
452 (mingetty-configuration-motd conf))))
454 (define mingetty-dmd-service
456 (($ <mingetty-configuration> mingetty tty motd auto-login login-program
457 login-pause? allow-empty-passwords?)
460 (documentation "Run mingetty on an tty.")
461 (provision (list (symbol-append 'term- (string->symbol tty))))
463 ;; Since the login prompt shows the host name, wait for the 'host-name'
464 ;; service to be done. Also wait for udev essentially so that the tty
465 ;; text is not lost in the middle of kernel messages (XXX).
466 (requirement '(user-processes host-name udev))
468 (start #~(make-forkexec-constructor
469 (list (string-append #$mingetty "/sbin/mingetty")
472 #~("--autologin" #$auto-login)
475 #~("--loginprog" #$login-program)
480 (stop #~(make-kill-destructor)))))))
482 (define mingetty-service-type
483 (service-type (name 'mingetty)
484 (extensions (list (service-extension dmd-root-service-type
485 mingetty-dmd-service)
486 (service-extension pam-root-service-type
487 mingetty-pam-service)))))
489 (define* (mingetty-service config)
490 "Return a service to run mingetty according to @var{config}, which specifies
491 the tty to run, among other things."
492 (service mingetty-service-type config))
494 (define-record-type* <nscd-configuration> nscd-configuration
495 make-nscd-configuration
497 (log-file nscd-configuration-log-file ;string
498 (default "/var/log/nscd.log"))
499 (debug-level nscd-debug-level ;integer
501 ;; TODO: See nscd.conf in glibc for other options to add.
502 (caches nscd-configuration-caches ;list of <nscd-cache>
503 (default %nscd-default-caches))
504 (name-services nscd-configuration-name-services ;list of <packages>
506 (glibc nscd-configuration-glibc ;<package>
507 (default (canonical-package glibc))))
509 (define-record-type* <nscd-cache> nscd-cache make-nscd-cache
511 (database nscd-cache-database) ;symbol
512 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
513 (negative-time-to-live nscd-cache-negative-time-to-live
514 (default 20)) ;integer
515 (suggested-size nscd-cache-suggested-size ;integer ("default module
518 (check-files? nscd-cache-check-files? ;Boolean
520 (persistent? nscd-cache-persistent? ;Boolean
522 (shared? nscd-cache-shared? ;Boolean
524 (max-database-size nscd-cache-max-database-size ;integer
525 (default (* 32 (expt 2 20))))
526 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
529 (define %nscd-default-caches
530 ;; Caches that we want to enable by default. Note that when providing an
531 ;; empty nscd.conf, all caches are disabled.
532 (list (nscd-cache (database 'hosts)
534 ;; Aggressively cache the host name cache to improve
535 ;; privacy and resilience.
536 (positive-time-to-live (* 3600 12))
537 (negative-time-to-live 20)
540 (nscd-cache (database 'services)
542 ;; Services are unlikely to change, so we can be even more
544 (positive-time-to-live (* 3600 24))
545 (negative-time-to-live 3600)
546 (check-files? #t) ;check /etc/services changes
549 (define %nscd-default-configuration
550 ;; Default nscd configuration.
551 (nscd-configuration))
553 (define (nscd.conf-file config)
554 "Return the @file{nscd.conf} configuration file for @var{config}, an
555 @code{<nscd-configuration>} object."
556 (define cache->config
558 (($ <nscd-cache> (= symbol->string database)
559 positive-ttl negative-ttl size check-files?
560 persistent? shared? max-size propagate?)
561 (string-append "\nenable-cache\t" database "\tyes\n"
563 "positive-time-to-live\t" database "\t"
564 (number->string positive-ttl) "\n"
565 "negative-time-to-live\t" database "\t"
566 (number->string negative-ttl) "\n"
567 "suggested-size\t" database "\t"
568 (number->string size) "\n"
569 "check-files\t" database "\t"
570 (if check-files? "yes\n" "no\n")
571 "persistent\t" database "\t"
572 (if persistent? "yes\n" "no\n")
573 "shared\t" database "\t"
574 (if shared? "yes\n" "no\n")
575 "max-db-size\t" database "\t"
576 (number->string max-size) "\n"
577 "auto-propagate\t" database "\t"
578 (if propagate? "yes\n" "no\n")))))
581 (($ <nscd-configuration> log-file debug-level caches)
582 (plain-file "nscd.conf"
584 # Configuration of libc's name service cache daemon (nscd).\n\n"
586 (string-append "logfile\t" log-file)
590 (string-append "debug-level\t"
591 (number->string debug-level))
595 (map cache->config caches)))))))
597 (define (nscd-dmd-service config)
598 "Return a dmd service for CONFIG, an <nscd-configuration> object."
599 (let ((nscd.conf (nscd.conf-file config))
600 (name-services (nscd-configuration-name-services config)))
602 (documentation "Run libc's name service cache daemon (nscd).")
604 (requirement '(user-processes))
605 (start #~(make-forkexec-constructor
606 (list (string-append #$(nscd-configuration-glibc config)
608 "-f" #$nscd.conf "--foreground")
610 #:environment-variables
611 (list (string-append "LD_LIBRARY_PATH="
614 (string-append dir "/lib"))
615 (list #$@name-services))
617 (stop #~(make-kill-destructor))
621 (define nscd-activation
622 ;; Actions to take before starting nscd.
624 (use-modules (guix build utils))
625 (mkdir-p "/var/run/nscd")
626 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
628 (define nscd-service-type
629 (service-type (name 'nscd)
631 (list (service-extension activation-service-type
632 (const nscd-activation))
633 (service-extension dmd-root-service-type
636 ;; This can be extended by providing additional name services
638 (compose concatenate)
639 (extend (lambda (config name-services)
642 (name-services (append
643 (nscd-configuration-name-services config)
646 (define* (nscd-service #:optional (config %nscd-default-configuration))
647 "Return a service that runs libc's name service cache daemon (nscd) with the
648 given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
649 Service Switch}, for an example."
650 (service nscd-service-type config))
652 (define syslog-service-type
655 (lambda (config-file)
657 (documentation "Run the syslog daemon (syslogd).")
658 (provision '(syslogd))
659 (requirement '(user-processes))
660 (start #~(make-forkexec-constructor
661 (list (string-append #$inetutils "/libexec/syslogd")
662 "--no-detach" "--rcfile" #$config-file)))
663 (stop #~(make-kill-destructor))))))
665 ;; Snippet adapted from the GNU inetutils manual.
666 (define %default-syslog.conf
667 (plain-file "syslog.conf" "
668 # Log all error messages, authentication messages of
669 # level notice or higher and anything of level err or
670 # higher to the console.
671 # Don't log private authentication messages!
672 *.alert;auth.notice;authpriv.none /dev/console
674 # Log anything (except mail) of level info or higher.
675 # Don't log private authentication messages!
676 *.info;mail.none;authpriv.none /var/log/messages
678 # Same, in a different place.
679 *.info;mail.none;authpriv.none /dev/tty12
681 # The authpriv file has restricted access.
682 authpriv.* /var/log/secure
684 # Log all the mail messages in one place.
685 mail.* /var/log/maillog
688 (define* (syslog-service #:key (config-file %default-syslog.conf))
689 "Return a service that runs @code{syslogd}.
690 If configuration file name @var{config-file} is not specified, use some
691 reasonable default settings."
692 (service syslog-service-type config-file))
694 (define* (guix-build-accounts count #:key
698 "Return a list of COUNT user accounts for Guix build users, with UIDs
699 starting at FIRST-UID, and under GID."
700 (unfold (cut > <> count)
703 (name (format #f "guixbuilder~2,'0d" n))
705 (uid (+ first-uid n -1))
708 ;; guix-daemon expects GROUP to be listed as a
709 ;; supplementary group too:
710 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
711 (supplementary-groups (list group "kvm"))
713 (comment (format #f "Guix Build User ~2d" n))
714 (home-directory "/var/empty")
715 (shell #~(string-append #$shadow "/sbin/nologin"))))
719 (define (hydra-key-authorization guix)
720 "Return a gexp with code to register the hydra.gnu.org public key with
722 #~(unless (file-exists? "/etc/guix/acl")
723 (let ((pid (primitive-fork)))
726 (let* ((key (string-append #$guix
727 "/share/guix/hydra.gnu.org.pub"))
728 (port (open-file key "r0b")))
729 (format #t "registering public key '~a'...~%" key)
730 (close-port (current-input-port))
732 (execl (string-append #$guix "/bin/guix")
733 "guix" "archive" "--authorize")
736 (let ((status (cdr (waitpid pid))))
737 (unless (zero? status)
738 (format (current-error-port) "warning: \
739 failed to register hydra.gnu.org public key: ~a~%" status))))))))
741 (define-record-type* <guix-configuration>
742 guix-configuration make-guix-configuration
744 (guix guix-configuration-guix ;<package>
746 (build-group guix-configuration-build-group ;string
747 (default "guixbuild"))
748 (build-accounts guix-configuration-build-accounts ;integer
750 (authorize-key? guix-configuration-authorize-key? ;Boolean
752 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
754 (extra-options guix-configuration-extra-options ;list of strings
756 (lsof guix-configuration-lsof ;<package>
758 (lsh guix-configuration-lsh ;<package>
761 (define %default-guix-configuration
762 (guix-configuration))
764 (define (guix-dmd-service config)
765 "Return a <dmd-service> for the Guix daemon service with CONFIG."
767 (($ <guix-configuration> guix build-group build-accounts authorize-key?
768 use-substitutes? extra-options lsof lsh)
770 (documentation "Run the Guix daemon.")
771 (provision '(guix-daemon))
772 (requirement '(user-processes))
774 #~(make-forkexec-constructor
775 (list (string-append #$guix "/bin/guix-daemon")
776 "--build-users-group" #$build-group
777 #$@(if use-substitutes?
779 '("--no-substitutes"))
782 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
784 #:environment-variables
785 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
786 (stop #~(make-kill-destructor)))))))
788 (define (guix-accounts config)
789 "Return the user accounts and user groups for CONFIG."
791 (($ <guix-configuration> _ build-group build-accounts)
796 ;; Use a fixed GID so that we can create the store with the right
799 (guix-build-accounts build-accounts
800 #:group build-group)))))
802 (define (guix-activation config)
803 "Return the activation gexp for CONFIG."
805 (($ <guix-configuration> guix build-group build-accounts authorize-key?)
806 ;; Assume that the store has BUILD-GROUP as its group. We could
807 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
808 ;; chown leads to an entire copy of the tree, which is a bad idea.
810 ;; Optionally authorize hydra.gnu.org's key.
812 (hydra-key-authorization guix)))))
814 (define guix-service-type
818 (list (service-extension dmd-root-service-type guix-dmd-service)
819 (service-extension account-service-type guix-accounts)
820 (service-extension activation-service-type guix-activation)))))
822 (define* (guix-service #:optional (config %default-guix-configuration))
823 "Return a service that runs the Guix build daemon according to
825 (service guix-service-type config))
832 (define-record-type* <udev-configuration>
833 udev-configuration make-udev-configuration
835 (udev udev-configuration-udev ;<package>
837 (rules udev-configuration-rules ;list of <package>
840 (define (udev-rules-union packages)
841 "Return the union of the @code{lib/udev/rules.d} directories found in each
842 item of @var{packages}."
845 (use-modules (guix build union)
850 (define %standard-locations
851 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
853 (define (rules-sub-directory directory)
854 ;; Return the sub-directory of DIRECTORY containing udev rules, or
855 ;; #f if none was found.
856 (find directory-exists?
857 (map (cut string-append directory <>) %standard-locations)))
859 (mkdir-p (string-append #$output "/lib/udev"))
860 (union-build (string-append #$output "/lib/udev/rules.d")
861 (filter-map rules-sub-directory '#$packages))))
863 (computed-file "udev-rules" build
864 #:modules '((guix build union)
865 (guix build utils))))
867 (define* (kvm-udev-rule)
868 "Return a directory with a udev rule that changes the group of
869 @file{/dev/kvm} to \"kvm\" and makes it #o660."
870 ;; Apparently QEMU-KVM used to ship this rule, but now we have to add it by
872 (computed-file "kvm-udev-rules"
874 (use-modules (guix build utils))
877 (string-append #$output "/lib/udev/rules.d"))
880 (call-with-output-file
881 (string-append rules.d "/90-kvm.rules")
883 ;; Build users are part of the "kvm" group, so we
884 ;; can fearlessly make /dev/kvm 660 (see
885 ;; <http://bugs.gnu.org/18994>, for background.)
887 KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n" port))))
888 #:modules '((guix build utils))))
890 (define udev-dmd-service
891 ;; Return a <dmd-service> for UDEV with RULES.
893 (($ <udev-configuration> udev rules)
894 (let* ((rules (udev-rules-union (cons* udev (kvm-udev-rule) rules)))
895 (udev.conf (computed-file "udev.conf"
896 #~(call-with-output-file #$output
899 "udev_rules=\"~a/lib/udev/rules.d\"\n"
905 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
907 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
908 (requirement '(root-file-system))
910 (documentation "Populate the /dev directory, dynamically.")
913 (@ (srfi srfi-1) find))
916 ;; Choose the right 'udevd'.
918 (map (lambda (suffix)
919 (string-append #$udev suffix))
920 '("/libexec/udev/udevd" ;udev
921 "/sbin/udevd")))) ;eudev
923 (define (wait-for-udevd)
924 ;; Wait until someone's listening on udevd's control
926 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
930 (connect sock PF_UNIX "/run/udev/control")
933 (format #t "waiting for udevd...~%")
937 ;; Allow udev to find the modules.
938 (setenv "LINUX_MODULE_DIRECTORY"
939 "/run/booted-system/kernel/lib/modules")
941 ;; The first one is for udev, the second one for eudev.
942 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
943 (setenv "EUDEV_RULES_DIRECTORY"
944 (string-append #$rules "/lib/udev/rules.d"))
946 (let ((pid (primitive-fork)))
949 (exec-command (list udevd)))
951 ;; Wait until udevd is up and running. This
952 ;; appears to be needed so that the events
953 ;; triggered below are actually handled.
956 ;; Trigger device node creation.
957 (system* (string-append #$udev "/bin/udevadm")
958 "trigger" "--action=add")
960 ;; Wait for things to settle down.
961 (system* (string-append #$udev "/bin/udevadm")
964 (stop #~(make-kill-destructor))
966 ;; When halting the system, 'udev' is actually killed by
967 ;; 'user-processes', i.e., before its own 'stop' method was called.
968 ;; Thus, make sure it is not respawned.
971 (define udev-service-type
972 (service-type (name 'udev)
974 (list (service-extension dmd-root-service-type
977 (compose concatenate) ;concatenate the list of rules
978 (extend (lambda (config rules)
980 (($ <udev-configuration> udev initial-rules)
983 (rules (append initial-rules rules)))))))))
985 (define* (udev-service #:key (udev eudev) (rules '()))
986 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
987 extra rules from the packages listed in @var{rules}."
988 (service udev-service-type
989 (udev-configuration (udev udev) (rules rules))))
991 (define device-mapping-service-type
997 (provision (list (symbol-append 'device-mapping- (string->symbol target))))
998 (requirement '(udev))
999 (documentation "Map a device node using Linux's device mapper.")
1000 (start #~(lambda () #$open))
1001 (stop #~(lambda _ (not #$close)))
1004 (define (device-mapping-service target open close)
1005 "Return a service that maps device @var{target}, a string such as
1006 @code{\"home\"} (meaning @code{/dev/mapper/home}). Evaluate @var{open}, a
1007 gexp, to open it, and evaluate @var{close} to close it."
1008 (service device-mapping-service-type
1009 (list target open close)))
1011 (define swap-service-type
1016 (if (string-prefix? "/dev/mapper/" device)
1017 (list (symbol-append 'device-mapping-
1018 (string->symbol (basename device))))
1022 (provision (list (symbol-append 'swap- (string->symbol device))))
1023 (requirement `(udev ,@requirement))
1024 (documentation "Enable the given swap device.")
1026 (restart-on-EINTR (swapon #$device))
1029 (restart-on-EINTR (swapoff #$device))
1033 (define (swap-service device)
1034 "Return a service that uses @var{device} as a swap device."
1035 (service swap-service-type device))
1037 (define %base-services
1038 ;; Convenience variable holding the basic services.
1039 (let ((motd (plain-file "motd" "
1040 This is the GNU operating system, welcome!\n\n")))
1041 (list (console-font-service "tty1")
1042 (console-font-service "tty2")
1043 (console-font-service "tty3")
1044 (console-font-service "tty4")
1045 (console-font-service "tty5")
1046 (console-font-service "tty6")
1048 (mingetty-service (mingetty-configuration
1049 (tty "tty1") (motd motd)))
1050 (mingetty-service (mingetty-configuration
1051 (tty "tty2") (motd motd)))
1052 (mingetty-service (mingetty-configuration
1053 (tty "tty3") (motd motd)))
1054 (mingetty-service (mingetty-configuration
1055 (tty "tty4") (motd motd)))
1056 (mingetty-service (mingetty-configuration
1057 (tty "tty5") (motd motd)))
1058 (mingetty-service (mingetty-configuration
1059 (tty "tty6") (motd motd)))
1061 (static-networking-service "lo" "127.0.0.1"
1062 #:provision '(loopback))
1067 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
1068 ;; used, so enable them by default. The FUSE and ALSA rules are
1069 ;; less critical, but handy.
1070 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
1072 ;;; base.scm ends here