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