gnu: Add guile-newt.
[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?)
09b7300c
LC
688 (let ((knob "/sys/module/vt/parameters/default_utf8"))
689 (shepherd-service
690 (documentation "Set virtual terminals in UTF-8 module.")
691 (provision '(virtual-terminal))
692 (requirement '(root-file-system))
693 (start #~(lambda _
694 ;; In containers /sys is read-only so don't insist on
695 ;; writing to this file.
696 (unless (= 1 (call-with-input-file #$knob read))
697 (call-with-output-file #$knob
698 (lambda (port)
699 (display 1 port))))
700 #t))
701 (stop #~(const #f)))))
bb3062ad 702 #t)) ;default to UTF-8
62ca0fdf 703
0adfe95a 704(define console-keymap-service-type
d4053c71 705 (shepherd-service-type
00184239 706 'console-keymap
b3d05f48 707 (lambda (files)
d4053c71 708 (shepherd-service
0adfe95a
LC
709 (documentation (string-append "Load console keymap (loadkeys)."))
710 (provision '(console-keymap))
711 (start #~(lambda _
9fc037fe 712 (zero? (system* #$(file-append kbd "/bin/loadkeys")
b3d05f48 713 #$@files))))
0adfe95a
LC
714 (respawn? #f)))))
715
b3d05f48
AK
716(define (console-keymap-service . files)
717 "Return a service to load console keymaps from @var{files}."
718 (service console-keymap-service-type files))
0adfe95a 719
4a84a487
LC
720(define %default-console-font
721 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
722 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
723 ;; codepoints notably found in the UTF-8 manual.
724 "LatGrkCyr-8x16")
725
726(define (console-font-shepherd-services tty+font)
727 "Return a list of Shepherd services for each pair in TTY+FONT."
728 (map (match-lambda
729 ((tty . font)
730 (let ((device (string-append "/dev/" tty)))
731 (shepherd-service
732 (documentation "Load a Unicode console font.")
733 (provision (list (symbol-append 'console-font-
734 (string->symbol tty))))
735
736 ;; Start after mingetty has been started on TTY, otherwise the settings
737 ;; are ignored.
738 (requirement (list (symbol-append 'term-
739 (string->symbol tty))))
740
741 (start #~(lambda _
787e8a80
LC
742 ;; It could be that mingetty is not fully ready yet,
743 ;; which we check by calling 'ttyname'.
744 (let loop ((i 10))
745 (unless (or (zero? i)
746 (call-with-input-file #$device
747 (lambda (port)
748 (false-if-exception (ttyname port)))))
749 (usleep 500)
750 (loop (- i 1))))
751
bb3062ad
LC
752 ;; Assume the VT is already in UTF-8 mode, thanks to
753 ;; the 'virtual-terminal' service.
754 ;;
755 ;; 'setfont' returns EX_OSERR (71) when an
756 ;; KDFONTOP ioctl fails, for example. Like
757 ;; systemd's vconsole support, let's not treat
758 ;; this as an error.
759 (case (status:exit-val
760 (system* #$(file-append kbd "/bin/setfont")
761 "-C" #$device #$font))
762 ((0 71) #t)
763 (else #f))))
4a84a487
LC
764 (stop #~(const #t))
765 (respawn? #f)))))
766 tty+font))
0adfe95a 767
4a84a487
LC
768(define console-font-service-type
769 (service-type (name 'console-fonts)
770 (extensions
771 (list (service-extension shepherd-root-service-type
772 console-font-shepherd-services)))
773 (compose concatenate)
6b9e1fef
LC
774 (extend append)
775 (description
776 "Install the given fonts on the specified ttys (fonts are per
777virtual console on GNU/Linux). The value of this service is a list of
778tty/font pairs like:
779
780@example
781'((\"tty1\" . \"LatGrkCyr-8x16\"))
782@end example\n")))
5eca9459 783
62ca0fdf 784(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
4a84a487
LC
785 "This procedure is deprecated in favor of @code{console-font-service-type}.
786
787Return a service that sets up Unicode support in @var{tty} and loads
62ca0fdf 788@var{font} for that tty (fonts are per virtual console in Linux.)"
4a84a487
LC
789 (simple-service (symbol-append 'console-font- (string->symbol tty))
790 console-font-service-type `((,tty . ,font))))
62ca0fdf 791
317d3b47
DC
792(define %default-motd
793 (plain-file "motd" "This is the GNU operating system, welcome!\n\n"))
794
795(define-record-type* <login-configuration>
796 login-configuration make-login-configuration
797 login-configuration?
798 (motd login-configuration-motd ;file-like
799 (default %default-motd))
800 ;; Allow empty passwords by default so that first-time users can log in when
801 ;; the 'root' account has just been created.
802 (allow-empty-passwords? login-configuration-allow-empty-passwords?
803 (default #t))) ;Boolean
804
805(define (login-pam-service config)
806 "Return the list of PAM service needed for CONF."
807 ;; Let 'login' be known to PAM.
808 (list (unix-pam-service "login"
809 #:allow-empty-passwords?
810 (login-configuration-allow-empty-passwords? config)
811 #:motd
812 (login-configuration-motd config))))
813
814(define login-service-type
815 (service-type (name 'login)
816 (extensions (list (service-extension pam-root-service-type
6b9e1fef
LC
817 login-pam-service)))
818 (description
819 "Provide a console log-in service as specified by its
820configuration value, a @code{login-configuration} object.")))
317d3b47
DC
821
822(define* (login-service #:optional (config (login-configuration)))
823 "Return a service configure login according to @var{config}, which specifies
824the message of the day, among other things."
825 (service login-service-type config))
826
9ee4c9ab
LF
827(define-record-type* <agetty-configuration>
828 agetty-configuration make-agetty-configuration
829 agetty-configuration?
830 (agetty agetty-configuration-agetty ;<package>
831 (default util-linux))
5a9902c8 832 (tty agetty-configuration-tty) ;string | #f
9ee4c9ab
LF
833 (term agetty-term ;string | #f
834 (default #f))
835 (baud-rate agetty-baud-rate ;string | #f
836 (default #f))
837 (auto-login agetty-auto-login ;list of strings | #f
838 (default #f))
839 (login-program agetty-login-program ;gexp
840 (default (file-append shadow "/bin/login")))
841 (login-pause? agetty-login-pause? ;Boolean
842 (default #f))
843 (eight-bits? agetty-eight-bits? ;Boolean
844 (default #f))
845 (no-reset? agetty-no-reset? ;Boolean
846 (default #f))
847 (remote? agetty-remote? ;Boolean
848 (default #f))
849 (flow-control? agetty-flow-control? ;Boolean
850 (default #f))
851 (host agetty-host ;string | #f
852 (default #f))
853 (no-issue? agetty-no-issue? ;Boolean
854 (default #f))
855 (init-string agetty-init-string ;string | #f
856 (default #f))
857 (no-clear? agetty-no-clear? ;Boolean
858 (default #f))
859 (local-line agetty-local-line ;always | never | auto
860 (default #f))
861 (extract-baud? agetty-extract-baud? ;Boolean
862 (default #f))
863 (skip-login? agetty-skip-login? ;Boolean
864 (default #f))
865 (no-newline? agetty-no-newline? ;Boolean
866 (default #f))
867 (login-options agetty-login-options ;string | #f
868 (default #f))
869 (chroot agetty-chroot ;string | #f
870 (default #f))
871 (hangup? agetty-hangup? ;Boolean
872 (default #f))
873 (keep-baud? agetty-keep-baud? ;Boolean
874 (default #f))
875 (timeout agetty-timeout ;integer | #f
876 (default #f))
877 (detect-case? agetty-detect-case? ;Boolean
878 (default #f))
879 (wait-cr? agetty-wait-cr? ;Boolean
880 (default #f))
881 (no-hints? agetty-no-hints? ;Boolean
882 (default #f))
883 (no-hostname? agetty-no hostname? ;Boolean
884 (default #f))
885 (long-hostname? agetty-long-hostname? ;Boolean
886 (default #f))
887 (erase-characters agetty-erase-characters ;string | #f
888 (default #f))
889 (kill-characters agetty-kill-characters ;string | #f
890 (default #f))
891 (chdir agetty-chdir ;string | #f
892 (default #f))
893 (delay agetty-delay ;integer | #f
894 (default #f))
895 (nice agetty-nice ;integer | #f
896 (default #f))
897 ;; "Escape hatch" for passing arbitrary command-line arguments.
898 (extra-options agetty-extra-options ;list of strings
899 (default '()))
900;;; XXX Unimplemented for now!
901;;; (issue-file agetty-issue-file ;file-like
902;;; (default #f))
903 )
904
5a9902c8
DM
905(define (default-serial-port)
906 "Return a gexp that determines a reasonable default serial port
907to use as the tty. This is primarily useful for headless systems."
908 #~(begin
909 ;; console=device,options
910 ;; device: can be tty0, ttyS0, lp0, ttyUSB0 (serial).
911 ;; options: BBBBPNF. P n|o|e, N number of bits,
912 ;; F flow control (r RTS)
913 (let* ((not-comma (char-set-complement (char-set #\,)))
914 (command (linux-command-line))
915 (agetty-specs (find-long-options "agetty.tty" command))
916 (console-specs (filter (lambda (spec)
917 (and (string-prefix? "tty" spec)
918 (not (or
919 (string-prefix? "tty0" spec)
920 (string-prefix? "tty1" spec)
921 (string-prefix? "tty2" spec)
922 (string-prefix? "tty3" spec)
923 (string-prefix? "tty4" spec)
924 (string-prefix? "tty5" spec)
925 (string-prefix? "tty6" spec)
926 (string-prefix? "tty7" spec)
927 (string-prefix? "tty8" spec)
928 (string-prefix? "tty9" spec)))))
929 (find-long-options "console" command)))
930 (specs (append agetty-specs console-specs)))
931 (match specs
932 (() #f)
933 ((spec _ ...)
934 ;; Extract device name from first spec.
935 (match (string-tokenize spec not-comma)
936 ((device-name _ ...)
937 device-name)))))))
938
9ee4c9ab
LF
939(define agetty-shepherd-service
940 (match-lambda
941 (($ <agetty-configuration> agetty tty term baud-rate auto-login
942 login-program login-pause? eight-bits? no-reset? remote? flow-control?
943 host no-issue? init-string no-clear? local-line extract-baud?
944 skip-login? no-newline? login-options chroot hangup? keep-baud? timeout
945 detect-case? wait-cr? no-hints? no-hostname? long-hostname?
946 erase-characters kill-characters chdir delay nice extra-options)
947 (list
948 (shepherd-service
5a9902c8 949 (modules '((ice-9 match) (gnu build linux-boot)))
9ee4c9ab 950 (documentation "Run agetty on a tty.")
5a9902c8 951 (provision (list (symbol-append 'term- (string->symbol (or tty "auto")))))
9ee4c9ab
LF
952
953 ;; Since the login prompt shows the host name, wait for the 'host-name'
954 ;; service to be done. Also wait for udev essentially so that the tty
955 ;; text is not lost in the middle of kernel messages (see also
956 ;; mingetty-shepherd-service).
957 (requirement '(user-processes host-name udev))
958
c32e3dde
DM
959 (start #~(lambda args
960 (let ((defaulted-tty #$(or tty (default-serial-port))))
961 (apply
962 (if defaulted-tty
963 (make-forkexec-constructor
964 (list #$(file-append util-linux "/sbin/agetty")
965 #$@extra-options
966 #$@(if eight-bits?
967 #~("--8bits")
968 #~())
969 #$@(if no-reset?
970 #~("--noreset")
971 #~())
972 #$@(if remote?
973 #~("--remote")
974 #~())
975 #$@(if flow-control?
976 #~("--flow-control")
977 #~())
978 #$@(if host
979 #~("--host" #$host)
980 #~())
981 #$@(if no-issue?
982 #~("--noissue")
983 #~())
984 #$@(if init-string
985 #~("--init-string" #$init-string)
986 #~())
987 #$@(if no-clear?
988 #~("--noclear")
989 #~())
9ee4c9ab
LF
990;;; FIXME This doesn't work as expected. According to agetty(8), if this option
991;;; is not passed, then the default is 'auto'. However, in my tests, when that
992;;; option is selected, agetty never presents the login prompt, and the
993;;; term-ttyS0 service respawns every few seconds.
c32e3dde
DM
994 #$@(if local-line
995 #~(#$(match local-line
996 ('auto "--local-line=auto")
997 ('always "--local-line=always")
998 ('never "-local-line=never")))
999 #~())
1000 #$@(if tty
1001 #~()
1002 #~("--keep-baud"))
1003 #$@(if extract-baud?
1004 #~("--extract-baud")
1005 #~())
1006 #$@(if skip-login?
1007 #~("--skip-login")
1008 #~())
1009 #$@(if no-newline?
1010 #~("--nonewline")
1011 #~())
1012 #$@(if login-options
1013 #~("--login-options" #$login-options)
1014 #~())
1015 #$@(if chroot
1016 #~("--chroot" #$chroot)
1017 #~())
1018 #$@(if hangup?
1019 #~("--hangup")
1020 #~())
1021 #$@(if keep-baud?
1022 #~("--keep-baud")
1023 #~())
1024 #$@(if timeout
1025 #~("--timeout" #$(number->string timeout))
1026 #~())
1027 #$@(if detect-case?
1028 #~("--detect-case")
1029 #~())
1030 #$@(if wait-cr?
1031 #~("--wait-cr")
1032 #~())
1033 #$@(if no-hints?
1034 #~("--nohints?")
1035 #~())
1036 #$@(if no-hostname?
1037 #~("--nohostname")
1038 #~())
1039 #$@(if long-hostname?
1040 #~("--long-hostname")
1041 #~())
1042 #$@(if erase-characters
1043 #~("--erase-chars" #$erase-characters)
1044 #~())
1045 #$@(if kill-characters
1046 #~("--kill-chars" #$kill-characters)
1047 #~())
1048 #$@(if chdir
1049 #~("--chdir" #$chdir)
1050 #~())
1051 #$@(if delay
1052 #~("--delay" #$(number->string delay))
1053 #~())
1054 #$@(if nice
1055 #~("--nice" #$(number->string nice))
1056 #~())
1057 #$@(if auto-login
1058 (list "--autologin" auto-login)
1059 '())
1060 #$@(if login-program
1061 #~("--login-program" #$login-program)
1062 #~())
1063 #$@(if login-pause?
1064 #~("--login-pause")
1065 #~())
1066 defaulted-tty
1067 #$@(if baud-rate
1068 #~(#$baud-rate)
1069 #~())
1070 #$@(if term
1071 #~(#$term)
1072 #~())))
1073 (const #f)) ; never start.
1074 args))))
9ee4c9ab
LF
1075 (stop #~(make-kill-destructor)))))))
1076
1077(define agetty-service-type
1078 (service-type (name 'agetty)
1079 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1080 agetty-shepherd-service)))
1081 (description
1082 "Provide console login using the @command{agetty}
1083program.")))
9ee4c9ab
LF
1084
1085(define* (agetty-service config)
1086 "Return a service to run agetty according to @var{config}, which specifies
1087the tty to run, among other things."
1088 (service agetty-service-type config))
1089
66e4f01c
LC
1090(define-record-type* <mingetty-configuration>
1091 mingetty-configuration make-mingetty-configuration
1092 mingetty-configuration?
1093 (mingetty mingetty-configuration-mingetty ;<package>
1094 (default mingetty))
1095 (tty mingetty-configuration-tty) ;string
66e4f01c
LC
1096 (auto-login mingetty-auto-login ;string | #f
1097 (default #f))
1098 (login-program mingetty-login-program ;gexp
1099 (default #f))
1100 (login-pause? mingetty-login-pause? ;Boolean
317d3b47 1101 (default #f)))
0adfe95a 1102
d4053c71 1103(define mingetty-shepherd-service
0adfe95a 1104 (match-lambda
317d3b47
DC
1105 (($ <mingetty-configuration> mingetty tty auto-login login-program
1106 login-pause?)
0adfe95a 1107 (list
d4053c71 1108 (shepherd-service
0adfe95a
LC
1109 (documentation "Run mingetty on an tty.")
1110 (provision (list (symbol-append 'term- (string->symbol tty))))
1111
1112 ;; Since the login prompt shows the host name, wait for the 'host-name'
1113 ;; service to be done. Also wait for udev essentially so that the tty
1114 ;; text is not lost in the middle of kernel messages (XXX).
bb3062ad 1115 (requirement '(user-processes host-name udev virtual-terminal))
0adfe95a 1116
7e0a6fac
DM
1117 (start #~(make-forkexec-constructor
1118 (list #$(file-append mingetty "/sbin/mingetty")
a043b5b8
LC
1119 "--noclear"
1120
1121 ;; Avoiding 'vhangup' allows us to avoid 'setfont'
1122 ;; errors down the path where various ioctls get
1123 ;; EIO--see 'hung_up_tty_ioctl' in driver/tty/tty_io.c
1124 ;; in Linux.
1125 "--nohangup" #$tty
1126
7e0a6fac
DM
1127 #$@(if auto-login
1128 #~("--autologin" #$auto-login)
1129 #~())
1130 #$@(if login-program
1131 #~("--loginprog" #$login-program)
1132 #~())
1133 #$@(if login-pause?
1134 #~("--loginpause")
1135 #~()))))
0adfe95a
LC
1136 (stop #~(make-kill-destructor)))))))
1137
1138(define mingetty-service-type
1139 (service-type (name 'mingetty)
d4053c71 1140 (extensions (list (service-extension shepherd-root-service-type
6b9e1fef
LC
1141 mingetty-shepherd-service)))
1142 (description
1143 "Provide console login using the @command{mingetty}
1144program.")))
0adfe95a
LC
1145
1146(define* (mingetty-service config)
1147 "Return a service to run mingetty according to @var{config}, which specifies
1148the tty to run, among other things."
1149 (service mingetty-service-type config))
db4fdc04 1150
6454b333
LC
1151(define-record-type* <nscd-configuration> nscd-configuration
1152 make-nscd-configuration
1153 nscd-configuration?
1154 (log-file nscd-configuration-log-file ;string
1155 (default "/var/log/nscd.log"))
1156 (debug-level nscd-debug-level ;integer
1157 (default 0))
1158 ;; TODO: See nscd.conf in glibc for other options to add.
1159 (caches nscd-configuration-caches ;list of <nscd-cache>
b893f1ae
LC
1160 (default %nscd-default-caches))
1161 (name-services nscd-configuration-name-services ;list of <packages>
1162 (default '()))
1163 (glibc nscd-configuration-glibc ;<package>
1164 (default (canonical-package glibc))))
6454b333
LC
1165
1166(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
1167 nscd-cache?
1168 (database nscd-cache-database) ;symbol
1169 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
1170 (negative-time-to-live nscd-cache-negative-time-to-live
1171 (default 20)) ;integer
1172 (suggested-size nscd-cache-suggested-size ;integer ("default module
1173 ;of hash table")
1174 (default 211))
1175 (check-files? nscd-cache-check-files? ;Boolean
1176 (default #t))
1177 (persistent? nscd-cache-persistent? ;Boolean
1178 (default #t))
1179 (shared? nscd-cache-shared? ;Boolean
1180 (default #t))
1181 (max-database-size nscd-cache-max-database-size ;integer
1182 (default (* 32 (expt 2 20))))
1183 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
1184 (default #t)))
1185
1186(define %nscd-default-caches
1187 ;; Caches that we want to enable by default. Note that when providing an
1188 ;; empty nscd.conf, all caches are disabled.
1189 (list (nscd-cache (database 'hosts)
1190
1191 ;; Aggressively cache the host name cache to improve
1192 ;; privacy and resilience.
1193 (positive-time-to-live (* 3600 12))
1194 (negative-time-to-live 20)
1195 (persistent? #t))
1196
1197 (nscd-cache (database 'services)
1198
1199 ;; Services are unlikely to change, so we can be even more
1200 ;; aggressive.
1201 (positive-time-to-live (* 3600 24))
1202 (negative-time-to-live 3600)
1203 (check-files? #t) ;check /etc/services changes
1204 (persistent? #t))))
1205
1206(define %nscd-default-configuration
1207 ;; Default nscd configuration.
1208 (nscd-configuration))
1209
1210(define (nscd.conf-file config)
1211 "Return the @file{nscd.conf} configuration file for @var{config}, an
1212@code{<nscd-configuration>} object."
1213 (define cache->config
1214 (match-lambda
be1c2c54
LC
1215 (($ <nscd-cache> (= symbol->string database)
1216 positive-ttl negative-ttl size check-files?
1217 persistent? shared? max-size propagate?)
1218 (string-append "\nenable-cache\t" database "\tyes\n"
1219
1220 "positive-time-to-live\t" database "\t"
1221 (number->string positive-ttl) "\n"
1222 "negative-time-to-live\t" database "\t"
1223 (number->string negative-ttl) "\n"
1224 "suggested-size\t" database "\t"
1225 (number->string size) "\n"
1226 "check-files\t" database "\t"
1227 (if check-files? "yes\n" "no\n")
1228 "persistent\t" database "\t"
1229 (if persistent? "yes\n" "no\n")
1230 "shared\t" database "\t"
1231 (if shared? "yes\n" "no\n")
1232 "max-db-size\t" database "\t"
1233 (number->string max-size) "\n"
1234 "auto-propagate\t" database "\t"
1235 (if propagate? "yes\n" "no\n")))))
6454b333
LC
1236
1237 (match config
1238 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
1239 (plain-file "nscd.conf"
1240 (string-append "\
6454b333 1241# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
1242 (if log-file
1243 (string-append "logfile\t" log-file)
1244 "")
1245 "\n"
1246 (if debug-level
1247 (string-append "debug-level\t"
1248 (number->string debug-level))
1249 "")
1250 "\n"
1251 (string-concatenate
1252 (map cache->config caches)))))))
6454b333 1253
d4053c71
AK
1254(define (nscd-shepherd-service config)
1255 "Return a shepherd service for CONFIG, an <nscd-configuration> object."
0adfe95a
LC
1256 (let ((nscd.conf (nscd.conf-file config))
1257 (name-services (nscd-configuration-name-services config)))
d4053c71 1258 (list (shepherd-service
0adfe95a
LC
1259 (documentation "Run libc's name service cache daemon (nscd).")
1260 (provision '(nscd))
1261 (requirement '(user-processes))
1262 (start #~(make-forkexec-constructor
9fc037fe 1263 (list #$(file-append (nscd-configuration-glibc config)
0adfe95a
LC
1264 "/sbin/nscd")
1265 "-f" #$nscd.conf "--foreground")
1266
04101d99
LC
1267 ;; Wait for the PID file. However, the PID file is
1268 ;; written before nscd is actually listening on its
1269 ;; socket (XXX).
1270 #:pid-file "/var/run/nscd/nscd.pid"
1271
0adfe95a
LC
1272 #:environment-variables
1273 (list (string-append "LD_LIBRARY_PATH="
1274 (string-join
1275 (map (lambda (dir)
1276 (string-append dir "/lib"))
1277 (list #$@name-services))
1278 ":")))))
cc7234ae 1279 (stop #~(make-kill-destructor))))))
0adfe95a
LC
1280
1281(define nscd-activation
1282 ;; Actions to take before starting nscd.
1283 #~(begin
1284 (use-modules (guix build utils))
1285 (mkdir-p "/var/run/nscd")
49f9d7f6
LC
1286 (mkdir-p "/var/db/nscd") ;for the persistent cache
1287
1288 ;; In libc 2.25 nscd uses inotify to watch /etc/resolv.conf, but only if
c298fb13
LC
1289 ;; that file exists when it is started. Thus create it here. Note: on
1290 ;; some systems, such as when NetworkManager is used, /etc/resolv.conf
1291 ;; is a symlink, hence 'lstat'.
1292 (unless (false-if-exception (lstat "/etc/resolv.conf"))
49f9d7f6
LC
1293 (call-with-output-file "/etc/resolv.conf"
1294 (lambda (port)
1295 (display "# This is a placeholder.\n" port))))))
0adfe95a
LC
1296
1297(define nscd-service-type
1298 (service-type (name 'nscd)
1299 (extensions
1300 (list (service-extension activation-service-type
1301 (const nscd-activation))
d4053c71
AK
1302 (service-extension shepherd-root-service-type
1303 nscd-shepherd-service)))
0adfe95a
LC
1304
1305 ;; This can be extended by providing additional name services
1306 ;; such as nss-mdns.
1307 (compose concatenate)
1308 (extend (lambda (config name-services)
1309 (nscd-configuration
1310 (inherit config)
1311 (name-services (append
1312 (nscd-configuration-name-services config)
6b9e1fef
LC
1313 name-services)))))
1314 (description
1315 "Runs libc's @dfn{name service cache daemon} (nscd) with the
1316given configuration---an @code{<nscd-configuration>} object. @xref{Name
1317Service Switch}, for an example.")))
0adfe95a 1318
b893f1ae 1319(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 1320 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
1321given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
1322Service Switch}, for an example."
0adfe95a
LC
1323 (service nscd-service-type config))
1324
ec2e2f6c
DC
1325
1326(define-record-type* <syslog-configuration>
1327 syslog-configuration make-syslog-configuration
1328 syslog-configuration?
1329 (syslogd syslog-configuration-syslogd
9e41130b 1330 (default (file-append inetutils "/libexec/syslogd")))
ec2e2f6c
DC
1331 (config-file syslog-configuration-config-file
1332 (default %default-syslog.conf)))
1333
0adfe95a 1334(define syslog-service-type
d4053c71 1335 (shepherd-service-type
00184239 1336 'syslog
ec2e2f6c 1337 (lambda (config)
d4053c71 1338 (shepherd-service
0adfe95a
LC
1339 (documentation "Run the syslog daemon (syslogd).")
1340 (provision '(syslogd))
1341 (requirement '(user-processes))
1342 (start #~(make-forkexec-constructor
ec2e2f6c 1343 (list #$(syslog-configuration-syslogd config)
afa54a38
LC
1344 "--rcfile" #$(syslog-configuration-config-file config))
1345 #:pid-file "/var/run/syslog.pid"))
0adfe95a 1346 (stop #~(make-kill-destructor))))))
be1c2c54
LC
1347
1348;; Snippet adapted from the GNU inetutils manual.
1349(define %default-syslog.conf
1350 (plain-file "syslog.conf" "
1f3fc60d 1351 # Log all error messages, authentication messages of
db4fdc04
LC
1352 # level notice or higher and anything of level err or
1353 # higher to the console.
1354 # Don't log private authentication messages!
6a191274 1355 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
1356
1357 # Log anything (except mail) of level info or higher.
1358 # Don't log private authentication messages!
1359 *.info;mail.none;authpriv.none /var/log/messages
1360
b6d8066d
AW
1361 # Like /var/log/messages, but also including \"debug\"-level logs.
1362 *.debug;mail.none;authpriv.none /var/log/debug
1363
db4fdc04
LC
1364 # Same, in a different place.
1365 *.info;mail.none;authpriv.none /dev/tty12
1366
1367 # The authpriv file has restricted access.
1368 authpriv.* /var/log/secure
1369
1370 # Log all the mail messages in one place.
1371 mail.* /var/log/maillog
be1c2c54 1372"))
0adfe95a 1373
ec2e2f6c
DC
1374(define* (syslog-service #:optional (config (syslog-configuration)))
1375 "Return a service that runs @command{syslogd} and takes
1376@var{<syslog-configuration>} as a parameter.
44abcb28
LC
1377
1378@xref{syslogd invocation,,, inetutils, GNU Inetutils}, for more
1379information on the configuration file syntax."
ec2e2f6c
DC
1380 (service syslog-service-type config))
1381
db4fdc04 1382
909147e4
RW
1383(define pam-limits-service-type
1384 (let ((security-limits
1385 ;; Create /etc/security containing the provided "limits.conf" file.
1386 (lambda (limits-file)
1387 `(("security"
1388 ,(computed-file
1389 "security"
1390 #~(begin
1391 (mkdir #$output)
1392 (stat #$limits-file)
1393 (symlink #$limits-file
1394 (string-append #$output "/limits.conf"))))))))
1395 (pam-extension
1396 (lambda (pam)
1397 (let ((pam-limits (pam-entry
1398 (control "required")
1399 (module "pam_limits.so")
1400 (arguments '("conf=/etc/security/limits.conf")))))
1401 (if (member (pam-service-name pam)
1402 '("login" "su" "slim"))
1403 (pam-service
1404 (inherit pam)
1405 (session (cons pam-limits
1406 (pam-service-session pam))))
1407 pam)))))
1408 (service-type
1409 (name 'limits)
1410 (extensions
1411 (list (service-extension etc-service-type security-limits)
1412 (service-extension pam-root-service-type
6b9e1fef
LC
1413 (lambda _ (list pam-extension)))))
1414 (description
1415 "Install the specified resource usage limits by populating
1416@file{/etc/security/limits.conf} and using the @code{pam_limits}
1417authentication module."))))
909147e4
RW
1418
1419(define* (pam-limits-service #:optional (limits '()))
1420 "Return a service that makes selected programs respect the list of
1421pam-limits-entry specified in LIMITS via pam_limits.so."
1422 (service pam-limits-service-type
1423 (plain-file "limits.conf"
1424 (string-join (map pam-limits-entry->string limits)
1425 "\n"))))
1426
1c52181f
LC
1427\f
1428;;;
1429;;; Guix services.
1430;;;
1431
db4fdc04 1432(define* (guix-build-accounts count #:key
ab6a279a 1433 (group "guixbuild")
db4fdc04 1434 (first-uid 30001)
db4fdc04
LC
1435 (shadow shadow))
1436 "Return a list of COUNT user accounts for Guix build users, with UIDs
1437starting at FIRST-UID, and under GID."
5250a4f2
LC
1438 (unfold (cut > <> count)
1439 (lambda (n)
1440 (user-account
1441 (name (format #f "guixbuilder~2,'0d" n))
1442 (system? #t)
1443 (uid (+ first-uid n -1))
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")
9e41130b 1453 (shell (file-append shadow "/sbin/nologin"))))
5250a4f2
LC
1454 1+
1455 1))
db4fdc04 1456
5b58c28b
LC
1457(define (hydra-key-authorization key guix)
1458 "Return a gexp with code to register KEY, a file containing a 'guix archive'
1459public key, with GUIX."
2c5c696c
LC
1460 #~(unless (file-exists? "/etc/guix/acl")
1461 (let ((pid (primitive-fork)))
1462 (case pid
1463 ((0)
5b58c28b 1464 (let* ((key #$key)
2c5c696c
LC
1465 (port (open-file key "r0b")))
1466 (format #t "registering public key '~a'...~%" key)
1467 (close-port (current-input-port))
2c5c696c 1468 (dup port 0)
9fc037fe 1469 (execl #$(file-append guix "/bin/guix")
2c5c696c
LC
1470 "guix" "archive" "--authorize")
1471 (exit 1)))
1472 (else
1473 (let ((status (cdr (waitpid pid))))
1474 (unless (zero? status)
1475 (format (current-error-port) "warning: \
1476failed to register hydra.gnu.org public key: ~a~%" status))))))))
1477
5b58c28b
LC
1478(define %default-authorized-guix-keys
1479 ;; List of authorized substitute keys.
c22c9fa5 1480 (list (file-append guix "/share/guix/hydra.gnu.org.pub")
be5622e7 1481 (file-append guix "/share/guix/berlin.guixsd.org.pub")))
5b58c28b 1482
0adfe95a
LC
1483(define-record-type* <guix-configuration>
1484 guix-configuration make-guix-configuration
1485 guix-configuration?
1486 (guix guix-configuration-guix ;<package>
1487 (default guix))
1488 (build-group guix-configuration-build-group ;string
1489 (default "guixbuild"))
1490 (build-accounts guix-configuration-build-accounts ;integer
1491 (default 10))
1492 (authorize-key? guix-configuration-authorize-key? ;Boolean
1493 (default #t))
5b58c28b
LC
1494 (authorized-keys guix-configuration-authorized-keys ;list of gexps
1495 (default %default-authorized-guix-keys))
0adfe95a
LC
1496 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
1497 (default #t))
b0b9f6e0
LC
1498 (substitute-urls guix-configuration-substitute-urls ;list of strings
1499 (default %default-substitute-urls))
88554b5d
LC
1500 (chroot-directories guix-configuration-chroot-directories ;list of file-like/strings
1501 (default '()))
3bee4b61
LC
1502 (max-silent-time guix-configuration-max-silent-time ;integer
1503 (default 0))
1504 (timeout guix-configuration-timeout ;integer
1505 (default 0))
f4596f76
LC
1506 (log-compression guix-configuration-log-compression
1507 (default 'bzip2))
0adfe95a
LC
1508 (extra-options guix-configuration-extra-options ;list of strings
1509 (default '()))
dc0ef095
LC
1510 (log-file guix-configuration-log-file ;string
1511 (default "/var/log/guix-daemon.log"))
93d32da9 1512 (http-proxy guix-http-proxy ;string | #f
b191f0a6
LF
1513 (default #f))
1514 (tmpdir guix-tmpdir ;string | #f
93d32da9 1515 (default #f)))
0adfe95a
LC
1516
1517(define %default-guix-configuration
1518 (guix-configuration))
1519
d4053c71
AK
1520(define (guix-shepherd-service config)
1521 "Return a <shepherd-service> for the Guix daemon service with CONFIG."
f4596f76
LC
1522 (match-record config <guix-configuration>
1523 (guix build-group build-accounts authorize-key? authorized-keys
1524 use-substitutes? substitute-urls max-silent-time timeout
88554b5d
LC
1525 log-compression extra-options log-file http-proxy tmpdir
1526 chroot-directories)
f4596f76
LC
1527 (list (shepherd-service
1528 (documentation "Run the Guix daemon.")
1529 (provision '(guix-daemon))
1530 (requirement '(user-processes))
88554b5d 1531 (modules '((srfi srfi-1)))
f4596f76
LC
1532 (start
1533 #~(make-forkexec-constructor
88554b5d
LC
1534 (cons* #$(file-append guix "/bin/guix-daemon")
1535 "--build-users-group" #$build-group
1536 "--max-silent-time" #$(number->string max-silent-time)
1537 "--timeout" #$(number->string timeout)
1538 "--log-compression" #$(symbol->string log-compression)
1539 #$@(if use-substitutes?
1540 '()
1541 '("--no-substitutes"))
1542 "--substitute-urls" #$(string-join substitute-urls)
1543 #$@extra-options
1544
1545 ;; Add CHROOT-DIRECTORIES and all their dependencies (if
1546 ;; these are store items) to the chroot.
1547 (append-map (lambda (file)
1548 (append-map (lambda (directory)
1549 (list "--chroot-directory"
1550 directory))
1551 (call-with-input-file file
1552 read)))
1553 '#$(map references-file chroot-directories)))
f4596f76
LC
1554
1555 #:environment-variables
1556 (list #$@(if http-proxy
1557 (list (string-append "http_proxy=" http-proxy))
1558 '())
1559 #$@(if tmpdir
1560 (list (string-append "TMPDIR=" tmpdir))
1561 '()))
1562
1563 #:log-file #$log-file))
1564 (stop #~(make-kill-destructor))))))
0adfe95a
LC
1565
1566(define (guix-accounts config)
1567 "Return the user accounts and user groups for CONFIG."
1568 (match config
1569 (($ <guix-configuration> _ build-group build-accounts)
1570 (cons (user-group
1571 (name build-group)
1572 (system? #t)
1573
1574 ;; Use a fixed GID so that we can create the store with the right
1575 ;; owner.
1576 (id 30000))
1577 (guix-build-accounts build-accounts
1578 #:group build-group)))))
1579
1580(define (guix-activation config)
1581 "Return the activation gexp for CONFIG."
1582 (match config
5b58c28b 1583 (($ <guix-configuration> guix build-group build-accounts authorize-key? keys)
0adfe95a 1584 ;; Assume that the store has BUILD-GROUP as its group. We could
0af94ad5 1585 ;; otherwise call 'chown' here, but the problem is that on a COW overlayfs,
0adfe95a
LC
1586 ;; chown leads to an entire copy of the tree, which is a bad idea.
1587
1588 ;; Optionally authorize hydra.gnu.org's key.
5f4a446d 1589 (if authorize-key?
5b58c28b
LC
1590 #~(begin
1591 #$@(map (cut hydra-key-authorization <> guix) keys))
5f4a446d 1592 #~#f))))
0adfe95a 1593
88554b5d
LC
1594(define* (references-file item #:optional (name "references"))
1595 "Return a file that contains the list of references of ITEM."
1596 (if (struct? item) ;lowerable object
1597 (computed-file name
1598 (with-imported-modules (source-module-closure
1599 '((guix build store-copy)))
1600 #~(begin
1601 (use-modules (guix build store-copy))
1602
1603 (call-with-output-file #$output
1604 (lambda (port)
6892f0a2
LC
1605 (write (map store-info-item
1606 (call-with-input-file "graph"
1607 read-reference-graph))
88554b5d
LC
1608 port)))))
1609 #:options `(#:local-build? #f
1610 #:references-graphs (("graph" ,item))))
1611 (plain-file name "()")))
1612
0adfe95a
LC
1613(define guix-service-type
1614 (service-type
1615 (name 'guix)
1616 (extensions
d4053c71 1617 (list (service-extension shepherd-root-service-type guix-shepherd-service)
0adfe95a 1618 (service-extension account-service-type guix-accounts)
9a8b9eb8
LC
1619 (service-extension activation-service-type guix-activation)
1620 (service-extension profile-service-type
3d3c5650 1621 (compose list guix-configuration-guix))))
88554b5d
LC
1622
1623 ;; Extensions can specify extra directories to add to the build chroot.
1624 (compose concatenate)
1625 (extend (lambda (config directories)
1626 (guix-configuration
1627 (inherit config)
1628 (chroot-directories
1629 (append (guix-configuration-chroot-directories config)
1630 directories)))))
1631
6b9e1fef
LC
1632 (default-value (guix-configuration))
1633 (description
1634 "Run the build daemon of GNU@tie{}Guix, aka. @command{guix-daemon}.")))
0adfe95a
LC
1635
1636(define* (guix-service #:optional (config %default-guix-configuration))
1637 "Return a service that runs the Guix build daemon according to
1638@var{config}."
1639 (service guix-service-type config))
1640
1c52181f
LC
1641
1642(define-record-type* <guix-publish-configuration>
1643 guix-publish-configuration make-guix-publish-configuration
1644 guix-publish-configuration?
1645 (guix guix-publish-configuration-guix ;package
1646 (default guix))
1647 (port guix-publish-configuration-port ;number
1648 (default 80))
1649 (host guix-publish-configuration-host ;string
697ddb88 1650 (default "localhost"))
f2767d3e 1651 (compression-level guix-publish-configuration-compression-level ;integer
697ddb88 1652 (default 3))
f2767d3e 1653 (nar-path guix-publish-configuration-nar-path ;string
a35136cb
LC
1654 (default "nar"))
1655 (cache guix-publish-configuration-cache ;#f | string
1656 (default #f))
1657 (workers guix-publish-configuration-workers ;#f | integer
1658 (default #f))
1659 (ttl guix-publish-configuration-ttl ;#f | integer
1660 (default #f)))
1c52181f 1661
d4053c71 1662(define guix-publish-shepherd-service
1c52181f 1663 (match-lambda
a35136cb
LC
1664 (($ <guix-publish-configuration> guix port host compression
1665 nar-path cache workers ttl)
d4053c71 1666 (list (shepherd-service
1c52181f
LC
1667 (provision '(guix-publish))
1668 (requirement '(guix-daemon))
1669 (start #~(make-forkexec-constructor
9fc037fe 1670 (list #$(file-append guix "/bin/guix")
1c52181f
LC
1671 "publish" "-u" "guix-publish"
1672 "-p" #$(number->string port)
697ddb88
LC
1673 "-C" #$(number->string compression)
1674 (string-append "--nar-path=" #$nar-path)
a35136cb
LC
1675 (string-append "--listen=" #$host)
1676 #$@(if workers
1677 #~((string-append "--workers="
1678 #$(number->string
1679 workers)))
1680 #~())
1681 #$@(if ttl
1682 #~((string-append "--ttl="
1683 #$(number->string ttl)
1684 "s"))
1685 #~())
1686 #$@(if cache
1687 #~((string-append "--cache=" #$cache))
412701b0
LC
1688 #~()))
1689
1690 ;; Make sure we run in a UTF-8 locale so we can produce
1691 ;; nars for packages that contain UTF-8 file names such
1692 ;; as 'nss-certs'. See <https://bugs.gnu.org/26948>.
1693 #:environment-variables
1694 (list (string-append "GUIX_LOCPATH="
1695 #$glibc-utf8-locales "/lib/locale")
1696 "LC_ALL=en_US.utf8")))
1c52181f
LC
1697 (stop #~(make-kill-destructor)))))))
1698
1699(define %guix-publish-accounts
1700 (list (user-group (name "guix-publish") (system? #t))
1701 (user-account
1702 (name "guix-publish")
1703 (group "guix-publish")
1704 (system? #t)
1705 (comment "guix publish user")
1706 (home-directory "/var/empty")
9e41130b 1707 (shell (file-append shadow "/sbin/nologin")))))
1c52181f 1708
a35136cb
LC
1709(define (guix-publish-activation config)
1710 (let ((cache (guix-publish-configuration-cache config)))
1711 (if cache
1712 (with-imported-modules '((guix build utils))
1713 #~(begin
1714 (use-modules (guix build utils))
1715
1716 (mkdir-p #$cache)
1717 (let* ((pw (getpw "guix-publish"))
1718 (uid (passwd:uid pw))
1719 (gid (passwd:gid pw)))
1720 (chown #$cache uid gid))))
1721 #t)))
1722
1c52181f
LC
1723(define guix-publish-service-type
1724 (service-type (name 'guix-publish)
1725 (extensions
d4053c71
AK
1726 (list (service-extension shepherd-root-service-type
1727 guix-publish-shepherd-service)
1c52181f 1728 (service-extension account-service-type
a35136cb
LC
1729 (const %guix-publish-accounts))
1730 (service-extension activation-service-type
1731 guix-publish-activation)))
6b9e1fef
LC
1732 (default-value (guix-publish-configuration))
1733 (description
1734 "Add a Shepherd service running @command{guix publish}, a
1735command that allows you to share pre-built binaries with others over HTTP.")))
1c52181f
LC
1736
1737(define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
1738 "Return a service that runs @command{guix publish} listening on @var{host}
1739and @var{port} (@pxref{Invoking guix publish}).
1740
1741This assumes that @file{/etc/guix} already contains a signing key pair as
1742created by @command{guix archive --generate-key} (@pxref{Invoking guix
1743archive}). If that is not the case, the service will fail to start."
f1e900a3 1744 ;; Deprecated.
1c52181f
LC
1745 (service guix-publish-service-type
1746 (guix-publish-configuration (guix guix) (port port) (host host))))
1747
0adfe95a
LC
1748\f
1749;;;
1750;;; Udev.
1751;;;
1752
1753(define-record-type* <udev-configuration>
1754 udev-configuration make-udev-configuration
1755 udev-configuration?
1756 (udev udev-configuration-udev ;<package>
1757 (default udev))
1758 (rules udev-configuration-rules ;list of <package>
1759 (default '())))
db4fdc04 1760
ecd06ca9
LC
1761(define (udev-rules-union packages)
1762 "Return the union of the @code{lib/udev/rules.d} directories found in each
1763item of @var{packages}."
1764 (define build
4ee96a79
LC
1765 (with-imported-modules '((guix build union)
1766 (guix build utils))
1767 #~(begin
1768 (use-modules (guix build union)
1769 (guix build utils)
1770 (srfi srfi-1)
1771 (srfi srfi-26))
ecd06ca9 1772
4ee96a79
LC
1773 (define %standard-locations
1774 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
ecd06ca9 1775
4ee96a79
LC
1776 (define (rules-sub-directory directory)
1777 ;; Return the sub-directory of DIRECTORY containing udev rules, or
1778 ;; #f if none was found.
1779 (find directory-exists?
1780 (map (cut string-append directory <>) %standard-locations)))
ecd06ca9 1781
4ee96a79
LC
1782 (mkdir-p (string-append #$output "/lib/udev"))
1783 (union-build (string-append #$output "/lib/udev/rules.d")
1784 (filter-map rules-sub-directory '#$packages)))))
ecd06ca9 1785
4ee96a79 1786 (computed-file "udev-rules" build))
ecd06ca9 1787
80e6f37e
RW
1788(define (udev-rule file-name contents)
1789 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
1790 (computed-file file-name
4ee96a79
LC
1791 (with-imported-modules '((guix build utils))
1792 #~(begin
1793 (use-modules (guix build utils))
1794
1795 (define rules.d
1796 (string-append #$output "/lib/udev/rules.d"))
1797
1798 (mkdir-p rules.d)
1799 (call-with-output-file
1800 (string-append rules.d "/" #$file-name)
1801 (lambda (port)
1802 (display #$contents port)))))))
7f28bf9a 1803
6e644cfd
MC
1804(define (file->udev-rule file-name file)
1805 "Return a directory with a udev rule file FILE-NAME which is a copy of FILE."
1806 (computed-file file-name
1807 (with-imported-modules '((guix build utils))
1808 #~(begin
1809 (use-modules (guix build utils))
1810
1811 (define rules.d
1812 (string-append #$output "/lib/udev/rules.d"))
1813
1814 (define file-copy-dest
1815 (string-append rules.d "/" #$file-name))
1816
1817 (mkdir-p rules.d)
1818 (copy-file #$file file-copy-dest)))))
1819
80e6f37e
RW
1820(define kvm-udev-rule
1821 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
1822 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
1823 ;; but now we have to add it by ourselves.
1824
1825 ;; Build users are part of the "kvm" group, so we can fearlessly make
1826 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
1827 (udev-rule "90-kvm.rules"
1828 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
1829
d4053c71
AK
1830(define udev-shepherd-service
1831 ;; Return a <shepherd-service> for UDEV with RULES.
0adfe95a
LC
1832 (match-lambda
1833 (($ <udev-configuration> udev rules)
80e6f37e 1834 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
1835 (udev.conf (computed-file "udev.conf"
1836 #~(call-with-output-file #$output
1837 (lambda (port)
1838 (format port
1839 "udev_rules=\"~a/lib/udev/rules.d\"\n"
1840 #$rules))))))
1841 (list
d4053c71 1842 (shepherd-service
0adfe95a
LC
1843 (provision '(udev))
1844
1845 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
1846 ;; be added: see
1847 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
1848 (requirement '(root-file-system))
1849
1850 (documentation "Populate the /dev directory, dynamically.")
1851 (start #~(lambda ()
0adfe95a 1852 (define udevd
7fd30825
LC
1853 ;; 'udevd' from eudev.
1854 #$(file-append udev "/sbin/udevd"))
0adfe95a
LC
1855
1856 (define (wait-for-udevd)
1857 ;; Wait until someone's listening on udevd's control
1858 ;; socket.
1859 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1860 (let try ()
1861 (catch 'system-error
1862 (lambda ()
1863 (connect sock PF_UNIX "/run/udev/control")
1864 (close-port sock))
1865 (lambda args
1866 (format #t "waiting for udevd...~%")
1867 (usleep 500000)
1868 (try))))))
1869
1870 ;; Allow udev to find the modules.
1871 (setenv "LINUX_MODULE_DIRECTORY"
1872 "/run/booted-system/kernel/lib/modules")
1873
1874 ;; The first one is for udev, the second one for eudev.
1875 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1876 (setenv "EUDEV_RULES_DIRECTORY"
9fc037fe 1877 #$(file-append rules "/lib/udev/rules.d"))
0adfe95a 1878
86e6b4c9
DM
1879 (let* ((kernel-release
1880 (utsname:release (uname)))
1881 (linux-module-directory
1882 (getenv "LINUX_MODULE_DIRECTORY"))
1883 (directory
1884 (string-append linux-module-directory "/"
1885 kernel-release))
1886 (old-umask (umask #o022)))
23784f0c
LC
1887 ;; If we're in a container, DIRECTORY might not exist,
1888 ;; for instance because the host runs a different
1889 ;; kernel. In that case, skip it; we'll just miss a few
1890 ;; nodes like /dev/fuse.
1891 (when (file-exists? directory)
1892 (make-static-device-nodes directory))
86e6b4c9
DM
1893 (umask old-umask))
1894
7fd30825
LC
1895 (let ((pid (fork+exec-command (list udevd))))
1896 ;; Wait until udevd is up and running. This appears to
1897 ;; be needed so that the events triggered below are
1898 ;; actually handled.
1899 (wait-for-udevd)
1900
1901 ;; Trigger device node creation.
1902 (system* #$(file-append udev "/bin/udevadm")
1903 "trigger" "--action=add")
1904
1905 ;; Wait for things to settle down.
1906 (system* #$(file-append udev "/bin/udevadm")
1907 "settle")
1908 pid)))
0adfe95a
LC
1909 (stop #~(make-kill-destructor))
1910
1911 ;; When halting the system, 'udev' is actually killed by
1912 ;; 'user-processes', i.e., before its own 'stop' method was called.
1913 ;; Thus, make sure it is not respawned.
86e6b4c9
DM
1914 (respawn? #f)
1915 ;; We need additional modules.
1916 (modules `((gnu build linux-boot)
1917 ,@%default-modules))))))))
0adfe95a
LC
1918
1919(define udev-service-type
1920 (service-type (name 'udev)
1921 (extensions
d4053c71
AK
1922 (list (service-extension shepherd-root-service-type
1923 udev-shepherd-service)))
0adfe95a
LC
1924
1925 (compose concatenate) ;concatenate the list of rules
1926 (extend (lambda (config rules)
1927 (match config
1928 (($ <udev-configuration> udev initial-rules)
1929 (udev-configuration
1930 (udev udev)
6b9e1fef
LC
1931 (rules (append initial-rules rules)))))))
1932 (description
1933 "Run @command{udev}, which populates the @file{/dev}
1934directory dynamically. Get extra rules from the packages listed in the
1935@code{rules} field of its value, @code{udev-configuration} object.")))
0adfe95a 1936
255f7308 1937(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
1938 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
1939extra rules from the packages listed in @var{rules}."
0adfe95a
LC
1940 (service udev-service-type
1941 (udev-configuration (udev udev) (rules rules))))
1942
0adfe95a 1943(define swap-service-type
d4053c71 1944 (shepherd-service-type
00184239 1945 'swap
0adfe95a
LC
1946 (lambda (device)
1947 (define requirement
1948 (if (string-prefix? "/dev/mapper/" device)
1949 (list (symbol-append 'device-mapping-
1950 (string->symbol (basename device))))
1951 '()))
1952
d4053c71 1953 (shepherd-service
0adfe95a
LC
1954 (provision (list (symbol-append 'swap- (string->symbol device))))
1955 (requirement `(udev ,@requirement))
1956 (documentation "Enable the given swap device.")
1957 (start #~(lambda ()
1958 (restart-on-EINTR (swapon #$device))
1959 #t))
1960 (stop #~(lambda _
1961 (restart-on-EINTR (swapoff #$device))
1962 #f))
1963 (respawn? #f)))))
5dae0186 1964
2a13d05e
LC
1965(define (swap-service device)
1966 "Return a service that uses @var{device} as a swap device."
0adfe95a 1967 (service swap-service-type device))
2a13d05e 1968
5986e941
LC
1969(define %default-gpm-options
1970 ;; Default options for GPM.
1971 '("-m" "/dev/input/mice" "-t" "ps2"))
1972
8664cc88
LC
1973(define-record-type* <gpm-configuration>
1974 gpm-configuration make-gpm-configuration gpm-configuration?
5986e941
LC
1975 (gpm gpm-configuration-gpm ;package
1976 (default gpm))
1977 (options gpm-configuration-options ;list of strings
1978 (default %default-gpm-options)))
8664cc88 1979
d4053c71 1980(define gpm-shepherd-service
8664cc88 1981 (match-lambda
a907d997 1982 (($ <gpm-configuration> gpm options)
d4053c71 1983 (list (shepherd-service
8664cc88
LC
1984 (requirement '(udev))
1985 (provision '(gpm))
1986 (start #~(lambda ()
1987 ;; 'gpm' runs in the background and sets a PID file.
1988 ;; Note that it requires running as "root".
1989 (false-if-exception (delete-file "/var/run/gpm.pid"))
9fc037fe 1990 (fork+exec-command (list #$(file-append gpm "/sbin/gpm")
8664cc88
LC
1991 #$@options))
1992
1993 ;; Wait for the PID file to appear; declare failure if
1994 ;; it doesn't show up.
1995 (let loop ((i 3))
1996 (or (file-exists? "/var/run/gpm.pid")
1997 (if (zero? i)
1998 #f
1999 (begin
2000 (sleep 1)
2001 (loop (1- i))))))))
2002
2003 (stop #~(lambda (_)
2004 ;; Return #f if successfully stopped.
9fc037fe 2005 (not (zero? (system* #$(file-append gpm "/sbin/gpm")
8664cc88
LC
2006 "-k"))))))))))
2007
2008(define gpm-service-type
2009 (service-type (name 'gpm)
2010 (extensions
d4053c71 2011 (list (service-extension shepherd-root-service-type
6b9e1fef 2012 gpm-shepherd-service)))
5986e941 2013 (default-value (gpm-configuration))
6b9e1fef
LC
2014 (description
2015 "Run GPM, the general-purpose mouse daemon, with the given
2016command-line options. GPM allows users to use the mouse in the console,
2017notably to select, copy, and paste text. The default options use the
2018@code{ps2} protocol, which works for both USB and PS/2 mice.")))
8664cc88 2019
5986e941
LC
2020(define* (gpm-service #:key (gpm gpm) ;deprecated
2021 (options %default-gpm-options))
8664cc88
LC
2022 "Run @var{gpm}, the general-purpose mouse daemon, with the given
2023command-line @var{options}. GPM allows users to use the mouse in the console,
2024notably to select, copy, and paste text. The default value of @var{options}
2025uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
2026
2027This service is not part of @var{%base-services}."
2028 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
2029 ;; "info mice" and "mouse_set X" to use the right mouse.
2030 (service gpm-service-type
2031 (gpm-configuration (gpm gpm) (options options))))
2032
46ec2707
DC
2033(define-record-type* <kmscon-configuration>
2034 kmscon-configuration make-kmscon-configuration
2035 kmscon-configuration?
2036 (kmscon kmscon-configuration-kmscon
2037 (default kmscon))
2038 (virtual-terminal kmscon-configuration-virtual-terminal)
2039 (login-program kmscon-configuration-login-program
9fc037fe 2040 (default (file-append shadow "/bin/login")))
46ec2707
DC
2041 (login-arguments kmscon-configuration-login-arguments
2042 (default '("-p")))
2043 (hardware-acceleration? kmscon-configuration-hardware-acceleration?
2044 (default #f))) ; #t causes failure
2045
2046(define kmscon-service-type
2047 (shepherd-service-type
2048 'kmscon
2049 (lambda (config)
2050 (let ((kmscon (kmscon-configuration-kmscon config))
2051 (virtual-terminal (kmscon-configuration-virtual-terminal config))
2052 (login-program (kmscon-configuration-login-program config))
2053 (login-arguments (kmscon-configuration-login-arguments config))
2054 (hardware-acceleration? (kmscon-configuration-hardware-acceleration? config)))
2055
2056 (define kmscon-command
2057 #~(list
9fc037fe 2058 #$(file-append kmscon "/bin/kmscon") "--login"
46ec2707
DC
2059 "--vt" #$virtual-terminal
2060 #$@(if hardware-acceleration? '("--hwaccel") '())
2061 "--" #$login-program #$@login-arguments))
2062
2063 (shepherd-service
2064 (documentation "kmscon virtual terminal")
bb3062ad 2065 (requirement '(user-processes udev dbus-system virtual-terminal))
46ec2707
DC
2066 (provision (list (symbol-append 'term- (string->symbol virtual-terminal))))
2067 (start #~(make-forkexec-constructor #$kmscon-command))
2068 (stop #~(make-kill-destructor)))))))
2069
c9436025
DM
2070(define-record-type* <static-networking>
2071 static-networking make-static-networking
2072 static-networking?
2073 (interface static-networking-interface)
2074 (ip static-networking-ip)
2075 (netmask static-networking-netmask
2076 (default #f))
2077 (gateway static-networking-gateway ;FIXME: doesn't belong here
2078 (default #f))
2079 (provision static-networking-provision
2080 (default #f))
2081 (requirement static-networking-requirement
2082 (default '()))
2083 (name-servers static-networking-name-servers ;FIXME: doesn't belong here
2084 (default '())))
2085
2086(define static-networking-shepherd-service
2087 (match-lambda
2088 (($ <static-networking> interface ip netmask gateway provision
2089 requirement name-servers)
2090 (let ((loopback? (and provision (memq 'loopback provision))))
2091 (shepherd-service
2092
2093 (documentation
2094 "Bring up the networking interface using a static IP address.")
2095 (requirement requirement)
2096 (provision (or provision
2097 (list (symbol-append 'networking-
2098 (string->symbol interface)))))
2099
2100 (start #~(lambda _
2101 ;; Return #t if successfully started.
2102 (let* ((addr (inet-pton AF_INET #$ip))
2103 (sockaddr (make-socket-address AF_INET addr 0))
2104 (mask (and #$netmask
2105 (inet-pton AF_INET #$netmask)))
2106 (maskaddr (and mask
2107 (make-socket-address AF_INET
2108 mask 0)))
2109 (gateway (and #$gateway
2110 (inet-pton AF_INET #$gateway)))
2111 (gatewayaddr (and gateway
2112 (make-socket-address AF_INET
2113 gateway 0))))
2114 (configure-network-interface #$interface sockaddr
2115 (logior IFF_UP
2116 #$(if loopback?
2117 #~IFF_LOOPBACK
2118 0))
2119 #:netmask maskaddr)
2120 (when gateway
2121 (let ((sock (socket AF_INET SOCK_DGRAM 0)))
2122 (add-network-route/gateway sock gatewayaddr)
2123 (close-port sock))))))
2124 (stop #~(lambda _
2125 ;; Return #f is successfully stopped.
2126 (let ((sock (socket AF_INET SOCK_STREAM 0)))
2127 (when #$gateway
2128 (delete-network-route sock
2129 (make-socket-address
2130 AF_INET INADDR_ANY 0)))
2131 (set-network-interface-flags sock #$interface 0)
2132 (close-port sock)
241358dc 2133 #f)))
c9436025
DM
2134 (respawn? #f))))))
2135
2136(define (static-networking-etc-files interfaces)
2137 "Return a /etc/resolv.conf entry for INTERFACES or the empty list."
2138 (match (delete-duplicates
2139 (append-map static-networking-name-servers
2140 interfaces))
2141 (()
2142 '())
2143 ((name-servers ...)
2144 (let ((content (string-join
2145 (map (cut string-append "nameserver " <>)
2146 name-servers)
2147 "\n" 'suffix)))
2148 `(("resolv.conf"
2149 ,(plain-file "resolv.conf"
2150 (string-append "\
2151# Generated by 'static-networking-service'.\n"
2152 content))))))))
2153
2154(define (static-networking-shepherd-services interfaces)
2155 "Return the list of Shepherd services to bring up INTERFACES, a list of
2156<static-networking> objects."
2157 (define (loopback? service)
2158 (memq 'loopback (shepherd-service-provision service)))
2159
2160 (let ((services (map static-networking-shepherd-service interfaces)))
2161 (match (remove loopback? services)
2162 (()
2163 ;; There's no interface other than 'loopback', so we assume that the
2164 ;; 'networking' service will be provided by dhclient or similar.
2165 services)
2166 ((non-loopback ...)
2167 ;; Assume we're providing all the interfaces, and thus, provide a
2168 ;; 'networking' service.
2169 (cons (shepherd-service
2170 (provision '(networking))
2171 (requirement (append-map shepherd-service-provision
2172 services))
2173 (start #~(const #t))
2174 (stop #~(const #f))
2175 (documentation "Bring up all the networking interfaces."))
2176 services)))))
2177
2178(define static-networking-service-type
2179 ;; The service type for statically-defined network interfaces.
2180 (service-type (name 'static-networking)
2181 (extensions
2182 (list
2183 (service-extension shepherd-root-service-type
2184 static-networking-shepherd-services)
2185 (service-extension etc-service-type
2186 static-networking-etc-files)))
2187 (compose concatenate)
2188 (extend append)
2189 (description
2190 "Turn up the specified network interfaces upon startup,
2191with the given IP address, gateway, netmask, and so on. The value for
2192services of this type is a list of @code{static-networking} objects, one per
2193network interface.")))
2194
2195(define* (static-networking-service interface ip
2196 #:key
2197 netmask gateway provision
2198 ;; Most interfaces require udev to be usable.
2199 (requirement '(udev))
2200 (name-servers '()))
2201 "Return a service that starts @var{interface} with address @var{ip}. If
2202@var{netmask} is true, use it as the network mask. If @var{gateway} is true,
2203it must be a string specifying the default network gateway.
2204
2205This procedure can be called several times, one for each network
2206interface of interest. Behind the scenes what it does is extend
2207@code{static-networking-service-type} with additional network interfaces
2208to handle."
2209 (simple-service 'static-network-interface
2210 static-networking-service-type
2211 (list (static-networking (interface interface) (ip ip)
2212 (netmask netmask) (gateway gateway)
2213 (provision provision)
2214 (requirement requirement)
2215 (name-servers name-servers)))))
2216
8664cc88 2217\f
8b198abe
LC
2218(define %base-services
2219 ;; Convenience variable holding the basic services.
317d3b47
DC
2220 (list (login-service)
2221
bb3062ad 2222 (service virtual-terminal-service-type)
4a84a487
LC
2223 (service console-font-service-type
2224 (map (lambda (tty)
2225 (cons tty %default-console-font))
2226 '("tty1" "tty2" "tty3" "tty4" "tty5" "tty6")))
317d3b47 2227
5a9902c8
DM
2228 (agetty-service (agetty-configuration
2229 (extra-options '("-L")) ; no carrier detect
2230 (term "vt100")
2231 (tty #f))) ; automatic
2232
317d3b47
DC
2233 (mingetty-service (mingetty-configuration
2234 (tty "tty1")))
2235 (mingetty-service (mingetty-configuration
2236 (tty "tty2")))
2237 (mingetty-service (mingetty-configuration
2238 (tty "tty3")))
2239 (mingetty-service (mingetty-configuration
2240 (tty "tty4")))
2241 (mingetty-service (mingetty-configuration
2242 (tty "tty5")))
2243 (mingetty-service (mingetty-configuration
2244 (tty "tty6")))
2245
8de3e4b3
LC
2246 (service static-networking-service-type
2247 (list (static-networking (interface "lo")
2248 (ip "127.0.0.1")
db8ed7ce 2249 (requirement '())
8de3e4b3 2250 (provision '(loopback)))))
317d3b47 2251 (syslog-service)
8faaf8d7 2252 (service urandom-seed-service-type)
317d3b47
DC
2253 (guix-service)
2254 (nscd-service)
2255
2256 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
2257 ;; used, so enable them by default. The FUSE and ALSA rules are
2258 ;; less critical, but handy.
387e1754
LC
2259 (udev-service #:rules (list lvm2 fuse alsa-utils crda))
2260
2261 (service special-files-service-type
2262 `(("/bin/sh" ,(file-append (canonical-package bash)
2263 "/bin/sh"))))))
8b198abe 2264
db4fdc04 2265;;; base.scm ends here