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