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