services: %base-services: Use nscd-service-type.
[jackhill/guix/guix.git] / gnu / services / base.scm
CommitLineData
db4fdc04 1;;; GNU Guix --- Functional package management for GNU
65a67bf7 2;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 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>
2d9dace8 9;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
db903549 10;;; Copyright © 2019 Efraim Flashner <efraim@flashner.co.il>
db4fdc04
LC
11;;;
12;;; This file is part of GNU Guix.
13;;;
14;;; GNU Guix is free software; you can redistribute it and/or modify it
15;;; under the terms of the GNU General Public License as published by
16;;; the Free Software Foundation; either version 3 of the License, or (at
17;;; your option) any later version.
18;;;
19;;; GNU Guix is distributed in the hope that it will be useful, but
20;;; WITHOUT ANY WARRANTY; without even the implied warranty of
21;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;;; GNU General Public License for more details.
23;;;
24;;; You should have received a copy of the GNU General Public License
25;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
26
27(define-module (gnu services base)
e87f0591 28 #:use-module (guix store)
65a67bf7 29 #:use-module (guix deprecation)
db4fdc04 30 #:use-module (gnu services)
0190c1c0 31 #:use-module (gnu services shepherd)
6e828634 32 #:use-module (gnu system pam)
db4fdc04 33 #:use-module (gnu system shadow) ; 'user-account', etc.
d1ff5f9d 34 #:use-module (gnu system uuid)
0adfe95a 35 #:use-module (gnu system file-systems) ; 'file-system', etc.
060d62a7 36 #:use-module (gnu system mapped-devices)
278d486b
LC
37 #:use-module ((gnu system linux-initrd)
38 #:select (file-system-packages))
db4fdc04 39 #:use-module (gnu packages admin)
151a2c07 40 #:use-module ((gnu packages linux)
b58cbf9a 41 #:select (alsa-utils crda eudev e2fsprogs fuse gpm kbd lvm2 rng-tools))
db4fdc04 42 #:use-module ((gnu packages base)
412701b0 43 #:select (canonical-package glibc glibc-utf8-locales))
387e1754 44 #:use-module (gnu packages bash)
db4fdc04 45 #:use-module (gnu packages package-management)
9ee4c9ab 46 #:use-module (gnu packages linux)
46ec2707 47 #:use-module (gnu packages terminals)
e2f4b305 48 #:use-module ((gnu build file-systems)
2c071ce9 49 #:select (mount-flags->bit-mask))
b5f4e686 50 #:use-module (guix gexp)
6454b333 51 #:use-module (guix records)
943e1b97 52 #:use-module (guix modules)
db4fdc04
LC
53 #:use-module (srfi srfi-1)
54 #:use-module (srfi srfi-26)
6454b333 55 #:use-module (ice-9 match)
db4fdc04 56 #:use-module (ice-9 format)
e43e84ba
LC
57 #:export (fstab-service-type
58 root-file-system-service
aa1145df 59 file-system-service-type
2a13d05e 60 swap-service
206a28d8 61 user-processes-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
bb3062ad 67 virtual-terminal-service-type
c797fabe 68
c9436025
DM
69 static-networking
70
71 static-networking?
72 static-networking-interface
73 static-networking-ip
74 static-networking-netmask
75 static-networking-gateway
76 static-networking-requirement
77
78 static-networking-service
79 static-networking-service-type
80
c797fabe
RW
81 udev-configuration
82 udev-configuration?
83 udev-configuration-rules
0adfe95a 84 udev-service-type
151a2c07 85 udev-service
80e6f37e 86 udev-rule
6e644cfd 87 file->udev-rule
66e4f01c 88
317d3b47
DC
89 login-configuration
90 login-configuration?
91 login-service-type
92 login-service
93
9ee4c9ab
LF
94 agetty-configuration
95 agetty-configuration?
96 agetty-service
97 agetty-service-type
98
66e4f01c
LC
99 mingetty-configuration
100 mingetty-configuration?
db4fdc04 101 mingetty-service
cd6f6c22 102 mingetty-service-type
6454b333
LC
103
104 %nscd-default-caches
105 %nscd-default-configuration
106
107 nscd-configuration
108 nscd-configuration?
109
110 nscd-cache
111 nscd-cache?
112
0adfe95a 113 nscd-service-type
db4fdc04 114 nscd-service
ec2e2f6c
DC
115
116 syslog-configuration
117 syslog-configuration?
db4fdc04 118 syslog-service
9009538d 119 syslog-service-type
44abcb28 120 %default-syslog.conf
0adfe95a 121
5b58c28b 122 %default-authorized-guix-keys
0adfe95a
LC
123 guix-configuration
124 guix-configuration?
70dfa4e0
MO
125
126 guix-configuration-guix
127 guix-configuration-build-group
128 guix-configuration-build-accounts
129 guix-configuration-authorize-key?
130 guix-configuration-authorized-keys
131 guix-configuration-use-substitutes?
132 guix-configuration-substitute-urls
133 guix-configuration-extra-options
134 guix-configuration-log-file
70dfa4e0 135
8b198abe 136 guix-service
cd6f6c22 137 guix-service-type
1c52181f
LC
138 guix-publish-configuration
139 guix-publish-configuration?
f1e900a3
LC
140 guix-publish-configuration-guix
141 guix-publish-configuration-port
142 guix-publish-configuration-host
697ddb88
LC
143 guix-publish-configuration-compression-level
144 guix-publish-configuration-nar-path
a35136cb
LC
145 guix-publish-configuration-cache
146 guix-publish-configuration-ttl
1c52181f
LC
147 guix-publish-service
148 guix-publish-service-type
24e96431
149
150 gpm-configuration
151 gpm-configuration?
8664cc88
LC
152 gpm-service-type
153 gpm-service
0adfe95a 154
9009538d 155 urandom-seed-service-type
a535e122 156 urandom-seed-service
24e96431
157
158 rngd-configuration
159 rngd-configuration?
b58cbf9a
DC
160 rngd-service-type
161 rngd-service
46ec2707
DC
162
163 kmscon-configuration
164 kmscon-configuration?
165 kmscon-service-type
166
909147e4
RW
167 pam-limits-service-type
168 pam-limits-service
a535e122 169
8b198abe 170 %base-services))
db4fdc04
LC
171
172;;; Commentary:
173;;;
174;;; Base system services---i.e., services that 99% of the users will want to
175;;; use.
176;;;
177;;; Code:
178
206a28d8
LC
179
180\f
181;;;
182;;; User processes.
183;;;
184
185(define %do-not-kill-file
186 ;; Name of the file listing PIDs of processes that must survive when halting
187 ;; the system. Typical example is user-space file systems.
188 "/etc/shepherd/do-not-kill")
189
190(define (user-processes-shepherd-service requirements)
191 "Return the 'user-processes' Shepherd service with dependencies on
192REQUIREMENTS (a list of service names).
193
194This is a synchronization point used to make sure user processes and daemons
195get started only after crucial initial services have been started---file
196system mounts, etc. This is similar to the 'sysvinit' target in systemd."
197 (define grace-delay
198 ;; Delay after sending SIGTERM and before sending SIGKILL.
199 4)
200
201 (list (shepherd-service
202 (documentation "When stopped, terminate all user processes.")
203 (provision '(user-processes))
204 (requirement requirements)
205 (start #~(const #t))
206 (stop #~(lambda _
207 (define (kill-except omit signal)
208 ;; Kill all the processes with SIGNAL except those listed
209 ;; in OMIT and the current process.
210 (let ((omit (cons (getpid) omit)))
211 (for-each (lambda (pid)
212 (unless (memv pid omit)
213 (false-if-exception
214 (kill pid signal))))
215 (processes))))
216
217 (define omitted-pids
218 ;; List of PIDs that must not be killed.
219 (if (file-exists? #$%do-not-kill-file)
220 (map string->number
221 (call-with-input-file #$%do-not-kill-file
222 (compose string-tokenize
223 (@ (ice-9 rdelim) read-string))))
224 '()))
225
226 (define (now)
227 (car (gettimeofday)))
228
229 (define (sleep* n)
230 ;; Really sleep N seconds.
231 ;; Work around <http://bugs.gnu.org/19581>.
232 (define start (now))
233 (let loop ((elapsed 0))
234 (when (> n elapsed)
235 (sleep (- n elapsed))
236 (loop (- (now) start)))))
237
238 (define lset= (@ (srfi srfi-1) lset=))
239
240 (display "sending all processes the TERM signal\n")
241
242 (if (null? omitted-pids)
243 (begin
244 ;; Easy: terminate all of them.
245 (kill -1 SIGTERM)
246 (sleep* #$grace-delay)
247 (kill -1 SIGKILL))
248 (begin
249 ;; Kill them all except OMITTED-PIDS. XXX: We would
250 ;; like to (kill -1 SIGSTOP) to get a fixed list of
251 ;; processes, like 'killall5' does, but that seems
252 ;; unreliable.
253 (kill-except omitted-pids SIGTERM)
254 (sleep* #$grace-delay)
255 (kill-except omitted-pids SIGKILL)
256 (delete-file #$%do-not-kill-file)))
257
258 (let wait ()
259 ;; Reap children, if any, so that we don't end up with
260 ;; zombies and enter an infinite loop.
261 (let reap-children ()
262 (define result
263 (false-if-exception
264 (waitpid WAIT_ANY (if (null? omitted-pids)
265 0
266 WNOHANG))))
267
268 (when (and (pair? result)
269 (not (zero? (car result))))
270 (reap-children)))
271
272 (let ((pids (processes)))
273 (unless (lset= = pids (cons 1 omitted-pids))
274 (format #t "waiting for process termination\
275 (processes left: ~s)~%"
276 pids)
277 (sleep* 2)
278 (wait))))
279
280 (display "all processes have been terminated\n")
281 #f))
282 (respawn? #f))))
283
284(define user-processes-service-type
285 (service-type
286 (name 'user-processes)
287 (extensions (list (service-extension shepherd-root-service-type
288 user-processes-shepherd-service)))
289 (compose concatenate)
290 (extend append)
291
292 ;; The value is the list of Shepherd services 'user-processes' depends on.
293 ;; Extensions can add new services to this list.
294 (default-value '())
295
296 (description "The @code{user-processes} service is responsible for
297terminating all the processes so that the root file system can be re-mounted
298read-only, just before rebooting/halting. Processes still running after a few
299seconds after @code{SIGTERM} has been sent are terminated with
300@code{SIGKILL}.")))
301
0adfe95a
LC
302\f
303;;;
304;;; File systems.
305;;;
a00dd9fb 306
e43e84ba
LC
307(define (file-system->fstab-entry file-system)
308 "Return a @file{/etc/fstab} entry for @var{file-system}."
a5acc17a
LC
309 (string-append (match (file-system-device file-system)
310 ((? file-system-label? label)
311 (string-append "LABEL="
0d56d9c7 312 (file-system-label->string label)))
a5acc17a
LC
313 ((? uuid? uuid)
314 (string-append "UUID=" (uuid->string uuid)))
315 ((? string? device)
316 device))
e43e84ba
LC
317 "\t"
318 (file-system-mount-point file-system) "\t"
319 (file-system-type file-system) "\t"
320 (or (file-system-options file-system) "defaults") "\t"
321
322 ;; XXX: Omit the 'fs_freq' and 'fs_passno' fields because we
323 ;; don't have anything sensible to put in there.
324 ))
325
326(define (file-systems->fstab file-systems)
327 "Return a @file{/etc} entry for an @file{fstab} describing
328@var{file-systems}."
329 `(("fstab" ,(plain-file "fstab"
330 (string-append
331 "\
332# This file was generated from your GuixSD configuration. Any changes
333# will be lost upon reboot or reconfiguration.\n\n"
334 (string-join (map file-system->fstab-entry
335 file-systems)
336 "\n")
337 "\n")))))
338
339(define fstab-service-type
340 ;; The /etc/fstab service.
341 (service-type (name 'fstab)
342 (extensions
343 (list (service-extension etc-service-type
344 file-systems->fstab)))
aa1145df 345 (compose concatenate)
6b9e1fef
LC
346 (extend append)
347 (description
348 "Populate the @file{/etc/fstab} based on the given file
349system objects.")))
e43e84ba 350
d4053c71
AK
351(define %root-file-system-shepherd-service
352 (shepherd-service
be1c2c54
LC
353 (documentation "Take care of the root file system.")
354 (provision '(root-file-system))
355 (start #~(const #t))
356 (stop #~(lambda _
357 ;; Return #f if successfully stopped.
358 (sync)
359
360 (call-with-blocked-asyncs
361 (lambda ()
362 (let ((null (%make-void-port "w")))
34044d55 363 ;; Close 'shepherd.log'.
be1c2c54 364 (display "closing log\n")
34044d55 365 ((@ (shepherd comm) stop-logging))
be1c2c54
LC
366
367 ;; Redirect the default output ports..
368 (set-current-output-port null)
369 (set-current-error-port null)
370
371 ;; Close /dev/console.
372 (for-each close-fdes '(0 1 2))
373
374 ;; At this point, there are no open files left, so the
375 ;; root file system can be re-mounted read-only.
376 (mount #f "/" #f
377 (logior MS_REMOUNT MS_RDONLY)
378 #:update-mtab? #f)
379
380 #f)))))
381 (respawn? #f)))
a00dd9fb 382
0adfe95a 383(define root-file-system-service-type
d4053c71
AK
384 (shepherd-service-type 'root-file-system
385 (const %root-file-system-shepherd-service)))
0adfe95a
LC
386
387(define (root-file-system-service)
388 "Return a service whose sole purpose is to re-mount read-only the root file
389system upon shutdown (aka. cleanly \"umounting\" root.)
390
391This service must be the root of the service dependency graph so that its
d4053c71 392'stop' action is invoked when shepherd is the only process left."
0adfe95a
LC
393 (service root-file-system-service-type #f))
394
d4053c71 395(define (file-system->shepherd-service-name file-system)
0adfe95a
LC
396 "Return the symbol that denotes the service mounting and unmounting
397FILE-SYSTEM."
398 (symbol-append 'file-system-
399 (string->symbol (file-system-mount-point file-system))))
400
d4053c71
AK
401(define (mapped-device->shepherd-service-name md)
402 "Return the symbol that denotes the shepherd service of MD, a <mapped-device>."
e502bf89
LC
403 (symbol-append 'device-mapping-
404 (string->symbol (mapped-device-target md))))
405
d4053c71 406(define dependency->shepherd-service-name
e502bf89
LC
407 (match-lambda
408 ((? mapped-device? md)
d4053c71 409 (mapped-device->shepherd-service-name md))
e502bf89 410 ((? file-system? fs)
d4053c71 411 (file-system->shepherd-service-name fs))))
e502bf89 412
d4053c71 413(define (file-system-shepherd-service file-system)
aa1145df
LC
414 "Return the shepherd service for @var{file-system}, or @code{#f} if
415@var{file-system} is not auto-mounted upon boot."
e43e84ba 416 (let ((target (file-system-mount-point file-system))
e43e84ba 417 (create? (file-system-create-mount-point? file-system))
26e34e1e
DM
418 (dependencies (file-system-dependencies file-system))
419 (packages (file-system-packages (list file-system))))
aa1145df 420 (and (file-system-mount? file-system)
943e1b97
LC
421 (with-imported-modules (source-module-closure
422 '((gnu build file-systems)))
a91c3fc7
LC
423 (shepherd-service
424 (provision (list (file-system->shepherd-service-name file-system)))
c106d03b 425 (requirement `(root-file-system udev
a91c3fc7
LC
426 ,@(map dependency->shepherd-service-name dependencies)))
427 (documentation "Check, mount, and unmount the given file system.")
428 (start #~(lambda args
9970ef61 429 #$(if create?
bf7ef1bb
JD
430 #~(mkdir-p #$target)
431 #t)
9328eafb
LC
432
433 (let (($PATH (getenv "PATH")))
434 ;; Make sure fsck.ext2 & co. can be found.
435 (dynamic-wind
436 (lambda ()
26e34e1e
DM
437 ;; Don’t display the PATH settings.
438 (with-output-to-port (%make-void-port "w")
439 (lambda ()
440 (set-path-environment-variable "PATH"
441 '("bin" "sbin")
442 '#$packages))))
9328eafb
LC
443 (lambda ()
444 (mount-file-system
1c65cca5
LC
445 (spec->file-system
446 '#$(file-system->spec file-system))
9328eafb
LC
447 #:root "/"))
448 (lambda ()
449 (setenv "PATH" $PATH)))
450 #t)))
a91c3fc7
LC
451 (stop #~(lambda args
452 ;; Normally there are no processes left at this point, so
453 ;; TARGET can be safely unmounted.
454
455 ;; Make sure PID 1 doesn't keep TARGET busy.
456 (chdir "/")
457
458 (umount #$target)
459 #f))
460
1c65cca5 461 ;; We need additional modules.
a91c3fc7 462 (modules `(((gnu build file-systems)
bf7ef1bb 463 #:select (mount-file-system))
1c65cca5 464 (gnu system file-systems)
aa1145df 465 ,@%default-modules)))))))
e43e84ba 466
a43aca97
LC
467(define (file-system-shepherd-services file-systems)
468 "Return the list of Shepherd services for FILE-SYSTEMS."
469 (let* ((file-systems (filter file-system-mount? file-systems)))
470 (define sink
471 (shepherd-service
472 (provision '(file-systems))
473 (requirement (cons* 'root-file-system 'user-file-systems
474 (map file-system->shepherd-service-name
475 file-systems)))
476 (documentation "Target for all the initially-mounted file systems")
477 (start #~(const #t))
478 (stop #~(const #f))))
479
6c445817
LC
480 (define known-mount-points
481 (map file-system-mount-point file-systems))
482
483 (define user-unmount
484 (shepherd-service
485 (documentation "Unmount manually-mounted file systems.")
486 (provision '(user-file-systems))
487 (start #~(const #t))
488 (stop #~(lambda args
489 (define (known? mount-point)
490 (member mount-point
491 (cons* "/proc" "/sys" '#$known-mount-points)))
492
493 ;; Make sure we don't keep the user's mount points busy.
494 (chdir "/")
495
496 (for-each (lambda (mount-point)
497 (format #t "unmounting '~a'...~%" mount-point)
498 (catch 'system-error
499 (lambda ()
500 (umount mount-point))
501 (lambda args
502 (let ((errno (system-error-errno args)))
503 (format #t "failed to unmount '~a': ~a~%"
504 mount-point (strerror errno))))))
505 (filter (negate known?) (mount-points)))
506 #f))))
507
508 (cons* sink user-unmount
509 (map file-system-shepherd-service file-systems))))
a43aca97 510
0adfe95a 511(define file-system-service-type
aa1145df 512 (service-type (name 'file-systems)
e43e84ba 513 (extensions
d4053c71 514 (list (service-extension shepherd-root-service-type
a43aca97 515 file-system-shepherd-services)
e43e84ba 516 (service-extension fstab-service-type
206a28d8
LC
517 identity)
518
519 ;; Have 'user-processes' depend on 'file-systems'.
520 (service-extension user-processes-service-type
521 (const '(file-systems)))))
aa1145df 522 (compose concatenate)
6b9e1fef
LC
523 (extend append)
524 (description
525 "Provide Shepherd services to mount and unmount the given
526file systems, as well as corresponding @file{/etc/fstab} entries.")))
0adfe95a 527
d6e2a622 528
0adfe95a 529\f
a535e122
LF
530;;;
531;;; Preserve entropy to seed /dev/urandom on boot.
532;;;
533
534(define %random-seed-file
535 "/var/lib/random-seed")
536
a535e122
LF
537(define (urandom-seed-shepherd-service _)
538 "Return a shepherd service for the /dev/urandom seed."
539 (list (shepherd-service
540 (documentation "Preserve entropy across reboots for /dev/urandom.")
541 (provision '(urandom-seed))
4a32f58a
LC
542
543 ;; Depend on udev so that /dev/hwrng is available.
544 (requirement '(file-systems udev))
545
a535e122
LF
546 (start #~(lambda _
547 ;; On boot, write random seed into /dev/urandom.
548 (when (file-exists? #$%random-seed-file)
549 (call-with-input-file #$%random-seed-file
550 (lambda (seed)
551 (call-with-output-file "/dev/urandom"
552 (lambda (urandom)
553 (dump-port seed urandom))))))
9a56cf2b
LF
554
555 ;; Try writing from /dev/hwrng into /dev/urandom.
556 ;; It seems that the file /dev/hwrng always exists, even
557 ;; when there is no hardware random number generator
558 ;; available. So, we handle a failed read or any other error
559 ;; reported by the operating system.
560 (let ((buf (catch 'system-error
561 (lambda ()
562 (call-with-input-file "/dev/hwrng"
563 (lambda (hwrng)
564 (get-bytevector-n hwrng 512))))
565 ;; Silence is golden...
566 (const #f))))
567 (when buf
568 (call-with-output-file "/dev/urandom"
569 (lambda (urandom)
570 (put-bytevector urandom buf)))))
571
71cb237a
LF
572 ;; Immediately refresh the seed in case the system doesn't
573 ;; shut down cleanly.
574 (call-with-input-file "/dev/urandom"
575 (lambda (urandom)
576 (let ((previous-umask (umask #o077))
577 (buf (make-bytevector 512)))
578 (mkdir-p (dirname #$%random-seed-file))
579 (get-bytevector-n! urandom buf 0 512)
580 (call-with-output-file #$%random-seed-file
581 (lambda (seed)
582 (put-bytevector seed buf)))
583 (umask previous-umask))))
a535e122
LF
584 #t))
585 (stop #~(lambda _
586 ;; During shutdown, write from /dev/urandom into random seed.
587 (let ((buf (make-bytevector 512)))
588 (call-with-input-file "/dev/urandom"
589 (lambda (urandom)
8fe5d95e
LF
590 (let ((previous-umask (umask #o077)))
591 (get-bytevector-n! urandom buf 0 512)
71cb237a 592 (mkdir-p (dirname #$%random-seed-file))
8fe5d95e
LF
593 (call-with-output-file #$%random-seed-file
594 (lambda (seed)
595 (put-bytevector seed buf)))
596 (umask previous-umask))
a535e122
LF
597 #t)))))
598 (modules `((rnrs bytevectors)
599 (rnrs io ports)
600 ,@%default-modules)))))
601
602(define urandom-seed-service-type
603 (service-type (name 'urandom-seed)
604 (extensions
605 (list (service-extension shepherd-root-service-type
4e9fd508
LC
606 urandom-seed-shepherd-service)
607
608 ;; Have 'user-processes' depend on 'urandom-seed'.
609 ;; This ensures that user processes and daemons don't
610 ;; start until we have seeded the PRNG.
611 (service-extension user-processes-service-type
612 (const '(urandom-seed)))))
8faaf8d7 613 (default-value #f)
6b9e1fef
LC
614 (description
615 "Seed the @file{/dev/urandom} pseudo-random number
616generator (RNG) with the value recorded when the system was last shut
617down.")))
a535e122 618
65a67bf7
LC
619(define-deprecated (urandom-seed-service)
620 urandom-seed-service-type
621 (service urandom-seed-service-type))
a535e122 622
b58cbf9a
DC
623
624;;;
625;;; Add hardware random number generator to entropy pool.
626;;;
627
628(define-record-type* <rngd-configuration>
629 rngd-configuration make-rngd-configuration
630 rngd-configuration?
631 (rng-tools rngd-configuration-rng-tools) ;package
632 (device rngd-configuration-device)) ;string
633
634(define rngd-service-type
635 (shepherd-service-type
636 'rngd
637 (lambda (config)
638 (define rng-tools (rngd-configuration-rng-tools config))
639 (define device (rngd-configuration-device config))
640
641 (define rngd-command
9e41130b 642 (list (file-append rng-tools "/sbin/rngd")
b58cbf9a
DC
643 "-f" "-r" device))
644
645 (shepherd-service
646 (documentation "Add TRNG to entropy pool.")
647 (requirement '(udev))
648 (provision '(trng))
649 (start #~(make-forkexec-constructor #$@rngd-command))
650 (stop #~(make-kill-destructor))))))
651
652(define* (rngd-service #:key
653 (rng-tools rng-tools)
654 (device "/dev/hwrng"))
655 "Return a service that runs the @command{rngd} program from @var{rng-tools}
656to add @var{device} to the kernel's entropy pool. The service will fail if
657@var{device} does not exist."
658 (service rngd-service-type
659 (rngd-configuration
660 (rng-tools rng-tools)
661 (device device))))
662
e10964ef 663\f
0adfe95a
LC
664;;;
665;;; Console & co.
666;;;
667
668(define host-name-service-type
d4053c71 669 (shepherd-service-type
00184239 670 'host-name
0adfe95a 671 (lambda (name)
d4053c71 672 (shepherd-service
0adfe95a
LC
673 (documentation "Initialize the machine's host name.")
674 (provision '(host-name))
675 (start #~(lambda _
676 (sethostname #$name)))
677 (respawn? #f)))))
a00dd9fb 678
db4fdc04 679(define (host-name-service name)
51da7ca0 680 "Return a service that sets the host name to @var{name}."
0adfe95a 681 (service host-name-service-type name))
db4fdc04 682
bb3062ad
LC
683(define virtual-terminal-service-type
684 ;; Ensure that virtual terminals run in UTF-8 mode. This is the case by
685 ;; default with recent Linux kernels, but this service allows us to ensure
686 ;; this. This service must start before any 'term-' service so that newly
687 ;; created terminals inherit this property. See
688 ;; <https://bugs.gnu.org/30505> for a discussion.
689 (shepherd-service-type
690 'virtual-terminal
691 (lambda (utf8?)
09b7300c
LC
692 (let ((knob "/sys/module/vt/parameters/default_utf8"))
693 (shepherd-service
694 (documentation "Set virtual terminals in UTF-8 module.")
695 (provision '(virtual-terminal))
696 (requirement '(root-file-system))
697 (start #~(lambda _
698 ;; In containers /sys is read-only so don't insist on
699 ;; writing to this file.
700 (unless (= 1 (call-with-input-file #$knob read))
701 (call-with-output-file #$knob
702 (lambda (port)
703 (display 1 port))))
704 #t))
705 (stop #~(const #f)))))
bb3062ad 706 #t)) ;default to UTF-8
62ca0fdf 707
0adfe95a 708(define console-keymap-service-type
d4053c71 709 (shepherd-service-type
00184239 710 'console-keymap
b3d05f48 711 (lambda (files)
d4053c71 712 (shepherd-service
0adfe95a
LC
713 (documentation (string-append "Load console keymap (loadkeys)."))
714 (provision '(console-keymap))
715 (start #~(lambda _
9fc037fe 716 (zero? (system* #$(file-append kbd "/bin/loadkeys")
b3d05f48 717 #$@files))))
0adfe95a
LC
718 (respawn? #f)))))
719
b3d05f48
AK
720(define (console-keymap-service . files)
721 "Return a service to load console keymaps from @var{files}."
722 (service console-keymap-service-type files))
0adfe95a 723
4a84a487
LC
724(define %default-console-font
725 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
726 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
727 ;; codepoints notably found in the UTF-8 manual.
728 "LatGrkCyr-8x16")
729
730(define (console-font-shepherd-services tty+font)
731 "Return a list of Shepherd services for each pair in TTY+FONT."
732 (map (match-lambda
733 ((tty . font)
734 (let ((device (string-append "/dev/" tty)))
735 (shepherd-service
736 (documentation "Load a Unicode console font.")
737 (provision (list (symbol-append 'console-font-
738 (string->symbol tty))))
739
740 ;; Start after mingetty has been started on TTY, otherwise the settings
741 ;; are ignored.
742 (requirement (list (symbol-append 'term-
743 (string->symbol tty))))
744
745 (start #~(lambda _
787e8a80
LC
746 ;; It could be that mingetty is not fully ready yet,
747 ;; which we check by calling 'ttyname'.
748 (let loop ((i 10))
749 (unless (or (zero? i)
750 (call-with-input-file #$device
751 (lambda (port)
752 (false-if-exception (ttyname port)))))
753 (usleep 500)
754 (loop (- i 1))))
755
bb3062ad
LC
756 ;; Assume the VT is already in UTF-8 mode, thanks to
757 ;; the 'virtual-terminal' service.
758 ;;
759 ;; 'setfont' returns EX_OSERR (71) when an
760 ;; KDFONTOP ioctl fails, for example. Like
761 ;; systemd's vconsole support, let's not treat
762 ;; this as an error.
763 (case (status:exit-val
764 (system* #$(file-append kbd "/bin/setfont")
765 "-C" #$device #$font))
766 ((0 71) #t)
767 (else #f))))
4a84a487
LC
768 (stop #~(const #t))
769 (respawn? #f)))))
770 tty+font))
0adfe95a 771
4a84a487
LC
772(define console-font-service-type
773 (service-type (name 'console-fonts)
774 (extensions
775 (list (service-extension shepherd-root-service-type
776 console-font-shepherd-services)))
777 (compose concatenate)
6b9e1fef
LC
778 (extend append)
779 (description
780 "Install the given fonts on the specified ttys (fonts are per
781virtual console on GNU/Linux). The value of this service is a list of
782tty/font pairs like:
783
784@example
785'((\"tty1\" . \"LatGrkCyr-8x16\"))
786@end example\n")))
5eca9459 787
62ca0fdf 788(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
4a84a487
LC
789 "This procedure is deprecated in favor of @code{console-font-service-type}.
790
791Return a service that sets up Unicode support in @var{tty} and loads
62ca0fdf 792@var{font} for that tty (fonts are per virtual console in Linux.)"
4a84a487
LC
793 (simple-service (symbol-append 'console-font- (string->symbol tty))
794 console-font-service-type `((,tty . ,font))))
62ca0fdf 795
317d3b47
DC
796(define %default-motd
797 (plain-file "motd" "This is the GNU operating system, welcome!\n\n"))
798
799(define-record-type* <login-configuration>
800 login-configuration make-login-configuration
801 login-configuration?
802 (motd login-configuration-motd ;file-like
803 (default %default-motd))
804 ;; Allow empty passwords by default so that first-time users can log in when
805 ;; the 'root' account has just been created.
806 (allow-empty-passwords? login-configuration-allow-empty-passwords?
807 (default #t))) ;Boolean
808
809(define (login-pam-service config)
810 "Return the list of PAM service needed for CONF."
811 ;; Let 'login' be known to PAM.
812 (list (unix-pam-service "login"
813 #:allow-empty-passwords?
814 (login-configuration-allow-empty-passwords? config)
815 #:motd
816 (login-configuration-motd config))))
817
818(define login-service-type
819 (service-type (name 'login)
820 (extensions (list (service-extension pam-root-service-type
6b9e1fef
LC
821 login-pam-service)))
822 (description
823 "Provide a console log-in service as specified by its
824configuration value, a @code{login-configuration} object.")))
317d3b47
DC
825
826(define* (login-service #:optional (config (login-configuration)))
827 "Return a service configure login according to @var{config}, which specifies
828the message of the day, among other things."
829 (service login-service-type config))
830
9ee4c9ab
LF
831(define-record-type* <agetty-configuration>
832 agetty-configuration make-agetty-configuration
833 agetty-configuration?
834 (agetty agetty-configuration-agetty ;<package>
835 (default util-linux))
5a9902c8 836 (tty agetty-configuration-tty) ;string | #f
9ee4c9ab
LF
837 (term agetty-term ;string | #f
838 (default #f))
839 (baud-rate agetty-baud-rate ;string | #f
840 (default #f))
841 (auto-login agetty-auto-login ;list of strings | #f
842 (default #f))
843 (login-program agetty-login-program ;gexp
844 (default (file-append shadow "/bin/login")))
845 (login-pause? agetty-login-pause? ;Boolean
846 (default #f))
847 (eight-bits? agetty-eight-bits? ;Boolean
848 (default #f))
849 (no-reset? agetty-no-reset? ;Boolean
850 (default #f))
851 (remote? agetty-remote? ;Boolean
852 (default #f))
853 (flow-control? agetty-flow-control? ;Boolean
854 (default #f))
855 (host agetty-host ;string | #f
856 (default #f))
857 (no-issue? agetty-no-issue? ;Boolean
858 (default #f))
859 (init-string agetty-init-string ;string | #f
860 (default #f))
861 (no-clear? agetty-no-clear? ;Boolean
862 (default #f))
863 (local-line agetty-local-line ;always | never | auto
864 (default #f))
865 (extract-baud? agetty-extract-baud? ;Boolean
866 (default #f))
867 (skip-login? agetty-skip-login? ;Boolean
868 (default #f))
869 (no-newline? agetty-no-newline? ;Boolean
870 (default #f))
871 (login-options agetty-login-options ;string | #f
872 (default #f))
873 (chroot agetty-chroot ;string | #f
874 (default #f))
875 (hangup? agetty-hangup? ;Boolean
876 (default #f))
877 (keep-baud? agetty-keep-baud? ;Boolean
878 (default #f))
879 (timeout agetty-timeout ;integer | #f
880 (default #f))
881 (detect-case? agetty-detect-case? ;Boolean
882 (default #f))
883 (wait-cr? agetty-wait-cr? ;Boolean
884 (default #f))
885 (no-hints? agetty-no-hints? ;Boolean
886 (default #f))
887 (no-hostname? agetty-no hostname? ;Boolean
888 (default #f))
889 (long-hostname? agetty-long-hostname? ;Boolean
890 (default #f))
891 (erase-characters agetty-erase-characters ;string | #f
892 (default #f))
893 (kill-characters agetty-kill-characters ;string | #f
894 (default #f))
895 (chdir agetty-chdir ;string | #f
896 (default #f))
897 (delay agetty-delay ;integer | #f
898 (default #f))
899 (nice agetty-nice ;integer | #f
900 (default #f))
901 ;; "Escape hatch" for passing arbitrary command-line arguments.
902 (extra-options agetty-extra-options ;list of strings
903 (default '()))
904;;; XXX Unimplemented for now!
905;;; (issue-file agetty-issue-file ;file-like
906;;; (default #f))
907 )
908
5a9902c8
DM
909(define (default-serial-port)
910 "Return a gexp that determines a reasonable default serial port
911to use as the tty. This is primarily useful for headless systems."
912 #~(begin
913 ;; console=device,options
914 ;; device: can be tty0, ttyS0, lp0, ttyUSB0 (serial).
915 ;; options: BBBBPNF. P n|o|e, N number of bits,
916 ;; F flow control (r RTS)
917 (let* ((not-comma (char-set-complement (char-set #\,)))
918 (command (linux-command-line))
919 (agetty-specs (find-long-options "agetty.tty" command))
920 (console-specs (filter (lambda (spec)
921 (and (string-prefix? "tty" spec)
922 (not (or
923 (string-prefix? "tty0" spec)
924 (string-prefix? "tty1" spec)
925 (string-prefix? "tty2" spec)
926 (string-prefix? "tty3" spec)
927 (string-prefix? "tty4" spec)
928 (string-prefix? "tty5" spec)
929 (string-prefix? "tty6" spec)
930 (string-prefix? "tty7" spec)
931 (string-prefix? "tty8" spec)
932 (string-prefix? "tty9" spec)))))
933 (find-long-options "console" command)))
934 (specs (append agetty-specs console-specs)))
935 (match specs
936 (() #f)
937 ((spec _ ...)
938 ;; Extract device name from first spec.
939 (match (string-tokenize spec not-comma)
940 ((device-name _ ...)
941 device-name)))))))
942
9ee4c9ab
LF
943(define agetty-shepherd-service
944 (match-lambda
945 (($ <agetty-configuration> agetty tty term baud-rate auto-login
946 login-program login-pause? eight-bits? no-reset? remote? flow-control?
947 host no-issue? init-string no-clear? local-line extract-baud?
948 skip-login? no-newline? login-options chroot hangup? keep-baud? timeout
949 detect-case? wait-cr? no-hints? no-hostname? long-hostname?
950 erase-characters kill-characters chdir delay nice extra-options)
951 (list
952 (shepherd-service
5a9902c8 953 (modules '((ice-9 match) (gnu build linux-boot)))
9ee4c9ab 954 (documentation "Run agetty on a tty.")
5a9902c8 955 (provision (list (symbol-append 'term- (string->symbol (or tty "auto")))))
9ee4c9ab
LF
956
957 ;; Since the login prompt shows the host name, wait for the 'host-name'
958 ;; service to be done. Also wait for udev essentially so that the tty
959 ;; text is not lost in the middle of kernel messages (see also
960 ;; mingetty-shepherd-service).
961 (requirement '(user-processes host-name udev))
962
c32e3dde
DM
963 (start #~(lambda args
964 (let ((defaulted-tty #$(or tty (default-serial-port))))
965 (apply
966 (if defaulted-tty
967 (make-forkexec-constructor
968 (list #$(file-append util-linux "/sbin/agetty")
969 #$@extra-options
970 #$@(if eight-bits?
971 #~("--8bits")
972 #~())
973 #$@(if no-reset?
974 #~("--noreset")
975 #~())
976 #$@(if remote?
977 #~("--remote")
978 #~())
979 #$@(if flow-control?
980 #~("--flow-control")
981 #~())
982 #$@(if host
983 #~("--host" #$host)
984 #~())
985 #$@(if no-issue?
986 #~("--noissue")
987 #~())
988 #$@(if init-string
989 #~("--init-string" #$init-string)
990 #~())
991 #$@(if no-clear?
992 #~("--noclear")
993 #~())
9ee4c9ab
LF
994;;; FIXME This doesn't work as expected. According to agetty(8), if this option
995;;; is not passed, then the default is 'auto'. However, in my tests, when that
996;;; option is selected, agetty never presents the login prompt, and the
997;;; term-ttyS0 service respawns every few seconds.
c32e3dde
DM
998 #$@(if local-line
999 #~(#$(match local-line
1000 ('auto "--local-line=auto")
1001 ('always "--local-line=always")
1002 ('never "-local-line=never")))
1003 #~())
1004 #$@(if tty
1005 #~()
1006 #~("--keep-baud"))
1007 #$@(if extract-baud?
1008 #~("--extract-baud")
1009 #~())
1010 #$@(if skip-login?
1011 #~("--skip-login")
1012 #~())
1013 #$@(if no-newline?
1014 #~("--nonewline")
1015 #~())
1016 #$@(if login-options
1017 #~("--login-options" #$login-options)
1018 #~())
1019 #$@(if chroot
1020 #~("--chroot" #$chroot)
1021 #~())
1022 #$@(if hangup?
1023 #~("--hangup")
1024 #~())
1025 #$@(if keep-baud?
1026 #~("--keep-baud")
1027 #~())
1028 #$@(if timeout
1029 #~("--timeout" #$(number->string timeout))
1030 #~())
1031 #$@(if detect-case?
1032 #~("--detect-case")
1033 #~())
1034 #$@(if wait-cr?
1035 #~("--wait-cr")
1036 #~())
1037 #$@(if no-hints?
1038 #~("--nohints?")
1039 #~())
1040 #$@(if no-hostname?
1041 #~("--nohostname")
1042 #~())
1043 #$@(if long-hostname?
1044 #~("--long-hostname")
1045 #~())
1046 #$@(if erase-characters
1047 #~("--erase-chars" #$erase-characters)
1048 #~())
1049 #$@(if kill-characters
1050 #~("--kill-chars" #$kill-characters)
1051 #~())
1052 #$@(if chdir
1053 #~("--chdir" #$chdir)
1054 #~())
1055 #$@(if delay
1056 #~("--delay" #$(number->string delay))
1057 #~())
1058 #$@(if nice
1059 #~("--nice" #$(number->string nice))
1060 #~())
1061 #$@(if auto-login
1062 (list "--autologin" auto-login)
1063 '())
1064 #$@(if login-program
1065 #~("--login-program" #$login-program)
1066 #~())
1067 #$@(if login-pause?
1068 #~("--login-pause")
1069 #~())
1070 defaulted-tty
1071 #$@(if baud-rate
1072 #~(#$baud-rate)
1073 #~())
1074 #$@(if term
1075 #~(#$term)
1076 #~())))
1077 (const #f)) ; never start.
1078 args))))
9ee4c9ab
LF
1079 (stop #~(make-kill-destructor)))))))
1080
1081(define agetty-service-type
1082 (service-type (name 'agetty)
1083 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1084 agetty-shepherd-service)))
1085 (description
1086 "Provide console login using the @command{agetty}
1087program.")))
9ee4c9ab
LF
1088
1089(define* (agetty-service config)
1090 "Return a service to run agetty according to @var{config}, which specifies
1091the tty to run, among other things."
1092 (service agetty-service-type config))
1093
66e4f01c
LC
1094(define-record-type* <mingetty-configuration>
1095 mingetty-configuration make-mingetty-configuration
1096 mingetty-configuration?
1097 (mingetty mingetty-configuration-mingetty ;<package>
1098 (default mingetty))
1099 (tty mingetty-configuration-tty) ;string
66e4f01c
LC
1100 (auto-login mingetty-auto-login ;string | #f
1101 (default #f))
1102 (login-program mingetty-login-program ;gexp
1103 (default #f))
1104 (login-pause? mingetty-login-pause? ;Boolean
317d3b47 1105 (default #f)))
0adfe95a 1106
d4053c71 1107(define mingetty-shepherd-service
0adfe95a 1108 (match-lambda
317d3b47
DC
1109 (($ <mingetty-configuration> mingetty tty auto-login login-program
1110 login-pause?)
0adfe95a 1111 (list
d4053c71 1112 (shepherd-service
0adfe95a
LC
1113 (documentation "Run mingetty on an tty.")
1114 (provision (list (symbol-append 'term- (string->symbol tty))))
1115
1116 ;; Since the login prompt shows the host name, wait for the 'host-name'
1117 ;; service to be done. Also wait for udev essentially so that the tty
1118 ;; text is not lost in the middle of kernel messages (XXX).
bb3062ad 1119 (requirement '(user-processes host-name udev virtual-terminal))
0adfe95a 1120
7e0a6fac
DM
1121 (start #~(make-forkexec-constructor
1122 (list #$(file-append mingetty "/sbin/mingetty")
a043b5b8
LC
1123 "--noclear"
1124
1125 ;; Avoiding 'vhangup' allows us to avoid 'setfont'
1126 ;; errors down the path where various ioctls get
1127 ;; EIO--see 'hung_up_tty_ioctl' in driver/tty/tty_io.c
1128 ;; in Linux.
1129 "--nohangup" #$tty
1130
7e0a6fac
DM
1131 #$@(if auto-login
1132 #~("--autologin" #$auto-login)
1133 #~())
1134 #$@(if login-program
1135 #~("--loginprog" #$login-program)
1136 #~())
1137 #$@(if login-pause?
1138 #~("--loginpause")
1139 #~()))))
0adfe95a
LC
1140 (stop #~(make-kill-destructor)))))))
1141
1142(define mingetty-service-type
1143 (service-type (name 'mingetty)
d4053c71 1144 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1145 mingetty-shepherd-service)))
1146 (description
1147 "Provide console login using the @command{mingetty}
1148program.")))
0adfe95a
LC
1149
1150(define* (mingetty-service config)
1151 "Return a service to run mingetty according to @var{config}, which specifies
1152the tty to run, among other things."
1153 (service mingetty-service-type config))
db4fdc04 1154
6454b333
LC
1155(define-record-type* <nscd-configuration> nscd-configuration
1156 make-nscd-configuration
1157 nscd-configuration?
1158 (log-file nscd-configuration-log-file ;string
1159 (default "/var/log/nscd.log"))
1160 (debug-level nscd-debug-level ;integer
1161 (default 0))
1162 ;; TODO: See nscd.conf in glibc for other options to add.
1163 (caches nscd-configuration-caches ;list of <nscd-cache>
b893f1ae
LC
1164 (default %nscd-default-caches))
1165 (name-services nscd-configuration-name-services ;list of <packages>
1166 (default '()))
1167 (glibc nscd-configuration-glibc ;<package>
1168 (default (canonical-package glibc))))
6454b333
LC
1169
1170(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
1171 nscd-cache?
1172 (database nscd-cache-database) ;symbol
1173 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
1174 (negative-time-to-live nscd-cache-negative-time-to-live
1175 (default 20)) ;integer
1176 (suggested-size nscd-cache-suggested-size ;integer ("default module
1177 ;of hash table")
1178 (default 211))
1179 (check-files? nscd-cache-check-files? ;Boolean
1180 (default #t))
1181 (persistent? nscd-cache-persistent? ;Boolean
1182 (default #t))
1183 (shared? nscd-cache-shared? ;Boolean
1184 (default #t))
1185 (max-database-size nscd-cache-max-database-size ;integer
1186 (default (* 32 (expt 2 20))))
1187 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
1188 (default #t)))
1189
1190(define %nscd-default-caches
1191 ;; Caches that we want to enable by default. Note that when providing an
1192 ;; empty nscd.conf, all caches are disabled.
1193 (list (nscd-cache (database 'hosts)
1194
1195 ;; Aggressively cache the host name cache to improve
1196 ;; privacy and resilience.
1197 (positive-time-to-live (* 3600 12))
1198 (negative-time-to-live 20)
1199 (persistent? #t))
1200
1201 (nscd-cache (database 'services)
1202
1203 ;; Services are unlikely to change, so we can be even more
1204 ;; aggressive.
1205 (positive-time-to-live (* 3600 24))
1206 (negative-time-to-live 3600)
1207 (check-files? #t) ;check /etc/services changes
1208 (persistent? #t))))
1209
1210(define %nscd-default-configuration
1211 ;; Default nscd configuration.
1212 (nscd-configuration))
1213
1214(define (nscd.conf-file config)
1215 "Return the @file{nscd.conf} configuration file for @var{config}, an
1216@code{<nscd-configuration>} object."
1217 (define cache->config
1218 (match-lambda
be1c2c54
LC
1219 (($ <nscd-cache> (= symbol->string database)
1220 positive-ttl negative-ttl size check-files?
1221 persistent? shared? max-size propagate?)
1222 (string-append "\nenable-cache\t" database "\tyes\n"
1223
1224 "positive-time-to-live\t" database "\t"
1225 (number->string positive-ttl) "\n"
1226 "negative-time-to-live\t" database "\t"
1227 (number->string negative-ttl) "\n"
1228 "suggested-size\t" database "\t"
1229 (number->string size) "\n"
1230 "check-files\t" database "\t"
1231 (if check-files? "yes\n" "no\n")
1232 "persistent\t" database "\t"
1233 (if persistent? "yes\n" "no\n")
1234 "shared\t" database "\t"
1235 (if shared? "yes\n" "no\n")
1236 "max-db-size\t" database "\t"
1237 (number->string max-size) "\n"
1238 "auto-propagate\t" database "\t"
1239 (if propagate? "yes\n" "no\n")))))
6454b333
LC
1240
1241 (match config
1242 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
1243 (plain-file "nscd.conf"
1244 (string-append "\
6454b333 1245# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
1246 (if log-file
1247 (string-append "logfile\t" log-file)
1248 "")
1249 "\n"
1250 (if debug-level
1251 (string-append "debug-level\t"
1252 (number->string debug-level))
1253 "")
1254 "\n"
1255 (string-concatenate
1256 (map cache->config caches)))))))
6454b333 1257
d3f75179
LC
1258(define (nscd-action-procedure nscd config option)
1259 ;; XXX: This is duplicated from mcron; factorize.
1260 #~(lambda (_ . args)
1261 ;; Run 'nscd' in a pipe so we can explicitly redirect its output to
1262 ;; 'current-output-port', which at this stage is bound to the client
1263 ;; connection.
1264 (let ((pipe (apply open-pipe* OPEN_READ #$nscd
1265 "-f" #$config #$option args)))
1266 (let loop ()
1267 (match (read-line pipe 'concat)
1268 ((? eof-object?)
1269 (catch 'system-error
1270 (lambda ()
1271 (zero? (close-pipe pipe)))
1272 (lambda args
1273 ;; There's a race with the SIGCHLD handler, which could
1274 ;; call 'waitpid' before 'close-pipe' above does. If we
1275 ;; get ECHILD, that means we lost the race, but that's
1276 ;; fine.
1277 (or (= ECHILD (system-error-errno args))
1278 (apply throw args)))))
1279 (line
1280 (display line)
1281 (loop)))))))
1282
1283(define (nscd-actions nscd config)
1284 "Return Shepherd actions for NSCD."
1285 ;; Make this functionality available as actions because that's a simple way
1286 ;; to run the right 'nscd' binary with the right config file.
1287 (list (shepherd-action
1288 (name 'statistics)
1289 (documentation "Display statistics about nscd usage.")
1290 (procedure (nscd-action-procedure nscd config "--statistics")))
1291 (shepherd-action
1292 (name 'invalidate)
1293 (documentation
1294 "Invalidate the given cache--e.g., 'hosts' for host name lookups.")
1295 (procedure (nscd-action-procedure nscd config "--invalidate")))))
1296
d4053c71
AK
1297(define (nscd-shepherd-service config)
1298 "Return a shepherd service for CONFIG, an <nscd-configuration> object."
d3f75179
LC
1299 (let ((nscd (file-append (nscd-configuration-glibc config)
1300 "/sbin/nscd"))
1301 (nscd.conf (nscd.conf-file config))
0adfe95a 1302 (name-services (nscd-configuration-name-services config)))
d4053c71 1303 (list (shepherd-service
0adfe95a
LC
1304 (documentation "Run libc's name service cache daemon (nscd).")
1305 (provision '(nscd))
1306 (requirement '(user-processes))
1307 (start #~(make-forkexec-constructor
d3f75179 1308 (list #$nscd "-f" #$nscd.conf "--foreground")
0adfe95a 1309
04101d99
LC
1310 ;; Wait for the PID file. However, the PID file is
1311 ;; written before nscd is actually listening on its
1312 ;; socket (XXX).
1313 #:pid-file "/var/run/nscd/nscd.pid"
1314
0adfe95a
LC
1315 #:environment-variables
1316 (list (string-append "LD_LIBRARY_PATH="
1317 (string-join
1318 (map (lambda (dir)
1319 (string-append dir "/lib"))
1320 (list #$@name-services))
1321 ":")))))
d3f75179
LC
1322 (stop #~(make-kill-destructor))
1323 (modules `((ice-9 popen) ;for the actions
1324 (ice-9 rdelim)
1325 (ice-9 match)
1326 ,@%default-modules))
1327 (actions (nscd-actions nscd nscd.conf))))))
0adfe95a
LC
1328
1329(define nscd-activation
1330 ;; Actions to take before starting nscd.
1331 #~(begin
1332 (use-modules (guix build utils))
1333 (mkdir-p "/var/run/nscd")
49f9d7f6
LC
1334 (mkdir-p "/var/db/nscd") ;for the persistent cache
1335
1336 ;; In libc 2.25 nscd uses inotify to watch /etc/resolv.conf, but only if
c298fb13
LC
1337 ;; that file exists when it is started. Thus create it here. Note: on
1338 ;; some systems, such as when NetworkManager is used, /etc/resolv.conf
1339 ;; is a symlink, hence 'lstat'.
1340 (unless (false-if-exception (lstat "/etc/resolv.conf"))
49f9d7f6
LC
1341 (call-with-output-file "/etc/resolv.conf"
1342 (lambda (port)
1343 (display "# This is a placeholder.\n" port))))))
0adfe95a
LC
1344
1345(define nscd-service-type
1346 (service-type (name 'nscd)
1347 (extensions
1348 (list (service-extension activation-service-type
1349 (const nscd-activation))
d4053c71
AK
1350 (service-extension shepherd-root-service-type
1351 nscd-shepherd-service)))
0adfe95a
LC
1352
1353 ;; This can be extended by providing additional name services
1354 ;; such as nss-mdns.
1355 (compose concatenate)
1356 (extend (lambda (config name-services)
1357 (nscd-configuration
1358 (inherit config)
1359 (name-services (append
1360 (nscd-configuration-name-services config)
6b9e1fef 1361 name-services)))))
db903549 1362 (default-value %nscd-default-configuration)
6b9e1fef
LC
1363 (description
1364 "Runs libc's @dfn{name service cache daemon} (nscd) with the
1365given configuration---an @code{<nscd-configuration>} object. @xref{Name
1366Service Switch}, for an example.")))
0adfe95a 1367
b893f1ae 1368(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 1369 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
1370given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
1371Service Switch}, for an example."
0adfe95a
LC
1372 (service nscd-service-type config))
1373
ec2e2f6c
DC
1374
1375(define-record-type* <syslog-configuration>
1376 syslog-configuration make-syslog-configuration
1377 syslog-configuration?
1378 (syslogd syslog-configuration-syslogd
9e41130b 1379 (default (file-append inetutils "/libexec/syslogd")))
ec2e2f6c
DC
1380 (config-file syslog-configuration-config-file
1381 (default %default-syslog.conf)))
1382
0adfe95a 1383(define syslog-service-type
d4053c71 1384 (shepherd-service-type
00184239 1385 'syslog
ec2e2f6c 1386 (lambda (config)
d4053c71 1387 (shepherd-service
0adfe95a
LC
1388 (documentation "Run the syslog daemon (syslogd).")
1389 (provision '(syslogd))
1390 (requirement '(user-processes))
1391 (start #~(make-forkexec-constructor
ec2e2f6c 1392 (list #$(syslog-configuration-syslogd config)
afa54a38
LC
1393 "--rcfile" #$(syslog-configuration-config-file config))
1394 #:pid-file "/var/run/syslog.pid"))
0adfe95a 1395 (stop #~(make-kill-destructor))))))
be1c2c54
LC
1396
1397;; Snippet adapted from the GNU inetutils manual.
1398(define %default-syslog.conf
1399 (plain-file "syslog.conf" "
1f3fc60d 1400 # Log all error messages, authentication messages of
db4fdc04
LC
1401 # level notice or higher and anything of level err or
1402 # higher to the console.
1403 # Don't log private authentication messages!
6a191274 1404 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
1405
1406 # Log anything (except mail) of level info or higher.
1407 # Don't log private authentication messages!
1408 *.info;mail.none;authpriv.none /var/log/messages
1409
b6d8066d
AW
1410 # Like /var/log/messages, but also including \"debug\"-level logs.
1411 *.debug;mail.none;authpriv.none /var/log/debug
1412
db4fdc04
LC
1413 # Same, in a different place.
1414 *.info;mail.none;authpriv.none /dev/tty12
1415
1416 # The authpriv file has restricted access.
1417 authpriv.* /var/log/secure
1418
1419 # Log all the mail messages in one place.
1420 mail.* /var/log/maillog
be1c2c54 1421"))
0adfe95a 1422
ec2e2f6c
DC
1423(define* (syslog-service #:optional (config (syslog-configuration)))
1424 "Return a service that runs @command{syslogd} and takes
1425@var{<syslog-configuration>} as a parameter.
44abcb28
LC
1426
1427@xref{syslogd invocation,,, inetutils, GNU Inetutils}, for more
1428information on the configuration file syntax."
ec2e2f6c
DC
1429 (service syslog-service-type config))
1430
db4fdc04 1431
909147e4
RW
1432(define pam-limits-service-type
1433 (let ((security-limits
1434 ;; Create /etc/security containing the provided "limits.conf" file.
1435 (lambda (limits-file)
1436 `(("security"
1437 ,(computed-file
1438 "security"
1439 #~(begin
1440 (mkdir #$output)
1441 (stat #$limits-file)
1442 (symlink #$limits-file
1443 (string-append #$output "/limits.conf"))))))))
1444 (pam-extension
1445 (lambda (pam)
1446 (let ((pam-limits (pam-entry
1447 (control "required")
1448 (module "pam_limits.so")
1449 (arguments '("conf=/etc/security/limits.conf")))))
1450 (if (member (pam-service-name pam)
1451 '("login" "su" "slim"))
1452 (pam-service
1453 (inherit pam)
1454 (session (cons pam-limits
1455 (pam-service-session pam))))
1456 pam)))))
1457 (service-type
1458 (name 'limits)
1459 (extensions
1460 (list (service-extension etc-service-type security-limits)
1461 (service-extension pam-root-service-type
6b9e1fef
LC
1462 (lambda _ (list pam-extension)))))
1463 (description
1464 "Install the specified resource usage limits by populating
1465@file{/etc/security/limits.conf} and using the @code{pam_limits}
1466authentication module."))))
909147e4
RW
1467
1468(define* (pam-limits-service #:optional (limits '()))
1469 "Return a service that makes selected programs respect the list of
1470pam-limits-entry specified in LIMITS via pam_limits.so."
1471 (service pam-limits-service-type
1472 (plain-file "limits.conf"
1473 (string-join (map pam-limits-entry->string limits)
1474 "\n"))))
1475
1c52181f
LC
1476\f
1477;;;
1478;;; Guix services.
1479;;;
1480
db4fdc04 1481(define* (guix-build-accounts count #:key
ab6a279a 1482 (group "guixbuild")
db4fdc04 1483 (first-uid 30001)
db4fdc04
LC
1484 (shadow shadow))
1485 "Return a list of COUNT user accounts for Guix build users, with UIDs
1486starting at FIRST-UID, and under GID."
5250a4f2
LC
1487 (unfold (cut > <> count)
1488 (lambda (n)
1489 (user-account
1490 (name (format #f "guixbuilder~2,'0d" n))
1491 (system? #t)
1492 (uid (+ first-uid n -1))
1493 (group group)
1494
1495 ;; guix-daemon expects GROUP to be listed as a
1496 ;; supplementary group too:
1497 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
1498 (supplementary-groups (list group "kvm"))
1499
1500 (comment (format #f "Guix Build User ~2d" n))
1501 (home-directory "/var/empty")
9e41130b 1502 (shell (file-append shadow "/sbin/nologin"))))
5250a4f2
LC
1503 1+
1504 1))
db4fdc04 1505
970ebdae
LC
1506(define (hydra-key-authorization keys guix)
1507 "Return a gexp with code to register KEYS, a list of files containing 'guix
1508archive' public keys, with GUIX."
2c5c696c 1509 #~(unless (file-exists? "/etc/guix/acl")
970ebdae
LC
1510 (for-each (lambda (key)
1511 (let ((pid (primitive-fork)))
1512 (case pid
1513 ((0)
1514 (let* ((port (open-file key "r0b")))
1515 (format #t "registering public key '~a'...~%" key)
1516 (close-port (current-input-port))
1517 (dup port 0)
1518 (execl #$(file-append guix "/bin/guix")
1519 "guix" "archive" "--authorize")
1520 (primitive-exit 1)))
1521 (else
1522 (let ((status (cdr (waitpid pid))))
1523 (unless (zero? status)
1524 (format (current-error-port) "warning: \
1525failed to register public key '~a': ~a~%" key status)))))))
1526 '(#$@keys))))
2c5c696c 1527
5b58c28b
LC
1528(define %default-authorized-guix-keys
1529 ;; List of authorized substitute keys.
c22c9fa5 1530 (list (file-append guix "/share/guix/hydra.gnu.org.pub")
be5622e7 1531 (file-append guix "/share/guix/berlin.guixsd.org.pub")))
5b58c28b 1532
0adfe95a
LC
1533(define-record-type* <guix-configuration>
1534 guix-configuration make-guix-configuration
1535 guix-configuration?
1536 (guix guix-configuration-guix ;<package>
1537 (default guix))
1538 (build-group guix-configuration-build-group ;string
1539 (default "guixbuild"))
1540 (build-accounts guix-configuration-build-accounts ;integer
1541 (default 10))
1542 (authorize-key? guix-configuration-authorize-key? ;Boolean
1543 (default #t))
5b58c28b
LC
1544 (authorized-keys guix-configuration-authorized-keys ;list of gexps
1545 (default %default-authorized-guix-keys))
0adfe95a
LC
1546 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1547 (default #t))
b0b9f6e0
LC
1548 (substitute-urls guix-configuration-substitute-urls ;list of strings
1549 (default %default-substitute-urls))
88554b5d
LC
1550 (chroot-directories guix-configuration-chroot-directories ;list of file-like/strings
1551 (default '()))
3bee4b61
LC
1552 (max-silent-time guix-configuration-max-silent-time ;integer
1553 (default 0))
1554 (timeout guix-configuration-timeout ;integer
1555 (default 0))
f4596f76
LC
1556 (log-compression guix-configuration-log-compression
1557 (default 'bzip2))
0adfe95a
LC
1558 (extra-options guix-configuration-extra-options ;list of strings
1559 (default '()))
dc0ef095
LC
1560 (log-file guix-configuration-log-file ;string
1561 (default "/var/log/guix-daemon.log"))
93d32da9 1562 (http-proxy guix-http-proxy ;string | #f
b191f0a6
LF
1563 (default #f))
1564 (tmpdir guix-tmpdir ;string | #f
93d32da9 1565 (default #f)))
0adfe95a
LC
1566
1567(define %default-guix-configuration
1568 (guix-configuration))
1569
d4053c71
AK
1570(define (guix-shepherd-service config)
1571 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
f4596f76
LC
1572 (match-record config <guix-configuration>
1573 (guix build-group build-accounts authorize-key? authorized-keys
1574 use-substitutes? substitute-urls max-silent-time timeout
88554b5d
LC
1575 log-compression extra-options log-file http-proxy tmpdir
1576 chroot-directories)
f4596f76
LC
1577 (list (shepherd-service
1578 (documentation "Run the Guix daemon.")
1579 (provision '(guix-daemon))
1580 (requirement '(user-processes))
88554b5d 1581 (modules '((srfi srfi-1)))
f4596f76
LC
1582 (start
1583 #~(make-forkexec-constructor
88554b5d
LC
1584 (cons* #$(file-append guix "/bin/guix-daemon")
1585 "--build-users-group" #$build-group
1586 "--max-silent-time" #$(number->string max-silent-time)
1587 "--timeout" #$(number->string timeout)
1588 "--log-compression" #$(symbol->string log-compression)
1589 #$@(if use-substitutes?
1590 '()
1591 '("--no-substitutes"))
1592 "--substitute-urls" #$(string-join substitute-urls)
1593 #$@extra-options
1594
1595 ;; Add CHROOT-DIRECTORIES and all their dependencies (if
1596 ;; these are store items) to the chroot.
1597 (append-map (lambda (file)
1598 (append-map (lambda (directory)
1599 (list "--chroot-directory"
1600 directory))
1601 (call-with-input-file file
1602 read)))
1603 '#$(map references-file chroot-directories)))
f4596f76
LC
1604
1605 #:environment-variables
1606 (list #$@(if http-proxy
1607 (list (string-append "http_proxy=" http-proxy))
1608 '())
1609 #$@(if tmpdir
1610 (list (string-append "TMPDIR=" tmpdir))
7e4bc215
LC
1611 '())
1612
1613 ;; Make sure we run in a UTF-8 locale so that 'guix
1614 ;; offload' correctly restores nars that contain UTF-8
1615 ;; file names such as 'nss-certs'. See
1616 ;; <https://bugs.gnu.org/32942>.
1617 (string-append "GUIX_LOCPATH="
1618 #$glibc-utf8-locales "/lib/locale")
1619 "LC_ALL=en_US.utf8")
f4596f76
LC
1620
1621 #:log-file #$log-file))
1622 (stop #~(make-kill-destructor))))))
0adfe95a
LC
1623
1624(define (guix-accounts config)
1625 "Return the user accounts and user groups for CONFIG."
1626 (match config
1627 (($ <guix-configuration> _ build-group build-accounts)
1628 (cons (user-group
1629 (name build-group)
1630 (system? #t)
1631
1632 ;; Use a fixed GID so that we can create the store with the right
1633 ;; owner.
1634 (id 30000))
1635 (guix-build-accounts build-accounts
1636 #:group build-group)))))
1637
1638(define (guix-activation config)
1639 "Return the activation gexp for CONFIG."
1640 (match config
5b58c28b 1641 (($ <guix-configuration> guix build-group build-accounts authorize-key? keys)
0adfe95a 1642 ;; Assume that the store has BUILD-GROUP as its group. We could
0af94ad5 1643 ;; otherwise call 'chown' here, but the problem is that on a COW overlayfs,
0adfe95a
LC
1644 ;; chown leads to an entire copy of the tree, which is a bad idea.
1645
0bc02bec 1646 ;; Optionally authorize substitute server keys.
5f4a446d 1647 (if authorize-key?
970ebdae 1648 (hydra-key-authorization keys guix)
5f4a446d 1649 #~#f))))
0adfe95a 1650
88554b5d
LC
1651(define* (references-file item #:optional (name "references"))
1652 "Return a file that contains the list of references of ITEM."
1653 (if (struct? item) ;lowerable object
1654 (computed-file name
1655 (with-imported-modules (source-module-closure
1656 '((guix build store-copy)))
1657 #~(begin
1658 (use-modules (guix build store-copy))
1659
1660 (call-with-output-file #$output
1661 (lambda (port)
6892f0a2
LC
1662 (write (map store-info-item
1663 (call-with-input-file "graph"
1664 read-reference-graph))
88554b5d
LC
1665 port)))))
1666 #:options `(#:local-build? #f
1667 #:references-graphs (("graph" ,item))))
1668 (plain-file name "()")))
1669
0adfe95a
LC
1670(define guix-service-type
1671 (service-type
1672 (name 'guix)
1673 (extensions
d4053c71 1674 (list (service-extension shepherd-root-service-type guix-shepherd-service)
0adfe95a 1675 (service-extension account-service-type guix-accounts)
9a8b9eb8
LC
1676 (service-extension activation-service-type guix-activation)
1677 (service-extension profile-service-type
3d3c5650 1678 (compose list guix-configuration-guix))))
88554b5d
LC
1679
1680 ;; Extensions can specify extra directories to add to the build chroot.
1681 (compose concatenate)
1682 (extend (lambda (config directories)
1683 (guix-configuration
1684 (inherit config)
1685 (chroot-directories
1686 (append (guix-configuration-chroot-directories config)
1687 directories)))))
1688
6b9e1fef
LC
1689 (default-value (guix-configuration))
1690 (description
1691 "Run the build daemon of GNU@tie{}Guix, aka. @command{guix-daemon}.")))
0adfe95a 1692
84a2de36
LC
1693(define-deprecated (guix-service #:optional
1694 (config %default-guix-configuration))
1695 guix-service-type
0adfe95a
LC
1696 "Return a service that runs the Guix build daemon according to
1697@var{config}."
1698 (service guix-service-type config))
1699
1c52181f
LC
1700
1701(define-record-type* <guix-publish-configuration>
1702 guix-publish-configuration make-guix-publish-configuration
1703 guix-publish-configuration?
1704 (guix guix-publish-configuration-guix ;package
1705 (default guix))
1706 (port guix-publish-configuration-port ;number
1707 (default 80))
1708 (host guix-publish-configuration-host ;string
697ddb88 1709 (default "localhost"))
f2767d3e 1710 (compression-level guix-publish-configuration-compression-level ;integer
697ddb88 1711 (default 3))
f2767d3e 1712 (nar-path guix-publish-configuration-nar-path ;string
a35136cb
LC
1713 (default "nar"))
1714 (cache guix-publish-configuration-cache ;#f | string
1715 (default #f))
1716 (workers guix-publish-configuration-workers ;#f | integer
1717 (default #f))
1718 (ttl guix-publish-configuration-ttl ;#f | integer
1719 (default #f)))
1c52181f 1720
d4053c71 1721(define guix-publish-shepherd-service
1c52181f 1722 (match-lambda
a35136cb
LC
1723 (($ <guix-publish-configuration> guix port host compression
1724 nar-path cache workers ttl)
d4053c71 1725 (list (shepherd-service
1c52181f
LC
1726 (provision '(guix-publish))
1727 (requirement '(guix-daemon))
1728 (start #~(make-forkexec-constructor
9fc037fe 1729 (list #$(file-append guix "/bin/guix")
1c52181f
LC
1730 "publish" "-u" "guix-publish"
1731 "-p" #$(number->string port)
697ddb88
LC
1732 "-C" #$(number->string compression)
1733 (string-append "--nar-path=" #$nar-path)
a35136cb
LC
1734 (string-append "--listen=" #$host)
1735 #$@(if workers
1736 #~((string-append "--workers="
1737 #$(number->string
1738 workers)))
1739 #~())
1740 #$@(if ttl
1741 #~((string-append "--ttl="
1742 #$(number->string ttl)
1743 "s"))
1744 #~())
1745 #$@(if cache
1746 #~((string-append "--cache=" #$cache))
412701b0
LC
1747 #~()))
1748
1749 ;; Make sure we run in a UTF-8 locale so we can produce
1750 ;; nars for packages that contain UTF-8 file names such
1751 ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
1752 #:environment-variables
1753 (list (string-append "GUIX_LOCPATH="
1754 #$glibc-utf8-locales "/lib/locale")
1755 "LC_ALL=en_US.utf8")))
1c52181f
LC
1756 (stop #~(make-kill-destructor)))))))
1757
1758(define %guix-publish-accounts
1759 (list (user-group (name "guix-publish") (system? #t))
1760 (user-account
1761 (name "guix-publish")
1762 (group "guix-publish")
1763 (system? #t)
1764 (comment "guix publish user")
1765 (home-directory "/var/empty")
9e41130b 1766 (shell (file-append shadow "/sbin/nologin")))))
1c52181f 1767
a35136cb
LC
1768(define (guix-publish-activation config)
1769 (let ((cache (guix-publish-configuration-cache config)))
1770 (if cache
1771 (with-imported-modules '((guix build utils))
1772 #~(begin
1773 (use-modules (guix build utils))
1774
1775 (mkdir-p #$cache)
1776 (let* ((pw (getpw "guix-publish"))
1777 (uid (passwd:uid pw))
1778 (gid (passwd:gid pw)))
1779 (chown #$cache uid gid))))
1780 #t)))
1781
1c52181f
LC
1782(define guix-publish-service-type
1783 (service-type (name 'guix-publish)
1784 (extensions
d4053c71
AK
1785 (list (service-extension shepherd-root-service-type
1786 guix-publish-shepherd-service)
1c52181f 1787 (service-extension account-service-type
a35136cb
LC
1788 (const %guix-publish-accounts))
1789 (service-extension activation-service-type
1790 guix-publish-activation)))
6b9e1fef
LC
1791 (default-value (guix-publish-configuration))
1792 (description
1793 "Add a Shepherd service running @command{guix publish}, a
1794command that allows you to share pre-built binaries with others over HTTP.")))
1c52181f 1795
84a2de36
LC
1796(define-deprecated (guix-publish-service #:key (guix guix)
1797 (port 80) (host "localhost"))
1798 guix-publish-service-type
1c52181f
LC
1799 "Return a service that runs @command{guix publish} listening on @var{host}
1800and @var{port} (@pxref{Invoking guix publish}).
1801
1802This assumes that @file{/etc/guix} already contains a signing key pair as
1803created by @command{guix archive --generate-key} (@pxref{Invoking guix
1804archive}). If that is not the case, the service will fail to start."
f1e900a3 1805 ;; Deprecated.
1c52181f
LC
1806 (service guix-publish-service-type
1807 (guix-publish-configuration (guix guix) (port port) (host host))))
1808
0adfe95a
LC
1809\f
1810;;;
1811;;; Udev.
1812;;;
1813
1814(define-record-type* <udev-configuration>
1815 udev-configuration make-udev-configuration
1816 udev-configuration?
1817 (udev udev-configuration-udev ;<package>
1818 (default udev))
1819 (rules udev-configuration-rules ;list of <package>
1820 (default '())))
db4fdc04 1821
ecd06ca9
LC
1822(define (udev-rules-union packages)
1823 "Return the union of the @code{lib/udev/rules.d} directories found in each
1824item of @var{packages}."
1825 (define build
4ee96a79
LC
1826 (with-imported-modules '((guix build union)
1827 (guix build utils))
1828 #~(begin
1829 (use-modules (guix build union)
1830 (guix build utils)
1831 (srfi srfi-1)
1832 (srfi srfi-26))
ecd06ca9 1833
4ee96a79
LC
1834 (define %standard-locations
1835 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
ecd06ca9 1836
4ee96a79
LC
1837 (define (rules-sub-directory directory)
1838 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1839 ;; #f if none was found.
1840 (find directory-exists?
1841 (map (cut string-append directory <>) %standard-locations)))
ecd06ca9 1842
4ee96a79
LC
1843 (mkdir-p (string-append #$output "/lib/udev"))
1844 (union-build (string-append #$output "/lib/udev/rules.d")
1845 (filter-map rules-sub-directory '#$packages)))))
ecd06ca9 1846
4ee96a79 1847 (computed-file "udev-rules" build))
ecd06ca9 1848
80e6f37e
RW
1849(define (udev-rule file-name contents)
1850 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1851 (computed-file file-name
4ee96a79
LC
1852 (with-imported-modules '((guix build utils))
1853 #~(begin
1854 (use-modules (guix build utils))
1855
1856 (define rules.d
1857 (string-append #$output "/lib/udev/rules.d"))
1858
1859 (mkdir-p rules.d)
1860 (call-with-output-file
1861 (string-append rules.d "/" #$file-name)
1862 (lambda (port)
1863 (display #$contents port)))))))
7f28bf9a 1864
6e644cfd
MC
1865(define (file->udev-rule file-name file)
1866 "Return a directory with a udev rule file FILE-NAME which is a copy of FILE."
1867 (computed-file file-name
1868 (with-imported-modules '((guix build utils))
1869 #~(begin
1870 (use-modules (guix build utils))
1871
1872 (define rules.d
1873 (string-append #$output "/lib/udev/rules.d"))
1874
1875 (define file-copy-dest
1876 (string-append rules.d "/" #$file-name))
1877
1878 (mkdir-p rules.d)
1879 (copy-file #$file file-copy-dest)))))
1880
80e6f37e
RW
1881(define kvm-udev-rule
1882 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1883 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1884 ;; but now we have to add it by ourselves.
1885
1886 ;; Build users are part of the "kvm" group, so we can fearlessly make
1887 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1888 (udev-rule "90-kvm.rules"
1889 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1890
d4053c71
AK
1891(define udev-shepherd-service
1892 ;; Return a <shepherd-service> for UDEV with RULES.
0adfe95a
LC
1893 (match-lambda
1894 (($ <udev-configuration> udev rules)
80e6f37e 1895 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
1896 (udev.conf (computed-file "udev.conf"
1897 #~(call-with-output-file #$output
1898 (lambda (port)
1899 (format port
1900 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1901 #$rules))))))
1902 (list
d4053c71 1903 (shepherd-service
0adfe95a
LC
1904 (provision '(udev))
1905
1906 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1907 ;; be added: see
1908 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1909 (requirement '(root-file-system))
1910
1911 (documentation "Populate the /dev directory, dynamically.")
1912 (start #~(lambda ()
0adfe95a 1913 (define udevd
7fd30825
LC
1914 ;; 'udevd' from eudev.
1915 #$(file-append udev "/sbin/udevd"))
0adfe95a
LC
1916
1917 (define (wait-for-udevd)
1918 ;; Wait until someone's listening on udevd's control
1919 ;; socket.
1920 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1921 (let try ()
1922 (catch 'system-error
1923 (lambda ()
1924 (connect sock PF_UNIX "/run/udev/control")
1925 (close-port sock))
1926 (lambda args
1927 (format #t "waiting for udevd...~%")
1928 (usleep 500000)
1929 (try))))))
1930
1931 ;; Allow udev to find the modules.
1932 (setenv "LINUX_MODULE_DIRECTORY"
1933 "/run/booted-system/kernel/lib/modules")
1934
1935 ;; The first one is for udev, the second one for eudev.
1936 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1937 (setenv "EUDEV_RULES_DIRECTORY"
9fc037fe 1938 #$(file-append rules "/lib/udev/rules.d"))
0adfe95a 1939
86e6b4c9
DM
1940 (let* ((kernel-release
1941 (utsname:release (uname)))
1942 (linux-module-directory
1943 (getenv "LINUX_MODULE_DIRECTORY"))
1944 (directory
1945 (string-append linux-module-directory "/"
1946 kernel-release))
1947 (old-umask (umask #o022)))
23784f0c
LC
1948 ;; If we're in a container, DIRECTORY might not exist,
1949 ;; for instance because the host runs a different
1950 ;; kernel. In that case, skip it; we'll just miss a few
1951 ;; nodes like /dev/fuse.
1952 (when (file-exists? directory)
1953 (make-static-device-nodes directory))
86e6b4c9
DM
1954 (umask old-umask))
1955
7fd30825
LC
1956 (let ((pid (fork+exec-command (list udevd))))
1957 ;; Wait until udevd is up and running. This appears to
1958 ;; be needed so that the events triggered below are
1959 ;; actually handled.
1960 (wait-for-udevd)
1961
1962 ;; Trigger device node creation.
1963 (system* #$(file-append udev "/bin/udevadm")
1964 "trigger" "--action=add")
1965
1966 ;; Wait for things to settle down.
1967 (system* #$(file-append udev "/bin/udevadm")
1968 "settle")
1969 pid)))
0adfe95a
LC
1970 (stop #~(make-kill-destructor))
1971
1972 ;; When halting the system, 'udev' is actually killed by
1973 ;; 'user-processes', i.e., before its own 'stop' method was called.
1974 ;; Thus, make sure it is not respawned.
86e6b4c9
DM
1975 (respawn? #f)
1976 ;; We need additional modules.
1977 (modules `((gnu build linux-boot)
bafcf1f3
LC
1978 ,@%default-modules))
1979
1980 (actions (list (shepherd-action
1981 (name 'rules)
1982 (documentation "Display the directory containing
1983the udev rules in use.")
1984 (procedure #~(lambda (_)
1985 (display #$rules)
1986 (newline))))))))))))
0adfe95a
LC
1987
1988(define udev-service-type
1989 (service-type (name 'udev)
1990 (extensions
d4053c71
AK
1991 (list (service-extension shepherd-root-service-type
1992 udev-shepherd-service)))
0adfe95a
LC
1993
1994 (compose concatenate) ;concatenate the list of rules
1995 (extend (lambda (config rules)
1996 (match config
1997 (($ <udev-configuration> udev initial-rules)
1998 (udev-configuration
1999 (udev udev)
6b9e1fef
LC
2000 (rules (append initial-rules rules)))))))
2001 (description
2002 "Run @command{udev}, which populates the @file{/dev}
2003directory dynamically. Get extra rules from the packages listed in the
2004@code{rules} field of its value, @code{udev-configuration} object.")))
0adfe95a 2005
255f7308 2006(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
2007 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
2008extra rules from the packages listed in @var{rules}."
0adfe95a
LC
2009 (service udev-service-type
2010 (udev-configuration (udev udev) (rules rules))))
2011
0adfe95a 2012(define swap-service-type
d4053c71 2013 (shepherd-service-type
00184239 2014 'swap
0adfe95a
LC
2015 (lambda (device)
2016 (define requirement
2017 (if (string-prefix? "/dev/mapper/" device)
2018 (list (symbol-append 'device-mapping-
2019 (string->symbol (basename device))))
2020 '()))
2021
d4053c71 2022 (shepherd-service
0adfe95a
LC
2023 (provision (list (symbol-append 'swap- (string->symbol device))))
2024 (requirement `(udev ,@requirement))
2025 (documentation "Enable the given swap device.")
2026 (start #~(lambda ()
2027 (restart-on-EINTR (swapon #$device))
2028 #t))
2029 (stop #~(lambda _
2030 (restart-on-EINTR (swapoff #$device))
2031 #f))
2032 (respawn? #f)))))
5dae0186 2033
2a13d05e
LC
2034(define (swap-service device)
2035 "Return a service that uses @var{device} as a swap device."
0adfe95a 2036 (service swap-service-type device))
2a13d05e 2037
5986e941
LC
2038(define %default-gpm-options
2039 ;; Default options for GPM.
2040 '("-m" "/dev/input/mice" "-t" "ps2"))
2041
8664cc88
LC
2042(define-record-type* <gpm-configuration>
2043 gpm-configuration make-gpm-configuration gpm-configuration?
5986e941
LC
2044 (gpm gpm-configuration-gpm ;package
2045 (default gpm))
2046 (options gpm-configuration-options ;list of strings
2047 (default %default-gpm-options)))
8664cc88 2048
d4053c71 2049(define gpm-shepherd-service
8664cc88 2050 (match-lambda
a907d997 2051 (($ <gpm-configuration> gpm options)
d4053c71 2052 (list (shepherd-service
8664cc88
LC
2053 (requirement '(udev))
2054 (provision '(gpm))
2055 (start #~(lambda ()
2056 ;; 'gpm' runs in the background and sets a PID file.
2057 ;; Note that it requires running as "root".
2058 (false-if-exception (delete-file "/var/run/gpm.pid"))
9fc037fe 2059 (fork+exec-command (list #$(file-append gpm "/sbin/gpm")
8664cc88
LC
2060 #$@options))
2061
2062 ;; Wait for the PID file to appear; declare failure if
2063 ;; it doesn't show up.
2064 (let loop ((i 3))
2065 (or (file-exists? "/var/run/gpm.pid")
2066 (if (zero? i)
2067 #f
2068 (begin
2069 (sleep 1)
2070 (loop (1- i))))))))
2071
2072 (stop #~(lambda (_)
2073 ;; Return #f if successfully stopped.
9fc037fe 2074 (not (zero? (system* #$(file-append gpm "/sbin/gpm")
8664cc88
LC
2075 "-k"))))))))))
2076
2077(define gpm-service-type
2078 (service-type (name 'gpm)
2079 (extensions
d4053c71 2080 (list (service-extension shepherd-root-service-type
6b9e1fef 2081 gpm-shepherd-service)))
5986e941 2082 (default-value (gpm-configuration))
6b9e1fef
LC
2083 (description
2084 "Run GPM, the general-purpose mouse daemon, with the given
2085command-line options. GPM allows users to use the mouse in the console,
2086notably to select, copy, and paste text. The default options use the
2087@code{ps2} protocol, which works for both USB and PS/2 mice.")))
8664cc88 2088
65a67bf7
LC
2089(define-deprecated (gpm-service #:key (gpm gpm)
2090 (options %default-gpm-options))
2091 gpm-service-type
8664cc88
LC
2092 "Run @var{gpm}, the general-purpose mouse daemon, with the given
2093command-line @var{options}. GPM allows users to use the mouse in the console,
2094notably to select, copy, and paste text. The default value of @var{options}
2095uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
2096
2097This service is not part of @var{%base-services}."
2098 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
2099 ;; "info mice" and "mouse_set X" to use the right mouse.
2100 (service gpm-service-type
2101 (gpm-configuration (gpm gpm) (options options))))
2102
46ec2707
DC
2103(define-record-type* <kmscon-configuration>
2104 kmscon-configuration make-kmscon-configuration
2105 kmscon-configuration?
2106 (kmscon kmscon-configuration-kmscon
2107 (default kmscon))
2108 (virtual-terminal kmscon-configuration-virtual-terminal)
2109 (login-program kmscon-configuration-login-program
9fc037fe 2110 (default (file-append shadow "/bin/login")))
46ec2707
DC
2111 (login-arguments kmscon-configuration-login-arguments
2112 (default '("-p")))
2d9dace8
MO
2113 (auto-login kmscon-configuration-auto-login
2114 (default #f))
46ec2707
DC
2115 (hardware-acceleration? kmscon-configuration-hardware-acceleration?
2116 (default #f))) ; #t causes failure
2117
2118(define kmscon-service-type
2119 (shepherd-service-type
2120 'kmscon
2121 (lambda (config)
2122 (let ((kmscon (kmscon-configuration-kmscon config))
2123 (virtual-terminal (kmscon-configuration-virtual-terminal config))
2124 (login-program (kmscon-configuration-login-program config))
2125 (login-arguments (kmscon-configuration-login-arguments config))
2d9dace8 2126 (auto-login (kmscon-configuration-auto-login config))
46ec2707
DC
2127 (hardware-acceleration? (kmscon-configuration-hardware-acceleration? config)))
2128
2129 (define kmscon-command
2130 #~(list
9fc037fe 2131 #$(file-append kmscon "/bin/kmscon") "--login"
46ec2707 2132 "--vt" #$virtual-terminal
f4e8bc5f 2133 "--no-switchvt" ;Prevent a switch to the virtual terminal.
46ec2707 2134 #$@(if hardware-acceleration? '("--hwaccel") '())
2d9dace8
MO
2135 "--login" "--"
2136 #$login-program #$@login-arguments
2137 #$@(if auto-login
2138 #~(#$auto-login)
2139 #~())))
46ec2707
DC
2140
2141 (shepherd-service
2142 (documentation "kmscon virtual terminal")
76421cf0 2143 (requirement '(user-processes udev dbus-system))
46ec2707
DC
2144 (provision (list (symbol-append 'term- (string->symbol virtual-terminal))))
2145 (start #~(make-forkexec-constructor #$kmscon-command))
2146 (stop #~(make-kill-destructor)))))))
2147
c9436025
DM
2148(define-record-type* <static-networking>
2149 static-networking make-static-networking
2150 static-networking?
2151 (interface static-networking-interface)
2152 (ip static-networking-ip)
2153 (netmask static-networking-netmask
2154 (default #f))
2155 (gateway static-networking-gateway ;FIXME: doesn't belong here
2156 (default #f))
2157 (provision static-networking-provision
2158 (default #f))
2159 (requirement static-networking-requirement
2160 (default '()))
2161 (name-servers static-networking-name-servers ;FIXME: doesn't belong here
2162 (default '())))
2163
2164(define static-networking-shepherd-service
2165 (match-lambda
2166 (($ <static-networking> interface ip netmask gateway provision
2167 requirement name-servers)
2168 (let ((loopback? (and provision (memq 'loopback provision))))
2169 (shepherd-service
2170
2171 (documentation
2172 "Bring up the networking interface using a static IP address.")
2173 (requirement requirement)
2174 (provision (or provision
2175 (list (symbol-append 'networking-
2176 (string->symbol interface)))))
2177
2178 (start #~(lambda _
2179 ;; Return #t if successfully started.
2180 (let* ((addr (inet-pton AF_INET #$ip))
2181 (sockaddr (make-socket-address AF_INET addr 0))
2182 (mask (and #$netmask
2183 (inet-pton AF_INET #$netmask)))
2184 (maskaddr (and mask
2185 (make-socket-address AF_INET
2186 mask 0)))
2187 (gateway (and #$gateway
2188 (inet-pton AF_INET #$gateway)))
2189 (gatewayaddr (and gateway
2190 (make-socket-address AF_INET
2191 gateway 0))))
2192 (configure-network-interface #$interface sockaddr
2193 (logior IFF_UP
2194 #$(if loopback?
2195 #~IFF_LOOPBACK
2196 0))
2197 #:netmask maskaddr)
2198 (when gateway
2199 (let ((sock (socket AF_INET SOCK_DGRAM 0)))
2200 (add-network-route/gateway sock gatewayaddr)
2201 (close-port sock))))))
2202 (stop #~(lambda _
2203 ;; Return #f is successfully stopped.
2204 (let ((sock (socket AF_INET SOCK_STREAM 0)))
2205 (when #$gateway
2206 (delete-network-route sock
2207 (make-socket-address
2208 AF_INET INADDR_ANY 0)))
2209 (set-network-interface-flags sock #$interface 0)
2210 (close-port sock)
241358dc 2211 #f)))
c9436025
DM
2212 (respawn? #f))))))
2213
2214(define (static-networking-etc-files interfaces)
2215 "Return a /etc/resolv.conf entry for INTERFACES or the empty list."
2216 (match (delete-duplicates
2217 (append-map static-networking-name-servers
2218 interfaces))
2219 (()
2220 '())
2221 ((name-servers ...)
2222 (let ((content (string-join
2223 (map (cut string-append "nameserver " <>)
2224 name-servers)
2225 "\n" 'suffix)))
2226 `(("resolv.conf"
2227 ,(plain-file "resolv.conf"
2228 (string-append "\
2229# Generated by 'static-networking-service'.\n"
2230 content))))))))
2231
2232(define (static-networking-shepherd-services interfaces)
2233 "Return the list of Shepherd services to bring up INTERFACES, a list of
2234<static-networking> objects."
2235 (define (loopback? service)
2236 (memq 'loopback (shepherd-service-provision service)))
2237
2238 (let ((services (map static-networking-shepherd-service interfaces)))
2239 (match (remove loopback? services)
2240 (()
2241 ;; There's no interface other than 'loopback', so we assume that the
2242 ;; 'networking' service will be provided by dhclient or similar.
2243 services)
2244 ((non-loopback ...)
2245 ;; Assume we're providing all the interfaces, and thus, provide a
2246 ;; 'networking' service.
2247 (cons (shepherd-service
2248 (provision '(networking))
2249 (requirement (append-map shepherd-service-provision
2250 services))
2251 (start #~(const #t))
2252 (stop #~(const #f))
2253 (documentation "Bring up all the networking interfaces."))
2254 services)))))
2255
2256(define static-networking-service-type
2257 ;; The service type for statically-defined network interfaces.
2258 (service-type (name 'static-networking)
2259 (extensions
2260 (list
2261 (service-extension shepherd-root-service-type
2262 static-networking-shepherd-services)
2263 (service-extension etc-service-type
2264 static-networking-etc-files)))
2265 (compose concatenate)
2266 (extend append)
2267 (description
2268 "Turn up the specified network interfaces upon startup,
2269with the given IP address, gateway, netmask, and so on. The value for
2270services of this type is a list of @code{static-networking} objects, one per
2271network interface.")))
2272
2273(define* (static-networking-service interface ip
2274 #:key
2275 netmask gateway provision
2276 ;; Most interfaces require udev to be usable.
2277 (requirement '(udev))
2278 (name-servers '()))
2279 "Return a service that starts @var{interface} with address @var{ip}. If
2280@var{netmask} is true, use it as the network mask. If @var{gateway} is true,
2281it must be a string specifying the default network gateway.
2282
2283This procedure can be called several times, one for each network
2284interface of interest. Behind the scenes what it does is extend
2285@code{static-networking-service-type} with additional network interfaces
2286to handle."
2287 (simple-service 'static-network-interface
2288 static-networking-service-type
2289 (list (static-networking (interface interface) (ip ip)
2290 (netmask netmask) (gateway gateway)
2291 (provision provision)
2292 (requirement requirement)
2293 (name-servers name-servers)))))
2294
8664cc88 2295\f
8b198abe
LC
2296(define %base-services
2297 ;; Convenience variable holding the basic services.
317d3b47
DC
2298 (list (login-service)
2299
bb3062ad 2300 (service virtual-terminal-service-type)
4a84a487
LC
2301 (service console-font-service-type
2302 (map (lambda (tty)
2303 (cons tty %default-console-font))
2304 '("tty1" "tty2" "tty3" "tty4" "tty5" "tty6")))
317d3b47 2305
5a9902c8
DM
2306 (agetty-service (agetty-configuration
2307 (extra-options '("-L")) ; no carrier detect
2308 (term "vt100")
2309 (tty #f))) ; automatic
2310
317d3b47
DC
2311 (mingetty-service (mingetty-configuration
2312 (tty "tty1")))
2313 (mingetty-service (mingetty-configuration
2314 (tty "tty2")))
2315 (mingetty-service (mingetty-configuration
2316 (tty "tty3")))
2317 (mingetty-service (mingetty-configuration
2318 (tty "tty4")))
2319 (mingetty-service (mingetty-configuration
2320 (tty "tty5")))
2321 (mingetty-service (mingetty-configuration
2322 (tty "tty6")))
2323
8de3e4b3
LC
2324 (service static-networking-service-type
2325 (list (static-networking (interface "lo")
2326 (ip "127.0.0.1")
db8ed7ce 2327 (requirement '())
8de3e4b3 2328 (provision '(loopback)))))
317d3b47 2329 (syslog-service)
8faaf8d7 2330 (service urandom-seed-service-type)
7194745a 2331 (service guix-service-type)
db903549 2332 (service nscd-service-type)
317d3b47
DC
2333
2334 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
2335 ;; used, so enable them by default. The FUSE and ALSA rules are
2336 ;; less critical, but handy.
387e1754
LC
2337 (udev-service #:rules (list lvm2 fuse alsa-utils crda))
2338
2339 (service special-files-service-type
2340 `(("/bin/sh" ,(file-append (canonical-package bash)
2341 "/bin/sh"))))))
8b198abe 2342
db4fdc04 2343;;; base.scm ends here