services: mingetty-service: Use <mingetty-configuration> objects.
[jackhill/guix/guix.git] / gnu / services / base.scm
CommitLineData
db4fdc04 1;;; GNU Guix --- Functional package management for GNU
4a4dd5d8 2;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
5eca9459 3;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
4307c476 4;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
db4fdc04
LC
5;;;
6;;; This file is part of GNU Guix.
7;;;
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.
12;;;
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.
17;;;
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/>.
20
21(define-module (gnu services base)
e87f0591 22 #:use-module (guix store)
db4fdc04 23 #:use-module (gnu services)
4a3b3b07 24 #:use-module (gnu services networking)
db4fdc04
LC
25 #:use-module (gnu system shadow) ; 'user-account', etc.
26 #:use-module (gnu system linux) ; 'pam-service', etc.
27 #:use-module (gnu packages admin)
151a2c07 28 #:use-module ((gnu packages linux)
68ac258b 29 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda))
db4fdc04 30 #:use-module ((gnu packages base)
bdb36958 31 #:select (canonical-package glibc))
db4fdc04 32 #:use-module (gnu packages package-management)
2d1d2dd8
LC
33 #:use-module (gnu packages lsh)
34 #:use-module (gnu packages lsof)
e2f4b305 35 #:use-module ((gnu build file-systems)
2c071ce9 36 #:select (mount-flags->bit-mask))
b5f4e686 37 #:use-module (guix gexp)
6454b333 38 #:use-module (guix records)
db4fdc04
LC
39 #:use-module (srfi srfi-1)
40 #:use-module (srfi srfi-26)
6454b333 41 #:use-module (ice-9 match)
db4fdc04 42 #:use-module (ice-9 format)
a00dd9fb 43 #:export (root-file-system-service
023f391c 44 file-system-service
d6e2a622 45 user-unmount-service
5dae0186 46 device-mapping-service
2a13d05e 47 swap-service
a00dd9fb
LC
48 user-processes-service
49 host-name-service
5eca9459 50 console-keymap-service
62ca0fdf 51 console-font-service
151a2c07 52 udev-service
66e4f01c
LC
53
54 mingetty-configuration
55 mingetty-configuration?
db4fdc04 56 mingetty-service
6454b333
LC
57
58 %nscd-default-caches
59 %nscd-default-configuration
60
61 nscd-configuration
62 nscd-configuration?
63
64 nscd-cache
65 nscd-cache?
66
db4fdc04
LC
67 nscd-service
68 syslog-service
8b198abe
LC
69 guix-service
70 %base-services))
db4fdc04
LC
71
72;;; Commentary:
73;;;
74;;; Base system services---i.e., services that 99% of the users will want to
75;;; use.
76;;;
77;;; Code:
78
a00dd9fb
LC
79(define (root-file-system-service)
80 "Return a service whose sole purpose is to re-mount read-only the root file
81system upon shutdown (aka. cleanly \"umounting\" root.)
82
83This service must be the root of the service dependency graph so that its
84'stop' action is invoked when dmd is the only process left."
be1c2c54
LC
85 (service
86 (documentation "Take care of the root file system.")
87 (provision '(root-file-system))
88 (start #~(const #t))
89 (stop #~(lambda _
90 ;; Return #f if successfully stopped.
91 (sync)
92
93 (call-with-blocked-asyncs
94 (lambda ()
95 (let ((null (%make-void-port "w")))
96 ;; Close 'dmd.log'.
97 (display "closing log\n")
98 ;; XXX: Ideally we'd use 'stop-logging', but that one
99 ;; doesn't actually close the port as of dmd 0.1.
100 (close-port (@@ (dmd comm) log-output-port))
101 (set! (@@ (dmd comm) log-output-port) null)
102
103 ;; Redirect the default output ports..
104 (set-current-output-port null)
105 (set-current-error-port null)
106
107 ;; Close /dev/console.
108 (for-each close-fdes '(0 1 2))
109
110 ;; At this point, there are no open files left, so the
111 ;; root file system can be re-mounted read-only.
112 (mount #f "/" #f
113 (logior MS_REMOUNT MS_RDONLY)
114 #:update-mtab? #f)
115
116 #f)))))
117 (respawn? #f)))
a00dd9fb 118
023f391c 119(define* (file-system-service device target type
2c071ce9 120 #:key (flags '()) (check? #t)
5dae0186
LC
121 create-mount-point? options (title 'any)
122 (requirements '()))
023f391c 123 "Return a service that mounts DEVICE on TARGET as a file system TYPE with
d4c87617
LC
124OPTIONS. TITLE is a symbol specifying what kind of name DEVICE is: 'label for
125a partition label, 'device for a device file name, or 'any. When CHECK? is
4e469051 126true, check the file system before mounting it. When CREATE-MOUNT-POINT? is
2c071ce9 127true, create TARGET if it does not exist yet. FLAGS is a list of symbols,
5dae0186
LC
128such as 'read-only' etc. Optionally, REQUIREMENTS may be a list of service
129names such as device-mapping services."
be1c2c54
LC
130 (service
131 (provision (list (symbol-append 'file-system- (string->symbol target))))
132 (requirement `(root-file-system ,@requirements))
133 (documentation "Check, mount, and unmount the given file system.")
134 (start #~(lambda args
135 ;; FIXME: Use or factorize with 'mount-file-system'.
136 (let ((device (canonicalize-device-spec #$device '#$title))
137 (flags #$(mount-flags->bit-mask flags)))
138 #$(if create-mount-point?
139 #~(mkdir-p #$target)
140 #~#t)
141 #$(if check?
142 #~(begin
143 ;; Make sure fsck.ext2 & co. can be found.
144 (setenv "PATH"
145 (string-append
146 #$e2fsprogs "/sbin:"
147 "/run/current-system/profile/sbin:"
148 (getenv "PATH")))
149 (check-file-system device #$type))
150 #~#t)
151
152 (mount device #$target #$type flags #$options)
153
154 ;; For read-only bind mounts, an extra remount is needed,
155 ;; as per <http://lwn.net/Articles/281157/>, which still
156 ;; applies to Linux 4.0.
157 (when (and (= MS_BIND (logand flags MS_BIND))
158 (= MS_RDONLY (logand flags MS_RDONLY)))
159 (mount device #$target #$type
160 (logior MS_BIND MS_REMOUNT MS_RDONLY))))
161 #t))
162 (stop #~(lambda args
163 ;; Normally there are no processes left at this point, so
164 ;; TARGET can be safely unmounted.
165
166 ;; Make sure PID 1 doesn't keep TARGET busy.
167 (chdir "/")
168
169 (umount #$target)
170 #f))))
023f391c 171
d6e2a622
LC
172(define (user-unmount-service known-mount-points)
173 "Return a service whose sole purpose is to unmount file systems not listed
174in KNOWN-MOUNT-POINTS when it is stopped."
be1c2c54
LC
175 (service
176 (documentation "Unmount manually-mounted file systems.")
177 (provision '(user-unmount))
178 (start #~(const #t))
179 (stop #~(lambda args
180 (define (known? mount-point)
181 (member mount-point
182 (cons* "/proc" "/sys"
183 '#$known-mount-points)))
184
185 ;; Make sure we don't keep the user's mount points busy.
186 (chdir "/")
187
188 (for-each (lambda (mount-point)
189 (format #t "unmounting '~a'...~%" mount-point)
190 (catch 'system-error
191 (lambda ()
192 (umount mount-point))
193 (lambda args
194 (let ((errno (system-error-errno args)))
195 (format #t "failed to unmount '~a': ~a~%"
196 mount-point (strerror errno))))))
197 (filter (negate known?) (mount-points)))
198 #f))))
d6e2a622 199
7d57cfd3
LC
200(define %do-not-kill-file
201 ;; Name of the file listing PIDs of processes that must survive when halting
202 ;; the system. Typical example is user-space file systems.
203 "/etc/dmd/do-not-kill")
204
7bed4df4 205(define* (user-processes-service requirements #:key (grace-delay 4))
a00dd9fb
LC
206 "Return the service that is responsible for terminating all the processes so
207that the root file system can be re-mounted read-only, just before
208rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
209has been sent are terminated with SIGKILL.
210
023f391c
LC
211The returned service will depend on 'root-file-system' and on all the services
212listed in REQUIREMENTS.
213
a00dd9fb
LC
214All the services that spawn processes must depend on this one so that they are
215stopped before 'kill' is called."
be1c2c54
LC
216 (service
217 (documentation "When stopped, terminate all user processes.")
218 (provision '(user-processes))
219 (requirement (cons 'root-file-system requirements))
220 (start #~(const #t))
221 (stop #~(lambda _
222 (define (kill-except omit signal)
223 ;; Kill all the processes with SIGNAL except those
224 ;; listed in OMIT and the current process.
225 (let ((omit (cons (getpid) omit)))
226 (for-each (lambda (pid)
227 (unless (memv pid omit)
228 (false-if-exception
229 (kill pid signal))))
230 (processes))))
231
232 (define omitted-pids
233 ;; List of PIDs that must not be killed.
234 (if (file-exists? #$%do-not-kill-file)
235 (map string->number
236 (call-with-input-file #$%do-not-kill-file
237 (compose string-tokenize
238 (@ (ice-9 rdelim) read-string))))
239 '()))
240
241 (define (now)
242 (car (gettimeofday)))
243
244 (define (sleep* n)
245 ;; Really sleep N seconds.
246 ;; Work around <http://bugs.gnu.org/19581>.
247 (define start (now))
248 (let loop ((elapsed 0))
249 (when (> n elapsed)
250 (sleep (- n elapsed))
251 (loop (- (now) start)))))
252
253 (define lset= (@ (srfi srfi-1) lset=))
254
255 (display "sending all processes the TERM signal\n")
256
257 (if (null? omitted-pids)
258 (begin
259 ;; Easy: terminate all of them.
260 (kill -1 SIGTERM)
261 (sleep* #$grace-delay)
262 (kill -1 SIGKILL))
263 (begin
264 ;; Kill them all except OMITTED-PIDS. XXX: We
265 ;; would like to (kill -1 SIGSTOP) to get a fixed
266 ;; list of processes, like 'killall5' does, but
267 ;; that seems unreliable.
268 (kill-except omitted-pids SIGTERM)
269 (sleep* #$grace-delay)
270 (kill-except omitted-pids SIGKILL)
271 (delete-file #$%do-not-kill-file)))
272
273 (let wait ()
274 (let ((pids (processes)))
275 (unless (lset= = pids (cons 1 omitted-pids))
276 (format #t "waiting for process termination\
d656c14e 277 (processes left: ~s)~%"
be1c2c54
LC
278 pids)
279 (sleep* 2)
280 (wait))))
d656c14e 281
be1c2c54
LC
282 (display "all processes have been terminated\n")
283 #f))
284 (respawn? #f)))
a00dd9fb 285
db4fdc04 286(define (host-name-service name)
51da7ca0 287 "Return a service that sets the host name to @var{name}."
be1c2c54
LC
288 (service
289 (documentation "Initialize the machine's host name.")
290 (provision '(host-name))
291 (start #~(lambda _
292 (sethostname #$name)))
293 (respawn? #f)))
db4fdc04 294
62ca0fdf
LC
295(define (unicode-start tty)
296 "Return a gexp to start Unicode support on @var{tty}."
297
298 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
299 ;; 'tty' command, that command returns TTY.
300 #~(begin
301 (let ((pid (primitive-fork)))
302 (case pid
303 ((0)
304 (close-fdes 0)
305 (dup2 (open-fdes #$tty O_RDONLY) 0)
306 (close-fdes 1)
307 (dup2 (open-fdes #$tty O_WRONLY) 1)
308 (execl (string-append #$kbd "/bin/unicode_start")
309 "unicode_start"))
310 (else
311 (zero? (cdr (waitpid pid))))))))
312
5eca9459
AK
313(define (console-keymap-service file)
314 "Return a service to load console keymap from @var{file}."
be1c2c54
LC
315 (service
316 (documentation (string-append "Load console keymap (loadkeys)."))
317 (provision '(console-keymap))
318 (start #~(lambda _
319 (zero? (system* (string-append #$kbd "/bin/loadkeys")
320 #$file))))
321 (respawn? #f)))
5eca9459 322
62ca0fdf
LC
323(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
324 "Return a service that sets up Unicode support in @var{tty} and loads
325@var{font} for that tty (fonts are per virtual console in Linux.)"
326 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
327 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
328 ;; codepoints notably found in the UTF-8 manual.
329 (let ((device (string-append "/dev/" tty)))
be1c2c54
LC
330 (service
331 (documentation "Load a Unicode console font.")
332 (provision (list (symbol-append 'console-font-
333 (string->symbol tty))))
334
335 ;; Start after mingetty has been started on TTY, otherwise the
336 ;; settings are ignored.
337 (requirement (list (symbol-append 'term-
338 (string->symbol tty))))
339
340 (start #~(lambda _
341 (and #$(unicode-start device)
342 (zero?
343 (system* (string-append #$kbd "/bin/setfont")
344 "-C" #$device #$font)))))
345 (stop #~(const #t))
346 (respawn? #f))))
62ca0fdf 347
66e4f01c
LC
348(define-record-type* <mingetty-configuration>
349 mingetty-configuration make-mingetty-configuration
350 mingetty-configuration?
351 (mingetty mingetty-configuration-mingetty ;<package>
352 (default mingetty))
353 (tty mingetty-configuration-tty) ;string
354 (motd mingetty-configuration-motd ;file-like
355 (default (plain-file "motd" "Welcome.\n")))
356 (auto-login mingetty-auto-login ;string | #f
357 (default #f))
358 (login-program mingetty-login-program ;gexp
359 (default #f))
360 (login-pause? mingetty-login-pause? ;Boolean
361 (default #f))
362
363 ;; Allow empty passwords by default so that first-time users can log in when
364 ;; the 'root' account has just been created.
365 (allow-empty-passwords? mingetty-configuration-allow-empty-passwords?
366 (default #t))) ;Boolean
367
368(define* (mingetty-service config)
369 "Return a service to run mingetty according to @var{config}, a
370@code{<mingetty-configuration>} object, which specifies the tty to run, among
371other things."
372 (match config
373 (($ <mingetty-configuration> mingetty tty motd auto-login login-program
374 login-pause? allow-empty-passwords?)
375 (service
376 (documentation "Run mingetty on an tty.")
377 (provision (list (symbol-append 'term- (string->symbol tty))))
378
379 ;; Since the login prompt shows the host name, wait for the 'host-name'
380 ;; service to be done. Also wait for udev essentially so that the tty
381 ;; text is not lost in the middle of kernel messages (XXX).
382 (requirement '(user-processes host-name udev))
383
384 (start #~(make-forkexec-constructor
385 (list (string-append #$mingetty "/sbin/mingetty")
386 "--noclear" #$tty
387 #$@(if auto-login
388 #~("--autologin" #$auto-login)
389 #~())
390 #$@(if login-program
391 #~("--loginprog" #$login-program)
392 #~())
393 #$@(if login-pause?
394 #~("--loginpause")
395 #~()))))
396 (stop #~(make-kill-destructor))
397
398 (pam-services
399 ;; Let 'login' be known to PAM. All the mingetty services will have
400 ;; that PAM service, but that's fine because they're all identical and
401 ;; duplicates are removed.
402 (list (unix-pam-service "login"
403 #:allow-empty-passwords? allow-empty-passwords?
404 #:motd motd)))))))
db4fdc04 405
6454b333
LC
406(define-record-type* <nscd-configuration> nscd-configuration
407 make-nscd-configuration
408 nscd-configuration?
409 (log-file nscd-configuration-log-file ;string
410 (default "/var/log/nscd.log"))
411 (debug-level nscd-debug-level ;integer
412 (default 0))
413 ;; TODO: See nscd.conf in glibc for other options to add.
414 (caches nscd-configuration-caches ;list of <nscd-cache>
415 (default %nscd-default-caches)))
416
417(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
418 nscd-cache?
419 (database nscd-cache-database) ;symbol
420 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
421 (negative-time-to-live nscd-cache-negative-time-to-live
422 (default 20)) ;integer
423 (suggested-size nscd-cache-suggested-size ;integer ("default module
424 ;of hash table")
425 (default 211))
426 (check-files? nscd-cache-check-files? ;Boolean
427 (default #t))
428 (persistent? nscd-cache-persistent? ;Boolean
429 (default #t))
430 (shared? nscd-cache-shared? ;Boolean
431 (default #t))
432 (max-database-size nscd-cache-max-database-size ;integer
433 (default (* 32 (expt 2 20))))
434 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
435 (default #t)))
436
437(define %nscd-default-caches
438 ;; Caches that we want to enable by default. Note that when providing an
439 ;; empty nscd.conf, all caches are disabled.
440 (list (nscd-cache (database 'hosts)
441
442 ;; Aggressively cache the host name cache to improve
443 ;; privacy and resilience.
444 (positive-time-to-live (* 3600 12))
445 (negative-time-to-live 20)
446 (persistent? #t))
447
448 (nscd-cache (database 'services)
449
450 ;; Services are unlikely to change, so we can be even more
451 ;; aggressive.
452 (positive-time-to-live (* 3600 24))
453 (negative-time-to-live 3600)
454 (check-files? #t) ;check /etc/services changes
455 (persistent? #t))))
456
457(define %nscd-default-configuration
458 ;; Default nscd configuration.
459 (nscd-configuration))
460
461(define (nscd.conf-file config)
462 "Return the @file{nscd.conf} configuration file for @var{config}, an
463@code{<nscd-configuration>} object."
464 (define cache->config
465 (match-lambda
be1c2c54
LC
466 (($ <nscd-cache> (= symbol->string database)
467 positive-ttl negative-ttl size check-files?
468 persistent? shared? max-size propagate?)
469 (string-append "\nenable-cache\t" database "\tyes\n"
470
471 "positive-time-to-live\t" database "\t"
472 (number->string positive-ttl) "\n"
473 "negative-time-to-live\t" database "\t"
474 (number->string negative-ttl) "\n"
475 "suggested-size\t" database "\t"
476 (number->string size) "\n"
477 "check-files\t" database "\t"
478 (if check-files? "yes\n" "no\n")
479 "persistent\t" database "\t"
480 (if persistent? "yes\n" "no\n")
481 "shared\t" database "\t"
482 (if shared? "yes\n" "no\n")
483 "max-db-size\t" database "\t"
484 (number->string max-size) "\n"
485 "auto-propagate\t" database "\t"
486 (if propagate? "yes\n" "no\n")))))
6454b333
LC
487
488 (match config
489 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
490 (plain-file "nscd.conf"
491 (string-append "\
6454b333 492# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
493 (if log-file
494 (string-append "logfile\t" log-file)
495 "")
496 "\n"
497 (if debug-level
498 (string-append "debug-level\t"
499 (number->string debug-level))
500 "")
501 "\n"
502 (string-concatenate
503 (map cache->config caches)))))))
6454b333
LC
504
505(define* (nscd-service #:optional (config %nscd-default-configuration)
4aee6e60
LC
506 #:key (glibc (canonical-package glibc))
507 (name-services '()))
6454b333 508 "Return a service that runs libc's name service cache daemon (nscd) with the
4aee6e60
LC
509given @var{config}---an @code{<nscd-configuration>} object. Optionally,
510@code{#:name-services} is a list of packages that provide name service switch
4c9050c6 511 (NSS) modules needed by nscd. @xref{Name Service Switch}, for an example."
be1c2c54
LC
512 (let ((nscd.conf (nscd.conf-file config)))
513 (service
514 (documentation "Run libc's name service cache daemon (nscd).")
515 (provision '(nscd))
516 (requirement '(user-processes))
517
518 (activate #~(begin
519 (use-modules (guix build utils))
520 (mkdir-p "/var/run/nscd")
521 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
522
523 (start #~(make-forkexec-constructor
524 (list (string-append #$glibc "/sbin/nscd")
525 "-f" #$nscd.conf "--foreground")
526
527 #:environment-variables
528 (list (string-append "LD_LIBRARY_PATH="
529 (string-join
530 (map (lambda (dir)
531 (string-append dir "/lib"))
532 (list #$@name-services))
533 ":")))))
534 (stop #~(make-kill-destructor))
535
536 (respawn? #f))))
537
538;; Snippet adapted from the GNU inetutils manual.
539(define %default-syslog.conf
540 (plain-file "syslog.conf" "
1f3fc60d 541 # Log all error messages, authentication messages of
db4fdc04
LC
542 # level notice or higher and anything of level err or
543 # higher to the console.
544 # Don't log private authentication messages!
6a191274 545 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
546
547 # Log anything (except mail) of level info or higher.
548 # Don't log private authentication messages!
549 *.info;mail.none;authpriv.none /var/log/messages
550
551 # Same, in a different place.
552 *.info;mail.none;authpriv.none /dev/tty12
553
554 # The authpriv file has restricted access.
555 authpriv.* /var/log/secure
556
557 # Log all the mail messages in one place.
558 mail.* /var/log/maillog
be1c2c54
LC
559"))
560(define* (syslog-service #:key (config-file %default-syslog.conf))
561 "Return a service that runs @code{syslogd}.
562If configuration file name @var{config-file} is not specified, use some
563reasonable default settings."
564 (service
565 (documentation "Run the syslog daemon (syslogd).")
566 (provision '(syslogd))
567 (requirement '(user-processes))
568 (start #~(make-forkexec-constructor
569 (list (string-append #$inetutils "/libexec/syslogd")
570 "--no-detach" "--rcfile" #$config-file)))
571 (stop #~(make-kill-destructor))))
db4fdc04
LC
572
573(define* (guix-build-accounts count #:key
ab6a279a 574 (group "guixbuild")
db4fdc04 575 (first-uid 30001)
db4fdc04
LC
576 (shadow shadow))
577 "Return a list of COUNT user accounts for Guix build users, with UIDs
578starting at FIRST-UID, and under GID."
5250a4f2
LC
579 (unfold (cut > <> count)
580 (lambda (n)
581 (user-account
582 (name (format #f "guixbuilder~2,'0d" n))
583 (system? #t)
584 (uid (+ first-uid n -1))
585 (group group)
586
587 ;; guix-daemon expects GROUP to be listed as a
588 ;; supplementary group too:
589 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
590 (supplementary-groups (list group "kvm"))
591
592 (comment (format #f "Guix Build User ~2d" n))
593 (home-directory "/var/empty")
594 (shell #~(string-append #$shadow "/sbin/nologin"))))
595 1+
596 1))
db4fdc04 597
2c5c696c
LC
598(define (hydra-key-authorization guix)
599 "Return a gexp with code to register the hydra.gnu.org public key with
600GUIX."
601 #~(unless (file-exists? "/etc/guix/acl")
602 (let ((pid (primitive-fork)))
603 (case pid
604 ((0)
605 (let* ((key (string-append #$guix
606 "/share/guix/hydra.gnu.org.pub"))
607 (port (open-file key "r0b")))
608 (format #t "registering public key '~a'...~%" key)
609 (close-port (current-input-port))
2c5c696c
LC
610 (dup port 0)
611 (execl (string-append #$guix "/bin/guix")
612 "guix" "archive" "--authorize")
613 (exit 1)))
614 (else
615 (let ((status (cdr (waitpid pid))))
616 (unless (zero? status)
617 (format (current-error-port) "warning: \
618failed to register hydra.gnu.org public key: ~a~%" status))))))))
619
db4fdc04 620(define* (guix-service #:key (guix guix) (builder-group "guixbuild")
02bb6b45 621 (build-accounts 10) (authorize-hydra-key? #t)
c11a6eb1 622 (use-substitutes? #t)
2d1d2dd8
LC
623 (extra-options '())
624 (lsof lsof) (lsh lsh))
51da7ca0
LC
625 "Return a service that runs the build daemon from @var{guix}, and has
626@var{build-accounts} user accounts available under @var{builder-group}.
2c5c696c 627
51da7ca0
LC
628When @var{authorize-hydra-key?} is true, the @code{hydra.gnu.org} public key
629provided by @var{guix} is authorized upon activation, meaning that substitutes
c11a6eb1
LC
630from @code{hydra.gnu.org} are used by default.
631
632If @var{use-substitutes?} is false, the daemon is run with
633@option{--no-substitutes} (@pxref{Invoking guix-daemon,
634@option{--no-substitutes}}).
635
636Finally, @var{extra-options} is a list of additional command-line options
637passed to @command{guix-daemon}."
185f6691 638 (define activate
e97c5be9
LC
639 ;; Assume that the store has BUILDER-GROUP as its group. We could
640 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
641 ;; chown leads to an entire copy of the tree, which is a bad idea.
185f6691 642
e97c5be9
LC
643 ;; Optionally authorize hydra.gnu.org's key.
644 (and authorize-hydra-key?
645 (hydra-key-authorization guix)))
185f6691 646
be1c2c54
LC
647 (service
648 (documentation "Run the Guix daemon.")
649 (provision '(guix-daemon))
650 (requirement '(user-processes))
651 (start
652 #~(make-forkexec-constructor
653 (list (string-append #$guix "/bin/guix-daemon")
654 "--build-users-group" #$builder-group
655 #$@(if use-substitutes?
656 '()
657 '("--no-substitutes"))
658 #$@extra-options)
659
660 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
661 ;; daemon's $PATH.
662 #:environment-variables
663 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
664 (stop #~(make-kill-destructor))
665 (user-accounts (guix-build-accounts build-accounts
666 #:group builder-group))
667 (user-groups (list (user-group
668 (name builder-group)
669 (system? #t)
670
671 ;; Use a fixed GID so that we can create the
672 ;; store with the right owner.
673 (id 30000))))
674 (activate activate)))
db4fdc04 675
ecd06ca9
LC
676(define (udev-rules-union packages)
677 "Return the union of the @code{lib/udev/rules.d} directories found in each
678item of @var{packages}."
679 (define build
680 #~(begin
681 (use-modules (guix build union)
682 (guix build utils)
683 (srfi srfi-1)
684 (srfi srfi-26))
685
686 (define %standard-locations
687 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
688
689 (define (rules-sub-directory directory)
690 ;; Return the sub-directory of DIRECTORY containing udev rules, or
691 ;; #f if none was found.
692 (find directory-exists?
693 (map (cut string-append directory <>) %standard-locations)))
694
695 (mkdir-p (string-append #$output "/lib/udev"))
696 (union-build (string-append #$output "/lib/udev/rules.d")
697 (filter-map rules-sub-directory '#$packages))))
698
be1c2c54
LC
699 (computed-file "udev-rules" build
700 #:modules '((guix build union)
701 (guix build utils))))
ecd06ca9 702
7f28bf9a
LC
703(define* (kvm-udev-rule)
704 "Return a directory with a udev rule that changes the group of
705@file{/dev/kvm} to \"kvm\" and makes it #o660."
706 ;; Apparently QEMU-KVM used to ship this rule, but now we have to add it by
707 ;; ourselves.
be1c2c54
LC
708 (computed-file "kvm-udev-rules"
709 #~(begin
710 (use-modules (guix build utils))
711
712 (define rules.d
713 (string-append #$output "/lib/udev/rules.d"))
714
715 (mkdir-p rules.d)
716 (call-with-output-file
717 (string-append rules.d "/90-kvm.rules")
718 (lambda (port)
719 ;; Build users are part of the "kvm" group, so we
720 ;; can fearlessly make /dev/kvm 660 (see
721 ;; <http://bugs.gnu.org/18994>, for background.)
722 (display "\
64720891 723KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n" port))))
be1c2c54 724 #:modules '((guix build utils))))
7f28bf9a 725
8a7330fd 726(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
727 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
728extra rules from the packages listed in @var{rules}."
be1c2c54
LC
729 (let* ((rules (udev-rules-union (cons* udev
730 (kvm-udev-rule)
731 rules)))
732 (udev.conf (computed-file "udev.conf"
733 #~(call-with-output-file #$output
734 (lambda (port)
735 (format port
736 "udev_rules=\"~a/lib/udev/rules.d\"\n"
737 #$rules))))))
738 (service
739 (provision '(udev))
740
741 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
742 ;; be added: see
743 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
744 (requirement '(root-file-system))
745
746 (documentation "Populate the /dev directory, dynamically.")
747 (start #~(lambda ()
748 (define find
749 (@ (srfi srfi-1) find))
750
751 (define udevd
752 ;; Choose the right 'udevd'.
753 (find file-exists?
754 (map (lambda (suffix)
755 (string-append #$udev suffix))
756 '("/libexec/udev/udevd" ;udev
757 "/sbin/udevd")))) ;eudev
758
759 (define (wait-for-udevd)
760 ;; Wait until someone's listening on udevd's control
761 ;; socket.
762 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
763 (let try ()
764 (catch 'system-error
765 (lambda ()
766 (connect sock PF_UNIX "/run/udev/control")
767 (close-port sock))
768 (lambda args
769 (format #t "waiting for udevd...~%")
770 (usleep 500000)
771 (try))))))
772
773 ;; Allow udev to find the modules.
774 (setenv "LINUX_MODULE_DIRECTORY"
775 "/run/booted-system/kernel/lib/modules")
776
777 ;; The first one is for udev, the second one for eudev.
778 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
779 (setenv "EUDEV_RULES_DIRECTORY"
780 (string-append #$rules "/lib/udev/rules.d"))
781
782 (let ((pid (primitive-fork)))
783 (case pid
784 ((0)
785 (exec-command (list udevd)))
786 (else
787 ;; Wait until udevd is up and running. This
788 ;; appears to be needed so that the events
789 ;; triggered below are actually handled.
790 (wait-for-udevd)
791
792 ;; Trigger device node creation.
793 (system* (string-append #$udev "/bin/udevadm")
794 "trigger" "--action=add")
795
796 ;; Wait for things to settle down.
797 (system* (string-append #$udev "/bin/udevadm")
798 "settle")
799 pid)))))
800 (stop #~(make-kill-destructor))
801
802 ;; When halting the system, 'udev' is actually killed by
803 ;; 'user-processes', i.e., before its own 'stop' method was
804 ;; called. Thus, make sure it is not respawned.
805 (respawn? #f))))
151a2c07 806
722554a3 807(define (device-mapping-service target open close)
5dae0186 808 "Return a service that maps device @var{target}, a string such as
722554a3
LC
809@code{\"home\"} (meaning @code{/dev/mapper/home}). Evaluate @var{open}, a
810gexp, to open it, and evaluate @var{close} to close it."
be1c2c54
LC
811 (service
812 (provision (list (symbol-append 'device-mapping- (string->symbol target))))
813 (requirement '(udev))
814 (documentation "Map a device node using Linux's device mapper.")
815 (start #~(lambda () #$open))
816 (stop #~(lambda _ (not #$close)))
817 (respawn? #f)))
5dae0186 818
2a13d05e
LC
819(define (swap-service device)
820 "Return a service that uses @var{device} as a swap device."
821 (define requirement
822 (if (string-prefix? "/dev/mapper/" device)
823 (list (symbol-append 'device-mapping-
824 (string->symbol (basename device))))
825 '()))
826
be1c2c54
LC
827 (service
828 (provision (list (symbol-append 'swap- (string->symbol device))))
829 (requirement `(udev ,@requirement))
830 (documentation "Enable the given swap device.")
831 (start #~(lambda ()
832 (restart-on-EINTR (swapon #$device))
833 #t))
834 (stop #~(lambda _
835 (restart-on-EINTR (swapoff #$device))
836 #f))
837 (respawn? #f)))
2a13d05e 838
8b198abe
LC
839(define %base-services
840 ;; Convenience variable holding the basic services.
ce8a6dfc 841 (let ((motd (plain-file "motd" "
8b198abe 842This is the GNU operating system, welcome!\n\n")))
62ca0fdf
LC
843 (list (console-font-service "tty1")
844 (console-font-service "tty2")
845 (console-font-service "tty3")
846 (console-font-service "tty4")
847 (console-font-service "tty5")
848 (console-font-service "tty6")
849
66e4f01c
LC
850 (mingetty-service (mingetty-configuration
851 (tty "tty1") (motd motd)))
852 (mingetty-service (mingetty-configuration
853 (tty "tty2") (motd motd)))
854 (mingetty-service (mingetty-configuration
855 (tty "tty3") (motd motd)))
856 (mingetty-service (mingetty-configuration
857 (tty "tty4") (motd motd)))
858 (mingetty-service (mingetty-configuration
859 (tty "tty5") (motd motd)))
860 (mingetty-service (mingetty-configuration
861 (tty "tty6") (motd motd)))
862
4a3b3b07
LC
863 (static-networking-service "lo" "127.0.0.1"
864 #:provision '(loopback))
8b198abe
LC
865 (syslog-service)
866 (guix-service)
151a2c07 867 (nscd-service)
ecd06ca9 868
52bd5734
LC
869 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
870 ;; used, so enable them by default. The FUSE and ALSA rules are
871 ;; less critical, but handy.
4307c476
MW
872 ;;
873 ;; XXX Keep this in sync with the 'udev-service' call in
874 ;; %desktop-services.
68ac258b 875 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
8b198abe 876
db4fdc04 877;;; base.scm ends here