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