gnu: %base-services: Use login-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 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 (first-uid 30001)
db4fdc04
LC
1485 (shadow shadow))
1486 "Return a list of COUNT user accounts for Guix build users, with UIDs
1487starting at FIRST-UID, and under GID."
5250a4f2
LC
1488 (unfold (cut > <> count)
1489 (lambda (n)
1490 (user-account
1491 (name (format #f "guixbuilder~2,'0d" n))
1492 (system? #t)
1493 (uid (+ first-uid n -1))
1494 (group group)
1495
1496 ;; guix-daemon expects GROUP to be listed as a
1497 ;; supplementary group too:
1498 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
1499 (supplementary-groups (list group "kvm"))
1500
1501 (comment (format #f "Guix Build User ~2d" n))
1502 (home-directory "/var/empty")
9e41130b 1503 (shell (file-append shadow "/sbin/nologin"))))
5250a4f2
LC
1504 1+
1505 1))
db4fdc04 1506
970ebdae
LC
1507(define (hydra-key-authorization keys guix)
1508 "Return a gexp with code to register KEYS, a list of files containing 'guix
1509archive' public keys, with GUIX."
2c5c696c 1510 #~(unless (file-exists? "/etc/guix/acl")
970ebdae
LC
1511 (for-each (lambda (key)
1512 (let ((pid (primitive-fork)))
1513 (case pid
1514 ((0)
1515 (let* ((port (open-file key "r0b")))
1516 (format #t "registering public key '~a'...~%" key)
1517 (close-port (current-input-port))
1518 (dup port 0)
1519 (execl #$(file-append guix "/bin/guix")
1520 "guix" "archive" "--authorize")
1521 (primitive-exit 1)))
1522 (else
1523 (let ((status (cdr (waitpid pid))))
1524 (unless (zero? status)
1525 (format (current-error-port) "warning: \
1526failed to register public key '~a': ~a~%" key status)))))))
1527 '(#$@keys))))
2c5c696c 1528
5b58c28b
LC
1529(define %default-authorized-guix-keys
1530 ;; List of authorized substitute keys.
c22c9fa5 1531 (list (file-append guix "/share/guix/hydra.gnu.org.pub")
be5622e7 1532 (file-append guix "/share/guix/berlin.guixsd.org.pub")))
5b58c28b 1533
0adfe95a
LC
1534(define-record-type* <guix-configuration>
1535 guix-configuration make-guix-configuration
1536 guix-configuration?
1537 (guix guix-configuration-guix ;<package>
1538 (default guix))
1539 (build-group guix-configuration-build-group ;string
1540 (default "guixbuild"))
1541 (build-accounts guix-configuration-build-accounts ;integer
1542 (default 10))
1543 (authorize-key? guix-configuration-authorize-key? ;Boolean
1544 (default #t))
5b58c28b
LC
1545 (authorized-keys guix-configuration-authorized-keys ;list of gexps
1546 (default %default-authorized-guix-keys))
0adfe95a
LC
1547 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1548 (default #t))
b0b9f6e0
LC
1549 (substitute-urls guix-configuration-substitute-urls ;list of strings
1550 (default %default-substitute-urls))
88554b5d
LC
1551 (chroot-directories guix-configuration-chroot-directories ;list of file-like/strings
1552 (default '()))
3bee4b61
LC
1553 (max-silent-time guix-configuration-max-silent-time ;integer
1554 (default 0))
1555 (timeout guix-configuration-timeout ;integer
1556 (default 0))
f4596f76
LC
1557 (log-compression guix-configuration-log-compression
1558 (default 'bzip2))
0adfe95a
LC
1559 (extra-options guix-configuration-extra-options ;list of strings
1560 (default '()))
dc0ef095
LC
1561 (log-file guix-configuration-log-file ;string
1562 (default "/var/log/guix-daemon.log"))
93d32da9 1563 (http-proxy guix-http-proxy ;string | #f
b191f0a6
LF
1564 (default #f))
1565 (tmpdir guix-tmpdir ;string | #f
93d32da9 1566 (default #f)))
0adfe95a
LC
1567
1568(define %default-guix-configuration
1569 (guix-configuration))
1570
d4053c71
AK
1571(define (guix-shepherd-service config)
1572 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
f4596f76
LC
1573 (match-record config <guix-configuration>
1574 (guix build-group build-accounts authorize-key? authorized-keys
1575 use-substitutes? substitute-urls max-silent-time timeout
88554b5d
LC
1576 log-compression extra-options log-file http-proxy tmpdir
1577 chroot-directories)
f4596f76
LC
1578 (list (shepherd-service
1579 (documentation "Run the Guix daemon.")
1580 (provision '(guix-daemon))
1581 (requirement '(user-processes))
88554b5d 1582 (modules '((srfi srfi-1)))
f4596f76
LC
1583 (start
1584 #~(make-forkexec-constructor
88554b5d
LC
1585 (cons* #$(file-append guix "/bin/guix-daemon")
1586 "--build-users-group" #$build-group
1587 "--max-silent-time" #$(number->string max-silent-time)
1588 "--timeout" #$(number->string timeout)
1589 "--log-compression" #$(symbol->string log-compression)
1590 #$@(if use-substitutes?
1591 '()
1592 '("--no-substitutes"))
1593 "--substitute-urls" #$(string-join substitute-urls)
1594 #$@extra-options
1595
1596 ;; Add CHROOT-DIRECTORIES and all their dependencies (if
1597 ;; these are store items) to the chroot.
1598 (append-map (lambda (file)
1599 (append-map (lambda (directory)
1600 (list "--chroot-directory"
1601 directory))
1602 (call-with-input-file file
1603 read)))
1604 '#$(map references-file chroot-directories)))
f4596f76
LC
1605
1606 #:environment-variables
1607 (list #$@(if http-proxy
1608 (list (string-append "http_proxy=" http-proxy))
1609 '())
1610 #$@(if tmpdir
1611 (list (string-append "TMPDIR=" tmpdir))
7e4bc215
LC
1612 '())
1613
1614 ;; Make sure we run in a UTF-8 locale so that 'guix
1615 ;; offload' correctly restores nars that contain UTF-8
1616 ;; file names such as 'nss-certs'. See
1617 ;; <https://bugs.gnu.org/32942>.
1618 (string-append "GUIX_LOCPATH="
1619 #$glibc-utf8-locales "/lib/locale")
1620 "LC_ALL=en_US.utf8")
f4596f76
LC
1621
1622 #:log-file #$log-file))
1623 (stop #~(make-kill-destructor))))))
0adfe95a
LC
1624
1625(define (guix-accounts config)
1626 "Return the user accounts and user groups for CONFIG."
1627 (match config
1628 (($ <guix-configuration> _ build-group build-accounts)
1629 (cons (user-group
1630 (name build-group)
1631 (system? #t)
1632
1633 ;; Use a fixed GID so that we can create the store with the right
1634 ;; owner.
1635 (id 30000))
1636 (guix-build-accounts build-accounts
1637 #:group build-group)))))
1638
1639(define (guix-activation config)
1640 "Return the activation gexp for CONFIG."
1641 (match config
5b58c28b 1642 (($ <guix-configuration> guix build-group build-accounts authorize-key? keys)
0adfe95a 1643 ;; Assume that the store has BUILD-GROUP as its group. We could
0af94ad5 1644 ;; otherwise call 'chown' here, but the problem is that on a COW overlayfs,
0adfe95a
LC
1645 ;; chown leads to an entire copy of the tree, which is a bad idea.
1646
0bc02bec 1647 ;; Optionally authorize substitute server keys.
5f4a446d 1648 (if authorize-key?
970ebdae 1649 (hydra-key-authorization keys guix)
5f4a446d 1650 #~#f))))
0adfe95a 1651
88554b5d
LC
1652(define* (references-file item #:optional (name "references"))
1653 "Return a file that contains the list of references of ITEM."
1654 (if (struct? item) ;lowerable object
1655 (computed-file name
1656 (with-imported-modules (source-module-closure
1657 '((guix build store-copy)))
1658 #~(begin
1659 (use-modules (guix build store-copy))
1660
1661 (call-with-output-file #$output
1662 (lambda (port)
6892f0a2
LC
1663 (write (map store-info-item
1664 (call-with-input-file "graph"
1665 read-reference-graph))
88554b5d
LC
1666 port)))))
1667 #:options `(#:local-build? #f
1668 #:references-graphs (("graph" ,item))))
1669 (plain-file name "()")))
1670
0adfe95a
LC
1671(define guix-service-type
1672 (service-type
1673 (name 'guix)
1674 (extensions
d4053c71 1675 (list (service-extension shepherd-root-service-type guix-shepherd-service)
0adfe95a 1676 (service-extension account-service-type guix-accounts)
9a8b9eb8
LC
1677 (service-extension activation-service-type guix-activation)
1678 (service-extension profile-service-type
3d3c5650 1679 (compose list guix-configuration-guix))))
88554b5d
LC
1680
1681 ;; Extensions can specify extra directories to add to the build chroot.
1682 (compose concatenate)
1683 (extend (lambda (config directories)
1684 (guix-configuration
1685 (inherit config)
1686 (chroot-directories
1687 (append (guix-configuration-chroot-directories config)
1688 directories)))))
1689
6b9e1fef
LC
1690 (default-value (guix-configuration))
1691 (description
1692 "Run the build daemon of GNU@tie{}Guix, aka. @command{guix-daemon}.")))
0adfe95a 1693
84a2de36
LC
1694(define-deprecated (guix-service #:optional
1695 (config %default-guix-configuration))
1696 guix-service-type
0adfe95a
LC
1697 "Return a service that runs the Guix build daemon according to
1698@var{config}."
1699 (service guix-service-type config))
1700
1c52181f
LC
1701
1702(define-record-type* <guix-publish-configuration>
1703 guix-publish-configuration make-guix-publish-configuration
1704 guix-publish-configuration?
1705 (guix guix-publish-configuration-guix ;package
1706 (default guix))
1707 (port guix-publish-configuration-port ;number
1708 (default 80))
1709 (host guix-publish-configuration-host ;string
697ddb88 1710 (default "localhost"))
f2767d3e 1711 (compression-level guix-publish-configuration-compression-level ;integer
697ddb88 1712 (default 3))
f2767d3e 1713 (nar-path guix-publish-configuration-nar-path ;string
a35136cb
LC
1714 (default "nar"))
1715 (cache guix-publish-configuration-cache ;#f | string
1716 (default #f))
1717 (workers guix-publish-configuration-workers ;#f | integer
1718 (default #f))
1719 (ttl guix-publish-configuration-ttl ;#f | integer
1720 (default #f)))
1c52181f 1721
d4053c71 1722(define guix-publish-shepherd-service
1c52181f 1723 (match-lambda
a35136cb
LC
1724 (($ <guix-publish-configuration> guix port host compression
1725 nar-path cache workers ttl)
d4053c71 1726 (list (shepherd-service
1c52181f
LC
1727 (provision '(guix-publish))
1728 (requirement '(guix-daemon))
1729 (start #~(make-forkexec-constructor
9fc037fe 1730 (list #$(file-append guix "/bin/guix")
1c52181f
LC
1731 "publish" "-u" "guix-publish"
1732 "-p" #$(number->string port)
697ddb88
LC
1733 "-C" #$(number->string compression)
1734 (string-append "--nar-path=" #$nar-path)
a35136cb
LC
1735 (string-append "--listen=" #$host)
1736 #$@(if workers
1737 #~((string-append "--workers="
1738 #$(number->string
1739 workers)))
1740 #~())
1741 #$@(if ttl
1742 #~((string-append "--ttl="
1743 #$(number->string ttl)
1744 "s"))
1745 #~())
1746 #$@(if cache
1747 #~((string-append "--cache=" #$cache))
412701b0
LC
1748 #~()))
1749
1750 ;; Make sure we run in a UTF-8 locale so we can produce
1751 ;; nars for packages that contain UTF-8 file names such
1752 ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
1753 #:environment-variables
1754 (list (string-append "GUIX_LOCPATH="
1755 #$glibc-utf8-locales "/lib/locale")
1756 "LC_ALL=en_US.utf8")))
1c52181f
LC
1757 (stop #~(make-kill-destructor)))))))
1758
1759(define %guix-publish-accounts
1760 (list (user-group (name "guix-publish") (system? #t))
1761 (user-account
1762 (name "guix-publish")
1763 (group "guix-publish")
1764 (system? #t)
1765 (comment "guix publish user")
1766 (home-directory "/var/empty")
9e41130b 1767 (shell (file-append shadow "/sbin/nologin")))))
1c52181f 1768
a35136cb
LC
1769(define (guix-publish-activation config)
1770 (let ((cache (guix-publish-configuration-cache config)))
1771 (if cache
1772 (with-imported-modules '((guix build utils))
1773 #~(begin
1774 (use-modules (guix build utils))
1775
1776 (mkdir-p #$cache)
1777 (let* ((pw (getpw "guix-publish"))
1778 (uid (passwd:uid pw))
1779 (gid (passwd:gid pw)))
1780 (chown #$cache uid gid))))
1781 #t)))
1782
1c52181f
LC
1783(define guix-publish-service-type
1784 (service-type (name 'guix-publish)
1785 (extensions
d4053c71
AK
1786 (list (service-extension shepherd-root-service-type
1787 guix-publish-shepherd-service)
1c52181f 1788 (service-extension account-service-type
a35136cb
LC
1789 (const %guix-publish-accounts))
1790 (service-extension activation-service-type
1791 guix-publish-activation)))
6b9e1fef
LC
1792 (default-value (guix-publish-configuration))
1793 (description
1794 "Add a Shepherd service running @command{guix publish}, a
1795command that allows you to share pre-built binaries with others over HTTP.")))
1c52181f 1796
84a2de36
LC
1797(define-deprecated (guix-publish-service #:key (guix guix)
1798 (port 80) (host "localhost"))
1799 guix-publish-service-type
1c52181f
LC
1800 "Return a service that runs @command{guix publish} listening on @var{host}
1801and @var{port} (@pxref{Invoking guix publish}).
1802
1803This assumes that @file{/etc/guix} already contains a signing key pair as
1804created by @command{guix archive --generate-key} (@pxref{Invoking guix
1805archive}). If that is not the case, the service will fail to start."
f1e900a3 1806 ;; Deprecated.
1c52181f
LC
1807 (service guix-publish-service-type
1808 (guix-publish-configuration (guix guix) (port port) (host host))))
1809
0adfe95a
LC
1810\f
1811;;;
1812;;; Udev.
1813;;;
1814
1815(define-record-type* <udev-configuration>
1816 udev-configuration make-udev-configuration
1817 udev-configuration?
1818 (udev udev-configuration-udev ;<package>
fd779db9 1819 (default eudev))
0adfe95a
LC
1820 (rules udev-configuration-rules ;list of <package>
1821 (default '())))
db4fdc04 1822
ecd06ca9
LC
1823(define (udev-rules-union packages)
1824 "Return the union of the @code{lib/udev/rules.d} directories found in each
1825item of @var{packages}."
1826 (define build
4ee96a79
LC
1827 (with-imported-modules '((guix build union)
1828 (guix build utils))
1829 #~(begin
1830 (use-modules (guix build union)
1831 (guix build utils)
1832 (srfi srfi-1)
1833 (srfi srfi-26))
ecd06ca9 1834
4ee96a79
LC
1835 (define %standard-locations
1836 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
ecd06ca9 1837
4ee96a79
LC
1838 (define (rules-sub-directory directory)
1839 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1840 ;; #f if none was found.
1841 (find directory-exists?
1842 (map (cut string-append directory <>) %standard-locations)))
ecd06ca9 1843
4ee96a79
LC
1844 (mkdir-p (string-append #$output "/lib/udev"))
1845 (union-build (string-append #$output "/lib/udev/rules.d")
1846 (filter-map rules-sub-directory '#$packages)))))
ecd06ca9 1847
4ee96a79 1848 (computed-file "udev-rules" build))
ecd06ca9 1849
80e6f37e
RW
1850(define (udev-rule file-name contents)
1851 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1852 (computed-file file-name
4ee96a79
LC
1853 (with-imported-modules '((guix build utils))
1854 #~(begin
1855 (use-modules (guix build utils))
1856
1857 (define rules.d
1858 (string-append #$output "/lib/udev/rules.d"))
1859
1860 (mkdir-p rules.d)
1861 (call-with-output-file
1862 (string-append rules.d "/" #$file-name)
1863 (lambda (port)
1864 (display #$contents port)))))))
7f28bf9a 1865
6e644cfd
MC
1866(define (file->udev-rule file-name file)
1867 "Return a directory with a udev rule file FILE-NAME which is a copy of FILE."
1868 (computed-file file-name
1869 (with-imported-modules '((guix build utils))
1870 #~(begin
1871 (use-modules (guix build utils))
1872
1873 (define rules.d
1874 (string-append #$output "/lib/udev/rules.d"))
1875
1876 (define file-copy-dest
1877 (string-append rules.d "/" #$file-name))
1878
1879 (mkdir-p rules.d)
1880 (copy-file #$file file-copy-dest)))))
1881
80e6f37e
RW
1882(define kvm-udev-rule
1883 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1884 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1885 ;; but now we have to add it by ourselves.
1886
1887 ;; Build users are part of the "kvm" group, so we can fearlessly make
1888 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1889 (udev-rule "90-kvm.rules"
1890 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1891
d4053c71
AK
1892(define udev-shepherd-service
1893 ;; Return a <shepherd-service> for UDEV with RULES.
0adfe95a
LC
1894 (match-lambda
1895 (($ <udev-configuration> udev rules)
80e6f37e 1896 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
1897 (udev.conf (computed-file "udev.conf"
1898 #~(call-with-output-file #$output
1899 (lambda (port)
1900 (format port
1901 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1902 #$rules))))))
1903 (list
d4053c71 1904 (shepherd-service
0adfe95a
LC
1905 (provision '(udev))
1906
1907 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1908 ;; be added: see
1909 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1910 (requirement '(root-file-system))
1911
1912 (documentation "Populate the /dev directory, dynamically.")
1913 (start #~(lambda ()
0adfe95a 1914 (define udevd
7fd30825
LC
1915 ;; 'udevd' from eudev.
1916 #$(file-append udev "/sbin/udevd"))
0adfe95a
LC
1917
1918 (define (wait-for-udevd)
1919 ;; Wait until someone's listening on udevd's control
1920 ;; socket.
1921 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1922 (let try ()
1923 (catch 'system-error
1924 (lambda ()
1925 (connect sock PF_UNIX "/run/udev/control")
1926 (close-port sock))
1927 (lambda args
1928 (format #t "waiting for udevd...~%")
1929 (usleep 500000)
1930 (try))))))
1931
1932 ;; Allow udev to find the modules.
1933 (setenv "LINUX_MODULE_DIRECTORY"
1934 "/run/booted-system/kernel/lib/modules")
1935
1936 ;; The first one is for udev, the second one for eudev.
1937 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1938 (setenv "EUDEV_RULES_DIRECTORY"
9fc037fe 1939 #$(file-append rules "/lib/udev/rules.d"))
0adfe95a 1940
86e6b4c9
DM
1941 (let* ((kernel-release
1942 (utsname:release (uname)))
1943 (linux-module-directory
1944 (getenv "LINUX_MODULE_DIRECTORY"))
1945 (directory
1946 (string-append linux-module-directory "/"
1947 kernel-release))
1948 (old-umask (umask #o022)))
23784f0c
LC
1949 ;; If we're in a container, DIRECTORY might not exist,
1950 ;; for instance because the host runs a different
1951 ;; kernel. In that case, skip it; we'll just miss a few
1952 ;; nodes like /dev/fuse.
1953 (when (file-exists? directory)
1954 (make-static-device-nodes directory))
86e6b4c9
DM
1955 (umask old-umask))
1956
7fd30825
LC
1957 (let ((pid (fork+exec-command (list udevd))))
1958 ;; Wait until udevd is up and running. This appears to
1959 ;; be needed so that the events triggered below are
1960 ;; actually handled.
1961 (wait-for-udevd)
1962
1963 ;; Trigger device node creation.
1964 (system* #$(file-append udev "/bin/udevadm")
1965 "trigger" "--action=add")
1966
1967 ;; Wait for things to settle down.
1968 (system* #$(file-append udev "/bin/udevadm")
1969 "settle")
1970 pid)))
0adfe95a
LC
1971 (stop #~(make-kill-destructor))
1972
1973 ;; When halting the system, 'udev' is actually killed by
1974 ;; 'user-processes', i.e., before its own 'stop' method was called.
1975 ;; Thus, make sure it is not respawned.
86e6b4c9
DM
1976 (respawn? #f)
1977 ;; We need additional modules.
1978 (modules `((gnu build linux-boot)
bafcf1f3
LC
1979 ,@%default-modules))
1980
1981 (actions (list (shepherd-action
1982 (name 'rules)
1983 (documentation "Display the directory containing
1984the udev rules in use.")
1985 (procedure #~(lambda (_)
1986 (display #$rules)
1987 (newline))))))))))))
0adfe95a
LC
1988
1989(define udev-service-type
1990 (service-type (name 'udev)
1991 (extensions
d4053c71
AK
1992 (list (service-extension shepherd-root-service-type
1993 udev-shepherd-service)))
0adfe95a
LC
1994
1995 (compose concatenate) ;concatenate the list of rules
1996 (extend (lambda (config rules)
1997 (match config
1998 (($ <udev-configuration> udev initial-rules)
1999 (udev-configuration
2000 (udev udev)
6b9e1fef 2001 (rules (append initial-rules rules)))))))
fd779db9 2002 (default-value (udev-configuration))
6b9e1fef
LC
2003 (description
2004 "Run @command{udev}, which populates the @file{/dev}
2005directory dynamically. Get extra rules from the packages listed in the
2006@code{rules} field of its value, @code{udev-configuration} object.")))
0adfe95a 2007
255f7308 2008(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
2009 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
2010extra rules from the packages listed in @var{rules}."
0adfe95a
LC
2011 (service udev-service-type
2012 (udev-configuration (udev udev) (rules rules))))
2013
0adfe95a 2014(define swap-service-type
d4053c71 2015 (shepherd-service-type
00184239 2016 'swap
0adfe95a
LC
2017 (lambda (device)
2018 (define requirement
2019 (if (string-prefix? "/dev/mapper/" device)
2020 (list (symbol-append 'device-mapping-
2021 (string->symbol (basename device))))
2022 '()))
2023
d4053c71 2024 (shepherd-service
0adfe95a
LC
2025 (provision (list (symbol-append 'swap- (string->symbol device))))
2026 (requirement `(udev ,@requirement))
2027 (documentation "Enable the given swap device.")
2028 (start #~(lambda ()
2029 (restart-on-EINTR (swapon #$device))
2030 #t))
2031 (stop #~(lambda _
2032 (restart-on-EINTR (swapoff #$device))
2033 #f))
2034 (respawn? #f)))))
5dae0186 2035
2a13d05e
LC
2036(define (swap-service device)
2037 "Return a service that uses @var{device} as a swap device."
0adfe95a 2038 (service swap-service-type device))
2a13d05e 2039
5986e941
LC
2040(define %default-gpm-options
2041 ;; Default options for GPM.
2042 '("-m" "/dev/input/mice" "-t" "ps2"))
2043
8664cc88
LC
2044(define-record-type* <gpm-configuration>
2045 gpm-configuration make-gpm-configuration gpm-configuration?
5986e941
LC
2046 (gpm gpm-configuration-gpm ;package
2047 (default gpm))
2048 (options gpm-configuration-options ;list of strings
2049 (default %default-gpm-options)))
8664cc88 2050
d4053c71 2051(define gpm-shepherd-service
8664cc88 2052 (match-lambda
a907d997 2053 (($ <gpm-configuration> gpm options)
d4053c71 2054 (list (shepherd-service
8664cc88
LC
2055 (requirement '(udev))
2056 (provision '(gpm))
2057 (start #~(lambda ()
2058 ;; 'gpm' runs in the background and sets a PID file.
2059 ;; Note that it requires running as "root".
2060 (false-if-exception (delete-file "/var/run/gpm.pid"))
9fc037fe 2061 (fork+exec-command (list #$(file-append gpm "/sbin/gpm")
8664cc88
LC
2062 #$@options))
2063
2064 ;; Wait for the PID file to appear; declare failure if
2065 ;; it doesn't show up.
2066 (let loop ((i 3))
2067 (or (file-exists? "/var/run/gpm.pid")
2068 (if (zero? i)
2069 #f
2070 (begin
2071 (sleep 1)
2072 (loop (1- i))))))))
2073
2074 (stop #~(lambda (_)
2075 ;; Return #f if successfully stopped.
9fc037fe 2076 (not (zero? (system* #$(file-append gpm "/sbin/gpm")
8664cc88
LC
2077 "-k"))))))))))
2078
2079(define gpm-service-type
2080 (service-type (name 'gpm)
2081 (extensions
d4053c71 2082 (list (service-extension shepherd-root-service-type
6b9e1fef 2083 gpm-shepherd-service)))
5986e941 2084 (default-value (gpm-configuration))
6b9e1fef
LC
2085 (description
2086 "Run GPM, the general-purpose mouse daemon, with the given
2087command-line options. GPM allows users to use the mouse in the console,
2088notably to select, copy, and paste text. The default options use the
2089@code{ps2} protocol, which works for both USB and PS/2 mice.")))
8664cc88 2090
65a67bf7
LC
2091(define-deprecated (gpm-service #:key (gpm gpm)
2092 (options %default-gpm-options))
2093 gpm-service-type
8664cc88
LC
2094 "Run @var{gpm}, the general-purpose mouse daemon, with the given
2095command-line @var{options}. GPM allows users to use the mouse in the console,
2096notably to select, copy, and paste text. The default value of @var{options}
2097uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
2098
2099This service is not part of @var{%base-services}."
2100 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
2101 ;; "info mice" and "mouse_set X" to use the right mouse.
2102 (service gpm-service-type
2103 (gpm-configuration (gpm gpm) (options options))))
2104
46ec2707
DC
2105(define-record-type* <kmscon-configuration>
2106 kmscon-configuration make-kmscon-configuration
2107 kmscon-configuration?
2108 (kmscon kmscon-configuration-kmscon
2109 (default kmscon))
2110 (virtual-terminal kmscon-configuration-virtual-terminal)
2111 (login-program kmscon-configuration-login-program
9fc037fe 2112 (default (file-append shadow "/bin/login")))
46ec2707
DC
2113 (login-arguments kmscon-configuration-login-arguments
2114 (default '("-p")))
2d9dace8
MO
2115 (auto-login kmscon-configuration-auto-login
2116 (default #f))
46ec2707
DC
2117 (hardware-acceleration? kmscon-configuration-hardware-acceleration?
2118 (default #f))) ; #t causes failure
2119
2120(define kmscon-service-type
2121 (shepherd-service-type
2122 'kmscon
2123 (lambda (config)
2124 (let ((kmscon (kmscon-configuration-kmscon config))
2125 (virtual-terminal (kmscon-configuration-virtual-terminal config))
2126 (login-program (kmscon-configuration-login-program config))
2127 (login-arguments (kmscon-configuration-login-arguments config))
2d9dace8 2128 (auto-login (kmscon-configuration-auto-login config))
46ec2707
DC
2129 (hardware-acceleration? (kmscon-configuration-hardware-acceleration? config)))
2130
2131 (define kmscon-command
2132 #~(list
9fc037fe 2133 #$(file-append kmscon "/bin/kmscon") "--login"
46ec2707 2134 "--vt" #$virtual-terminal
f4e8bc5f 2135 "--no-switchvt" ;Prevent a switch to the virtual terminal.
46ec2707 2136 #$@(if hardware-acceleration? '("--hwaccel") '())
2d9dace8
MO
2137 "--login" "--"
2138 #$login-program #$@login-arguments
2139 #$@(if auto-login
2140 #~(#$auto-login)
2141 #~())))
46ec2707
DC
2142
2143 (shepherd-service
2144 (documentation "kmscon virtual terminal")
76421cf0 2145 (requirement '(user-processes udev dbus-system))
46ec2707
DC
2146 (provision (list (symbol-append 'term- (string->symbol virtual-terminal))))
2147 (start #~(make-forkexec-constructor #$kmscon-command))
2148 (stop #~(make-kill-destructor)))))))
2149
c9436025
DM
2150(define-record-type* <static-networking>
2151 static-networking make-static-networking
2152 static-networking?
2153 (interface static-networking-interface)
2154 (ip static-networking-ip)
2155 (netmask static-networking-netmask
2156 (default #f))
2157 (gateway static-networking-gateway ;FIXME: doesn't belong here
2158 (default #f))
2159 (provision static-networking-provision
2160 (default #f))
2161 (requirement static-networking-requirement
2162 (default '()))
2163 (name-servers static-networking-name-servers ;FIXME: doesn't belong here
2164 (default '())))
2165
2166(define static-networking-shepherd-service
2167 (match-lambda
2168 (($ <static-networking> interface ip netmask gateway provision
2169 requirement name-servers)
2170 (let ((loopback? (and provision (memq 'loopback provision))))
2171 (shepherd-service
2172
2173 (documentation
2174 "Bring up the networking interface using a static IP address.")
2175 (requirement requirement)
2176 (provision (or provision
2177 (list (symbol-append 'networking-
2178 (string->symbol interface)))))
2179
2180 (start #~(lambda _
2181 ;; Return #t if successfully started.
2182 (let* ((addr (inet-pton AF_INET #$ip))
2183 (sockaddr (make-socket-address AF_INET addr 0))
2184 (mask (and #$netmask
2185 (inet-pton AF_INET #$netmask)))
2186 (maskaddr (and mask
2187 (make-socket-address AF_INET
2188 mask 0)))
2189 (gateway (and #$gateway
2190 (inet-pton AF_INET #$gateway)))
2191 (gatewayaddr (and gateway
2192 (make-socket-address AF_INET
2193 gateway 0))))
2194 (configure-network-interface #$interface sockaddr
2195 (logior IFF_UP
2196 #$(if loopback?
2197 #~IFF_LOOPBACK
2198 0))
2199 #:netmask maskaddr)
2200 (when gateway
2201 (let ((sock (socket AF_INET SOCK_DGRAM 0)))
2202 (add-network-route/gateway sock gatewayaddr)
2203 (close-port sock))))))
2204 (stop #~(lambda _
2205 ;; Return #f is successfully stopped.
2206 (let ((sock (socket AF_INET SOCK_STREAM 0)))
2207 (when #$gateway
2208 (delete-network-route sock
2209 (make-socket-address
2210 AF_INET INADDR_ANY 0)))
2211 (set-network-interface-flags sock #$interface 0)
2212 (close-port sock)
241358dc 2213 #f)))
c9436025
DM
2214 (respawn? #f))))))
2215
2216(define (static-networking-etc-files interfaces)
2217 "Return a /etc/resolv.conf entry for INTERFACES or the empty list."
2218 (match (delete-duplicates
2219 (append-map static-networking-name-servers
2220 interfaces))
2221 (()
2222 '())
2223 ((name-servers ...)
2224 (let ((content (string-join
2225 (map (cut string-append "nameserver " <>)
2226 name-servers)
2227 "\n" 'suffix)))
2228 `(("resolv.conf"
2229 ,(plain-file "resolv.conf"
2230 (string-append "\
2231# Generated by 'static-networking-service'.\n"
2232 content))))))))
2233
2234(define (static-networking-shepherd-services interfaces)
2235 "Return the list of Shepherd services to bring up INTERFACES, a list of
2236<static-networking> objects."
2237 (define (loopback? service)
2238 (memq 'loopback (shepherd-service-provision service)))
2239
2240 (let ((services (map static-networking-shepherd-service interfaces)))
2241 (match (remove loopback? services)
2242 (()
2243 ;; There's no interface other than 'loopback', so we assume that the
2244 ;; 'networking' service will be provided by dhclient or similar.
2245 services)
2246 ((non-loopback ...)
2247 ;; Assume we're providing all the interfaces, and thus, provide a
2248 ;; 'networking' service.
2249 (cons (shepherd-service
2250 (provision '(networking))
2251 (requirement (append-map shepherd-service-provision
2252 services))
2253 (start #~(const #t))
2254 (stop #~(const #f))
2255 (documentation "Bring up all the networking interfaces."))
2256 services)))))
2257
2258(define static-networking-service-type
2259 ;; The service type for statically-defined network interfaces.
2260 (service-type (name 'static-networking)
2261 (extensions
2262 (list
2263 (service-extension shepherd-root-service-type
2264 static-networking-shepherd-services)
2265 (service-extension etc-service-type
2266 static-networking-etc-files)))
2267 (compose concatenate)
2268 (extend append)
2269 (description
2270 "Turn up the specified network interfaces upon startup,
2271with the given IP address, gateway, netmask, and so on. The value for
2272services of this type is a list of @code{static-networking} objects, one per
2273network interface.")))
2274
2275(define* (static-networking-service interface ip
2276 #:key
2277 netmask gateway provision
2278 ;; Most interfaces require udev to be usable.
2279 (requirement '(udev))
2280 (name-servers '()))
2281 "Return a service that starts @var{interface} with address @var{ip}. If
2282@var{netmask} is true, use it as the network mask. If @var{gateway} is true,
2283it must be a string specifying the default network gateway.
2284
2285This procedure can be called several times, one for each network
2286interface of interest. Behind the scenes what it does is extend
2287@code{static-networking-service-type} with additional network interfaces
2288to handle."
2289 (simple-service 'static-network-interface
2290 static-networking-service-type
2291 (list (static-networking (interface interface) (ip ip)
2292 (netmask netmask) (gateway gateway)
2293 (provision provision)
2294 (requirement requirement)
2295 (name-servers name-servers)))))
2296
8664cc88 2297\f
8b198abe
LC
2298(define %base-services
2299 ;; Convenience variable holding the basic services.
178bce41 2300 (list (service login-service-type)
317d3b47 2301
bb3062ad 2302 (service virtual-terminal-service-type)
4a84a487
LC
2303 (service console-font-service-type
2304 (map (lambda (tty)
2305 (cons tty %default-console-font))
2306 '("tty1" "tty2" "tty3" "tty4" "tty5" "tty6")))
317d3b47 2307
5a9902c8
DM
2308 (agetty-service (agetty-configuration
2309 (extra-options '("-L")) ; no carrier detect
2310 (term "vt100")
2311 (tty #f))) ; automatic
2312
317d3b47
DC
2313 (mingetty-service (mingetty-configuration
2314 (tty "tty1")))
2315 (mingetty-service (mingetty-configuration
2316 (tty "tty2")))
2317 (mingetty-service (mingetty-configuration
2318 (tty "tty3")))
2319 (mingetty-service (mingetty-configuration
2320 (tty "tty4")))
2321 (mingetty-service (mingetty-configuration
2322 (tty "tty5")))
2323 (mingetty-service (mingetty-configuration
2324 (tty "tty6")))
2325
8de3e4b3
LC
2326 (service static-networking-service-type
2327 (list (static-networking (interface "lo")
2328 (ip "127.0.0.1")
db8ed7ce 2329 (requirement '())
8de3e4b3 2330 (provision '(loopback)))))
317d3b47 2331 (syslog-service)
8faaf8d7 2332 (service urandom-seed-service-type)
7194745a 2333 (service guix-service-type)
db903549 2334 (service nscd-service-type)
317d3b47
DC
2335
2336 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
2337 ;; used, so enable them by default. The FUSE and ALSA rules are
2338 ;; less critical, but handy.
fd779db9
EF
2339 (service udev-service-type
2340 (udev-configuration
2341 (rules (list lvm2 fuse alsa-utils crda))))
387e1754
LC
2342
2343 (service special-files-service-type
2344 `(("/bin/sh" ,(file-append (canonical-package bash)
2345 "/bin/sh"))))))
8b198abe 2346
db4fdc04 2347;;; base.scm ends here