1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
4 ;;; Copyright © 2015, 2016 Mark H Weaver <mhw@netris.org>
5 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
6 ;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
7 ;;; Copyright © 2016 David Craven <david@craven.ch>
8 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
10 ;;; This file is part of GNU Guix.
12 ;;; GNU Guix is free software; you can redistribute it and/or modify it
13 ;;; under the terms of the GNU General Public License as published by
14 ;;; the Free Software Foundation; either version 3 of the License, or (at
15 ;;; your option) any later version.
17 ;;; GNU Guix is distributed in the hope that it will be useful, but
18 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;;; GNU General Public License for more details.
22 ;;; You should have received a copy of the GNU General Public License
23 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
25 (define-module (gnu services base)
26 #:use-module (guix store)
27 #:use-module (gnu services)
28 #:use-module (gnu services shepherd)
29 #:use-module (gnu services networking)
30 #:use-module (gnu system pam)
31 #:use-module (gnu system shadow) ; 'user-account', etc.
32 #:use-module (gnu system file-systems) ; 'file-system', etc.
33 #:use-module (gnu system mapped-devices)
34 #:use-module (gnu packages admin)
35 #:use-module ((gnu packages linux)
36 #:select (alsa-utils crda eudev e2fsprogs fuse gpm kbd lvm2 rng-tools))
37 #:use-module ((gnu packages base)
38 #:select (canonical-package glibc))
39 #:use-module (gnu packages package-management)
40 #:use-module (gnu packages ssh)
41 #:use-module (gnu packages lsof)
42 #:use-module ((gnu build file-systems)
43 #:select (mount-flags->bit-mask))
44 #:use-module (guix gexp)
45 #:use-module (guix records)
46 #:use-module (srfi srfi-1)
47 #:use-module (srfi srfi-26)
48 #:use-module (ice-9 match)
49 #:use-module (ice-9 format)
50 #:export (fstab-service-type
51 root-file-system-service
55 user-processes-service
56 session-environment-service
57 session-environment-service-type
59 console-keymap-service
64 udev-configuration-rules
69 mingetty-configuration
70 mingetty-configuration?
75 %nscd-default-configuration
93 guix-publish-configuration
94 guix-publish-configuration?
96 guix-publish-service-type
103 urandom-seed-service-type
110 pam-limits-service-type
117 ;;; Base system services---i.e., services that 99% of the users will want to
127 (define (file-system->fstab-entry file-system)
128 "Return a @file{/etc/fstab} entry for @var{file-system}."
129 (string-append (case (file-system-title file-system)
131 (string-append "LABEL=" (file-system-device file-system)))
135 (uuid->string (file-system-device file-system))))
137 (file-system-device file-system)))
139 (file-system-mount-point file-system) "\t"
140 (file-system-type file-system) "\t"
141 (or (file-system-options file-system) "defaults") "\t"
143 ;; XXX: Omit the 'fs_freq' and 'fs_passno' fields because we
144 ;; don't have anything sensible to put in there.
147 (define (file-systems->fstab file-systems)
148 "Return a @file{/etc} entry for an @file{fstab} describing
150 `(("fstab" ,(plain-file "fstab"
153 # This file was generated from your GuixSD configuration. Any changes
154 # will be lost upon reboot or reconfiguration.\n\n"
155 (string-join (map file-system->fstab-entry
160 (define fstab-service-type
161 ;; The /etc/fstab service.
162 (service-type (name 'fstab)
164 (list (service-extension etc-service-type
165 file-systems->fstab)))
169 (define %root-file-system-shepherd-service
171 (documentation "Take care of the root file system.")
172 (provision '(root-file-system))
175 ;; Return #f if successfully stopped.
178 (call-with-blocked-asyncs
180 (let ((null (%make-void-port "w")))
181 ;; Close 'shepherd.log'.
182 (display "closing log\n")
183 ((@ (shepherd comm) stop-logging))
185 ;; Redirect the default output ports..
186 (set-current-output-port null)
187 (set-current-error-port null)
189 ;; Close /dev/console.
190 (for-each close-fdes '(0 1 2))
192 ;; At this point, there are no open files left, so the
193 ;; root file system can be re-mounted read-only.
195 (logior MS_REMOUNT MS_RDONLY)
201 (define root-file-system-service-type
202 (shepherd-service-type 'root-file-system
203 (const %root-file-system-shepherd-service)))
205 (define (root-file-system-service)
206 "Return a service whose sole purpose is to re-mount read-only the root file
207 system upon shutdown (aka. cleanly \"umounting\" root.)
209 This service must be the root of the service dependency graph so that its
210 'stop' action is invoked when shepherd is the only process left."
211 (service root-file-system-service-type #f))
213 (define (file-system->shepherd-service-name file-system)
214 "Return the symbol that denotes the service mounting and unmounting
216 (symbol-append 'file-system-
217 (string->symbol (file-system-mount-point file-system))))
219 (define (mapped-device->shepherd-service-name md)
220 "Return the symbol that denotes the shepherd service of MD, a <mapped-device>."
221 (symbol-append 'device-mapping-
222 (string->symbol (mapped-device-target md))))
224 (define dependency->shepherd-service-name
226 ((? mapped-device? md)
227 (mapped-device->shepherd-service-name md))
229 (file-system->shepherd-service-name fs))))
231 (define (file-system-shepherd-service file-system)
232 "Return a list containing the shepherd service for @var{file-system}."
233 (let ((target (file-system-mount-point file-system))
234 (device (file-system-device file-system))
235 (type (file-system-type file-system))
236 (title (file-system-title file-system))
237 (check? (file-system-check? file-system))
238 (create? (file-system-create-mount-point? file-system))
239 (dependencies (file-system-dependencies file-system)))
240 (if (file-system-mount? file-system)
241 (with-imported-modules '((gnu build file-systems)
242 (guix build bournish))
245 (provision (list (file-system->shepherd-service-name file-system)))
246 (requirement `(root-file-system
247 ,@(map dependency->shepherd-service-name dependencies)))
248 (documentation "Check, mount, and unmount the given file system.")
249 (start #~(lambda args
250 ;; FIXME: Use or factorize with 'mount-file-system'.
251 (let ((device (canonicalize-device-spec #$device '#$title))
252 (flags #$(mount-flags->bit-mask
253 (file-system-flags file-system))))
259 ;; Make sure fsck.ext2 & co. can be found.
263 "/run/current-system/profile/sbin:"
265 (check-file-system device #$type))
268 (mount device #$target #$type flags
269 #$(file-system-options file-system))
271 ;; For read-only bind mounts, an extra remount is
272 ;; needed, as per <http://lwn.net/Articles/281157/>,
273 ;; which still applies to Linux 4.0.
274 (when (and (= MS_BIND (logand flags MS_BIND))
275 (= MS_RDONLY (logand flags MS_RDONLY)))
276 (mount device #$target #$type
277 (logior MS_BIND MS_REMOUNT MS_RDONLY))))
280 ;; Normally there are no processes left at this point, so
281 ;; TARGET can be safely unmounted.
283 ;; Make sure PID 1 doesn't keep TARGET busy.
289 ;; We need an additional module.
290 (modules `(((gnu build file-systems)
291 #:select (check-file-system canonicalize-device-spec))
292 ,@%default-modules)))))
295 (define file-system-service-type
296 ;; TODO(?): Make this an extensible service that takes <file-system> objects
297 ;; and returns a list of <shepherd-service>.
298 (service-type (name 'file-system)
300 (list (service-extension shepherd-root-service-type
301 file-system-shepherd-service)
302 (service-extension fstab-service-type
305 (define* (file-system-service file-system)
306 "Return a service that mounts @var{file-system}, a @code{<file-system>}
308 (service file-system-service-type file-system))
310 (define user-unmount-service-type
311 (shepherd-service-type
313 (lambda (known-mount-points)
315 (documentation "Unmount manually-mounted file systems.")
316 (provision '(user-file-systems))
319 (define (known? mount-point)
321 (cons* "/proc" "/sys" '#$known-mount-points)))
323 ;; Make sure we don't keep the user's mount points busy.
326 (for-each (lambda (mount-point)
327 (format #t "unmounting '~a'...~%" mount-point)
330 (umount mount-point))
332 (let ((errno (system-error-errno args)))
333 (format #t "failed to unmount '~a': ~a~%"
334 mount-point (strerror errno))))))
335 (filter (negate known?) (mount-points)))
338 (define (user-unmount-service known-mount-points)
339 "Return a service whose sole purpose is to unmount file systems not listed
340 in KNOWN-MOUNT-POINTS when it is stopped."
341 (service user-unmount-service-type known-mount-points))
343 (define %do-not-kill-file
344 ;; Name of the file listing PIDs of processes that must survive when halting
345 ;; the system. Typical example is user-space file systems.
346 "/etc/shepherd/do-not-kill")
348 (define user-processes-service-type
349 (shepherd-service-type
352 ((requirements grace-delay)
354 (documentation "When stopped, terminate all user processes.")
355 (provision '(user-processes))
356 (requirement (cons* 'root-file-system 'user-file-systems
357 (map file-system->shepherd-service-name
361 (define (kill-except omit signal)
362 ;; Kill all the processes with SIGNAL except those listed
363 ;; in OMIT and the current process.
364 (let ((omit (cons (getpid) omit)))
365 (for-each (lambda (pid)
366 (unless (memv pid omit)
372 ;; List of PIDs that must not be killed.
373 (if (file-exists? #$%do-not-kill-file)
375 (call-with-input-file #$%do-not-kill-file
376 (compose string-tokenize
377 (@ (ice-9 rdelim) read-string))))
381 (car (gettimeofday)))
384 ;; Really sleep N seconds.
385 ;; Work around <http://bugs.gnu.org/19581>.
387 (let loop ((elapsed 0))
389 (sleep (- n elapsed))
390 (loop (- (now) start)))))
392 (define lset= (@ (srfi srfi-1) lset=))
394 (display "sending all processes the TERM signal\n")
396 (if (null? omitted-pids)
398 ;; Easy: terminate all of them.
400 (sleep* #$grace-delay)
403 ;; Kill them all except OMITTED-PIDS. XXX: We would
404 ;; like to (kill -1 SIGSTOP) to get a fixed list of
405 ;; processes, like 'killall5' does, but that seems
407 (kill-except omitted-pids SIGTERM)
408 (sleep* #$grace-delay)
409 (kill-except omitted-pids SIGKILL)
410 (delete-file #$%do-not-kill-file)))
413 (let ((pids (processes)))
414 (unless (lset= = pids (cons 1 omitted-pids))
415 (format #t "waiting for process termination\
416 (processes left: ~s)~%"
421 (display "all processes have been terminated\n")
425 (define* (user-processes-service file-systems #:key (grace-delay 4))
426 "Return the service that is responsible for terminating all the processes so
427 that the root file system can be re-mounted read-only, just before
428 rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
429 has been sent are terminated with SIGKILL.
431 The returned service will depend on 'root-file-system' and on all the shepherd
432 services corresponding to FILE-SYSTEMS.
434 All the services that spawn processes must depend on this one so that they are
435 stopped before 'kill' is called."
436 (service user-processes-service-type
437 (list (filter file-system-mount? file-systems) grace-delay)))
441 ;;; Preserve entropy to seed /dev/urandom on boot.
444 (define %random-seed-file
445 "/var/lib/random-seed")
447 (define (urandom-seed-shepherd-service _)
448 "Return a shepherd service for the /dev/urandom seed."
449 (list (shepherd-service
450 (documentation "Preserve entropy across reboots for /dev/urandom.")
451 (provision '(urandom-seed))
452 (requirement '(user-processes))
454 ;; On boot, write random seed into /dev/urandom.
455 (when (file-exists? #$%random-seed-file)
456 (call-with-input-file #$%random-seed-file
458 (call-with-output-file "/dev/urandom"
460 (dump-port seed urandom))))))
461 ;; Immediately refresh the seed in case the system doesn't
462 ;; shut down cleanly.
463 (call-with-input-file "/dev/urandom"
465 (let ((previous-umask (umask #o077))
466 (buf (make-bytevector 512)))
467 (mkdir-p (dirname #$%random-seed-file))
468 (get-bytevector-n! urandom buf 0 512)
469 (call-with-output-file #$%random-seed-file
471 (put-bytevector seed buf)))
472 (umask previous-umask))))
475 ;; During shutdown, write from /dev/urandom into random seed.
476 (let ((buf (make-bytevector 512)))
477 (call-with-input-file "/dev/urandom"
479 (let ((previous-umask (umask #o077)))
480 (get-bytevector-n! urandom buf 0 512)
481 (mkdir-p (dirname #$%random-seed-file))
482 (call-with-output-file #$%random-seed-file
484 (put-bytevector seed buf)))
485 (umask previous-umask))
487 (modules `((rnrs bytevectors)
489 ,@%default-modules)))))
491 (define urandom-seed-service-type
492 (service-type (name 'urandom-seed)
494 (list (service-extension shepherd-root-service-type
495 urandom-seed-shepherd-service)))))
497 (define (urandom-seed-service)
498 (service urandom-seed-service-type #f))
502 ;;; Add hardware random number generator to entropy pool.
505 (define-record-type* <rngd-configuration>
506 rngd-configuration make-rngd-configuration
508 (rng-tools rngd-configuration-rng-tools) ;package
509 (device rngd-configuration-device)) ;string
511 (define rngd-service-type
512 (shepherd-service-type
515 (define rng-tools (rngd-configuration-rng-tools config))
516 (define device (rngd-configuration-device config))
519 (list #~(string-append #$rng-tools "/sbin/rngd")
523 (documentation "Add TRNG to entropy pool.")
524 (requirement '(udev))
526 (start #~(make-forkexec-constructor #$@rngd-command))
527 (stop #~(make-kill-destructor))))))
529 (define* (rngd-service #:key
530 (rng-tools rng-tools)
531 (device "/dev/hwrng"))
532 "Return a service that runs the @command{rngd} program from @var{rng-tools}
533 to add @var{device} to the kernel's entropy pool. The service will fail if
534 @var{device} does not exist."
535 (service rngd-service-type
537 (rng-tools rng-tools)
542 ;;; System-wide environment variables.
545 (define (environment-variables->environment-file vars)
546 "Return a file for pam_env(8) that contains environment variables VARS."
547 (apply mixed-text-file "environment"
548 (append-map (match-lambda
550 (list key "=" value "\n")))
553 (define session-environment-service-type
555 (name 'session-environment)
557 (list (service-extension
560 (list `("environment"
561 ,(environment-variables->environment-file vars)))))))
562 (compose concatenate)
565 (define (session-environment-service vars)
566 "Return a service that builds the @file{/etc/environment}, which can be read
567 by PAM-aware applications to set environment variables for sessions.
569 VARS should be an association list in which both the keys and the values are
570 strings or string-valued gexps."
571 (service session-environment-service-type vars))
578 (define host-name-service-type
579 (shepherd-service-type
583 (documentation "Initialize the machine's host name.")
584 (provision '(host-name))
586 (sethostname #$name)))
589 (define (host-name-service name)
590 "Return a service that sets the host name to @var{name}."
591 (service host-name-service-type name))
593 (define (unicode-start tty)
594 "Return a gexp to start Unicode support on @var{tty}."
596 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
597 ;; 'tty' command, that command returns TTY.
599 (let ((pid (primitive-fork)))
603 (dup2 (open-fdes #$tty O_RDONLY) 0)
605 (dup2 (open-fdes #$tty O_WRONLY) 1)
606 (execl (string-append #$kbd "/bin/unicode_start")
609 (zero? (cdr (waitpid pid))))))))
611 (define console-keymap-service-type
612 (shepherd-service-type
616 (documentation (string-append "Load console keymap (loadkeys)."))
617 (provision '(console-keymap))
619 (zero? (system* (string-append #$kbd "/bin/loadkeys")
623 (define (console-keymap-service . files)
624 "Return a service to load console keymaps from @var{files}."
625 (service console-keymap-service-type files))
627 (define console-font-service-type
628 (shepherd-service-type
632 (let ((device (string-append "/dev/" tty)))
634 (documentation "Load a Unicode console font.")
635 (provision (list (symbol-append 'console-font-
636 (string->symbol tty))))
638 ;; Start after mingetty has been started on TTY, otherwise the settings
640 (requirement (list (symbol-append 'term-
641 (string->symbol tty))))
644 (and #$(unicode-start device)
646 (system* (string-append #$kbd "/bin/setfont")
647 "-C" #$device #$font)))))
651 (define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
652 "Return a service that sets up Unicode support in @var{tty} and loads
653 @var{font} for that tty (fonts are per virtual console in Linux.)"
654 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
655 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
656 ;; codepoints notably found in the UTF-8 manual.
657 (service console-font-service-type (list tty font)))
659 (define-record-type* <mingetty-configuration>
660 mingetty-configuration make-mingetty-configuration
661 mingetty-configuration?
662 (mingetty mingetty-configuration-mingetty ;<package>
664 (tty mingetty-configuration-tty) ;string
665 (motd mingetty-configuration-motd ;file-like
666 (default (plain-file "motd" "Welcome.\n")))
667 (auto-login mingetty-auto-login ;string | #f
669 (login-program mingetty-login-program ;gexp
671 (login-pause? mingetty-login-pause? ;Boolean
674 ;; Allow empty passwords by default so that first-time users can log in when
675 ;; the 'root' account has just been created.
676 (allow-empty-passwords? mingetty-configuration-allow-empty-passwords?
677 (default #t))) ;Boolean
679 (define (mingetty-pam-service conf)
680 "Return the list of PAM service needed for CONF."
681 ;; Let 'login' be known to PAM. All the mingetty services will have that
682 ;; PAM service, but that's fine because they're all identical and duplicates
684 (list (unix-pam-service "login"
685 #:allow-empty-passwords?
686 (mingetty-configuration-allow-empty-passwords? conf)
688 (mingetty-configuration-motd conf))))
690 (define mingetty-shepherd-service
692 (($ <mingetty-configuration> mingetty tty motd auto-login login-program
693 login-pause? allow-empty-passwords?)
696 (documentation "Run mingetty on an tty.")
697 (provision (list (symbol-append 'term- (string->symbol tty))))
699 ;; Since the login prompt shows the host name, wait for the 'host-name'
700 ;; service to be done. Also wait for udev essentially so that the tty
701 ;; text is not lost in the middle of kernel messages (XXX).
702 (requirement '(user-processes host-name udev))
704 (start #~(make-forkexec-constructor
705 (list (string-append #$mingetty "/sbin/mingetty")
708 #~("--autologin" #$auto-login)
711 #~("--loginprog" #$login-program)
716 (stop #~(make-kill-destructor)))))))
718 (define mingetty-service-type
719 (service-type (name 'mingetty)
720 (extensions (list (service-extension shepherd-root-service-type
721 mingetty-shepherd-service)
722 (service-extension pam-root-service-type
723 mingetty-pam-service)))))
725 (define* (mingetty-service config)
726 "Return a service to run mingetty according to @var{config}, which specifies
727 the tty to run, among other things."
728 (service mingetty-service-type config))
730 (define-record-type* <nscd-configuration> nscd-configuration
731 make-nscd-configuration
733 (log-file nscd-configuration-log-file ;string
734 (default "/var/log/nscd.log"))
735 (debug-level nscd-debug-level ;integer
737 ;; TODO: See nscd.conf in glibc for other options to add.
738 (caches nscd-configuration-caches ;list of <nscd-cache>
739 (default %nscd-default-caches))
740 (name-services nscd-configuration-name-services ;list of <packages>
742 (glibc nscd-configuration-glibc ;<package>
743 (default (canonical-package glibc))))
745 (define-record-type* <nscd-cache> nscd-cache make-nscd-cache
747 (database nscd-cache-database) ;symbol
748 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
749 (negative-time-to-live nscd-cache-negative-time-to-live
750 (default 20)) ;integer
751 (suggested-size nscd-cache-suggested-size ;integer ("default module
754 (check-files? nscd-cache-check-files? ;Boolean
756 (persistent? nscd-cache-persistent? ;Boolean
758 (shared? nscd-cache-shared? ;Boolean
760 (max-database-size nscd-cache-max-database-size ;integer
761 (default (* 32 (expt 2 20))))
762 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
765 (define %nscd-default-caches
766 ;; Caches that we want to enable by default. Note that when providing an
767 ;; empty nscd.conf, all caches are disabled.
768 (list (nscd-cache (database 'hosts)
770 ;; Aggressively cache the host name cache to improve
771 ;; privacy and resilience.
772 (positive-time-to-live (* 3600 12))
773 (negative-time-to-live 20)
776 (nscd-cache (database 'services)
778 ;; Services are unlikely to change, so we can be even more
780 (positive-time-to-live (* 3600 24))
781 (negative-time-to-live 3600)
782 (check-files? #t) ;check /etc/services changes
785 (define %nscd-default-configuration
786 ;; Default nscd configuration.
787 (nscd-configuration))
789 (define (nscd.conf-file config)
790 "Return the @file{nscd.conf} configuration file for @var{config}, an
791 @code{<nscd-configuration>} object."
792 (define cache->config
794 (($ <nscd-cache> (= symbol->string database)
795 positive-ttl negative-ttl size check-files?
796 persistent? shared? max-size propagate?)
797 (string-append "\nenable-cache\t" database "\tyes\n"
799 "positive-time-to-live\t" database "\t"
800 (number->string positive-ttl) "\n"
801 "negative-time-to-live\t" database "\t"
802 (number->string negative-ttl) "\n"
803 "suggested-size\t" database "\t"
804 (number->string size) "\n"
805 "check-files\t" database "\t"
806 (if check-files? "yes\n" "no\n")
807 "persistent\t" database "\t"
808 (if persistent? "yes\n" "no\n")
809 "shared\t" database "\t"
810 (if shared? "yes\n" "no\n")
811 "max-db-size\t" database "\t"
812 (number->string max-size) "\n"
813 "auto-propagate\t" database "\t"
814 (if propagate? "yes\n" "no\n")))))
817 (($ <nscd-configuration> log-file debug-level caches)
818 (plain-file "nscd.conf"
820 # Configuration of libc's name service cache daemon (nscd).\n\n"
822 (string-append "logfile\t" log-file)
826 (string-append "debug-level\t"
827 (number->string debug-level))
831 (map cache->config caches)))))))
833 (define (nscd-shepherd-service config)
834 "Return a shepherd service for CONFIG, an <nscd-configuration> object."
835 (let ((nscd.conf (nscd.conf-file config))
836 (name-services (nscd-configuration-name-services config)))
837 (list (shepherd-service
838 (documentation "Run libc's name service cache daemon (nscd).")
840 (requirement '(user-processes))
841 (start #~(make-forkexec-constructor
842 (list (string-append #$(nscd-configuration-glibc config)
844 "-f" #$nscd.conf "--foreground")
846 ;; Wait for the PID file. However, the PID file is
847 ;; written before nscd is actually listening on its
849 #:pid-file "/var/run/nscd/nscd.pid"
851 #:environment-variables
852 (list (string-append "LD_LIBRARY_PATH="
855 (string-append dir "/lib"))
856 (list #$@name-services))
858 (stop #~(make-kill-destructor))))))
860 (define nscd-activation
861 ;; Actions to take before starting nscd.
863 (use-modules (guix build utils))
864 (mkdir-p "/var/run/nscd")
865 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
867 (define nscd-service-type
868 (service-type (name 'nscd)
870 (list (service-extension activation-service-type
871 (const nscd-activation))
872 (service-extension shepherd-root-service-type
873 nscd-shepherd-service)))
875 ;; This can be extended by providing additional name services
877 (compose concatenate)
878 (extend (lambda (config name-services)
881 (name-services (append
882 (nscd-configuration-name-services config)
885 (define* (nscd-service #:optional (config %nscd-default-configuration))
886 "Return a service that runs libc's name service cache daemon (nscd) with the
887 given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
888 Service Switch}, for an example."
889 (service nscd-service-type config))
891 (define syslog-service-type
892 (shepherd-service-type
894 (lambda (config-file)
896 (documentation "Run the syslog daemon (syslogd).")
897 (provision '(syslogd))
898 (requirement '(user-processes))
899 (start #~(make-forkexec-constructor
900 (list (string-append #$inetutils "/libexec/syslogd")
901 "--no-detach" "--rcfile" #$config-file)))
902 (stop #~(make-kill-destructor))))))
904 ;; Snippet adapted from the GNU inetutils manual.
905 (define %default-syslog.conf
906 (plain-file "syslog.conf" "
907 # Log all error messages, authentication messages of
908 # level notice or higher and anything of level err or
909 # higher to the console.
910 # Don't log private authentication messages!
911 *.alert;auth.notice;authpriv.none /dev/console
913 # Log anything (except mail) of level info or higher.
914 # Don't log private authentication messages!
915 *.info;mail.none;authpriv.none /var/log/messages
917 # Same, in a different place.
918 *.info;mail.none;authpriv.none /dev/tty12
920 # The authpriv file has restricted access.
921 authpriv.* /var/log/secure
923 # Log all the mail messages in one place.
924 mail.* /var/log/maillog
927 (define* (syslog-service #:key (config-file %default-syslog.conf))
928 "Return a service that runs @command{syslogd}. If configuration file
929 name @var{config-file} is not specified, use some reasonable default
932 @xref{syslogd invocation,,, inetutils, GNU Inetutils}, for more
933 information on the configuration file syntax."
934 (service syslog-service-type config-file))
936 (define pam-limits-service-type
937 (let ((security-limits
938 ;; Create /etc/security containing the provided "limits.conf" file.
939 (lambda (limits-file)
946 (symlink #$limits-file
947 (string-append #$output "/limits.conf"))))))))
950 (let ((pam-limits (pam-entry
952 (module "pam_limits.so")
953 (arguments '("conf=/etc/security/limits.conf")))))
954 (if (member (pam-service-name pam)
955 '("login" "su" "slim"))
958 (session (cons pam-limits
959 (pam-service-session pam))))
964 (list (service-extension etc-service-type security-limits)
965 (service-extension pam-root-service-type
966 (lambda _ (list pam-extension))))))))
968 (define* (pam-limits-service #:optional (limits '()))
969 "Return a service that makes selected programs respect the list of
970 pam-limits-entry specified in LIMITS via pam_limits.so."
971 (service pam-limits-service-type
972 (plain-file "limits.conf"
973 (string-join (map pam-limits-entry->string limits)
981 (define* (guix-build-accounts count #:key
985 "Return a list of COUNT user accounts for Guix build users, with UIDs
986 starting at FIRST-UID, and under GID."
987 (unfold (cut > <> count)
990 (name (format #f "guixbuilder~2,'0d" n))
992 (uid (+ first-uid n -1))
995 ;; guix-daemon expects GROUP to be listed as a
996 ;; supplementary group too:
997 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
998 (supplementary-groups (list group "kvm"))
1000 (comment (format #f "Guix Build User ~2d" n))
1001 (home-directory "/var/empty")
1002 (shell #~(string-append #$shadow "/sbin/nologin"))))
1006 (define (hydra-key-authorization guix)
1007 "Return a gexp with code to register the hydra.gnu.org public key with
1009 #~(unless (file-exists? "/etc/guix/acl")
1010 (let ((pid (primitive-fork)))
1013 (let* ((key (string-append #$guix
1014 "/share/guix/hydra.gnu.org.pub"))
1015 (port (open-file key "r0b")))
1016 (format #t "registering public key '~a'...~%" key)
1017 (close-port (current-input-port))
1019 (execl (string-append #$guix "/bin/guix")
1020 "guix" "archive" "--authorize")
1023 (let ((status (cdr (waitpid pid))))
1024 (unless (zero? status)
1025 (format (current-error-port) "warning: \
1026 failed to register hydra.gnu.org public key: ~a~%" status))))))))
1028 (define-record-type* <guix-configuration>
1029 guix-configuration make-guix-configuration
1031 (guix guix-configuration-guix ;<package>
1033 (build-group guix-configuration-build-group ;string
1034 (default "guixbuild"))
1035 (build-accounts guix-configuration-build-accounts ;integer
1037 (authorize-key? guix-configuration-authorize-key? ;Boolean
1039 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1041 (substitute-urls guix-configuration-substitute-urls ;list of strings
1042 (default %default-substitute-urls))
1043 (extra-options guix-configuration-extra-options ;list of strings
1045 (lsof guix-configuration-lsof ;<package>
1047 (lsh guix-configuration-lsh ;<package>
1050 (define %default-guix-configuration
1051 (guix-configuration))
1053 (define (guix-shepherd-service config)
1054 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
1056 (($ <guix-configuration> guix build-group build-accounts authorize-key?
1057 use-substitutes? substitute-urls extra-options
1059 (list (shepherd-service
1060 (documentation "Run the Guix daemon.")
1061 (provision '(guix-daemon))
1062 (requirement '(user-processes))
1064 #~(make-forkexec-constructor
1065 (list (string-append #$guix "/bin/guix-daemon")
1066 "--build-users-group" #$build-group
1067 #$@(if use-substitutes?
1069 '("--no-substitutes"))
1070 "--substitute-urls" #$(string-join substitute-urls)
1073 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
1075 #:environment-variables
1076 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
1077 (stop #~(make-kill-destructor)))))))
1079 (define (guix-accounts config)
1080 "Return the user accounts and user groups for CONFIG."
1082 (($ <guix-configuration> _ build-group build-accounts)
1087 ;; Use a fixed GID so that we can create the store with the right
1090 (guix-build-accounts build-accounts
1091 #:group build-group)))))
1093 (define (guix-activation config)
1094 "Return the activation gexp for CONFIG."
1096 (($ <guix-configuration> guix build-group build-accounts authorize-key?)
1097 ;; Assume that the store has BUILD-GROUP as its group. We could
1098 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
1099 ;; chown leads to an entire copy of the tree, which is a bad idea.
1101 ;; Optionally authorize hydra.gnu.org's key.
1103 (hydra-key-authorization guix)
1106 (define guix-service-type
1110 (list (service-extension shepherd-root-service-type guix-shepherd-service)
1111 (service-extension account-service-type guix-accounts)
1112 (service-extension activation-service-type guix-activation)
1113 (service-extension profile-service-type
1114 (compose list guix-configuration-guix))))))
1116 (define* (guix-service #:optional (config %default-guix-configuration))
1117 "Return a service that runs the Guix build daemon according to
1119 (service guix-service-type config))
1122 (define-record-type* <guix-publish-configuration>
1123 guix-publish-configuration make-guix-publish-configuration
1124 guix-publish-configuration?
1125 (guix guix-publish-configuration-guix ;package
1127 (port guix-publish-configuration-port ;number
1129 (host guix-publish-configuration-host ;string
1130 (default "localhost")))
1132 (define guix-publish-shepherd-service
1134 (($ <guix-publish-configuration> guix port host)
1135 (list (shepherd-service
1136 (provision '(guix-publish))
1137 (requirement '(guix-daemon))
1138 (start #~(make-forkexec-constructor
1139 (list (string-append #$guix "/bin/guix")
1140 "publish" "-u" "guix-publish"
1141 "-p" #$(number->string port)
1142 (string-append "--listen=" #$host))))
1143 (stop #~(make-kill-destructor)))))))
1145 (define %guix-publish-accounts
1146 (list (user-group (name "guix-publish") (system? #t))
1148 (name "guix-publish")
1149 (group "guix-publish")
1151 (comment "guix publish user")
1152 (home-directory "/var/empty")
1153 (shell #~(string-append #$shadow "/sbin/nologin")))))
1155 (define guix-publish-service-type
1156 (service-type (name 'guix-publish)
1158 (list (service-extension shepherd-root-service-type
1159 guix-publish-shepherd-service)
1160 (service-extension account-service-type
1161 (const %guix-publish-accounts))))))
1163 (define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
1164 "Return a service that runs @command{guix publish} listening on @var{host}
1165 and @var{port} (@pxref{Invoking guix publish}).
1167 This assumes that @file{/etc/guix} already contains a signing key pair as
1168 created by @command{guix archive --generate-key} (@pxref{Invoking guix
1169 archive}). If that is not the case, the service will fail to start."
1170 (service guix-publish-service-type
1171 (guix-publish-configuration (guix guix) (port port) (host host))))
1178 (define-record-type* <udev-configuration>
1179 udev-configuration make-udev-configuration
1181 (udev udev-configuration-udev ;<package>
1183 (rules udev-configuration-rules ;list of <package>
1186 (define (udev-rules-union packages)
1187 "Return the union of the @code{lib/udev/rules.d} directories found in each
1188 item of @var{packages}."
1190 (with-imported-modules '((guix build union)
1193 (use-modules (guix build union)
1198 (define %standard-locations
1199 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
1201 (define (rules-sub-directory directory)
1202 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1203 ;; #f if none was found.
1204 (find directory-exists?
1205 (map (cut string-append directory <>) %standard-locations)))
1207 (mkdir-p (string-append #$output "/lib/udev"))
1208 (union-build (string-append #$output "/lib/udev/rules.d")
1209 (filter-map rules-sub-directory '#$packages)))))
1211 (computed-file "udev-rules" build))
1213 (define (udev-rule file-name contents)
1214 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1215 (computed-file file-name
1216 (with-imported-modules '((guix build utils))
1218 (use-modules (guix build utils))
1221 (string-append #$output "/lib/udev/rules.d"))
1224 (call-with-output-file
1225 (string-append rules.d "/" #$file-name)
1227 (display #$contents port)))))))
1229 (define kvm-udev-rule
1230 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1231 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1232 ;; but now we have to add it by ourselves.
1234 ;; Build users are part of the "kvm" group, so we can fearlessly make
1235 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1236 (udev-rule "90-kvm.rules"
1237 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1239 (define udev-shepherd-service
1240 ;; Return a <shepherd-service> for UDEV with RULES.
1242 (($ <udev-configuration> udev rules)
1243 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
1244 (udev.conf (computed-file "udev.conf"
1245 #~(call-with-output-file #$output
1248 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1254 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1256 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1257 (requirement '(root-file-system))
1259 (documentation "Populate the /dev directory, dynamically.")
1262 (@ (srfi srfi-1) find))
1265 ;; Choose the right 'udevd'.
1267 (map (lambda (suffix)
1268 (string-append #$udev suffix))
1269 '("/libexec/udev/udevd" ;udev
1270 "/sbin/udevd")))) ;eudev
1272 (define (wait-for-udevd)
1273 ;; Wait until someone's listening on udevd's control
1275 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1277 (catch 'system-error
1279 (connect sock PF_UNIX "/run/udev/control")
1282 (format #t "waiting for udevd...~%")
1286 ;; Allow udev to find the modules.
1287 (setenv "LINUX_MODULE_DIRECTORY"
1288 "/run/booted-system/kernel/lib/modules")
1290 ;; The first one is for udev, the second one for eudev.
1291 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1292 (setenv "EUDEV_RULES_DIRECTORY"
1293 (string-append #$rules "/lib/udev/rules.d"))
1295 (let ((pid (primitive-fork)))
1298 (exec-command (list udevd)))
1300 ;; Wait until udevd is up and running. This
1301 ;; appears to be needed so that the events
1302 ;; triggered below are actually handled.
1305 ;; Trigger device node creation.
1306 (system* (string-append #$udev "/bin/udevadm")
1307 "trigger" "--action=add")
1309 ;; Wait for things to settle down.
1310 (system* (string-append #$udev "/bin/udevadm")
1313 (stop #~(make-kill-destructor))
1315 ;; When halting the system, 'udev' is actually killed by
1316 ;; 'user-processes', i.e., before its own 'stop' method was called.
1317 ;; Thus, make sure it is not respawned.
1320 (define udev-service-type
1321 (service-type (name 'udev)
1323 (list (service-extension shepherd-root-service-type
1324 udev-shepherd-service)))
1326 (compose concatenate) ;concatenate the list of rules
1327 (extend (lambda (config rules)
1329 (($ <udev-configuration> udev initial-rules)
1332 (rules (append initial-rules rules)))))))))
1334 (define* (udev-service #:key (udev eudev) (rules '()))
1335 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
1336 extra rules from the packages listed in @var{rules}."
1337 (service udev-service-type
1338 (udev-configuration (udev udev) (rules rules))))
1340 (define swap-service-type
1341 (shepherd-service-type
1345 (if (string-prefix? "/dev/mapper/" device)
1346 (list (symbol-append 'device-mapping-
1347 (string->symbol (basename device))))
1351 (provision (list (symbol-append 'swap- (string->symbol device))))
1352 (requirement `(udev ,@requirement))
1353 (documentation "Enable the given swap device.")
1355 (restart-on-EINTR (swapon #$device))
1358 (restart-on-EINTR (swapoff #$device))
1362 (define (swap-service device)
1363 "Return a service that uses @var{device} as a swap device."
1364 (service swap-service-type device))
1366 (define-record-type* <gpm-configuration>
1367 gpm-configuration make-gpm-configuration gpm-configuration?
1368 (gpm gpm-configuration-gpm) ;package
1369 (options gpm-configuration-options)) ;list of strings
1371 (define gpm-shepherd-service
1373 (($ <gpm-configuration> gpm options)
1374 (list (shepherd-service
1375 (requirement '(udev))
1378 ;; 'gpm' runs in the background and sets a PID file.
1379 ;; Note that it requires running as "root".
1380 (false-if-exception (delete-file "/var/run/gpm.pid"))
1381 (fork+exec-command (list (string-append #$gpm "/sbin/gpm")
1384 ;; Wait for the PID file to appear; declare failure if
1385 ;; it doesn't show up.
1387 (or (file-exists? "/var/run/gpm.pid")
1395 ;; Return #f if successfully stopped.
1396 (not (zero? (system* (string-append #$gpm "/sbin/gpm")
1399 (define gpm-service-type
1400 (service-type (name 'gpm)
1402 (list (service-extension shepherd-root-service-type
1403 gpm-shepherd-service)))))
1405 (define* (gpm-service #:key (gpm gpm)
1406 (options '("-m" "/dev/input/mice" "-t" "ps2")))
1407 "Run @var{gpm}, the general-purpose mouse daemon, with the given
1408 command-line @var{options}. GPM allows users to use the mouse in the console,
1409 notably to select, copy, and paste text. The default value of @var{options}
1410 uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
1412 This service is not part of @var{%base-services}."
1413 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
1414 ;; "info mice" and "mouse_set X" to use the right mouse.
1415 (service gpm-service-type
1416 (gpm-configuration (gpm gpm) (options options))))
1419 (define %base-services
1420 ;; Convenience variable holding the basic services.
1421 (let ((motd (plain-file "motd" "
1422 This is the GNU operating system, welcome!\n\n")))
1423 (list (console-font-service "tty1")
1424 (console-font-service "tty2")
1425 (console-font-service "tty3")
1426 (console-font-service "tty4")
1427 (console-font-service "tty5")
1428 (console-font-service "tty6")
1430 (mingetty-service (mingetty-configuration
1431 (tty "tty1") (motd motd)))
1432 (mingetty-service (mingetty-configuration
1433 (tty "tty2") (motd motd)))
1434 (mingetty-service (mingetty-configuration
1435 (tty "tty3") (motd motd)))
1436 (mingetty-service (mingetty-configuration
1437 (tty "tty4") (motd motd)))
1438 (mingetty-service (mingetty-configuration
1439 (tty "tty5") (motd motd)))
1440 (mingetty-service (mingetty-configuration
1441 (tty "tty6") (motd motd)))
1443 (static-networking-service "lo" "127.0.0.1"
1444 #:provision '(loopback))
1446 (urandom-seed-service)
1450 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
1451 ;; used, so enable them by default. The FUSE and ALSA rules are
1452 ;; less critical, but handy.
1453 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
1455 ;;; base.scm ends here