system: Account skeleton API is non-monadic.
[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>
b893f1ae
LC
415 (default %nscd-default-caches))
416 (name-services nscd-configuration-name-services ;list of <packages>
417 (default '()))
418 (glibc nscd-configuration-glibc ;<package>
419 (default (canonical-package glibc))))
6454b333
LC
420
421(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
422 nscd-cache?
423 (database nscd-cache-database) ;symbol
424 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
425 (negative-time-to-live nscd-cache-negative-time-to-live
426 (default 20)) ;integer
427 (suggested-size nscd-cache-suggested-size ;integer ("default module
428 ;of hash table")
429 (default 211))
430 (check-files? nscd-cache-check-files? ;Boolean
431 (default #t))
432 (persistent? nscd-cache-persistent? ;Boolean
433 (default #t))
434 (shared? nscd-cache-shared? ;Boolean
435 (default #t))
436 (max-database-size nscd-cache-max-database-size ;integer
437 (default (* 32 (expt 2 20))))
438 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
439 (default #t)))
440
441(define %nscd-default-caches
442 ;; Caches that we want to enable by default. Note that when providing an
443 ;; empty nscd.conf, all caches are disabled.
444 (list (nscd-cache (database 'hosts)
445
446 ;; Aggressively cache the host name cache to improve
447 ;; privacy and resilience.
448 (positive-time-to-live (* 3600 12))
449 (negative-time-to-live 20)
450 (persistent? #t))
451
452 (nscd-cache (database 'services)
453
454 ;; Services are unlikely to change, so we can be even more
455 ;; aggressive.
456 (positive-time-to-live (* 3600 24))
457 (negative-time-to-live 3600)
458 (check-files? #t) ;check /etc/services changes
459 (persistent? #t))))
460
461(define %nscd-default-configuration
462 ;; Default nscd configuration.
463 (nscd-configuration))
464
465(define (nscd.conf-file config)
466 "Return the @file{nscd.conf} configuration file for @var{config}, an
467@code{<nscd-configuration>} object."
468 (define cache->config
469 (match-lambda
be1c2c54
LC
470 (($ <nscd-cache> (= symbol->string database)
471 positive-ttl negative-ttl size check-files?
472 persistent? shared? max-size propagate?)
473 (string-append "\nenable-cache\t" database "\tyes\n"
474
475 "positive-time-to-live\t" database "\t"
476 (number->string positive-ttl) "\n"
477 "negative-time-to-live\t" database "\t"
478 (number->string negative-ttl) "\n"
479 "suggested-size\t" database "\t"
480 (number->string size) "\n"
481 "check-files\t" database "\t"
482 (if check-files? "yes\n" "no\n")
483 "persistent\t" database "\t"
484 (if persistent? "yes\n" "no\n")
485 "shared\t" database "\t"
486 (if shared? "yes\n" "no\n")
487 "max-db-size\t" database "\t"
488 (number->string max-size) "\n"
489 "auto-propagate\t" database "\t"
490 (if propagate? "yes\n" "no\n")))))
6454b333
LC
491
492 (match config
493 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
494 (plain-file "nscd.conf"
495 (string-append "\
6454b333 496# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
497 (if log-file
498 (string-append "logfile\t" log-file)
499 "")
500 "\n"
501 (if debug-level
502 (string-append "debug-level\t"
503 (number->string debug-level))
504 "")
505 "\n"
506 (string-concatenate
507 (map cache->config caches)))))))
6454b333 508
b893f1ae 509(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 510 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
511given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
512Service Switch}, for an example."
be1c2c54
LC
513 (let ((nscd.conf (nscd.conf-file config)))
514 (service
515 (documentation "Run libc's name service cache daemon (nscd).")
516 (provision '(nscd))
517 (requirement '(user-processes))
518
519 (activate #~(begin
520 (use-modules (guix build utils))
521 (mkdir-p "/var/run/nscd")
522 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
523
524 (start #~(make-forkexec-constructor
b893f1ae
LC
525 (list (string-append #$(nscd-configuration-glibc config)
526 "/sbin/nscd")
be1c2c54
LC
527 "-f" #$nscd.conf "--foreground")
528
529 #:environment-variables
530 (list (string-append "LD_LIBRARY_PATH="
531 (string-join
532 (map (lambda (dir)
533 (string-append dir "/lib"))
b893f1ae
LC
534 (list
535 #$@(nscd-configuration-name-services
536 config)))
be1c2c54
LC
537 ":")))))
538 (stop #~(make-kill-destructor))
539
540 (respawn? #f))))
541
542;; Snippet adapted from the GNU inetutils manual.
543(define %default-syslog.conf
544 (plain-file "syslog.conf" "
1f3fc60d 545 # Log all error messages, authentication messages of
db4fdc04
LC
546 # level notice or higher and anything of level err or
547 # higher to the console.
548 # Don't log private authentication messages!
6a191274 549 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
550
551 # Log anything (except mail) of level info or higher.
552 # Don't log private authentication messages!
553 *.info;mail.none;authpriv.none /var/log/messages
554
555 # Same, in a different place.
556 *.info;mail.none;authpriv.none /dev/tty12
557
558 # The authpriv file has restricted access.
559 authpriv.* /var/log/secure
560
561 # Log all the mail messages in one place.
562 mail.* /var/log/maillog
be1c2c54
LC
563"))
564(define* (syslog-service #:key (config-file %default-syslog.conf))
565 "Return a service that runs @code{syslogd}.
566If configuration file name @var{config-file} is not specified, use some
567reasonable default settings."
568 (service
569 (documentation "Run the syslog daemon (syslogd).")
570 (provision '(syslogd))
571 (requirement '(user-processes))
572 (start #~(make-forkexec-constructor
573 (list (string-append #$inetutils "/libexec/syslogd")
574 "--no-detach" "--rcfile" #$config-file)))
575 (stop #~(make-kill-destructor))))
db4fdc04
LC
576
577(define* (guix-build-accounts count #:key
ab6a279a 578 (group "guixbuild")
db4fdc04 579 (first-uid 30001)
db4fdc04
LC
580 (shadow shadow))
581 "Return a list of COUNT user accounts for Guix build users, with UIDs
582starting at FIRST-UID, and under GID."
5250a4f2
LC
583 (unfold (cut > <> count)
584 (lambda (n)
585 (user-account
586 (name (format #f "guixbuilder~2,'0d" n))
587 (system? #t)
588 (uid (+ first-uid n -1))
589 (group group)
590
591 ;; guix-daemon expects GROUP to be listed as a
592 ;; supplementary group too:
593 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
594 (supplementary-groups (list group "kvm"))
595
596 (comment (format #f "Guix Build User ~2d" n))
597 (home-directory "/var/empty")
598 (shell #~(string-append #$shadow "/sbin/nologin"))))
599 1+
600 1))
db4fdc04 601
2c5c696c
LC
602(define (hydra-key-authorization guix)
603 "Return a gexp with code to register the hydra.gnu.org public key with
604GUIX."
605 #~(unless (file-exists? "/etc/guix/acl")
606 (let ((pid (primitive-fork)))
607 (case pid
608 ((0)
609 (let* ((key (string-append #$guix
610 "/share/guix/hydra.gnu.org.pub"))
611 (port (open-file key "r0b")))
612 (format #t "registering public key '~a'...~%" key)
613 (close-port (current-input-port))
2c5c696c
LC
614 (dup port 0)
615 (execl (string-append #$guix "/bin/guix")
616 "guix" "archive" "--authorize")
617 (exit 1)))
618 (else
619 (let ((status (cdr (waitpid pid))))
620 (unless (zero? status)
621 (format (current-error-port) "warning: \
622failed to register hydra.gnu.org public key: ~a~%" status))))))))
623
db4fdc04 624(define* (guix-service #:key (guix guix) (builder-group "guixbuild")
02bb6b45 625 (build-accounts 10) (authorize-hydra-key? #t)
c11a6eb1 626 (use-substitutes? #t)
2d1d2dd8
LC
627 (extra-options '())
628 (lsof lsof) (lsh lsh))
51da7ca0
LC
629 "Return a service that runs the build daemon from @var{guix}, and has
630@var{build-accounts} user accounts available under @var{builder-group}.
2c5c696c 631
51da7ca0
LC
632When @var{authorize-hydra-key?} is true, the @code{hydra.gnu.org} public key
633provided by @var{guix} is authorized upon activation, meaning that substitutes
c11a6eb1
LC
634from @code{hydra.gnu.org} are used by default.
635
636If @var{use-substitutes?} is false, the daemon is run with
637@option{--no-substitutes} (@pxref{Invoking guix-daemon,
638@option{--no-substitutes}}).
639
640Finally, @var{extra-options} is a list of additional command-line options
641passed to @command{guix-daemon}."
185f6691 642 (define activate
e97c5be9
LC
643 ;; Assume that the store has BUILDER-GROUP as its group. We could
644 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
645 ;; chown leads to an entire copy of the tree, which is a bad idea.
185f6691 646
e97c5be9
LC
647 ;; Optionally authorize hydra.gnu.org's key.
648 (and authorize-hydra-key?
649 (hydra-key-authorization guix)))
185f6691 650
be1c2c54
LC
651 (service
652 (documentation "Run the Guix daemon.")
653 (provision '(guix-daemon))
654 (requirement '(user-processes))
655 (start
656 #~(make-forkexec-constructor
657 (list (string-append #$guix "/bin/guix-daemon")
658 "--build-users-group" #$builder-group
659 #$@(if use-substitutes?
660 '()
661 '("--no-substitutes"))
662 #$@extra-options)
663
664 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
665 ;; daemon's $PATH.
666 #:environment-variables
667 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
668 (stop #~(make-kill-destructor))
669 (user-accounts (guix-build-accounts build-accounts
670 #:group builder-group))
671 (user-groups (list (user-group
672 (name builder-group)
673 (system? #t)
674
675 ;; Use a fixed GID so that we can create the
676 ;; store with the right owner.
677 (id 30000))))
678 (activate activate)))
db4fdc04 679
ecd06ca9
LC
680(define (udev-rules-union packages)
681 "Return the union of the @code{lib/udev/rules.d} directories found in each
682item of @var{packages}."
683 (define build
684 #~(begin
685 (use-modules (guix build union)
686 (guix build utils)
687 (srfi srfi-1)
688 (srfi srfi-26))
689
690 (define %standard-locations
691 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
692
693 (define (rules-sub-directory directory)
694 ;; Return the sub-directory of DIRECTORY containing udev rules, or
695 ;; #f if none was found.
696 (find directory-exists?
697 (map (cut string-append directory <>) %standard-locations)))
698
699 (mkdir-p (string-append #$output "/lib/udev"))
700 (union-build (string-append #$output "/lib/udev/rules.d")
701 (filter-map rules-sub-directory '#$packages))))
702
be1c2c54
LC
703 (computed-file "udev-rules" build
704 #:modules '((guix build union)
705 (guix build utils))))
ecd06ca9 706
7f28bf9a
LC
707(define* (kvm-udev-rule)
708 "Return a directory with a udev rule that changes the group of
709@file{/dev/kvm} to \"kvm\" and makes it #o660."
710 ;; Apparently QEMU-KVM used to ship this rule, but now we have to add it by
711 ;; ourselves.
be1c2c54
LC
712 (computed-file "kvm-udev-rules"
713 #~(begin
714 (use-modules (guix build utils))
715
716 (define rules.d
717 (string-append #$output "/lib/udev/rules.d"))
718
719 (mkdir-p rules.d)
720 (call-with-output-file
721 (string-append rules.d "/90-kvm.rules")
722 (lambda (port)
723 ;; Build users are part of the "kvm" group, so we
724 ;; can fearlessly make /dev/kvm 660 (see
725 ;; <http://bugs.gnu.org/18994>, for background.)
726 (display "\
64720891 727KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n" port))))
be1c2c54 728 #:modules '((guix build utils))))
7f28bf9a 729
8a7330fd 730(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
731 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
732extra rules from the packages listed in @var{rules}."
be1c2c54
LC
733 (let* ((rules (udev-rules-union (cons* udev
734 (kvm-udev-rule)
735 rules)))
736 (udev.conf (computed-file "udev.conf"
737 #~(call-with-output-file #$output
738 (lambda (port)
739 (format port
740 "udev_rules=\"~a/lib/udev/rules.d\"\n"
741 #$rules))))))
742 (service
743 (provision '(udev))
744
745 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
746 ;; be added: see
747 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
748 (requirement '(root-file-system))
749
750 (documentation "Populate the /dev directory, dynamically.")
751 (start #~(lambda ()
752 (define find
753 (@ (srfi srfi-1) find))
754
755 (define udevd
756 ;; Choose the right 'udevd'.
757 (find file-exists?
758 (map (lambda (suffix)
759 (string-append #$udev suffix))
760 '("/libexec/udev/udevd" ;udev
761 "/sbin/udevd")))) ;eudev
762
763 (define (wait-for-udevd)
764 ;; Wait until someone's listening on udevd's control
765 ;; socket.
766 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
767 (let try ()
768 (catch 'system-error
769 (lambda ()
770 (connect sock PF_UNIX "/run/udev/control")
771 (close-port sock))
772 (lambda args
773 (format #t "waiting for udevd...~%")
774 (usleep 500000)
775 (try))))))
776
777 ;; Allow udev to find the modules.
778 (setenv "LINUX_MODULE_DIRECTORY"
779 "/run/booted-system/kernel/lib/modules")
780
781 ;; The first one is for udev, the second one for eudev.
782 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
783 (setenv "EUDEV_RULES_DIRECTORY"
784 (string-append #$rules "/lib/udev/rules.d"))
785
786 (let ((pid (primitive-fork)))
787 (case pid
788 ((0)
789 (exec-command (list udevd)))
790 (else
791 ;; Wait until udevd is up and running. This
792 ;; appears to be needed so that the events
793 ;; triggered below are actually handled.
794 (wait-for-udevd)
795
796 ;; Trigger device node creation.
797 (system* (string-append #$udev "/bin/udevadm")
798 "trigger" "--action=add")
799
800 ;; Wait for things to settle down.
801 (system* (string-append #$udev "/bin/udevadm")
802 "settle")
803 pid)))))
804 (stop #~(make-kill-destructor))
805
806 ;; When halting the system, 'udev' is actually killed by
807 ;; 'user-processes', i.e., before its own 'stop' method was
808 ;; called. Thus, make sure it is not respawned.
809 (respawn? #f))))
151a2c07 810
722554a3 811(define (device-mapping-service target open close)
5dae0186 812 "Return a service that maps device @var{target}, a string such as
722554a3
LC
813@code{\"home\"} (meaning @code{/dev/mapper/home}). Evaluate @var{open}, a
814gexp, to open it, and evaluate @var{close} to close it."
be1c2c54
LC
815 (service
816 (provision (list (symbol-append 'device-mapping- (string->symbol target))))
817 (requirement '(udev))
818 (documentation "Map a device node using Linux's device mapper.")
819 (start #~(lambda () #$open))
820 (stop #~(lambda _ (not #$close)))
821 (respawn? #f)))
5dae0186 822
2a13d05e
LC
823(define (swap-service device)
824 "Return a service that uses @var{device} as a swap device."
825 (define requirement
826 (if (string-prefix? "/dev/mapper/" device)
827 (list (symbol-append 'device-mapping-
828 (string->symbol (basename device))))
829 '()))
830
be1c2c54
LC
831 (service
832 (provision (list (symbol-append 'swap- (string->symbol device))))
833 (requirement `(udev ,@requirement))
834 (documentation "Enable the given swap device.")
835 (start #~(lambda ()
836 (restart-on-EINTR (swapon #$device))
837 #t))
838 (stop #~(lambda _
839 (restart-on-EINTR (swapoff #$device))
840 #f))
841 (respawn? #f)))
2a13d05e 842
8b198abe
LC
843(define %base-services
844 ;; Convenience variable holding the basic services.
ce8a6dfc 845 (let ((motd (plain-file "motd" "
8b198abe 846This is the GNU operating system, welcome!\n\n")))
62ca0fdf
LC
847 (list (console-font-service "tty1")
848 (console-font-service "tty2")
849 (console-font-service "tty3")
850 (console-font-service "tty4")
851 (console-font-service "tty5")
852 (console-font-service "tty6")
853
66e4f01c
LC
854 (mingetty-service (mingetty-configuration
855 (tty "tty1") (motd motd)))
856 (mingetty-service (mingetty-configuration
857 (tty "tty2") (motd motd)))
858 (mingetty-service (mingetty-configuration
859 (tty "tty3") (motd motd)))
860 (mingetty-service (mingetty-configuration
861 (tty "tty4") (motd motd)))
862 (mingetty-service (mingetty-configuration
863 (tty "tty5") (motd motd)))
864 (mingetty-service (mingetty-configuration
865 (tty "tty6") (motd motd)))
866
4a3b3b07
LC
867 (static-networking-service "lo" "127.0.0.1"
868 #:provision '(loopback))
8b198abe
LC
869 (syslog-service)
870 (guix-service)
151a2c07 871 (nscd-service)
ecd06ca9 872
52bd5734
LC
873 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
874 ;; used, so enable them by default. The FUSE and ALSA rules are
875 ;; less critical, but handy.
4307c476
MW
876 ;;
877 ;; XXX Keep this in sync with the 'udev-service' call in
878 ;; %desktop-services.
68ac258b 879 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
8b198abe 880
db4fdc04 881;;; base.scm ends here