services: guix: Allocate build user UIDs in the system range.
[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 821 login-pam-service)))
178bce41 822 (default-value (login-configuration))
6b9e1fef
LC
823 (description
824 "Provide a console log-in service as specified by its
825configuration value, a @code{login-configuration} object.")))
317d3b47
DC
826
827(define* (login-service #:optional (config (login-configuration)))
828 "Return a service configure login according to @var{config}, which specifies
829the message of the day, among other things."
830 (service login-service-type config))
831
9ee4c9ab
LF
832(define-record-type* <agetty-configuration>
833 agetty-configuration make-agetty-configuration
834 agetty-configuration?
835 (agetty agetty-configuration-agetty ;<package>
836 (default util-linux))
5a9902c8 837 (tty agetty-configuration-tty) ;string | #f
9ee4c9ab
LF
838 (term agetty-term ;string | #f
839 (default #f))
840 (baud-rate agetty-baud-rate ;string | #f
841 (default #f))
842 (auto-login agetty-auto-login ;list of strings | #f
843 (default #f))
844 (login-program agetty-login-program ;gexp
845 (default (file-append shadow "/bin/login")))
846 (login-pause? agetty-login-pause? ;Boolean
847 (default #f))
848 (eight-bits? agetty-eight-bits? ;Boolean
849 (default #f))
850 (no-reset? agetty-no-reset? ;Boolean
851 (default #f))
852 (remote? agetty-remote? ;Boolean
853 (default #f))
854 (flow-control? agetty-flow-control? ;Boolean
855 (default #f))
856 (host agetty-host ;string | #f
857 (default #f))
858 (no-issue? agetty-no-issue? ;Boolean
859 (default #f))
860 (init-string agetty-init-string ;string | #f
861 (default #f))
862 (no-clear? agetty-no-clear? ;Boolean
863 (default #f))
864 (local-line agetty-local-line ;always | never | auto
865 (default #f))
866 (extract-baud? agetty-extract-baud? ;Boolean
867 (default #f))
868 (skip-login? agetty-skip-login? ;Boolean
869 (default #f))
870 (no-newline? agetty-no-newline? ;Boolean
871 (default #f))
872 (login-options agetty-login-options ;string | #f
873 (default #f))
874 (chroot agetty-chroot ;string | #f
875 (default #f))
876 (hangup? agetty-hangup? ;Boolean
877 (default #f))
878 (keep-baud? agetty-keep-baud? ;Boolean
879 (default #f))
880 (timeout agetty-timeout ;integer | #f
881 (default #f))
882 (detect-case? agetty-detect-case? ;Boolean
883 (default #f))
884 (wait-cr? agetty-wait-cr? ;Boolean
885 (default #f))
886 (no-hints? agetty-no-hints? ;Boolean
887 (default #f))
888 (no-hostname? agetty-no hostname? ;Boolean
889 (default #f))
890 (long-hostname? agetty-long-hostname? ;Boolean
891 (default #f))
892 (erase-characters agetty-erase-characters ;string | #f
893 (default #f))
894 (kill-characters agetty-kill-characters ;string | #f
895 (default #f))
896 (chdir agetty-chdir ;string | #f
897 (default #f))
898 (delay agetty-delay ;integer | #f
899 (default #f))
900 (nice agetty-nice ;integer | #f
901 (default #f))
902 ;; "Escape hatch" for passing arbitrary command-line arguments.
903 (extra-options agetty-extra-options ;list of strings
904 (default '()))
905;;; XXX Unimplemented for now!
906;;; (issue-file agetty-issue-file ;file-like
907;;; (default #f))
908 )
909
5a9902c8
DM
910(define (default-serial-port)
911 "Return a gexp that determines a reasonable default serial port
912to use as the tty. This is primarily useful for headless systems."
913 #~(begin
914 ;; console=device,options
915 ;; device: can be tty0, ttyS0, lp0, ttyUSB0 (serial).
916 ;; options: BBBBPNF. P n|o|e, N number of bits,
917 ;; F flow control (r RTS)
918 (let* ((not-comma (char-set-complement (char-set #\,)))
919 (command (linux-command-line))
920 (agetty-specs (find-long-options "agetty.tty" command))
921 (console-specs (filter (lambda (spec)
922 (and (string-prefix? "tty" spec)
923 (not (or
924 (string-prefix? "tty0" spec)
925 (string-prefix? "tty1" spec)
926 (string-prefix? "tty2" spec)
927 (string-prefix? "tty3" spec)
928 (string-prefix? "tty4" spec)
929 (string-prefix? "tty5" spec)
930 (string-prefix? "tty6" spec)
931 (string-prefix? "tty7" spec)
932 (string-prefix? "tty8" spec)
933 (string-prefix? "tty9" spec)))))
934 (find-long-options "console" command)))
935 (specs (append agetty-specs console-specs)))
936 (match specs
937 (() #f)
938 ((spec _ ...)
939 ;; Extract device name from first spec.
940 (match (string-tokenize spec not-comma)
941 ((device-name _ ...)
942 device-name)))))))
943
9ee4c9ab
LF
944(define agetty-shepherd-service
945 (match-lambda
946 (($ <agetty-configuration> agetty tty term baud-rate auto-login
947 login-program login-pause? eight-bits? no-reset? remote? flow-control?
948 host no-issue? init-string no-clear? local-line extract-baud?
949 skip-login? no-newline? login-options chroot hangup? keep-baud? timeout
950 detect-case? wait-cr? no-hints? no-hostname? long-hostname?
951 erase-characters kill-characters chdir delay nice extra-options)
952 (list
953 (shepherd-service
5a9902c8 954 (modules '((ice-9 match) (gnu build linux-boot)))
9ee4c9ab 955 (documentation "Run agetty on a tty.")
5a9902c8 956 (provision (list (symbol-append 'term- (string->symbol (or tty "auto")))))
9ee4c9ab
LF
957
958 ;; Since the login prompt shows the host name, wait for the 'host-name'
959 ;; service to be done. Also wait for udev essentially so that the tty
960 ;; text is not lost in the middle of kernel messages (see also
961 ;; mingetty-shepherd-service).
962 (requirement '(user-processes host-name udev))
963
c32e3dde
DM
964 (start #~(lambda args
965 (let ((defaulted-tty #$(or tty (default-serial-port))))
966 (apply
967 (if defaulted-tty
968 (make-forkexec-constructor
969 (list #$(file-append util-linux "/sbin/agetty")
970 #$@extra-options
971 #$@(if eight-bits?
972 #~("--8bits")
973 #~())
974 #$@(if no-reset?
975 #~("--noreset")
976 #~())
977 #$@(if remote?
978 #~("--remote")
979 #~())
980 #$@(if flow-control?
981 #~("--flow-control")
982 #~())
983 #$@(if host
984 #~("--host" #$host)
985 #~())
986 #$@(if no-issue?
987 #~("--noissue")
988 #~())
989 #$@(if init-string
990 #~("--init-string" #$init-string)
991 #~())
992 #$@(if no-clear?
993 #~("--noclear")
994 #~())
9ee4c9ab
LF
995;;; FIXME This doesn't work as expected. According to agetty(8), if this option
996;;; is not passed, then the default is 'auto'. However, in my tests, when that
997;;; option is selected, agetty never presents the login prompt, and the
998;;; term-ttyS0 service respawns every few seconds.
c32e3dde
DM
999 #$@(if local-line
1000 #~(#$(match local-line
1001 ('auto "--local-line=auto")
1002 ('always "--local-line=always")
1003 ('never "-local-line=never")))
1004 #~())
1005 #$@(if tty
1006 #~()
1007 #~("--keep-baud"))
1008 #$@(if extract-baud?
1009 #~("--extract-baud")
1010 #~())
1011 #$@(if skip-login?
1012 #~("--skip-login")
1013 #~())
1014 #$@(if no-newline?
1015 #~("--nonewline")
1016 #~())
1017 #$@(if login-options
1018 #~("--login-options" #$login-options)
1019 #~())
1020 #$@(if chroot
1021 #~("--chroot" #$chroot)
1022 #~())
1023 #$@(if hangup?
1024 #~("--hangup")
1025 #~())
1026 #$@(if keep-baud?
1027 #~("--keep-baud")
1028 #~())
1029 #$@(if timeout
1030 #~("--timeout" #$(number->string timeout))
1031 #~())
1032 #$@(if detect-case?
1033 #~("--detect-case")
1034 #~())
1035 #$@(if wait-cr?
1036 #~("--wait-cr")
1037 #~())
1038 #$@(if no-hints?
1039 #~("--nohints?")
1040 #~())
1041 #$@(if no-hostname?
1042 #~("--nohostname")
1043 #~())
1044 #$@(if long-hostname?
1045 #~("--long-hostname")
1046 #~())
1047 #$@(if erase-characters
1048 #~("--erase-chars" #$erase-characters)
1049 #~())
1050 #$@(if kill-characters
1051 #~("--kill-chars" #$kill-characters)
1052 #~())
1053 #$@(if chdir
1054 #~("--chdir" #$chdir)
1055 #~())
1056 #$@(if delay
1057 #~("--delay" #$(number->string delay))
1058 #~())
1059 #$@(if nice
1060 #~("--nice" #$(number->string nice))
1061 #~())
1062 #$@(if auto-login
1063 (list "--autologin" auto-login)
1064 '())
1065 #$@(if login-program
1066 #~("--login-program" #$login-program)
1067 #~())
1068 #$@(if login-pause?
1069 #~("--login-pause")
1070 #~())
1071 defaulted-tty
1072 #$@(if baud-rate
1073 #~(#$baud-rate)
1074 #~())
1075 #$@(if term
1076 #~(#$term)
1077 #~())))
1078 (const #f)) ; never start.
1079 args))))
9ee4c9ab
LF
1080 (stop #~(make-kill-destructor)))))))
1081
1082(define agetty-service-type
1083 (service-type (name 'agetty)
1084 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1085 agetty-shepherd-service)))
1086 (description
1087 "Provide console login using the @command{agetty}
1088program.")))
9ee4c9ab
LF
1089
1090(define* (agetty-service config)
1091 "Return a service to run agetty according to @var{config}, which specifies
1092the tty to run, among other things."
1093 (service agetty-service-type config))
1094
66e4f01c
LC
1095(define-record-type* <mingetty-configuration>
1096 mingetty-configuration make-mingetty-configuration
1097 mingetty-configuration?
1098 (mingetty mingetty-configuration-mingetty ;<package>
1099 (default mingetty))
1100 (tty mingetty-configuration-tty) ;string
66e4f01c
LC
1101 (auto-login mingetty-auto-login ;string | #f
1102 (default #f))
1103 (login-program mingetty-login-program ;gexp
1104 (default #f))
1105 (login-pause? mingetty-login-pause? ;Boolean
317d3b47 1106 (default #f)))
0adfe95a 1107
d4053c71 1108(define mingetty-shepherd-service
0adfe95a 1109 (match-lambda
317d3b47
DC
1110 (($ <mingetty-configuration> mingetty tty auto-login login-program
1111 login-pause?)
0adfe95a 1112 (list
d4053c71 1113 (shepherd-service
0adfe95a
LC
1114 (documentation "Run mingetty on an tty.")
1115 (provision (list (symbol-append 'term- (string->symbol tty))))
1116
1117 ;; Since the login prompt shows the host name, wait for the 'host-name'
1118 ;; service to be done. Also wait for udev essentially so that the tty
1119 ;; text is not lost in the middle of kernel messages (XXX).
bb3062ad 1120 (requirement '(user-processes host-name udev virtual-terminal))
0adfe95a 1121
7e0a6fac
DM
1122 (start #~(make-forkexec-constructor
1123 (list #$(file-append mingetty "/sbin/mingetty")
a043b5b8
LC
1124 "--noclear"
1125
1126 ;; Avoiding 'vhangup' allows us to avoid 'setfont'
1127 ;; errors down the path where various ioctls get
1128 ;; EIO--see 'hung_up_tty_ioctl' in driver/tty/tty_io.c
1129 ;; in Linux.
1130 "--nohangup" #$tty
1131
7e0a6fac
DM
1132 #$@(if auto-login
1133 #~("--autologin" #$auto-login)
1134 #~())
1135 #$@(if login-program
1136 #~("--loginprog" #$login-program)
1137 #~())
1138 #$@(if login-pause?
1139 #~("--loginpause")
1140 #~()))))
0adfe95a
LC
1141 (stop #~(make-kill-destructor)))))))
1142
1143(define mingetty-service-type
1144 (service-type (name 'mingetty)
d4053c71 1145 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1146 mingetty-shepherd-service)))
1147 (description
1148 "Provide console login using the @command{mingetty}
1149program.")))
0adfe95a
LC
1150
1151(define* (mingetty-service config)
1152 "Return a service to run mingetty according to @var{config}, which specifies
1153the tty to run, among other things."
1154 (service mingetty-service-type config))
db4fdc04 1155
6454b333
LC
1156(define-record-type* <nscd-configuration> nscd-configuration
1157 make-nscd-configuration
1158 nscd-configuration?
1159 (log-file nscd-configuration-log-file ;string
1160 (default "/var/log/nscd.log"))
1161 (debug-level nscd-debug-level ;integer
1162 (default 0))
1163 ;; TODO: See nscd.conf in glibc for other options to add.
1164 (caches nscd-configuration-caches ;list of <nscd-cache>
b893f1ae
LC
1165 (default %nscd-default-caches))
1166 (name-services nscd-configuration-name-services ;list of <packages>
1167 (default '()))
1168 (glibc nscd-configuration-glibc ;<package>
1169 (default (canonical-package glibc))))
6454b333
LC
1170
1171(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
1172 nscd-cache?
1173 (database nscd-cache-database) ;symbol
1174 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
1175 (negative-time-to-live nscd-cache-negative-time-to-live
1176 (default 20)) ;integer
1177 (suggested-size nscd-cache-suggested-size ;integer ("default module
1178 ;of hash table")
1179 (default 211))
1180 (check-files? nscd-cache-check-files? ;Boolean
1181 (default #t))
1182 (persistent? nscd-cache-persistent? ;Boolean
1183 (default #t))
1184 (shared? nscd-cache-shared? ;Boolean
1185 (default #t))
1186 (max-database-size nscd-cache-max-database-size ;integer
1187 (default (* 32 (expt 2 20))))
1188 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
1189 (default #t)))
1190
1191(define %nscd-default-caches
1192 ;; Caches that we want to enable by default. Note that when providing an
1193 ;; empty nscd.conf, all caches are disabled.
1194 (list (nscd-cache (database 'hosts)
1195
1196 ;; Aggressively cache the host name cache to improve
1197 ;; privacy and resilience.
1198 (positive-time-to-live (* 3600 12))
1199 (negative-time-to-live 20)
1200 (persistent? #t))
1201
1202 (nscd-cache (database 'services)
1203
1204 ;; Services are unlikely to change, so we can be even more
1205 ;; aggressive.
1206 (positive-time-to-live (* 3600 24))
1207 (negative-time-to-live 3600)
1208 (check-files? #t) ;check /etc/services changes
1209 (persistent? #t))))
1210
1211(define %nscd-default-configuration
1212 ;; Default nscd configuration.
1213 (nscd-configuration))
1214
1215(define (nscd.conf-file config)
1216 "Return the @file{nscd.conf} configuration file for @var{config}, an
1217@code{<nscd-configuration>} object."
1218 (define cache->config
1219 (match-lambda
be1c2c54
LC
1220 (($ <nscd-cache> (= symbol->string database)
1221 positive-ttl negative-ttl size check-files?
1222 persistent? shared? max-size propagate?)
1223 (string-append "\nenable-cache\t" database "\tyes\n"
1224
1225 "positive-time-to-live\t" database "\t"
1226 (number->string positive-ttl) "\n"
1227 "negative-time-to-live\t" database "\t"
1228 (number->string negative-ttl) "\n"
1229 "suggested-size\t" database "\t"
1230 (number->string size) "\n"
1231 "check-files\t" database "\t"
1232 (if check-files? "yes\n" "no\n")
1233 "persistent\t" database "\t"
1234 (if persistent? "yes\n" "no\n")
1235 "shared\t" database "\t"
1236 (if shared? "yes\n" "no\n")
1237 "max-db-size\t" database "\t"
1238 (number->string max-size) "\n"
1239 "auto-propagate\t" database "\t"
1240 (if propagate? "yes\n" "no\n")))))
6454b333
LC
1241
1242 (match config
1243 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
1244 (plain-file "nscd.conf"
1245 (string-append "\
6454b333 1246# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
1247 (if log-file
1248 (string-append "logfile\t" log-file)
1249 "")
1250 "\n"
1251 (if debug-level
1252 (string-append "debug-level\t"
1253 (number->string debug-level))
1254 "")
1255 "\n"
1256 (string-concatenate
1257 (map cache->config caches)))))))
6454b333 1258
d3f75179
LC
1259(define (nscd-action-procedure nscd config option)
1260 ;; XXX: This is duplicated from mcron; factorize.
1261 #~(lambda (_ . args)
1262 ;; Run 'nscd' in a pipe so we can explicitly redirect its output to
1263 ;; 'current-output-port', which at this stage is bound to the client
1264 ;; connection.
1265 (let ((pipe (apply open-pipe* OPEN_READ #$nscd
1266 "-f" #$config #$option args)))
1267 (let loop ()
1268 (match (read-line pipe 'concat)
1269 ((? eof-object?)
1270 (catch 'system-error
1271 (lambda ()
1272 (zero? (close-pipe pipe)))
1273 (lambda args
1274 ;; There's a race with the SIGCHLD handler, which could
1275 ;; call 'waitpid' before 'close-pipe' above does. If we
1276 ;; get ECHILD, that means we lost the race, but that's
1277 ;; fine.
1278 (or (= ECHILD (system-error-errno args))
1279 (apply throw args)))))
1280 (line
1281 (display line)
1282 (loop)))))))
1283
1284(define (nscd-actions nscd config)
1285 "Return Shepherd actions for NSCD."
1286 ;; Make this functionality available as actions because that's a simple way
1287 ;; to run the right 'nscd' binary with the right config file.
1288 (list (shepherd-action
1289 (name 'statistics)
1290 (documentation "Display statistics about nscd usage.")
1291 (procedure (nscd-action-procedure nscd config "--statistics")))
1292 (shepherd-action
1293 (name 'invalidate)
1294 (documentation
1295 "Invalidate the given cache--e.g., 'hosts' for host name lookups.")
1296 (procedure (nscd-action-procedure nscd config "--invalidate")))))
1297
d4053c71
AK
1298(define (nscd-shepherd-service config)
1299 "Return a shepherd service for CONFIG, an <nscd-configuration> object."
d3f75179
LC
1300 (let ((nscd (file-append (nscd-configuration-glibc config)
1301 "/sbin/nscd"))
1302 (nscd.conf (nscd.conf-file config))
0adfe95a 1303 (name-services (nscd-configuration-name-services config)))
d4053c71 1304 (list (shepherd-service
0adfe95a
LC
1305 (documentation "Run libc's name service cache daemon (nscd).")
1306 (provision '(nscd))
1307 (requirement '(user-processes))
1308 (start #~(make-forkexec-constructor
d3f75179 1309 (list #$nscd "-f" #$nscd.conf "--foreground")
0adfe95a 1310
04101d99
LC
1311 ;; Wait for the PID file. However, the PID file is
1312 ;; written before nscd is actually listening on its
1313 ;; socket (XXX).
1314 #:pid-file "/var/run/nscd/nscd.pid"
1315
0adfe95a
LC
1316 #:environment-variables
1317 (list (string-append "LD_LIBRARY_PATH="
1318 (string-join
1319 (map (lambda (dir)
1320 (string-append dir "/lib"))
1321 (list #$@name-services))
1322 ":")))))
d3f75179
LC
1323 (stop #~(make-kill-destructor))
1324 (modules `((ice-9 popen) ;for the actions
1325 (ice-9 rdelim)
1326 (ice-9 match)
1327 ,@%default-modules))
1328 (actions (nscd-actions nscd nscd.conf))))))
0adfe95a
LC
1329
1330(define nscd-activation
1331 ;; Actions to take before starting nscd.
1332 #~(begin
1333 (use-modules (guix build utils))
1334 (mkdir-p "/var/run/nscd")
49f9d7f6
LC
1335 (mkdir-p "/var/db/nscd") ;for the persistent cache
1336
1337 ;; In libc 2.25 nscd uses inotify to watch /etc/resolv.conf, but only if
c298fb13
LC
1338 ;; that file exists when it is started. Thus create it here. Note: on
1339 ;; some systems, such as when NetworkManager is used, /etc/resolv.conf
1340 ;; is a symlink, hence 'lstat'.
1341 (unless (false-if-exception (lstat "/etc/resolv.conf"))
49f9d7f6
LC
1342 (call-with-output-file "/etc/resolv.conf"
1343 (lambda (port)
1344 (display "# This is a placeholder.\n" port))))))
0adfe95a
LC
1345
1346(define nscd-service-type
1347 (service-type (name 'nscd)
1348 (extensions
1349 (list (service-extension activation-service-type
1350 (const nscd-activation))
d4053c71
AK
1351 (service-extension shepherd-root-service-type
1352 nscd-shepherd-service)))
0adfe95a
LC
1353
1354 ;; This can be extended by providing additional name services
1355 ;; such as nss-mdns.
1356 (compose concatenate)
1357 (extend (lambda (config name-services)
1358 (nscd-configuration
1359 (inherit config)
1360 (name-services (append
1361 (nscd-configuration-name-services config)
6b9e1fef 1362 name-services)))))
db903549 1363 (default-value %nscd-default-configuration)
6b9e1fef
LC
1364 (description
1365 "Runs libc's @dfn{name service cache daemon} (nscd) with the
1366given configuration---an @code{<nscd-configuration>} object. @xref{Name
1367Service Switch}, for an example.")))
0adfe95a 1368
b893f1ae 1369(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 1370 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
1371given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
1372Service Switch}, for an example."
0adfe95a
LC
1373 (service nscd-service-type config))
1374
ec2e2f6c
DC
1375
1376(define-record-type* <syslog-configuration>
1377 syslog-configuration make-syslog-configuration
1378 syslog-configuration?
1379 (syslogd syslog-configuration-syslogd
9e41130b 1380 (default (file-append inetutils "/libexec/syslogd")))
ec2e2f6c
DC
1381 (config-file syslog-configuration-config-file
1382 (default %default-syslog.conf)))
1383
0adfe95a 1384(define syslog-service-type
d4053c71 1385 (shepherd-service-type
00184239 1386 'syslog
ec2e2f6c 1387 (lambda (config)
d4053c71 1388 (shepherd-service
0adfe95a
LC
1389 (documentation "Run the syslog daemon (syslogd).")
1390 (provision '(syslogd))
1391 (requirement '(user-processes))
1392 (start #~(make-forkexec-constructor
ec2e2f6c 1393 (list #$(syslog-configuration-syslogd config)
afa54a38
LC
1394 "--rcfile" #$(syslog-configuration-config-file config))
1395 #:pid-file "/var/run/syslog.pid"))
0adfe95a 1396 (stop #~(make-kill-destructor))))))
be1c2c54
LC
1397
1398;; Snippet adapted from the GNU inetutils manual.
1399(define %default-syslog.conf
1400 (plain-file "syslog.conf" "
1f3fc60d 1401 # Log all error messages, authentication messages of
db4fdc04
LC
1402 # level notice or higher and anything of level err or
1403 # higher to the console.
1404 # Don't log private authentication messages!
6a191274 1405 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
1406
1407 # Log anything (except mail) of level info or higher.
1408 # Don't log private authentication messages!
1409 *.info;mail.none;authpriv.none /var/log/messages
1410
b6d8066d
AW
1411 # Like /var/log/messages, but also including \"debug\"-level logs.
1412 *.debug;mail.none;authpriv.none /var/log/debug
1413
db4fdc04
LC
1414 # Same, in a different place.
1415 *.info;mail.none;authpriv.none /dev/tty12
1416
1417 # The authpriv file has restricted access.
1418 authpriv.* /var/log/secure
1419
1420 # Log all the mail messages in one place.
1421 mail.* /var/log/maillog
be1c2c54 1422"))
0adfe95a 1423
ec2e2f6c
DC
1424(define* (syslog-service #:optional (config (syslog-configuration)))
1425 "Return a service that runs @command{syslogd} and takes
1426@var{<syslog-configuration>} as a parameter.
44abcb28
LC
1427
1428@xref{syslogd invocation,,, inetutils, GNU Inetutils}, for more
1429information on the configuration file syntax."
ec2e2f6c
DC
1430 (service syslog-service-type config))
1431
db4fdc04 1432
909147e4
RW
1433(define pam-limits-service-type
1434 (let ((security-limits
1435 ;; Create /etc/security containing the provided "limits.conf" file.
1436 (lambda (limits-file)
1437 `(("security"
1438 ,(computed-file
1439 "security"
1440 #~(begin
1441 (mkdir #$output)
1442 (stat #$limits-file)
1443 (symlink #$limits-file
1444 (string-append #$output "/limits.conf"))))))))
1445 (pam-extension
1446 (lambda (pam)
1447 (let ((pam-limits (pam-entry
1448 (control "required")
1449 (module "pam_limits.so")
1450 (arguments '("conf=/etc/security/limits.conf")))))
1451 (if (member (pam-service-name pam)
1452 '("login" "su" "slim"))
1453 (pam-service
1454 (inherit pam)
1455 (session (cons pam-limits
1456 (pam-service-session pam))))
1457 pam)))))
1458 (service-type
1459 (name 'limits)
1460 (extensions
1461 (list (service-extension etc-service-type security-limits)
1462 (service-extension pam-root-service-type
6b9e1fef
LC
1463 (lambda _ (list pam-extension)))))
1464 (description
1465 "Install the specified resource usage limits by populating
1466@file{/etc/security/limits.conf} and using the @code{pam_limits}
1467authentication module."))))
909147e4
RW
1468
1469(define* (pam-limits-service #:optional (limits '()))
1470 "Return a service that makes selected programs respect the list of
1471pam-limits-entry specified in LIMITS via pam_limits.so."
1472 (service pam-limits-service-type
1473 (plain-file "limits.conf"
1474 (string-join (map pam-limits-entry->string limits)
1475 "\n"))))
1476
1c52181f
LC
1477\f
1478;;;
1479;;; Guix services.
1480;;;
1481
db4fdc04 1482(define* (guix-build-accounts count #:key
ab6a279a 1483 (group "guixbuild")
db4fdc04 1484 (shadow shadow))
309d87c3
LC
1485 "Return a list of COUNT user accounts for Guix build users with the given
1486GID."
5250a4f2
LC
1487 (unfold (cut > <> count)
1488 (lambda (n)
1489 (user-account
1490 (name (format #f "guixbuilder~2,'0d" n))
1491 (system? #t)
5250a4f2
LC
1492 (group group)
1493
1494 ;; guix-daemon expects GROUP to be listed as a
1495 ;; supplementary group too:
1496 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
1497 (supplementary-groups (list group "kvm"))
1498
1499 (comment (format #f "Guix Build User ~2d" n))
1500 (home-directory "/var/empty")
9e41130b 1501 (shell (file-append shadow "/sbin/nologin"))))
5250a4f2
LC
1502 1+
1503 1))
db4fdc04 1504
970ebdae
LC
1505(define (hydra-key-authorization keys guix)
1506 "Return a gexp with code to register KEYS, a list of files containing 'guix
1507archive' public keys, with GUIX."
2c5c696c 1508 #~(unless (file-exists? "/etc/guix/acl")
970ebdae
LC
1509 (for-each (lambda (key)
1510 (let ((pid (primitive-fork)))
1511 (case pid
1512 ((0)
1513 (let* ((port (open-file key "r0b")))
1514 (format #t "registering public key '~a'...~%" key)
1515 (close-port (current-input-port))
1516 (dup port 0)
1517 (execl #$(file-append guix "/bin/guix")
1518 "guix" "archive" "--authorize")
1519 (primitive-exit 1)))
1520 (else
1521 (let ((status (cdr (waitpid pid))))
1522 (unless (zero? status)
1523 (format (current-error-port) "warning: \
1524failed to register public key '~a': ~a~%" key status)))))))
1525 '(#$@keys))))
2c5c696c 1526
5b58c28b
LC
1527(define %default-authorized-guix-keys
1528 ;; List of authorized substitute keys.
c22c9fa5 1529 (list (file-append guix "/share/guix/hydra.gnu.org.pub")
be5622e7 1530 (file-append guix "/share/guix/berlin.guixsd.org.pub")))
5b58c28b 1531
0adfe95a
LC
1532(define-record-type* <guix-configuration>
1533 guix-configuration make-guix-configuration
1534 guix-configuration?
1535 (guix guix-configuration-guix ;<package>
1536 (default guix))
1537 (build-group guix-configuration-build-group ;string
1538 (default "guixbuild"))
1539 (build-accounts guix-configuration-build-accounts ;integer
1540 (default 10))
1541 (authorize-key? guix-configuration-authorize-key? ;Boolean
1542 (default #t))
5b58c28b
LC
1543 (authorized-keys guix-configuration-authorized-keys ;list of gexps
1544 (default %default-authorized-guix-keys))
0adfe95a
LC
1545 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1546 (default #t))
b0b9f6e0
LC
1547 (substitute-urls guix-configuration-substitute-urls ;list of strings
1548 (default %default-substitute-urls))
88554b5d
LC
1549 (chroot-directories guix-configuration-chroot-directories ;list of file-like/strings
1550 (default '()))
3bee4b61
LC
1551 (max-silent-time guix-configuration-max-silent-time ;integer
1552 (default 0))
1553 (timeout guix-configuration-timeout ;integer
1554 (default 0))
f4596f76
LC
1555 (log-compression guix-configuration-log-compression
1556 (default 'bzip2))
0adfe95a
LC
1557 (extra-options guix-configuration-extra-options ;list of strings
1558 (default '()))
dc0ef095
LC
1559 (log-file guix-configuration-log-file ;string
1560 (default "/var/log/guix-daemon.log"))
93d32da9 1561 (http-proxy guix-http-proxy ;string | #f
b191f0a6
LF
1562 (default #f))
1563 (tmpdir guix-tmpdir ;string | #f
93d32da9 1564 (default #f)))
0adfe95a
LC
1565
1566(define %default-guix-configuration
1567 (guix-configuration))
1568
d4053c71
AK
1569(define (guix-shepherd-service config)
1570 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
f4596f76
LC
1571 (match-record config <guix-configuration>
1572 (guix build-group build-accounts authorize-key? authorized-keys
1573 use-substitutes? substitute-urls max-silent-time timeout
88554b5d
LC
1574 log-compression extra-options log-file http-proxy tmpdir
1575 chroot-directories)
f4596f76
LC
1576 (list (shepherd-service
1577 (documentation "Run the Guix daemon.")
1578 (provision '(guix-daemon))
1579 (requirement '(user-processes))
88554b5d 1580 (modules '((srfi srfi-1)))
f4596f76
LC
1581 (start
1582 #~(make-forkexec-constructor
88554b5d
LC
1583 (cons* #$(file-append guix "/bin/guix-daemon")
1584 "--build-users-group" #$build-group
1585 "--max-silent-time" #$(number->string max-silent-time)
1586 "--timeout" #$(number->string timeout)
1587 "--log-compression" #$(symbol->string log-compression)
1588 #$@(if use-substitutes?
1589 '()
1590 '("--no-substitutes"))
1591 "--substitute-urls" #$(string-join substitute-urls)
1592 #$@extra-options
1593
1594 ;; Add CHROOT-DIRECTORIES and all their dependencies (if
1595 ;; these are store items) to the chroot.
1596 (append-map (lambda (file)
1597 (append-map (lambda (directory)
1598 (list "--chroot-directory"
1599 directory))
1600 (call-with-input-file file
1601 read)))
1602 '#$(map references-file chroot-directories)))
f4596f76
LC
1603
1604 #:environment-variables
1605 (list #$@(if http-proxy
1606 (list (string-append "http_proxy=" http-proxy))
1607 '())
1608 #$@(if tmpdir
1609 (list (string-append "TMPDIR=" tmpdir))
7e4bc215
LC
1610 '())
1611
1612 ;; Make sure we run in a UTF-8 locale so that 'guix
1613 ;; offload' correctly restores nars that contain UTF-8
1614 ;; file names such as 'nss-certs'. See
1615 ;; <https://bugs.gnu.org/32942>.
1616 (string-append "GUIX_LOCPATH="
1617 #$glibc-utf8-locales "/lib/locale")
1618 "LC_ALL=en_US.utf8")
f4596f76
LC
1619
1620 #:log-file #$log-file))
1621 (stop #~(make-kill-destructor))))))
0adfe95a
LC
1622
1623(define (guix-accounts config)
1624 "Return the user accounts and user groups for CONFIG."
1625 (match config
1626 (($ <guix-configuration> _ build-group build-accounts)
1627 (cons (user-group
1628 (name build-group)
1629 (system? #t)
1630
1631 ;; Use a fixed GID so that we can create the store with the right
1632 ;; owner.
1633 (id 30000))
1634 (guix-build-accounts build-accounts
1635 #:group build-group)))))
1636
1637(define (guix-activation config)
1638 "Return the activation gexp for CONFIG."
1639 (match config
5b58c28b 1640 (($ <guix-configuration> guix build-group build-accounts authorize-key? keys)
0adfe95a 1641 ;; Assume that the store has BUILD-GROUP as its group. We could
0af94ad5 1642 ;; otherwise call 'chown' here, but the problem is that on a COW overlayfs,
0adfe95a
LC
1643 ;; chown leads to an entire copy of the tree, which is a bad idea.
1644
0bc02bec 1645 ;; Optionally authorize substitute server keys.
5f4a446d 1646 (if authorize-key?
970ebdae 1647 (hydra-key-authorization keys guix)
5f4a446d 1648 #~#f))))
0adfe95a 1649
88554b5d
LC
1650(define* (references-file item #:optional (name "references"))
1651 "Return a file that contains the list of references of ITEM."
1652 (if (struct? item) ;lowerable object
1653 (computed-file name
1654 (with-imported-modules (source-module-closure
1655 '((guix build store-copy)))
1656 #~(begin
1657 (use-modules (guix build store-copy))
1658
1659 (call-with-output-file #$output
1660 (lambda (port)
6892f0a2
LC
1661 (write (map store-info-item
1662 (call-with-input-file "graph"
1663 read-reference-graph))
88554b5d
LC
1664 port)))))
1665 #:options `(#:local-build? #f
1666 #:references-graphs (("graph" ,item))))
1667 (plain-file name "()")))
1668
0adfe95a
LC
1669(define guix-service-type
1670 (service-type
1671 (name 'guix)
1672 (extensions
d4053c71 1673 (list (service-extension shepherd-root-service-type guix-shepherd-service)
0adfe95a 1674 (service-extension account-service-type guix-accounts)
9a8b9eb8
LC
1675 (service-extension activation-service-type guix-activation)
1676 (service-extension profile-service-type
3d3c5650 1677 (compose list guix-configuration-guix))))
88554b5d
LC
1678
1679 ;; Extensions can specify extra directories to add to the build chroot.
1680 (compose concatenate)
1681 (extend (lambda (config directories)
1682 (guix-configuration
1683 (inherit config)
1684 (chroot-directories
1685 (append (guix-configuration-chroot-directories config)
1686 directories)))))
1687
6b9e1fef
LC
1688 (default-value (guix-configuration))
1689 (description
1690 "Run the build daemon of GNU@tie{}Guix, aka. @command{guix-daemon}.")))
0adfe95a 1691
84a2de36
LC
1692(define-deprecated (guix-service #:optional
1693 (config %default-guix-configuration))
1694 guix-service-type
0adfe95a
LC
1695 "Return a service that runs the Guix build daemon according to
1696@var{config}."
1697 (service guix-service-type config))
1698
1c52181f
LC
1699
1700(define-record-type* <guix-publish-configuration>
1701 guix-publish-configuration make-guix-publish-configuration
1702 guix-publish-configuration?
1703 (guix guix-publish-configuration-guix ;package
1704 (default guix))
1705 (port guix-publish-configuration-port ;number
1706 (default 80))
1707 (host guix-publish-configuration-host ;string
697ddb88 1708 (default "localhost"))
f2767d3e 1709 (compression-level guix-publish-configuration-compression-level ;integer
697ddb88 1710 (default 3))
f2767d3e 1711 (nar-path guix-publish-configuration-nar-path ;string
a35136cb
LC
1712 (default "nar"))
1713 (cache guix-publish-configuration-cache ;#f | string
1714 (default #f))
1715 (workers guix-publish-configuration-workers ;#f | integer
1716 (default #f))
1717 (ttl guix-publish-configuration-ttl ;#f | integer
1718 (default #f)))
1c52181f 1719
d4053c71 1720(define guix-publish-shepherd-service
1c52181f 1721 (match-lambda
a35136cb
LC
1722 (($ <guix-publish-configuration> guix port host compression
1723 nar-path cache workers ttl)
d4053c71 1724 (list (shepherd-service
1c52181f
LC
1725 (provision '(guix-publish))
1726 (requirement '(guix-daemon))
1727 (start #~(make-forkexec-constructor
9fc037fe 1728 (list #$(file-append guix "/bin/guix")
1c52181f
LC
1729 "publish" "-u" "guix-publish"
1730 "-p" #$(number->string port)
697ddb88
LC
1731 "-C" #$(number->string compression)
1732 (string-append "--nar-path=" #$nar-path)
a35136cb
LC
1733 (string-append "--listen=" #$host)
1734 #$@(if workers
1735 #~((string-append "--workers="
1736 #$(number->string
1737 workers)))
1738 #~())
1739 #$@(if ttl
1740 #~((string-append "--ttl="
1741 #$(number->string ttl)
1742 "s"))
1743 #~())
1744 #$@(if cache
1745 #~((string-append "--cache=" #$cache))
412701b0
LC
1746 #~()))
1747
1748 ;; Make sure we run in a UTF-8 locale so we can produce
1749 ;; nars for packages that contain UTF-8 file names such
1750 ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
1751 #:environment-variables
1752 (list (string-append "GUIX_LOCPATH="
1753 #$glibc-utf8-locales "/lib/locale")
1754 "LC_ALL=en_US.utf8")))
1c52181f
LC
1755 (stop #~(make-kill-destructor)))))))
1756
1757(define %guix-publish-accounts
1758 (list (user-group (name "guix-publish") (system? #t))
1759 (user-account
1760 (name "guix-publish")
1761 (group "guix-publish")
1762 (system? #t)
1763 (comment "guix publish user")
1764 (home-directory "/var/empty")
9e41130b 1765 (shell (file-append shadow "/sbin/nologin")))))
1c52181f 1766
a35136cb
LC
1767(define (guix-publish-activation config)
1768 (let ((cache (guix-publish-configuration-cache config)))
1769 (if cache
1770 (with-imported-modules '((guix build utils))
1771 #~(begin
1772 (use-modules (guix build utils))
1773
1774 (mkdir-p #$cache)
1775 (let* ((pw (getpw "guix-publish"))
1776 (uid (passwd:uid pw))
1777 (gid (passwd:gid pw)))
1778 (chown #$cache uid gid))))
1779 #t)))
1780
1c52181f
LC
1781(define guix-publish-service-type
1782 (service-type (name 'guix-publish)
1783 (extensions
d4053c71
AK
1784 (list (service-extension shepherd-root-service-type
1785 guix-publish-shepherd-service)
1c52181f 1786 (service-extension account-service-type
a35136cb
LC
1787 (const %guix-publish-accounts))
1788 (service-extension activation-service-type
1789 guix-publish-activation)))
6b9e1fef
LC
1790 (default-value (guix-publish-configuration))
1791 (description
1792 "Add a Shepherd service running @command{guix publish}, a
1793command that allows you to share pre-built binaries with others over HTTP.")))
1c52181f 1794
84a2de36
LC
1795(define-deprecated (guix-publish-service #:key (guix guix)
1796 (port 80) (host "localhost"))
1797 guix-publish-service-type
1c52181f
LC
1798 "Return a service that runs @command{guix publish} listening on @var{host}
1799and @var{port} (@pxref{Invoking guix publish}).
1800
1801This assumes that @file{/etc/guix} already contains a signing key pair as
1802created by @command{guix archive --generate-key} (@pxref{Invoking guix
1803archive}). If that is not the case, the service will fail to start."
f1e900a3 1804 ;; Deprecated.
1c52181f
LC
1805 (service guix-publish-service-type
1806 (guix-publish-configuration (guix guix) (port port) (host host))))
1807
0adfe95a
LC
1808\f
1809;;;
1810;;; Udev.
1811;;;
1812
1813(define-record-type* <udev-configuration>
1814 udev-configuration make-udev-configuration
1815 udev-configuration?
1816 (udev udev-configuration-udev ;<package>
fd779db9 1817 (default eudev))
0adfe95a
LC
1818 (rules udev-configuration-rules ;list of <package>
1819 (default '())))
db4fdc04 1820
ecd06ca9
LC
1821(define (udev-rules-union packages)
1822 "Return the union of the @code{lib/udev/rules.d} directories found in each
1823item of @var{packages}."
1824 (define build
4ee96a79
LC
1825 (with-imported-modules '((guix build union)
1826 (guix build utils))
1827 #~(begin
1828 (use-modules (guix build union)
1829 (guix build utils)
1830 (srfi srfi-1)
1831 (srfi srfi-26))
ecd06ca9 1832
4ee96a79
LC
1833 (define %standard-locations
1834 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
ecd06ca9 1835
4ee96a79
LC
1836 (define (rules-sub-directory directory)
1837 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1838 ;; #f if none was found.
1839 (find directory-exists?
1840 (map (cut string-append directory <>) %standard-locations)))
ecd06ca9 1841
4ee96a79
LC
1842 (mkdir-p (string-append #$output "/lib/udev"))
1843 (union-build (string-append #$output "/lib/udev/rules.d")
1844 (filter-map rules-sub-directory '#$packages)))))
ecd06ca9 1845
4ee96a79 1846 (computed-file "udev-rules" build))
ecd06ca9 1847
80e6f37e
RW
1848(define (udev-rule file-name contents)
1849 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1850 (computed-file file-name
4ee96a79
LC
1851 (with-imported-modules '((guix build utils))
1852 #~(begin
1853 (use-modules (guix build utils))
1854
1855 (define rules.d
1856 (string-append #$output "/lib/udev/rules.d"))
1857
1858 (mkdir-p rules.d)
1859 (call-with-output-file
1860 (string-append rules.d "/" #$file-name)
1861 (lambda (port)
1862 (display #$contents port)))))))
7f28bf9a 1863
6e644cfd
MC
1864(define (file->udev-rule file-name file)
1865 "Return a directory with a udev rule file FILE-NAME which is a copy of FILE."
1866 (computed-file file-name
1867 (with-imported-modules '((guix build utils))
1868 #~(begin
1869 (use-modules (guix build utils))
1870
1871 (define rules.d
1872 (string-append #$output "/lib/udev/rules.d"))
1873
1874 (define file-copy-dest
1875 (string-append rules.d "/" #$file-name))
1876
1877 (mkdir-p rules.d)
1878 (copy-file #$file file-copy-dest)))))
1879
80e6f37e
RW
1880(define kvm-udev-rule
1881 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1882 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1883 ;; but now we have to add it by ourselves.
1884
1885 ;; Build users are part of the "kvm" group, so we can fearlessly make
1886 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1887 (udev-rule "90-kvm.rules"
1888 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1889
d4053c71
AK
1890(define udev-shepherd-service
1891 ;; Return a <shepherd-service> for UDEV with RULES.
0adfe95a
LC
1892 (match-lambda
1893 (($ <udev-configuration> udev rules)
80e6f37e 1894 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
1895 (udev.conf (computed-file "udev.conf"
1896 #~(call-with-output-file #$output
1897 (lambda (port)
1898 (format port
1899 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1900 #$rules))))))
1901 (list
d4053c71 1902 (shepherd-service
0adfe95a
LC
1903 (provision '(udev))
1904
1905 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1906 ;; be added: see
1907 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1908 (requirement '(root-file-system))
1909
1910 (documentation "Populate the /dev directory, dynamically.")
1911 (start #~(lambda ()
0adfe95a 1912 (define udevd
7fd30825
LC
1913 ;; 'udevd' from eudev.
1914 #$(file-append udev "/sbin/udevd"))
0adfe95a
LC
1915
1916 (define (wait-for-udevd)
1917 ;; Wait until someone's listening on udevd's control
1918 ;; socket.
1919 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1920 (let try ()
1921 (catch 'system-error
1922 (lambda ()
1923 (connect sock PF_UNIX "/run/udev/control")
1924 (close-port sock))
1925 (lambda args
1926 (format #t "waiting for udevd...~%")
1927 (usleep 500000)
1928 (try))))))
1929
1930 ;; Allow udev to find the modules.
1931 (setenv "LINUX_MODULE_DIRECTORY"
1932 "/run/booted-system/kernel/lib/modules")
1933
1934 ;; The first one is for udev, the second one for eudev.
1935 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1936 (setenv "EUDEV_RULES_DIRECTORY"
9fc037fe 1937 #$(file-append rules "/lib/udev/rules.d"))
0adfe95a 1938
86e6b4c9
DM
1939 (let* ((kernel-release
1940 (utsname:release (uname)))
1941 (linux-module-directory
1942 (getenv "LINUX_MODULE_DIRECTORY"))
1943 (directory
1944 (string-append linux-module-directory "/"
1945 kernel-release))
1946 (old-umask (umask #o022)))
23784f0c
LC
1947 ;; If we're in a container, DIRECTORY might not exist,
1948 ;; for instance because the host runs a different
1949 ;; kernel. In that case, skip it; we'll just miss a few
1950 ;; nodes like /dev/fuse.
1951 (when (file-exists? directory)
1952 (make-static-device-nodes directory))
86e6b4c9
DM
1953 (umask old-umask))
1954
7fd30825
LC
1955 (let ((pid (fork+exec-command (list udevd))))
1956 ;; Wait until udevd is up and running. This appears to
1957 ;; be needed so that the events triggered below are
1958 ;; actually handled.
1959 (wait-for-udevd)
1960
1961 ;; Trigger device node creation.
1962 (system* #$(file-append udev "/bin/udevadm")
1963 "trigger" "--action=add")
1964
1965 ;; Wait for things to settle down.
1966 (system* #$(file-append udev "/bin/udevadm")
1967 "settle")
1968 pid)))
0adfe95a
LC
1969 (stop #~(make-kill-destructor))
1970
1971 ;; When halting the system, 'udev' is actually killed by
1972 ;; 'user-processes', i.e., before its own 'stop' method was called.
1973 ;; Thus, make sure it is not respawned.
86e6b4c9
DM
1974 (respawn? #f)
1975 ;; We need additional modules.
1976 (modules `((gnu build linux-boot)
bafcf1f3
LC
1977 ,@%default-modules))
1978
1979 (actions (list (shepherd-action
1980 (name 'rules)
1981 (documentation "Display the directory containing
1982the udev rules in use.")
1983 (procedure #~(lambda (_)
1984 (display #$rules)
1985 (newline))))))))))))
0adfe95a
LC
1986
1987(define udev-service-type
1988 (service-type (name 'udev)
1989 (extensions
d4053c71
AK
1990 (list (service-extension shepherd-root-service-type
1991 udev-shepherd-service)))
0adfe95a
LC
1992
1993 (compose concatenate) ;concatenate the list of rules
1994 (extend (lambda (config rules)
1995 (match config
1996 (($ <udev-configuration> udev initial-rules)
1997 (udev-configuration
1998 (udev udev)
6b9e1fef 1999 (rules (append initial-rules rules)))))))
fd779db9 2000 (default-value (udev-configuration))
6b9e1fef
LC
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.
178bce41 2298 (list (service login-service-type)
317d3b47 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
76a2b2db
EF
2306 (service agetty-service-type (agetty-configuration
2307 (extra-options '("-L")) ; no carrier detect
2308 (term "vt100")
2309 (tty #f))) ; automatic
2310
2311 (service mingetty-service-type (mingetty-configuration
2312 (tty "tty1")))
2313 (service mingetty-service-type (mingetty-configuration
2314 (tty "tty2")))
2315 (service mingetty-service-type (mingetty-configuration
2316 (tty "tty3")))
2317 (service mingetty-service-type (mingetty-configuration
2318 (tty "tty4")))
2319 (service mingetty-service-type (mingetty-configuration
2320 (tty "tty5")))
2321 (service mingetty-service-type (mingetty-configuration
2322 (tty "tty6")))
317d3b47 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.
fd779db9
EF
2337 (service udev-service-type
2338 (udev-configuration
2339 (rules (list lvm2 fuse alsa-utils crda))))
387e1754
LC
2340
2341 (service special-files-service-type
2342 `(("/bin/sh" ,(file-append (canonical-package bash)
2343 "/bin/sh"))))))
8b198abe 2344
db4fdc04 2345;;; base.scm ends here