file-systems: Do not read superblocks past the end of a device.
[jackhill/guix/guix.git] / gnu / services / base.scm
CommitLineData
db4fdc04 1;;; GNU Guix --- Functional package management for GNU
9a8b9eb8 2;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
34044d55 3;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
5f4a446d 4;;; Copyright © 2015, 2016 Mark H Weaver <mhw@netris.org>
e10964ef 5;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
a535e122 6;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
b58cbf9a 7;;; Copyright © 2016 David Craven <david@craven.ch>
909147e4 8;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
db4fdc04
LC
9;;;
10;;; This file is part of GNU Guix.
11;;;
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.
16;;;
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.
21;;;
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/>.
24
25(define-module (gnu services base)
e87f0591 26 #:use-module (guix store)
db4fdc04 27 #:use-module (gnu services)
0190c1c0 28 #:use-module (gnu services shepherd)
4a3b3b07 29 #:use-module (gnu services networking)
6e828634 30 #:use-module (gnu system pam)
db4fdc04 31 #:use-module (gnu system shadow) ; 'user-account', etc.
0adfe95a 32 #:use-module (gnu system file-systems) ; 'file-system', etc.
060d62a7 33 #:use-module (gnu system mapped-devices)
db4fdc04 34 #:use-module (gnu packages admin)
151a2c07 35 #:use-module ((gnu packages linux)
b58cbf9a 36 #:select (alsa-utils crda eudev e2fsprogs fuse gpm kbd lvm2 rng-tools))
db4fdc04 37 #:use-module ((gnu packages base)
bdb36958 38 #:select (canonical-package glibc))
db4fdc04 39 #:use-module (gnu packages package-management)
2d1d2dd8 40 #:use-module (gnu packages lsof)
46ec2707 41 #:use-module (gnu packages terminals)
e2f4b305 42 #:use-module ((gnu build file-systems)
2c071ce9 43 #:select (mount-flags->bit-mask))
b5f4e686 44 #:use-module (guix gexp)
6454b333 45 #:use-module (guix records)
db4fdc04
LC
46 #:use-module (srfi srfi-1)
47 #:use-module (srfi srfi-26)
6454b333 48 #:use-module (ice-9 match)
db4fdc04 49 #:use-module (ice-9 format)
e43e84ba
LC
50 #:export (fstab-service-type
51 root-file-system-service
aa1145df 52 file-system-service-type
d6e2a622 53 user-unmount-service
2a13d05e 54 swap-service
a00dd9fb 55 user-processes-service
e10964ef
SB
56 session-environment-service
57 session-environment-service-type
a00dd9fb 58 host-name-service
5eca9459 59 console-keymap-service
4a84a487
LC
60 %default-console-font
61 console-font-service-type
62ca0fdf 62 console-font-service
c797fabe
RW
63
64 udev-configuration
65 udev-configuration?
66 udev-configuration-rules
0adfe95a 67 udev-service-type
151a2c07 68 udev-service
80e6f37e 69 udev-rule
66e4f01c 70
317d3b47
DC
71 login-configuration
72 login-configuration?
73 login-service-type
74 login-service
75
66e4f01c
LC
76 mingetty-configuration
77 mingetty-configuration?
db4fdc04 78 mingetty-service
cd6f6c22 79 mingetty-service-type
6454b333
LC
80
81 %nscd-default-caches
82 %nscd-default-configuration
83
84 nscd-configuration
85 nscd-configuration?
86
87 nscd-cache
88 nscd-cache?
89
0adfe95a 90 nscd-service-type
db4fdc04 91 nscd-service
ec2e2f6c
DC
92
93 syslog-configuration
94 syslog-configuration?
db4fdc04 95 syslog-service
9009538d 96 syslog-service-type
44abcb28 97 %default-syslog.conf
0adfe95a 98
5b58c28b 99 %default-authorized-guix-keys
0adfe95a
LC
100 guix-configuration
101 guix-configuration?
70dfa4e0
MO
102
103 guix-configuration-guix
104 guix-configuration-build-group
105 guix-configuration-build-accounts
106 guix-configuration-authorize-key?
107 guix-configuration-authorized-keys
108 guix-configuration-use-substitutes?
109 guix-configuration-substitute-urls
110 guix-configuration-extra-options
111 guix-configuration-log-file
112 guix-configuration-lsof
113
8b198abe 114 guix-service
cd6f6c22 115 guix-service-type
1c52181f
LC
116 guix-publish-configuration
117 guix-publish-configuration?
118 guix-publish-service
119 guix-publish-service-type
24e96431
120
121 gpm-configuration
122 gpm-configuration?
8664cc88
LC
123 gpm-service-type
124 gpm-service
0adfe95a 125
9009538d 126 urandom-seed-service-type
a535e122 127 urandom-seed-service
24e96431
128
129 rngd-configuration
130 rngd-configuration?
b58cbf9a
DC
131 rngd-service-type
132 rngd-service
46ec2707
DC
133
134 kmscon-configuration
135 kmscon-configuration?
136 kmscon-service-type
137
909147e4
RW
138 pam-limits-service-type
139 pam-limits-service
a535e122 140
8b198abe 141 %base-services))
db4fdc04
LC
142
143;;; Commentary:
144;;;
145;;; Base system services---i.e., services that 99% of the users will want to
146;;; use.
147;;;
148;;; Code:
149
0adfe95a
LC
150\f
151;;;
152;;; File systems.
153;;;
a00dd9fb 154
e43e84ba
LC
155(define (file-system->fstab-entry file-system)
156 "Return a @file{/etc/fstab} entry for @var{file-system}."
157 (string-append (case (file-system-title file-system)
158 ((label)
159 (string-append "LABEL=" (file-system-device file-system)))
160 ((uuid)
161 (string-append
162 "UUID="
163 (uuid->string (file-system-device file-system))))
164 (else
165 (file-system-device file-system)))
166 "\t"
167 (file-system-mount-point file-system) "\t"
168 (file-system-type file-system) "\t"
169 (or (file-system-options file-system) "defaults") "\t"
170
171 ;; XXX: Omit the 'fs_freq' and 'fs_passno' fields because we
172 ;; don't have anything sensible to put in there.
173 ))
174
175(define (file-systems->fstab file-systems)
176 "Return a @file{/etc} entry for an @file{fstab} describing
177@var{file-systems}."
178 `(("fstab" ,(plain-file "fstab"
179 (string-append
180 "\
181# This file was generated from your GuixSD configuration. Any changes
182# will be lost upon reboot or reconfiguration.\n\n"
183 (string-join (map file-system->fstab-entry
184 file-systems)
185 "\n")
186 "\n")))))
187
188(define fstab-service-type
189 ;; The /etc/fstab service.
190 (service-type (name 'fstab)
191 (extensions
192 (list (service-extension etc-service-type
193 file-systems->fstab)))
aa1145df 194 (compose concatenate)
e43e84ba
LC
195 (extend append)))
196
d4053c71
AK
197(define %root-file-system-shepherd-service
198 (shepherd-service
be1c2c54
LC
199 (documentation "Take care of the root file system.")
200 (provision '(root-file-system))
201 (start #~(const #t))
202 (stop #~(lambda _
203 ;; Return #f if successfully stopped.
204 (sync)
205
206 (call-with-blocked-asyncs
207 (lambda ()
208 (let ((null (%make-void-port "w")))
34044d55 209 ;; Close 'shepherd.log'.
be1c2c54 210 (display "closing log\n")
34044d55 211 ((@ (shepherd comm) stop-logging))
be1c2c54
LC
212
213 ;; Redirect the default output ports..
214 (set-current-output-port null)
215 (set-current-error-port null)
216
217 ;; Close /dev/console.
218 (for-each close-fdes '(0 1 2))
219
220 ;; At this point, there are no open files left, so the
221 ;; root file system can be re-mounted read-only.
222 (mount #f "/" #f
223 (logior MS_REMOUNT MS_RDONLY)
224 #:update-mtab? #f)
225
226 #f)))))
227 (respawn? #f)))
a00dd9fb 228
0adfe95a 229(define root-file-system-service-type
d4053c71
AK
230 (shepherd-service-type 'root-file-system
231 (const %root-file-system-shepherd-service)))
0adfe95a
LC
232
233(define (root-file-system-service)
234 "Return a service whose sole purpose is to re-mount read-only the root file
235system upon shutdown (aka. cleanly \"umounting\" root.)
236
237This service must be the root of the service dependency graph so that its
d4053c71 238'stop' action is invoked when shepherd is the only process left."
0adfe95a
LC
239 (service root-file-system-service-type #f))
240
d4053c71 241(define (file-system->shepherd-service-name file-system)
0adfe95a
LC
242 "Return the symbol that denotes the service mounting and unmounting
243FILE-SYSTEM."
244 (symbol-append 'file-system-
245 (string->symbol (file-system-mount-point file-system))))
246
d4053c71
AK
247(define (mapped-device->shepherd-service-name md)
248 "Return the symbol that denotes the shepherd service of MD, a <mapped-device>."
e502bf89
LC
249 (symbol-append 'device-mapping-
250 (string->symbol (mapped-device-target md))))
251
d4053c71 252(define dependency->shepherd-service-name
e502bf89
LC
253 (match-lambda
254 ((? mapped-device? md)
d4053c71 255 (mapped-device->shepherd-service-name md))
e502bf89 256 ((? file-system? fs)
d4053c71 257 (file-system->shepherd-service-name fs))))
e502bf89 258
d4053c71 259(define (file-system-shepherd-service file-system)
aa1145df
LC
260 "Return the shepherd service for @var{file-system}, or @code{#f} if
261@var{file-system} is not auto-mounted upon boot."
e43e84ba
LC
262 (let ((target (file-system-mount-point file-system))
263 (device (file-system-device file-system))
264 (type (file-system-type file-system))
265 (title (file-system-title file-system))
bf7ef1bb
JD
266 (flags (file-system-flags file-system))
267 (options (file-system-options file-system))
e43e84ba
LC
268 (check? (file-system-check? file-system))
269 (create? (file-system-create-mount-point? file-system))
270 (dependencies (file-system-dependencies file-system)))
aa1145df
LC
271 (and (file-system-mount? file-system)
272 (with-imported-modules '((gnu build file-systems)
273 (guix build bournish))
a91c3fc7
LC
274 (shepherd-service
275 (provision (list (file-system->shepherd-service-name file-system)))
276 (requirement `(root-file-system
277 ,@(map dependency->shepherd-service-name dependencies)))
278 (documentation "Check, mount, and unmount the given file system.")
279 (start #~(lambda args
bf7ef1bb
JD
280 #$(if create?
281 #~(mkdir-p #$target)
282 #t)
9328eafb
LC
283
284 (let (($PATH (getenv "PATH")))
285 ;; Make sure fsck.ext2 & co. can be found.
286 (dynamic-wind
287 (lambda ()
288 (setenv "PATH"
289 (string-append
290 #$e2fsprogs "/sbin:"
291 "/run/current-system/profile/sbin:"
292 $PATH)))
293 (lambda ()
294 (mount-file-system
295 `(#$device #$title #$target #$type #$flags
296 #$options #$check?)
297 #:root "/"))
298 (lambda ()
299 (setenv "PATH" $PATH)))
300 #t)))
a91c3fc7
LC
301 (stop #~(lambda args
302 ;; Normally there are no processes left at this point, so
303 ;; TARGET can be safely unmounted.
304
305 ;; Make sure PID 1 doesn't keep TARGET busy.
306 (chdir "/")
307
308 (umount #$target)
309 #f))
310
311 ;; We need an additional module.
312 (modules `(((gnu build file-systems)
bf7ef1bb 313 #:select (mount-file-system))
aa1145df 314 ,@%default-modules)))))))
e43e84ba 315
0adfe95a 316(define file-system-service-type
aa1145df 317 (service-type (name 'file-systems)
e43e84ba 318 (extensions
d4053c71 319 (list (service-extension shepherd-root-service-type
aa1145df
LC
320 (lambda (file-systems)
321 (filter-map file-system-shepherd-service
322 file-systems)))
e43e84ba 323 (service-extension fstab-service-type
aa1145df
LC
324 identity)))
325 (compose concatenate)
326 (extend append)))
0adfe95a
LC
327
328(define user-unmount-service-type
d4053c71 329 (shepherd-service-type
5f44ee4f 330 'user-file-systems
0adfe95a 331 (lambda (known-mount-points)
d4053c71 332 (shepherd-service
0adfe95a 333 (documentation "Unmount manually-mounted file systems.")
5f44ee4f 334 (provision '(user-file-systems))
0adfe95a
LC
335 (start #~(const #t))
336 (stop #~(lambda args
337 (define (known? mount-point)
338 (member mount-point
339 (cons* "/proc" "/sys" '#$known-mount-points)))
340
341 ;; Make sure we don't keep the user's mount points busy.
342 (chdir "/")
343
344 (for-each (lambda (mount-point)
345 (format #t "unmounting '~a'...~%" mount-point)
346 (catch 'system-error
347 (lambda ()
348 (umount mount-point))
349 (lambda args
350 (let ((errno (system-error-errno args)))
351 (format #t "failed to unmount '~a': ~a~%"
352 mount-point (strerror errno))))))
353 (filter (negate known?) (mount-points)))
354 #f))))))
023f391c 355
d6e2a622
LC
356(define (user-unmount-service known-mount-points)
357 "Return a service whose sole purpose is to unmount file systems not listed
358in KNOWN-MOUNT-POINTS when it is stopped."
0adfe95a 359 (service user-unmount-service-type known-mount-points))
d6e2a622 360
7d57cfd3
LC
361(define %do-not-kill-file
362 ;; Name of the file listing PIDs of processes that must survive when halting
363 ;; the system. Typical example is user-space file systems.
b8c02c18 364 "/etc/shepherd/do-not-kill")
7d57cfd3 365
0adfe95a 366(define user-processes-service-type
d4053c71 367 (shepherd-service-type
00184239 368 'user-processes
0adfe95a
LC
369 (match-lambda
370 ((requirements grace-delay)
d4053c71 371 (shepherd-service
0adfe95a
LC
372 (documentation "When stopped, terminate all user processes.")
373 (provision '(user-processes))
5f44ee4f 374 (requirement (cons* 'root-file-system 'user-file-systems
d4053c71 375 (map file-system->shepherd-service-name
5f44ee4f 376 requirements)))
0adfe95a
LC
377 (start #~(const #t))
378 (stop #~(lambda _
379 (define (kill-except omit signal)
380 ;; Kill all the processes with SIGNAL except those listed
381 ;; in OMIT and the current process.
382 (let ((omit (cons (getpid) omit)))
383 (for-each (lambda (pid)
384 (unless (memv pid omit)
385 (false-if-exception
386 (kill pid signal))))
387 (processes))))
388
389 (define omitted-pids
390 ;; List of PIDs that must not be killed.
391 (if (file-exists? #$%do-not-kill-file)
392 (map string->number
393 (call-with-input-file #$%do-not-kill-file
394 (compose string-tokenize
395 (@ (ice-9 rdelim) read-string))))
396 '()))
397
398 (define (now)
399 (car (gettimeofday)))
400
401 (define (sleep* n)
402 ;; Really sleep N seconds.
403 ;; Work around <http://bugs.gnu.org/19581>.
404 (define start (now))
405 (let loop ((elapsed 0))
406 (when (> n elapsed)
407 (sleep (- n elapsed))
408 (loop (- (now) start)))))
409
410 (define lset= (@ (srfi srfi-1) lset=))
411
412 (display "sending all processes the TERM signal\n")
413
414 (if (null? omitted-pids)
415 (begin
416 ;; Easy: terminate all of them.
417 (kill -1 SIGTERM)
418 (sleep* #$grace-delay)
419 (kill -1 SIGKILL))
420 (begin
421 ;; Kill them all except OMITTED-PIDS. XXX: We would
422 ;; like to (kill -1 SIGSTOP) to get a fixed list of
423 ;; processes, like 'killall5' does, but that seems
424 ;; unreliable.
425 (kill-except omitted-pids SIGTERM)
426 (sleep* #$grace-delay)
427 (kill-except omitted-pids SIGKILL)
428 (delete-file #$%do-not-kill-file)))
429
430 (let wait ()
431 (let ((pids (processes)))
432 (unless (lset= = pids (cons 1 omitted-pids))
433 (format #t "waiting for process termination\
434 (processes left: ~s)~%"
435 pids)
436 (sleep* 2)
437 (wait))))
438
439 (display "all processes have been terminated\n")
440 #f))
441 (respawn? #f))))))
442
443(define* (user-processes-service file-systems #:key (grace-delay 4))
a00dd9fb
LC
444 "Return the service that is responsible for terminating all the processes so
445that the root file system can be re-mounted read-only, just before
446rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
447has been sent are terminated with SIGKILL.
448
d4053c71 449The returned service will depend on 'root-file-system' and on all the shepherd
0adfe95a 450services corresponding to FILE-SYSTEMS.
023f391c 451
a00dd9fb
LC
452All the services that spawn processes must depend on this one so that they are
453stopped before 'kill' is called."
0adfe95a 454 (service user-processes-service-type
be21979d 455 (list (filter file-system-mount? file-systems) grace-delay)))
d656c14e 456
0adfe95a 457\f
a535e122
LF
458;;;
459;;; Preserve entropy to seed /dev/urandom on boot.
460;;;
461
462(define %random-seed-file
463 "/var/lib/random-seed")
464
a535e122
LF
465(define (urandom-seed-shepherd-service _)
466 "Return a shepherd service for the /dev/urandom seed."
467 (list (shepherd-service
468 (documentation "Preserve entropy across reboots for /dev/urandom.")
469 (provision '(urandom-seed))
470 (requirement '(user-processes))
471 (start #~(lambda _
472 ;; On boot, write random seed into /dev/urandom.
473 (when (file-exists? #$%random-seed-file)
474 (call-with-input-file #$%random-seed-file
475 (lambda (seed)
476 (call-with-output-file "/dev/urandom"
477 (lambda (urandom)
478 (dump-port seed urandom))))))
71cb237a
LF
479 ;; Immediately refresh the seed in case the system doesn't
480 ;; shut down cleanly.
481 (call-with-input-file "/dev/urandom"
482 (lambda (urandom)
483 (let ((previous-umask (umask #o077))
484 (buf (make-bytevector 512)))
485 (mkdir-p (dirname #$%random-seed-file))
486 (get-bytevector-n! urandom buf 0 512)
487 (call-with-output-file #$%random-seed-file
488 (lambda (seed)
489 (put-bytevector seed buf)))
490 (umask previous-umask))))
a535e122
LF
491 #t))
492 (stop #~(lambda _
493 ;; During shutdown, write from /dev/urandom into random seed.
494 (let ((buf (make-bytevector 512)))
495 (call-with-input-file "/dev/urandom"
496 (lambda (urandom)
8fe5d95e
LF
497 (let ((previous-umask (umask #o077)))
498 (get-bytevector-n! urandom buf 0 512)
71cb237a 499 (mkdir-p (dirname #$%random-seed-file))
8fe5d95e
LF
500 (call-with-output-file #$%random-seed-file
501 (lambda (seed)
502 (put-bytevector seed buf)))
503 (umask previous-umask))
a535e122
LF
504 #t)))))
505 (modules `((rnrs bytevectors)
506 (rnrs io ports)
507 ,@%default-modules)))))
508
509(define urandom-seed-service-type
510 (service-type (name 'urandom-seed)
511 (extensions
512 (list (service-extension shepherd-root-service-type
71cb237a 513 urandom-seed-shepherd-service)))))
a535e122
LF
514
515(define (urandom-seed-service)
516 (service urandom-seed-service-type #f))
517
b58cbf9a
DC
518
519;;;
520;;; Add hardware random number generator to entropy pool.
521;;;
522
523(define-record-type* <rngd-configuration>
524 rngd-configuration make-rngd-configuration
525 rngd-configuration?
526 (rng-tools rngd-configuration-rng-tools) ;package
527 (device rngd-configuration-device)) ;string
528
529(define rngd-service-type
530 (shepherd-service-type
531 'rngd
532 (lambda (config)
533 (define rng-tools (rngd-configuration-rng-tools config))
534 (define device (rngd-configuration-device config))
535
536 (define rngd-command
9e41130b 537 (list (file-append rng-tools "/sbin/rngd")
b58cbf9a
DC
538 "-f" "-r" device))
539
540 (shepherd-service
541 (documentation "Add TRNG to entropy pool.")
542 (requirement '(udev))
543 (provision '(trng))
544 (start #~(make-forkexec-constructor #$@rngd-command))
545 (stop #~(make-kill-destructor))))))
546
547(define* (rngd-service #:key
548 (rng-tools rng-tools)
549 (device "/dev/hwrng"))
550 "Return a service that runs the @command{rngd} program from @var{rng-tools}
551to add @var{device} to the kernel's entropy pool. The service will fail if
552@var{device} does not exist."
553 (service rngd-service-type
554 (rngd-configuration
555 (rng-tools rng-tools)
556 (device device))))
557
558
e10964ef
SB
559;;;
560;;; System-wide environment variables.
561;;;
562
563(define (environment-variables->environment-file vars)
564 "Return a file for pam_env(8) that contains environment variables VARS."
565 (apply mixed-text-file "environment"
566 (append-map (match-lambda
567 ((key . value)
568 (list key "=" value "\n")))
569 vars)))
570
571(define session-environment-service-type
572 (service-type
573 (name 'session-environment)
574 (extensions
575 (list (service-extension
576 etc-service-type
577 (lambda (vars)
578 (list `("environment"
579 ,(environment-variables->environment-file vars)))))))
580 (compose concatenate)
581 (extend append)))
582
583(define (session-environment-service vars)
584 "Return a service that builds the @file{/etc/environment}, which can be read
585by PAM-aware applications to set environment variables for sessions.
586
587VARS should be an association list in which both the keys and the values are
588strings or string-valued gexps."
589 (service session-environment-service-type vars))
590
591\f
0adfe95a
LC
592;;;
593;;; Console & co.
594;;;
595
596(define host-name-service-type
d4053c71 597 (shepherd-service-type
00184239 598 'host-name
0adfe95a 599 (lambda (name)
d4053c71 600 (shepherd-service
0adfe95a
LC
601 (documentation "Initialize the machine's host name.")
602 (provision '(host-name))
603 (start #~(lambda _
604 (sethostname #$name)))
605 (respawn? #f)))))
a00dd9fb 606
db4fdc04 607(define (host-name-service name)
51da7ca0 608 "Return a service that sets the host name to @var{name}."
0adfe95a 609 (service host-name-service-type name))
db4fdc04 610
62ca0fdf
LC
611(define (unicode-start tty)
612 "Return a gexp to start Unicode support on @var{tty}."
613
614 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
615 ;; 'tty' command, that command returns TTY.
616 #~(begin
617 (let ((pid (primitive-fork)))
618 (case pid
619 ((0)
620 (close-fdes 0)
621 (dup2 (open-fdes #$tty O_RDONLY) 0)
622 (close-fdes 1)
623 (dup2 (open-fdes #$tty O_WRONLY) 1)
9fc037fe 624 (execl #$(file-append kbd "/bin/unicode_start")
62ca0fdf
LC
625 "unicode_start"))
626 (else
627 (zero? (cdr (waitpid pid))))))))
628
0adfe95a 629(define console-keymap-service-type
d4053c71 630 (shepherd-service-type
00184239 631 'console-keymap
b3d05f48 632 (lambda (files)
d4053c71 633 (shepherd-service
0adfe95a
LC
634 (documentation (string-append "Load console keymap (loadkeys)."))
635 (provision '(console-keymap))
636 (start #~(lambda _
9fc037fe 637 (zero? (system* #$(file-append kbd "/bin/loadkeys")
b3d05f48 638 #$@files))))
0adfe95a
LC
639 (respawn? #f)))))
640
b3d05f48
AK
641(define (console-keymap-service . files)
642 "Return a service to load console keymaps from @var{files}."
643 (service console-keymap-service-type files))
0adfe95a 644
4a84a487
LC
645(define %default-console-font
646 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
647 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
648 ;; codepoints notably found in the UTF-8 manual.
649 "LatGrkCyr-8x16")
650
651(define (console-font-shepherd-services tty+font)
652 "Return a list of Shepherd services for each pair in TTY+FONT."
653 (map (match-lambda
654 ((tty . font)
655 (let ((device (string-append "/dev/" tty)))
656 (shepherd-service
657 (documentation "Load a Unicode console font.")
658 (provision (list (symbol-append 'console-font-
659 (string->symbol tty))))
660
661 ;; Start after mingetty has been started on TTY, otherwise the settings
662 ;; are ignored.
663 (requirement (list (symbol-append 'term-
664 (string->symbol tty))))
665
666 (start #~(lambda _
667 (and #$(unicode-start device)
668 (zero?
9fc037fe 669 (system* #$(file-append kbd "/bin/setfont")
4a84a487
LC
670 "-C" #$device #$font)))))
671 (stop #~(const #t))
672 (respawn? #f)))))
673 tty+font))
0adfe95a 674
4a84a487
LC
675(define console-font-service-type
676 (service-type (name 'console-fonts)
677 (extensions
678 (list (service-extension shepherd-root-service-type
679 console-font-shepherd-services)))
680 (compose concatenate)
681 (extend append)))
5eca9459 682
62ca0fdf 683(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
4a84a487
LC
684 "This procedure is deprecated in favor of @code{console-font-service-type}.
685
686Return a service that sets up Unicode support in @var{tty} and loads
62ca0fdf 687@var{font} for that tty (fonts are per virtual console in Linux.)"
4a84a487
LC
688 (simple-service (symbol-append 'console-font- (string->symbol tty))
689 console-font-service-type `((,tty . ,font))))
62ca0fdf 690
317d3b47
DC
691(define %default-motd
692 (plain-file "motd" "This is the GNU operating system, welcome!\n\n"))
693
694(define-record-type* <login-configuration>
695 login-configuration make-login-configuration
696 login-configuration?
697 (motd login-configuration-motd ;file-like
698 (default %default-motd))
699 ;; Allow empty passwords by default so that first-time users can log in when
700 ;; the 'root' account has just been created.
701 (allow-empty-passwords? login-configuration-allow-empty-passwords?
702 (default #t))) ;Boolean
703
704(define (login-pam-service config)
705 "Return the list of PAM service needed for CONF."
706 ;; Let 'login' be known to PAM.
707 (list (unix-pam-service "login"
708 #:allow-empty-passwords?
709 (login-configuration-allow-empty-passwords? config)
710 #:motd
711 (login-configuration-motd config))))
712
713(define login-service-type
714 (service-type (name 'login)
715 (extensions (list (service-extension pam-root-service-type
716 login-pam-service)))))
717
718(define* (login-service #:optional (config (login-configuration)))
719 "Return a service configure login according to @var{config}, which specifies
720the message of the day, among other things."
721 (service login-service-type config))
722
66e4f01c
LC
723(define-record-type* <mingetty-configuration>
724 mingetty-configuration make-mingetty-configuration
725 mingetty-configuration?
726 (mingetty mingetty-configuration-mingetty ;<package>
727 (default mingetty))
728 (tty mingetty-configuration-tty) ;string
66e4f01c
LC
729 (auto-login mingetty-auto-login ;string | #f
730 (default #f))
731 (login-program mingetty-login-program ;gexp
732 (default #f))
733 (login-pause? mingetty-login-pause? ;Boolean
317d3b47 734 (default #f)))
0adfe95a 735
d4053c71 736(define mingetty-shepherd-service
0adfe95a 737 (match-lambda
317d3b47
DC
738 (($ <mingetty-configuration> mingetty tty auto-login login-program
739 login-pause?)
0adfe95a 740 (list
d4053c71 741 (shepherd-service
0adfe95a
LC
742 (documentation "Run mingetty on an tty.")
743 (provision (list (symbol-append 'term- (string->symbol tty))))
744
745 ;; Since the login prompt shows the host name, wait for the 'host-name'
746 ;; service to be done. Also wait for udev essentially so that the tty
747 ;; text is not lost in the middle of kernel messages (XXX).
748 (requirement '(user-processes host-name udev))
749
750 (start #~(make-forkexec-constructor
9fc037fe 751 (list #$(file-append mingetty "/sbin/mingetty")
0adfe95a
LC
752 "--noclear" #$tty
753 #$@(if auto-login
754 #~("--autologin" #$auto-login)
755 #~())
756 #$@(if login-program
757 #~("--loginprog" #$login-program)
758 #~())
759 #$@(if login-pause?
760 #~("--loginpause")
761 #~()))))
762 (stop #~(make-kill-destructor)))))))
763
764(define mingetty-service-type
765 (service-type (name 'mingetty)
d4053c71 766 (extensions (list (service-extension shepherd-root-service-type
317d3b47 767 mingetty-shepherd-service)))))
0adfe95a
LC
768
769(define* (mingetty-service config)
770 "Return a service to run mingetty according to @var{config}, which specifies
771the tty to run, among other things."
772 (service mingetty-service-type config))
db4fdc04 773
6454b333
LC
774(define-record-type* <nscd-configuration> nscd-configuration
775 make-nscd-configuration
776 nscd-configuration?
777 (log-file nscd-configuration-log-file ;string
778 (default "/var/log/nscd.log"))
779 (debug-level nscd-debug-level ;integer
780 (default 0))
781 ;; TODO: See nscd.conf in glibc for other options to add.
782 (caches nscd-configuration-caches ;list of <nscd-cache>
b893f1ae
LC
783 (default %nscd-default-caches))
784 (name-services nscd-configuration-name-services ;list of <packages>
785 (default '()))
786 (glibc nscd-configuration-glibc ;<package>
787 (default (canonical-package glibc))))
6454b333
LC
788
789(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
790 nscd-cache?
791 (database nscd-cache-database) ;symbol
792 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
793 (negative-time-to-live nscd-cache-negative-time-to-live
794 (default 20)) ;integer
795 (suggested-size nscd-cache-suggested-size ;integer ("default module
796 ;of hash table")
797 (default 211))
798 (check-files? nscd-cache-check-files? ;Boolean
799 (default #t))
800 (persistent? nscd-cache-persistent? ;Boolean
801 (default #t))
802 (shared? nscd-cache-shared? ;Boolean
803 (default #t))
804 (max-database-size nscd-cache-max-database-size ;integer
805 (default (* 32 (expt 2 20))))
806 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
807 (default #t)))
808
809(define %nscd-default-caches
810 ;; Caches that we want to enable by default. Note that when providing an
811 ;; empty nscd.conf, all caches are disabled.
812 (list (nscd-cache (database 'hosts)
813
814 ;; Aggressively cache the host name cache to improve
815 ;; privacy and resilience.
816 (positive-time-to-live (* 3600 12))
817 (negative-time-to-live 20)
818 (persistent? #t))
819
820 (nscd-cache (database 'services)
821
822 ;; Services are unlikely to change, so we can be even more
823 ;; aggressive.
824 (positive-time-to-live (* 3600 24))
825 (negative-time-to-live 3600)
826 (check-files? #t) ;check /etc/services changes
827 (persistent? #t))))
828
829(define %nscd-default-configuration
830 ;; Default nscd configuration.
831 (nscd-configuration))
832
833(define (nscd.conf-file config)
834 "Return the @file{nscd.conf} configuration file for @var{config}, an
835@code{<nscd-configuration>} object."
836 (define cache->config
837 (match-lambda
be1c2c54
LC
838 (($ <nscd-cache> (= symbol->string database)
839 positive-ttl negative-ttl size check-files?
840 persistent? shared? max-size propagate?)
841 (string-append "\nenable-cache\t" database "\tyes\n"
842
843 "positive-time-to-live\t" database "\t"
844 (number->string positive-ttl) "\n"
845 "negative-time-to-live\t" database "\t"
846 (number->string negative-ttl) "\n"
847 "suggested-size\t" database "\t"
848 (number->string size) "\n"
849 "check-files\t" database "\t"
850 (if check-files? "yes\n" "no\n")
851 "persistent\t" database "\t"
852 (if persistent? "yes\n" "no\n")
853 "shared\t" database "\t"
854 (if shared? "yes\n" "no\n")
855 "max-db-size\t" database "\t"
856 (number->string max-size) "\n"
857 "auto-propagate\t" database "\t"
858 (if propagate? "yes\n" "no\n")))))
6454b333
LC
859
860 (match config
861 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
862 (plain-file "nscd.conf"
863 (string-append "\
6454b333 864# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
865 (if log-file
866 (string-append "logfile\t" log-file)
867 "")
868 "\n"
869 (if debug-level
870 (string-append "debug-level\t"
871 (number->string debug-level))
872 "")
873 "\n"
874 (string-concatenate
875 (map cache->config caches)))))))
6454b333 876
d4053c71
AK
877(define (nscd-shepherd-service config)
878 "Return a shepherd service for CONFIG, an <nscd-configuration> object."
0adfe95a
LC
879 (let ((nscd.conf (nscd.conf-file config))
880 (name-services (nscd-configuration-name-services config)))
d4053c71 881 (list (shepherd-service
0adfe95a
LC
882 (documentation "Run libc's name service cache daemon (nscd).")
883 (provision '(nscd))
884 (requirement '(user-processes))
885 (start #~(make-forkexec-constructor
9fc037fe 886 (list #$(file-append (nscd-configuration-glibc config)
0adfe95a
LC
887 "/sbin/nscd")
888 "-f" #$nscd.conf "--foreground")
889
04101d99
LC
890 ;; Wait for the PID file. However, the PID file is
891 ;; written before nscd is actually listening on its
892 ;; socket (XXX).
893 #:pid-file "/var/run/nscd/nscd.pid"
894
0adfe95a
LC
895 #:environment-variables
896 (list (string-append "LD_LIBRARY_PATH="
897 (string-join
898 (map (lambda (dir)
899 (string-append dir "/lib"))
900 (list #$@name-services))
901 ":")))))
cc7234ae 902 (stop #~(make-kill-destructor))))))
0adfe95a
LC
903
904(define nscd-activation
905 ;; Actions to take before starting nscd.
906 #~(begin
907 (use-modules (guix build utils))
908 (mkdir-p "/var/run/nscd")
909 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
910
911(define nscd-service-type
912 (service-type (name 'nscd)
913 (extensions
914 (list (service-extension activation-service-type
915 (const nscd-activation))
d4053c71
AK
916 (service-extension shepherd-root-service-type
917 nscd-shepherd-service)))
0adfe95a
LC
918
919 ;; This can be extended by providing additional name services
920 ;; such as nss-mdns.
921 (compose concatenate)
922 (extend (lambda (config name-services)
923 (nscd-configuration
924 (inherit config)
925 (name-services (append
926 (nscd-configuration-name-services config)
927 name-services)))))))
928
b893f1ae 929(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 930 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
931given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
932Service Switch}, for an example."
0adfe95a
LC
933 (service nscd-service-type config))
934
ec2e2f6c
DC
935
936(define-record-type* <syslog-configuration>
937 syslog-configuration make-syslog-configuration
938 syslog-configuration?
939 (syslogd syslog-configuration-syslogd
9e41130b 940 (default (file-append inetutils "/libexec/syslogd")))
ec2e2f6c
DC
941 (config-file syslog-configuration-config-file
942 (default %default-syslog.conf)))
943
0adfe95a 944(define syslog-service-type
d4053c71 945 (shepherd-service-type
00184239 946 'syslog
ec2e2f6c 947 (lambda (config)
d4053c71 948 (shepherd-service
0adfe95a
LC
949 (documentation "Run the syslog daemon (syslogd).")
950 (provision '(syslogd))
951 (requirement '(user-processes))
952 (start #~(make-forkexec-constructor
ec2e2f6c 953 (list #$(syslog-configuration-syslogd config)
afa54a38
LC
954 "--rcfile" #$(syslog-configuration-config-file config))
955 #:pid-file "/var/run/syslog.pid"))
0adfe95a 956 (stop #~(make-kill-destructor))))))
be1c2c54
LC
957
958;; Snippet adapted from the GNU inetutils manual.
959(define %default-syslog.conf
960 (plain-file "syslog.conf" "
1f3fc60d 961 # Log all error messages, authentication messages of
db4fdc04
LC
962 # level notice or higher and anything of level err or
963 # higher to the console.
964 # Don't log private authentication messages!
6a191274 965 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
966
967 # Log anything (except mail) of level info or higher.
968 # Don't log private authentication messages!
969 *.info;mail.none;authpriv.none /var/log/messages
970
971 # Same, in a different place.
972 *.info;mail.none;authpriv.none /dev/tty12
973
974 # The authpriv file has restricted access.
975 authpriv.* /var/log/secure
976
977 # Log all the mail messages in one place.
978 mail.* /var/log/maillog
be1c2c54 979"))
0adfe95a 980
ec2e2f6c
DC
981(define* (syslog-service #:optional (config (syslog-configuration)))
982 "Return a service that runs @command{syslogd} and takes
983@var{<syslog-configuration>} as a parameter.
44abcb28
LC
984
985@xref{syslogd invocation,,, inetutils, GNU Inetutils}, for more
986information on the configuration file syntax."
ec2e2f6c
DC
987 (service syslog-service-type config))
988
db4fdc04 989
909147e4
RW
990(define pam-limits-service-type
991 (let ((security-limits
992 ;; Create /etc/security containing the provided "limits.conf" file.
993 (lambda (limits-file)
994 `(("security"
995 ,(computed-file
996 "security"
997 #~(begin
998 (mkdir #$output)
999 (stat #$limits-file)
1000 (symlink #$limits-file
1001 (string-append #$output "/limits.conf"))))))))
1002 (pam-extension
1003 (lambda (pam)
1004 (let ((pam-limits (pam-entry
1005 (control "required")
1006 (module "pam_limits.so")
1007 (arguments '("conf=/etc/security/limits.conf")))))
1008 (if (member (pam-service-name pam)
1009 '("login" "su" "slim"))
1010 (pam-service
1011 (inherit pam)
1012 (session (cons pam-limits
1013 (pam-service-session pam))))
1014 pam)))))
1015 (service-type
1016 (name 'limits)
1017 (extensions
1018 (list (service-extension etc-service-type security-limits)
1019 (service-extension pam-root-service-type
1020 (lambda _ (list pam-extension))))))))
1021
1022(define* (pam-limits-service #:optional (limits '()))
1023 "Return a service that makes selected programs respect the list of
1024pam-limits-entry specified in LIMITS via pam_limits.so."
1025 (service pam-limits-service-type
1026 (plain-file "limits.conf"
1027 (string-join (map pam-limits-entry->string limits)
1028 "\n"))))
1029
1c52181f
LC
1030\f
1031;;;
1032;;; Guix services.
1033;;;
1034
db4fdc04 1035(define* (guix-build-accounts count #:key
ab6a279a 1036 (group "guixbuild")
db4fdc04 1037 (first-uid 30001)
db4fdc04
LC
1038 (shadow shadow))
1039 "Return a list of COUNT user accounts for Guix build users, with UIDs
1040starting at FIRST-UID, and under GID."
5250a4f2
LC
1041 (unfold (cut > <> count)
1042 (lambda (n)
1043 (user-account
1044 (name (format #f "guixbuilder~2,'0d" n))
1045 (system? #t)
1046 (uid (+ first-uid n -1))
1047 (group group)
1048
1049 ;; guix-daemon expects GROUP to be listed as a
1050 ;; supplementary group too:
1051 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
1052 (supplementary-groups (list group "kvm"))
1053
1054 (comment (format #f "Guix Build User ~2d" n))
1055 (home-directory "/var/empty")
9e41130b 1056 (shell (file-append shadow "/sbin/nologin"))))
5250a4f2
LC
1057 1+
1058 1))
db4fdc04 1059
5b58c28b
LC
1060(define (hydra-key-authorization key guix)
1061 "Return a gexp with code to register KEY, a file containing a 'guix archive'
1062public key, with GUIX."
2c5c696c
LC
1063 #~(unless (file-exists? "/etc/guix/acl")
1064 (let ((pid (primitive-fork)))
1065 (case pid
1066 ((0)
5b58c28b 1067 (let* ((key #$key)
2c5c696c
LC
1068 (port (open-file key "r0b")))
1069 (format #t "registering public key '~a'...~%" key)
1070 (close-port (current-input-port))
2c5c696c 1071 (dup port 0)
9fc037fe 1072 (execl #$(file-append guix "/bin/guix")
2c5c696c
LC
1073 "guix" "archive" "--authorize")
1074 (exit 1)))
1075 (else
1076 (let ((status (cdr (waitpid pid))))
1077 (unless (zero? status)
1078 (format (current-error-port) "warning: \
1079failed to register hydra.gnu.org public key: ~a~%" status))))))))
1080
5b58c28b
LC
1081(define %default-authorized-guix-keys
1082 ;; List of authorized substitute keys.
9e41130b 1083 (list (file-append guix "/share/guix/hydra.gnu.org.pub")))
5b58c28b 1084
0adfe95a
LC
1085(define-record-type* <guix-configuration>
1086 guix-configuration make-guix-configuration
1087 guix-configuration?
1088 (guix guix-configuration-guix ;<package>
1089 (default guix))
1090 (build-group guix-configuration-build-group ;string
1091 (default "guixbuild"))
1092 (build-accounts guix-configuration-build-accounts ;integer
1093 (default 10))
1094 (authorize-key? guix-configuration-authorize-key? ;Boolean
1095 (default #t))
5b58c28b
LC
1096 (authorized-keys guix-configuration-authorized-keys ;list of gexps
1097 (default %default-authorized-guix-keys))
0adfe95a
LC
1098 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1099 (default #t))
b0b9f6e0
LC
1100 (substitute-urls guix-configuration-substitute-urls ;list of strings
1101 (default %default-substitute-urls))
0adfe95a
LC
1102 (extra-options guix-configuration-extra-options ;list of strings
1103 (default '()))
dc0ef095
LC
1104 (log-file guix-configuration-log-file ;string
1105 (default "/var/log/guix-daemon.log"))
0adfe95a 1106 (lsof guix-configuration-lsof ;<package>
f78903f3 1107 (default lsof)))
0adfe95a
LC
1108
1109(define %default-guix-configuration
1110 (guix-configuration))
1111
d4053c71
AK
1112(define (guix-shepherd-service config)
1113 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
0adfe95a 1114 (match config
5b58c28b
LC
1115 (($ <guix-configuration> guix build-group build-accounts
1116 authorize-key? keys
b0b9f6e0 1117 use-substitutes? substitute-urls extra-options
dc0ef095 1118 log-file lsof)
d4053c71 1119 (list (shepherd-service
0adfe95a
LC
1120 (documentation "Run the Guix daemon.")
1121 (provision '(guix-daemon))
1122 (requirement '(user-processes))
1123 (start
1124 #~(make-forkexec-constructor
9fc037fe 1125 (list #$(file-append guix "/bin/guix-daemon")
0adfe95a
LC
1126 "--build-users-group" #$build-group
1127 #$@(if use-substitutes?
1128 '()
1129 '("--no-substitutes"))
b0b9f6e0 1130 "--substitute-urls" #$(string-join substitute-urls)
0adfe95a
LC
1131 #$@extra-options)
1132
f78903f3 1133 ;; Add 'lsof' (for the GC) to the daemon's $PATH.
0adfe95a 1134 #:environment-variables
dc0ef095
LC
1135 (list (string-append "PATH=" #$lsof "/bin"))
1136
1137 #:log-file #$log-file))
0adfe95a
LC
1138 (stop #~(make-kill-destructor)))))))
1139
1140(define (guix-accounts config)
1141 "Return the user accounts and user groups for CONFIG."
1142 (match config
1143 (($ <guix-configuration> _ build-group build-accounts)
1144 (cons (user-group
1145 (name build-group)
1146 (system? #t)
1147
1148 ;; Use a fixed GID so that we can create the store with the right
1149 ;; owner.
1150 (id 30000))
1151 (guix-build-accounts build-accounts
1152 #:group build-group)))))
1153
1154(define (guix-activation config)
1155 "Return the activation gexp for CONFIG."
1156 (match config
5b58c28b 1157 (($ <guix-configuration> guix build-group build-accounts authorize-key? keys)
0adfe95a
LC
1158 ;; Assume that the store has BUILD-GROUP as its group. We could
1159 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
1160 ;; chown leads to an entire copy of the tree, which is a bad idea.
1161
1162 ;; Optionally authorize hydra.gnu.org's key.
5f4a446d 1163 (if authorize-key?
5b58c28b
LC
1164 #~(begin
1165 #$@(map (cut hydra-key-authorization <> guix) keys))
5f4a446d 1166 #~#f))))
0adfe95a
LC
1167
1168(define guix-service-type
1169 (service-type
1170 (name 'guix)
1171 (extensions
d4053c71 1172 (list (service-extension shepherd-root-service-type guix-shepherd-service)
0adfe95a 1173 (service-extension account-service-type guix-accounts)
9a8b9eb8
LC
1174 (service-extension activation-service-type guix-activation)
1175 (service-extension profile-service-type
1176 (compose list guix-configuration-guix))))))
0adfe95a
LC
1177
1178(define* (guix-service #:optional (config %default-guix-configuration))
1179 "Return a service that runs the Guix build daemon according to
1180@var{config}."
1181 (service guix-service-type config))
1182
1c52181f
LC
1183
1184(define-record-type* <guix-publish-configuration>
1185 guix-publish-configuration make-guix-publish-configuration
1186 guix-publish-configuration?
1187 (guix guix-publish-configuration-guix ;package
1188 (default guix))
1189 (port guix-publish-configuration-port ;number
1190 (default 80))
1191 (host guix-publish-configuration-host ;string
1192 (default "localhost")))
1193
d4053c71 1194(define guix-publish-shepherd-service
1c52181f
LC
1195 (match-lambda
1196 (($ <guix-publish-configuration> guix port host)
d4053c71 1197 (list (shepherd-service
1c52181f
LC
1198 (provision '(guix-publish))
1199 (requirement '(guix-daemon))
1200 (start #~(make-forkexec-constructor
9fc037fe 1201 (list #$(file-append guix "/bin/guix")
1c52181f
LC
1202 "publish" "-u" "guix-publish"
1203 "-p" #$(number->string port)
1204 (string-append "--listen=" #$host))))
1205 (stop #~(make-kill-destructor)))))))
1206
1207(define %guix-publish-accounts
1208 (list (user-group (name "guix-publish") (system? #t))
1209 (user-account
1210 (name "guix-publish")
1211 (group "guix-publish")
1212 (system? #t)
1213 (comment "guix publish user")
1214 (home-directory "/var/empty")
9e41130b 1215 (shell (file-append shadow "/sbin/nologin")))))
1c52181f
LC
1216
1217(define guix-publish-service-type
1218 (service-type (name 'guix-publish)
1219 (extensions
d4053c71
AK
1220 (list (service-extension shepherd-root-service-type
1221 guix-publish-shepherd-service)
1c52181f
LC
1222 (service-extension account-service-type
1223 (const %guix-publish-accounts))))))
1224
1225(define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
1226 "Return a service that runs @command{guix publish} listening on @var{host}
1227and @var{port} (@pxref{Invoking guix publish}).
1228
1229This assumes that @file{/etc/guix} already contains a signing key pair as
1230created by @command{guix archive --generate-key} (@pxref{Invoking guix
1231archive}). If that is not the case, the service will fail to start."
1232 (service guix-publish-service-type
1233 (guix-publish-configuration (guix guix) (port port) (host host))))
1234
0adfe95a
LC
1235\f
1236;;;
1237;;; Udev.
1238;;;
1239
1240(define-record-type* <udev-configuration>
1241 udev-configuration make-udev-configuration
1242 udev-configuration?
1243 (udev udev-configuration-udev ;<package>
1244 (default udev))
1245 (rules udev-configuration-rules ;list of <package>
1246 (default '())))
db4fdc04 1247
ecd06ca9
LC
1248(define (udev-rules-union packages)
1249 "Return the union of the @code{lib/udev/rules.d} directories found in each
1250item of @var{packages}."
1251 (define build
4ee96a79
LC
1252 (with-imported-modules '((guix build union)
1253 (guix build utils))
1254 #~(begin
1255 (use-modules (guix build union)
1256 (guix build utils)
1257 (srfi srfi-1)
1258 (srfi srfi-26))
ecd06ca9 1259
4ee96a79
LC
1260 (define %standard-locations
1261 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
ecd06ca9 1262
4ee96a79
LC
1263 (define (rules-sub-directory directory)
1264 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1265 ;; #f if none was found.
1266 (find directory-exists?
1267 (map (cut string-append directory <>) %standard-locations)))
ecd06ca9 1268
4ee96a79
LC
1269 (mkdir-p (string-append #$output "/lib/udev"))
1270 (union-build (string-append #$output "/lib/udev/rules.d")
1271 (filter-map rules-sub-directory '#$packages)))))
ecd06ca9 1272
4ee96a79 1273 (computed-file "udev-rules" build))
ecd06ca9 1274
80e6f37e
RW
1275(define (udev-rule file-name contents)
1276 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1277 (computed-file file-name
4ee96a79
LC
1278 (with-imported-modules '((guix build utils))
1279 #~(begin
1280 (use-modules (guix build utils))
1281
1282 (define rules.d
1283 (string-append #$output "/lib/udev/rules.d"))
1284
1285 (mkdir-p rules.d)
1286 (call-with-output-file
1287 (string-append rules.d "/" #$file-name)
1288 (lambda (port)
1289 (display #$contents port)))))))
7f28bf9a 1290
80e6f37e
RW
1291(define kvm-udev-rule
1292 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1293 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1294 ;; but now we have to add it by ourselves.
1295
1296 ;; Build users are part of the "kvm" group, so we can fearlessly make
1297 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1298 (udev-rule "90-kvm.rules"
1299 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1300
d4053c71
AK
1301(define udev-shepherd-service
1302 ;; Return a <shepherd-service> for UDEV with RULES.
0adfe95a
LC
1303 (match-lambda
1304 (($ <udev-configuration> udev rules)
80e6f37e 1305 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
1306 (udev.conf (computed-file "udev.conf"
1307 #~(call-with-output-file #$output
1308 (lambda (port)
1309 (format port
1310 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1311 #$rules))))))
1312 (list
d4053c71 1313 (shepherd-service
0adfe95a
LC
1314 (provision '(udev))
1315
1316 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1317 ;; be added: see
1318 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1319 (requirement '(root-file-system))
1320
1321 (documentation "Populate the /dev directory, dynamically.")
1322 (start #~(lambda ()
1323 (define find
1324 (@ (srfi srfi-1) find))
1325
1326 (define udevd
1327 ;; Choose the right 'udevd'.
1328 (find file-exists?
1329 (map (lambda (suffix)
1330 (string-append #$udev suffix))
1331 '("/libexec/udev/udevd" ;udev
1332 "/sbin/udevd")))) ;eudev
1333
1334 (define (wait-for-udevd)
1335 ;; Wait until someone's listening on udevd's control
1336 ;; socket.
1337 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1338 (let try ()
1339 (catch 'system-error
1340 (lambda ()
1341 (connect sock PF_UNIX "/run/udev/control")
1342 (close-port sock))
1343 (lambda args
1344 (format #t "waiting for udevd...~%")
1345 (usleep 500000)
1346 (try))))))
1347
1348 ;; Allow udev to find the modules.
1349 (setenv "LINUX_MODULE_DIRECTORY"
1350 "/run/booted-system/kernel/lib/modules")
1351
1352 ;; The first one is for udev, the second one for eudev.
1353 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1354 (setenv "EUDEV_RULES_DIRECTORY"
9fc037fe 1355 #$(file-append rules "/lib/udev/rules.d"))
0adfe95a
LC
1356
1357 (let ((pid (primitive-fork)))
1358 (case pid
1359 ((0)
1360 (exec-command (list udevd)))
1361 (else
1362 ;; Wait until udevd is up and running. This
1363 ;; appears to be needed so that the events
1364 ;; triggered below are actually handled.
1365 (wait-for-udevd)
1366
1367 ;; Trigger device node creation.
9fc037fe 1368 (system* #$(file-append udev "/bin/udevadm")
0adfe95a
LC
1369 "trigger" "--action=add")
1370
1371 ;; Wait for things to settle down.
9fc037fe 1372 (system* #$(file-append udev "/bin/udevadm")
0adfe95a
LC
1373 "settle")
1374 pid)))))
1375 (stop #~(make-kill-destructor))
1376
1377 ;; When halting the system, 'udev' is actually killed by
1378 ;; 'user-processes', i.e., before its own 'stop' method was called.
1379 ;; Thus, make sure it is not respawned.
1380 (respawn? #f)))))))
1381
1382(define udev-service-type
1383 (service-type (name 'udev)
1384 (extensions
d4053c71
AK
1385 (list (service-extension shepherd-root-service-type
1386 udev-shepherd-service)))
0adfe95a
LC
1387
1388 (compose concatenate) ;concatenate the list of rules
1389 (extend (lambda (config rules)
1390 (match config
1391 (($ <udev-configuration> udev initial-rules)
1392 (udev-configuration
1393 (udev udev)
1394 (rules (append initial-rules rules)))))))))
1395
255f7308 1396(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
1397 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
1398extra rules from the packages listed in @var{rules}."
0adfe95a
LC
1399 (service udev-service-type
1400 (udev-configuration (udev udev) (rules rules))))
1401
0adfe95a 1402(define swap-service-type
d4053c71 1403 (shepherd-service-type
00184239 1404 'swap
0adfe95a
LC
1405 (lambda (device)
1406 (define requirement
1407 (if (string-prefix? "/dev/mapper/" device)
1408 (list (symbol-append 'device-mapping-
1409 (string->symbol (basename device))))
1410 '()))
1411
d4053c71 1412 (shepherd-service
0adfe95a
LC
1413 (provision (list (symbol-append 'swap- (string->symbol device))))
1414 (requirement `(udev ,@requirement))
1415 (documentation "Enable the given swap device.")
1416 (start #~(lambda ()
1417 (restart-on-EINTR (swapon #$device))
1418 #t))
1419 (stop #~(lambda _
1420 (restart-on-EINTR (swapoff #$device))
1421 #f))
1422 (respawn? #f)))))
5dae0186 1423
2a13d05e
LC
1424(define (swap-service device)
1425 "Return a service that uses @var{device} as a swap device."
0adfe95a 1426 (service swap-service-type device))
2a13d05e 1427
8664cc88
LC
1428(define-record-type* <gpm-configuration>
1429 gpm-configuration make-gpm-configuration gpm-configuration?
1430 (gpm gpm-configuration-gpm) ;package
1431 (options gpm-configuration-options)) ;list of strings
1432
d4053c71 1433(define gpm-shepherd-service
8664cc88 1434 (match-lambda
a907d997 1435 (($ <gpm-configuration> gpm options)
d4053c71 1436 (list (shepherd-service
8664cc88
LC
1437 (requirement '(udev))
1438 (provision '(gpm))
1439 (start #~(lambda ()
1440 ;; 'gpm' runs in the background and sets a PID file.
1441 ;; Note that it requires running as "root".
1442 (false-if-exception (delete-file "/var/run/gpm.pid"))
9fc037fe 1443 (fork+exec-command (list #$(file-append gpm "/sbin/gpm")
8664cc88
LC
1444 #$@options))
1445
1446 ;; Wait for the PID file to appear; declare failure if
1447 ;; it doesn't show up.
1448 (let loop ((i 3))
1449 (or (file-exists? "/var/run/gpm.pid")
1450 (if (zero? i)
1451 #f
1452 (begin
1453 (sleep 1)
1454 (loop (1- i))))))))
1455
1456 (stop #~(lambda (_)
1457 ;; Return #f if successfully stopped.
9fc037fe 1458 (not (zero? (system* #$(file-append gpm "/sbin/gpm")
8664cc88
LC
1459 "-k"))))))))))
1460
1461(define gpm-service-type
1462 (service-type (name 'gpm)
1463 (extensions
d4053c71
AK
1464 (list (service-extension shepherd-root-service-type
1465 gpm-shepherd-service)))))
8664cc88
LC
1466
1467(define* (gpm-service #:key (gpm gpm)
1468 (options '("-m" "/dev/input/mice" "-t" "ps2")))
1469 "Run @var{gpm}, the general-purpose mouse daemon, with the given
1470command-line @var{options}. GPM allows users to use the mouse in the console,
1471notably to select, copy, and paste text. The default value of @var{options}
1472uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
1473
1474This service is not part of @var{%base-services}."
1475 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
1476 ;; "info mice" and "mouse_set X" to use the right mouse.
1477 (service gpm-service-type
1478 (gpm-configuration (gpm gpm) (options options))))
1479
46ec2707
DC
1480(define-record-type* <kmscon-configuration>
1481 kmscon-configuration make-kmscon-configuration
1482 kmscon-configuration?
1483 (kmscon kmscon-configuration-kmscon
1484 (default kmscon))
1485 (virtual-terminal kmscon-configuration-virtual-terminal)
1486 (login-program kmscon-configuration-login-program
9fc037fe 1487 (default (file-append shadow "/bin/login")))
46ec2707
DC
1488 (login-arguments kmscon-configuration-login-arguments
1489 (default '("-p")))
1490 (hardware-acceleration? kmscon-configuration-hardware-acceleration?
1491 (default #f))) ; #t causes failure
1492
1493(define kmscon-service-type
1494 (shepherd-service-type
1495 'kmscon
1496 (lambda (config)
1497 (let ((kmscon (kmscon-configuration-kmscon config))
1498 (virtual-terminal (kmscon-configuration-virtual-terminal config))
1499 (login-program (kmscon-configuration-login-program config))
1500 (login-arguments (kmscon-configuration-login-arguments config))
1501 (hardware-acceleration? (kmscon-configuration-hardware-acceleration? config)))
1502
1503 (define kmscon-command
1504 #~(list
9fc037fe 1505 #$(file-append kmscon "/bin/kmscon") "--login"
46ec2707
DC
1506 "--vt" #$virtual-terminal
1507 #$@(if hardware-acceleration? '("--hwaccel") '())
1508 "--" #$login-program #$@login-arguments))
1509
1510 (shepherd-service
1511 (documentation "kmscon virtual terminal")
1512 (requirement '(user-processes udev dbus-system))
1513 (provision (list (symbol-append 'term- (string->symbol virtual-terminal))))
1514 (start #~(make-forkexec-constructor #$kmscon-command))
1515 (stop #~(make-kill-destructor)))))))
1516
8664cc88 1517\f
8b198abe
LC
1518(define %base-services
1519 ;; Convenience variable holding the basic services.
317d3b47
DC
1520 (list (login-service)
1521
4a84a487
LC
1522 (service console-font-service-type
1523 (map (lambda (tty)
1524 (cons tty %default-console-font))
1525 '("tty1" "tty2" "tty3" "tty4" "tty5" "tty6")))
317d3b47
DC
1526
1527 (mingetty-service (mingetty-configuration
1528 (tty "tty1")))
1529 (mingetty-service (mingetty-configuration
1530 (tty "tty2")))
1531 (mingetty-service (mingetty-configuration
1532 (tty "tty3")))
1533 (mingetty-service (mingetty-configuration
1534 (tty "tty4")))
1535 (mingetty-service (mingetty-configuration
1536 (tty "tty5")))
1537 (mingetty-service (mingetty-configuration
1538 (tty "tty6")))
1539
1540 (static-networking-service "lo" "127.0.0.1"
1541 #:provision '(loopback))
1542 (syslog-service)
1543 (urandom-seed-service)
1544 (guix-service)
1545 (nscd-service)
1546
1547 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
1548 ;; used, so enable them by default. The FUSE and ALSA rules are
1549 ;; less critical, but handy.
1550 (udev-service #:rules (list lvm2 fuse alsa-utils crda))))
8b198abe 1551
db4fdc04 1552;;; base.scm ends here