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