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