gnu: certbot, python-acme: Update to 0.18.2.
[jackhill/guix/guix.git] / gnu / system.scm
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
4 ;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
5 ;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
6 ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
7 ;;;
8 ;;; This file is part of GNU Guix.
9 ;;;
10 ;;; GNU Guix is free software; you can redistribute it and/or modify it
11 ;;; under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 3 of the License, or (at
13 ;;; your option) any later version.
14 ;;;
15 ;;; GNU Guix is distributed in the hope that it will be useful, but
16 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;;; GNU General Public License for more details.
19 ;;;
20 ;;; You should have received a copy of the GNU General Public License
21 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22
23 (define-module (gnu system)
24 #:use-module (guix store)
25 #:use-module (guix monads)
26 #:use-module (guix gexp)
27 #:use-module (guix records)
28 #:use-module (guix packages)
29 #:use-module (guix derivations)
30 #:use-module (guix profiles)
31 #:use-module (guix ui)
32 #:use-module (gnu packages base)
33 #:use-module (gnu packages bash)
34 #:use-module (gnu packages guile)
35 #:use-module (gnu packages admin)
36 #:use-module (gnu packages linux)
37 #:use-module (gnu packages pciutils)
38 #:use-module (gnu packages package-management)
39 #:use-module (gnu packages less)
40 #:use-module (gnu packages zile)
41 #:use-module (gnu packages nano)
42 #:use-module (gnu packages lsof)
43 #:use-module (gnu packages gawk)
44 #:use-module (gnu packages man)
45 #:use-module (gnu packages texinfo)
46 #:use-module (gnu packages compression)
47 #:use-module (gnu packages firmware)
48 #:use-module (gnu services)
49 #:use-module (gnu services shepherd)
50 #:use-module (gnu services base)
51 #:use-module (gnu bootloader)
52 #:use-module (gnu system shadow)
53 #:use-module (gnu system nss)
54 #:use-module (gnu system locale)
55 #:use-module (gnu system pam)
56 #:use-module (gnu system linux-initrd)
57 #:use-module (gnu system uuid)
58 #:use-module (gnu system file-systems)
59 #:use-module (gnu system mapped-devices)
60 #:use-module (ice-9 match)
61 #:use-module (srfi srfi-1)
62 #:use-module (srfi srfi-26)
63 #:use-module (srfi srfi-34)
64 #:use-module (srfi srfi-35)
65 #:use-module (rnrs bytevectors)
66 #:export (operating-system
67 operating-system?
68
69 operating-system-bootloader
70 operating-system-services
71 operating-system-user-services
72 operating-system-packages
73 operating-system-host-name
74 operating-system-hosts-file
75 operating-system-kernel
76 operating-system-kernel-file
77 operating-system-kernel-arguments
78 operating-system-initrd
79 operating-system-users
80 operating-system-groups
81 operating-system-issue
82 operating-system-timezone
83 operating-system-locale
84 operating-system-locale-definitions
85 operating-system-locale-libcs
86 operating-system-mapped-devices
87 operating-system-file-systems
88 operating-system-store-file-system
89 operating-system-user-mapped-devices
90 operating-system-boot-mapped-devices
91 operating-system-activation-script
92 operating-system-user-accounts
93 operating-system-shepherd-service-names
94
95 operating-system-derivation
96 operating-system-profile
97 operating-system-bootcfg
98 operating-system-etc-directory
99 operating-system-locale-directory
100 operating-system-boot-script
101
102 system-linux-image-file-name
103
104 boot-parameters
105 boot-parameters?
106 boot-parameters-label
107 boot-parameters-root-device
108 boot-parameters-bootloader-name
109 boot-parameters-store-device
110 boot-parameters-store-mount-point
111 boot-parameters-kernel
112 boot-parameters-kernel-arguments
113 boot-parameters-initrd
114 read-boot-parameters
115 read-boot-parameters-file
116 boot-parameters->menu-entry
117
118 local-host-aliases
119 %setuid-programs
120 %base-packages
121 %base-firmware))
122
123 ;;; Commentary:
124 ;;;
125 ;;; This module supports whole-system configuration.
126 ;;;
127 ;;; Code:
128
129 (define (bootable-kernel-arguments kernel-arguments system.drv root-device)
130 "Prepend extra arguments to KERNEL-ARGUMENTS that allow SYSTEM.DRV to be
131 booted from ROOT-DEVICE"
132 (cons* (string-append "--root="
133 (if (uuid? root-device)
134
135 ;; Note: Always use the DCE format because that's
136 ;; what (gnu build linux-boot) expects for the
137 ;; '--root' kernel command-line option.
138 (uuid->string (uuid-bytevector root-device) 'dce)
139 root-device))
140 #~(string-append "--system=" #$system.drv)
141 #~(string-append "--load=" #$system.drv "/boot")
142 kernel-arguments))
143
144 ;; System-wide configuration.
145 ;; TODO: Add per-field docstrings/stexi.
146 (define-record-type* <operating-system> operating-system
147 make-operating-system
148 operating-system?
149 (kernel operating-system-kernel ; package
150 (default linux-libre))
151 (kernel-arguments operating-system-user-kernel-arguments
152 (default '())) ; list of gexps/strings
153 (bootloader operating-system-bootloader) ; <bootloader-configuration>
154
155 (initrd operating-system-initrd ; (list fs) -> M derivation
156 (default base-initrd))
157 (firmware operating-system-firmware ; list of packages
158 (default %base-firmware))
159
160 (host-name operating-system-host-name) ; string
161 (hosts-file operating-system-hosts-file ; file-like | #f
162 (default #f))
163
164 (mapped-devices operating-system-mapped-devices ; list of <mapped-device>
165 (default '()))
166 (file-systems operating-system-file-systems) ; list of fs
167 (swap-devices operating-system-swap-devices ; list of strings
168 (default '()))
169
170 (users operating-system-users ; list of user accounts
171 (default %base-user-accounts))
172 (groups operating-system-groups ; list of user groups
173 (default %base-groups))
174
175 (skeletons operating-system-skeletons ; list of name/monadic value
176 (default (default-skeletons)))
177 (issue operating-system-issue ; string
178 (default %default-issue))
179
180 (packages operating-system-packages ; list of (PACKAGE OUTPUT...)
181 (default %base-packages)) ; or just PACKAGE
182
183 (timezone operating-system-timezone) ; string
184 (locale operating-system-locale ; string
185 (default "en_US.utf8"))
186 (locale-definitions operating-system-locale-definitions ; list of <locale-definition>
187 (default %default-locale-definitions))
188 (locale-libcs operating-system-locale-libcs ; list of <packages>
189 (default %default-locale-libcs))
190 (name-service-switch operating-system-name-service-switch ; <name-service-switch>
191 (default %default-nss))
192
193 (services operating-system-user-services ; list of monadic services
194 (default %base-services))
195
196 (pam-services operating-system-pam-services ; list of PAM services
197 (default (base-pam-services)))
198 (setuid-programs operating-system-setuid-programs
199 (default %setuid-programs)) ; list of string-valued gexps
200
201 (sudoers-file operating-system-sudoers-file ; file-like
202 (default %sudoers-specification)))
203
204 (define (operating-system-kernel-arguments os system.drv root-device)
205 "Return all the kernel arguments, including the ones not specified
206 directly by the user."
207 (bootable-kernel-arguments (operating-system-user-kernel-arguments os)
208 system.drv
209 root-device))
210
211 \f
212 ;;;
213 ;;; Boot parameters
214 ;;;
215
216 (define-record-type* <boot-parameters>
217 boot-parameters make-boot-parameters boot-parameters?
218 (label boot-parameters-label)
219 ;; Because we will use the 'store-device' to create the GRUB search command,
220 ;; the 'store-device' has slightly different semantics than 'root-device'.
221 ;; The 'store-device' can be a file system uuid, a file system label, or #f,
222 ;; but it cannot be a device path such as "/dev/sda3", since GRUB would not
223 ;; understand that. The 'root-device', on the other hand, corresponds
224 ;; exactly to the device field of the <file-system> object representing the
225 ;; OS's root file system, so it might be a device path like "/dev/sda3".
226 (root-device boot-parameters-root-device)
227 (bootloader-name boot-parameters-bootloader-name)
228 (store-device boot-parameters-store-device)
229 (store-mount-point boot-parameters-store-mount-point)
230 (kernel boot-parameters-kernel)
231 (kernel-arguments boot-parameters-kernel-arguments)
232 (initrd boot-parameters-initrd))
233
234 (define (read-boot-parameters port)
235 "Read boot parameters from PORT and return the corresponding
236 <boot-parameters> object or #f if the format is unrecognized."
237 (define device-sexp->device
238 (match-lambda
239 (('uuid (? symbol? type) (? bytevector? bv))
240 (bytevector->uuid bv type))
241 ((? bytevector? bv) ;old format
242 (bytevector->uuid bv 'dce))
243 ((? string? device)
244 device)))
245
246 (define (ensure-not-/dev device)
247 (if (and (string? device) (string-prefix? "/" device))
248 #f
249 device))
250
251 (match (read port)
252 (('boot-parameters ('version 0)
253 ('label label) ('root-device root)
254 ('kernel linux)
255 rest ...)
256 (boot-parameters
257 (label label)
258 (root-device (device-sexp->device root))
259
260 (bootloader-name
261 (match (assq 'bootloader-name rest)
262 ((_ args) args)
263 (#f 'grub))) ; for compatibility reasons.
264
265 ;; In the past, we would store the directory name of the kernel instead
266 ;; of the absolute file name of its image. Detect that and correct it.
267 (kernel (if (string=? linux (direct-store-path linux))
268 (string-append linux "/"
269 (system-linux-image-file-name))
270 linux))
271
272 (kernel-arguments
273 (match (assq 'kernel-arguments rest)
274 ((_ args) args)
275 (#f '()))) ;the old format
276
277 (initrd
278 (match (assq 'initrd rest)
279 (('initrd ('string-append directory file)) ;the old format
280 (string-append directory file))
281 (('initrd (? string? file))
282 file)))
283
284 (store-device
285 ;; Linux device names like "/dev/sda1" are not suitable GRUB device
286 ;; identifiers, so we just filter them out.
287 (ensure-not-/dev
288 (match (assq 'store rest)
289 (('store ('device #f) _ ...)
290 root-device)
291 (('store ('device device) _ ...)
292 (device-sexp->device device))
293 (_ ;the old format
294 root-device))))
295
296 (store-mount-point
297 (match (assq 'store rest)
298 (('store ('device _) ('mount-point mount-point) _ ...)
299 mount-point)
300 (_ ;the old format
301 "/")))))
302 (x ;unsupported format
303 (warning (G_ "unrecognized boot parameters for '~a'~%")
304 system)
305 #f)))
306
307 (define (read-boot-parameters-file system)
308 "Read boot parameters from SYSTEM's (system or generation) \"parameters\"
309 file and returns the corresponding <boot-parameters> object or #f if the
310 format is unrecognized.
311 The object has its kernel-arguments extended in order to make it bootable."
312 (let* ((file (string-append system "/parameters"))
313 (params (call-with-input-file file read-boot-parameters))
314 (root (boot-parameters-root-device params))
315 (kernel-arguments (boot-parameters-kernel-arguments params)))
316 (if params
317 (boot-parameters
318 (inherit params)
319 (kernel-arguments (bootable-kernel-arguments kernel-arguments
320 system root)))
321 #f)))
322
323 (define (boot-parameters->menu-entry conf)
324 (menu-entry
325 (label (boot-parameters-label conf))
326 (device (boot-parameters-store-device conf))
327 (device-mount-point (boot-parameters-store-mount-point conf))
328 (linux (boot-parameters-kernel conf))
329 (linux-arguments (boot-parameters-kernel-arguments conf))
330 (initrd (boot-parameters-initrd conf))))
331
332
333 \f
334 ;;;
335 ;;; Services.
336 ;;;
337
338 (define (non-boot-file-system-service os)
339 "Return the file system service for the file systems of OS that are not
340 marked as 'needed-for-boot'."
341 (define file-systems
342 (remove file-system-needed-for-boot?
343 (operating-system-file-systems os)))
344
345 (define (device-mappings fs)
346 (let ((device (file-system-device fs)))
347 (if (string? device) ;title is 'device
348 (filter (lambda (md)
349 (string=? (string-append "/dev/mapper/"
350 (mapped-device-target md))
351 device))
352 (operating-system-mapped-devices os))
353 '())))
354
355 (define (add-dependencies fs)
356 ;; Add the dependencies due to device mappings to FS.
357 (file-system
358 (inherit fs)
359 (dependencies
360 (delete-duplicates (append (device-mappings fs)
361 (file-system-dependencies fs))
362 eq?))))
363
364 (service file-system-service-type
365 (map add-dependencies file-systems)))
366
367 (define (mapped-device-user device file-systems)
368 "Return a file system among FILE-SYSTEMS that uses DEVICE, or #f."
369 (let ((target (string-append "/dev/mapper/" (mapped-device-target device))))
370 (find (lambda (fs)
371 (or (member device (file-system-dependencies fs))
372 (and (eq? 'device (file-system-title fs))
373 (string=? (file-system-device fs) target))))
374 file-systems)))
375
376 (define (operating-system-user-mapped-devices os)
377 "Return the subset of mapped devices that can be installed in
378 user-land--i.e., those not needed during boot."
379 (let ((devices (operating-system-mapped-devices os))
380 (file-systems (operating-system-file-systems os)))
381 (filter (lambda (md)
382 (let ((user (mapped-device-user md file-systems)))
383 (or (not user)
384 (not (file-system-needed-for-boot? user)))))
385 devices)))
386
387 (define (operating-system-boot-mapped-devices os)
388 "Return the subset of mapped devices that must be installed during boot,
389 from the initrd."
390 (let ((devices (operating-system-mapped-devices os))
391 (file-systems (operating-system-file-systems os)))
392 (filter (lambda (md)
393 (let ((user (mapped-device-user md file-systems)))
394 (and user (file-system-needed-for-boot? user))))
395 devices)))
396
397 (define (device-mapping-services os)
398 "Return the list of device-mapping services for OS as a list."
399 (map device-mapping-service
400 (operating-system-user-mapped-devices os)))
401
402 (define (swap-services os)
403 "Return the list of swap services for OS."
404 (map swap-service (operating-system-swap-devices os)))
405
406 (define* (system-linux-image-file-name #:optional (system (%current-system)))
407 "Return the basename of the kernel image file for SYSTEM."
408 ;; FIXME: Evaluate the conditional based on the actual current system.
409 (cond
410 ((string-prefix? "arm" (%current-system)) "zImage")
411 ((string-prefix? "mips" (%current-system)) "vmlinuz")
412 ((string-prefix? "aarch64" (%current-system)) "Image")
413 (else "bzImage")))
414
415 (define (operating-system-kernel-file os)
416 "Return an object representing the absolute file name of the kernel image of
417 OS."
418 (file-append (operating-system-kernel os)
419 "/" (system-linux-image-file-name os)))
420
421 (define* (operating-system-directory-base-entries os #:key container?)
422 "Return the basic entries of the 'system' directory of OS for use as the
423 value of the SYSTEM-SERVICE-TYPE service."
424 (let ((locale (operating-system-locale-directory os)))
425 (with-monad %store-monad
426 (if container?
427 (return `(("locale" ,locale)))
428 (mlet %store-monad
429 ((kernel -> (operating-system-kernel os))
430 (initrd (operating-system-initrd-file os))
431 (params (operating-system-boot-parameters-file os)))
432 (return `(("kernel" ,kernel)
433 ("parameters" ,params)
434 ("initrd" ,initrd)
435 ("locale" ,locale)))))))) ;used by libc
436
437 (define* (essential-services os #:key container?)
438 "Return the list of essential services for OS. These are special services
439 that implement part of what's declared in OS are responsible for low-level
440 bookkeeping. CONTAINER? determines whether to return the list of services for
441 a container or that of a \"bare metal\" system."
442 (define known-fs
443 (map file-system-mount-point (operating-system-file-systems os)))
444
445 (let* ((mappings (device-mapping-services os))
446 (root-fs (root-file-system-service))
447 (other-fs (non-boot-file-system-service os))
448 (unmount (user-unmount-service known-fs))
449 (swaps (swap-services os))
450 (procs (user-processes-service))
451 (host-name (host-name-service (operating-system-host-name os)))
452 (entries (operating-system-directory-base-entries
453 os #:container? container?)))
454 (cons* (service system-service-type entries)
455 %boot-service
456
457 ;; %SHEPHERD-ROOT-SERVICE must come first so that the gexp that
458 ;; execs shepherd comes last in the boot script (XXX). Likewise,
459 ;; the cleanup service must come last so that its gexp runs before
460 ;; activation code.
461 %shepherd-root-service
462 %activation-service
463 (service cleanup-service-type #f)
464
465 (pam-root-service (operating-system-pam-services os))
466 (account-service (append (operating-system-accounts os)
467 (operating-system-groups os))
468 (operating-system-skeletons os))
469 (operating-system-etc-service os)
470 (service fstab-service-type '())
471 (session-environment-service
472 (operating-system-environment-variables os))
473 host-name procs root-fs unmount
474 (service setuid-program-service-type
475 (operating-system-setuid-programs os))
476 (service profile-service-type
477 (operating-system-packages os))
478 other-fs
479 (append mappings swaps
480
481 ;; Add the firmware service, unless we are building for a
482 ;; container.
483 (if container?
484 '()
485 (list %linux-bare-metal-service
486 (service firmware-service-type
487 (operating-system-firmware os))))))))
488
489 (define* (operating-system-services os #:key container?)
490 "Return all the services of OS, including \"internal\" services that do not
491 explicitly appear in OS."
492 (append (operating-system-user-services os)
493 (essential-services os #:container? container?)))
494
495 \f
496 ;;;
497 ;;; /etc.
498 ;;;
499
500 (define %base-firmware
501 ;; Firmware usable by default.
502 (list ath9k-htc-firmware
503 openfwwf-firmware))
504
505 (define %base-packages
506 ;; Default set of packages globally visible. It should include anything
507 ;; required for basic administrator tasks.
508 (cons* procps psmisc which less zile nano
509 lsof ;for Guix's 'list-runtime-roots'
510 pciutils usbutils
511 util-linux inetutils isc-dhcp
512 (@ (gnu packages admin) shadow) ;for 'passwd'
513
514 ;; wireless-tools is deprecated in favor of iw, but it's still what
515 ;; many people are familiar with, so keep it around.
516 iw wireless-tools rfkill
517
518 iproute
519 net-tools ; XXX: remove when Inetutils suffices
520 man-db
521 info-reader ;the standalone Info reader (no Perl)
522
523 ;; The 'sudo' command is already in %SETUID-PROGRAMS, but we also
524 ;; want the other commands and the man pages (notably because
525 ;; auto-completion in Emacs shell relies on man pages.)
526 sudo
527
528 ;; Get 'insmod' & co. from kmod, not module-init-tools, since udev
529 ;; already depends on it anyway.
530 kmod eudev
531
532 e2fsprogs kbd
533
534 bash-completion
535
536 ;; XXX: We don't use (canonical-package guile-2.2) here because that
537 ;; would create a collision in the global profile between the GMP
538 ;; variant propagated by 'guile-final' and the GMP variant propagated
539 ;; by 'gnutls', itself propagated by 'guix'.
540 guile-2.2
541
542 ;; The packages below are also in %FINAL-INPUTS, so take them from
543 ;; there to avoid duplication.
544 (map canonical-package
545 (list bash coreutils findutils grep sed
546 diffutils patch gawk tar gzip bzip2 xz lzip))))
547
548 (define %default-issue
549 ;; Default contents for /etc/issue.
550 "
551 This is the GNU system. Welcome.\n")
552
553 (define (local-host-aliases host-name)
554 "Return aliases for HOST-NAME, to be used in /etc/hosts."
555 (string-append "127.0.0.1 localhost " host-name "\n"
556 "::1 localhost " host-name "\n"))
557
558 (define (default-/etc/hosts host-name)
559 "Return the default /etc/hosts file."
560 (plain-file "hosts" (local-host-aliases host-name)))
561
562 (define* (operating-system-etc-service os)
563 "Return a <service> that builds containing the static part of the /etc
564 directory."
565 (let ((login.defs (plain-file "login.defs" "# Empty for now.\n"))
566
567 (issue (plain-file "issue" (operating-system-issue os)))
568 (nsswitch (plain-file "nsswitch.conf"
569 (name-service-switch->string
570 (operating-system-name-service-switch os))))
571
572 ;; Startup file for POSIX-compliant login shells, which set system-wide
573 ;; environment variables.
574 (profile (mixed-text-file "profile" "\
575 # Crucial variables that could be missing in the profiles' 'etc/profile'
576 # because they would require combining both profiles.
577 # FIXME: See <http://bugs.gnu.org/20255>.
578 export MANPATH=$HOME/.guix-profile/share/man:/run/current-system/profile/share/man
579 export INFOPATH=$HOME/.guix-profile/share/info:/run/current-system/profile/share/info
580 export XDG_DATA_DIRS=$HOME/.guix-profile/share:/run/current-system/profile/share
581 export XDG_CONFIG_DIRS=$HOME/.guix-profile/etc/xdg:/run/current-system/profile/etc/xdg
582
583 # Ignore the default value of 'PATH'.
584 unset PATH
585
586 # Load the system profile's settings.
587 GUIX_PROFILE=/run/current-system/profile \\
588 . /run/current-system/profile/etc/profile
589
590 # Prepend setuid programs.
591 export PATH=/run/setuid-programs:$PATH
592
593 # Since 'lshd' does not use pam_env, /etc/environment must be explicitly
594 # loaded when someone logs in via SSH. See <http://bugs.gnu.org/22175>.
595 # We need 'PATH' to be defined here, for 'cat' and 'cut'. Do this before
596 # reading the user's 'etc/profile' to allow variables to be overridden.
597 if [ -f /etc/environment -a -n \"$SSH_CLIENT\" \\
598 -a -z \"$LINUX_MODULE_DIRECTORY\" ]
599 then
600 . /etc/environment
601 export `cat /etc/environment | cut -d= -f1`
602 fi
603
604 if [ -f \"$HOME/.guix-profile/etc/profile\" ]
605 then
606 # Load the user profile's settings.
607 GUIX_PROFILE=\"$HOME/.guix-profile\" \\
608 . \"$HOME/.guix-profile/etc/profile\"
609 else
610 # At least define this one so that basic things just work
611 # when the user installs their first package.
612 export PATH=\"$HOME/.guix-profile/bin:$PATH\"
613 fi
614
615 # Set the umask, notably for users logging in via 'lsh'.
616 # See <http://bugs.gnu.org/22650>.
617 umask 022
618
619 # Allow Hunspell-based applications (IceCat, LibreOffice, etc.) to
620 # find dictionaries.
621 export DICPATH=\"$HOME/.guix-profile/share/hunspell:/run/current-system/profile/share/hunspell\"
622
623 # Allow GStreamer-based applications to find plugins.
624 export GST_PLUGIN_PATH=\"$HOME/.guix-profile/lib/gstreamer-1.0\"
625
626 if [ -n \"$BASH_VERSION\" -a -f /etc/bashrc ]
627 then
628 # Load Bash-specific initialization code.
629 . /etc/bashrc
630 fi
631 "))
632
633 (bashrc (plain-file "bashrc" "\
634 # Bash-specific initialization.
635
636 # The 'bash-completion' package.
637 if [ -f /run/current-system/profile/etc/profile.d/bash_completion.sh ]
638 then
639 # Bash-completion sources ~/.bash_completion. It installs a dynamic
640 # completion loader that searches its own completion files as well
641 # as those in ~/.guix-profile and /run/current-system/profile.
642 source /run/current-system/profile/etc/profile.d/bash_completion.sh
643 fi\n")))
644 (etc-service
645 `(("services" ,(file-append net-base "/etc/services"))
646 ("protocols" ,(file-append net-base "/etc/protocols"))
647 ("rpc" ,(file-append net-base "/etc/rpc"))
648 ("login.defs" ,#~#$login.defs)
649 ("issue" ,#~#$issue)
650 ("nsswitch.conf" ,#~#$nsswitch)
651 ("profile" ,#~#$profile)
652 ("bashrc" ,#~#$bashrc)
653 ("hosts" ,#~#$(or (operating-system-hosts-file os)
654 (default-/etc/hosts (operating-system-host-name os))))
655 ;; Write the operating-system-host-name to /etc/hostname to prevent
656 ;; NetworkManager from changing the system's hostname when connecting
657 ;; to certain networks. Some discussion at
658 ;; https://lists.gnu.org/archive/html/help-guix/2017-09/msg00037.html
659 ("hostname" ,(plain-file "hostname" (operating-system-host-name os)))
660 ("localtime" ,(file-append tzdata "/share/zoneinfo/"
661 (operating-system-timezone os)))
662 ("sudoers" ,(operating-system-sudoers-file os))))))
663
664 (define %root-account
665 ;; Default root account.
666 (user-account
667 (name "root")
668 (password "")
669 (uid 0) (group "root")
670 (comment "System administrator")
671 (home-directory "/root")))
672
673 (define (operating-system-accounts os)
674 "Return the user accounts for OS, including an obligatory 'root' account,
675 and excluding accounts requested by services."
676 ;; Make sure there's a root account.
677 (if (find (lambda (user)
678 (and=> (user-account-uid user) zero?))
679 (operating-system-users os))
680 (operating-system-users os)
681 (cons %root-account (operating-system-users os))))
682
683 (define (maybe-string->file file-name thing)
684 "If THING is a string, return a <plain-file> with THING as its content.
685 Otherwise just return THING.
686
687 This is for backward-compatibility of fields that used to be strings and are
688 now file-like objects.."
689 (match thing
690 ((? string?)
691 (warning (G_ "using a string for file '~a' is deprecated; \
692 use 'plain-file' instead~%")
693 file-name)
694 (plain-file file-name thing))
695 (x
696 x)))
697
698 (define (maybe-file->monadic file-name thing)
699 "If THING is a value in %STORE-MONAD, return it as is; otherwise return
700 THING in the %STORE-MONAD.
701
702 This is for backward-compatibility of fields that used to be monadic values
703 and are now file-like objects."
704 (with-monad %store-monad
705 (match thing
706 ((? procedure?)
707 (warning (G_ "using a monadic value for '~a' is deprecated; \
708 use 'plain-file' instead~%")
709 file-name)
710 thing)
711 (x
712 (return x)))))
713
714 (define (operating-system-etc-directory os)
715 "Return that static part of the /etc directory of OS."
716 (etc-directory
717 (fold-services (operating-system-services os)
718 #:target-type etc-service-type)))
719
720 (define (operating-system-environment-variables os)
721 "Return the environment variables of OS for
722 @var{session-environment-service-type}, to be used in @file{/etc/environment}."
723 `(("LANG" . ,(operating-system-locale os))
724 ("TZ" . ,(operating-system-timezone os))
725 ("TZDIR" . ,(file-append tzdata "/share/zoneinfo"))
726 ;; Tell 'modprobe' & co. where to look for modules.
727 ("LINUX_MODULE_DIRECTORY" . "/run/booted-system/kernel/lib/modules")
728 ;; These variables are honored by OpenSSL (libssl) and Git.
729 ("SSL_CERT_DIR" . "/etc/ssl/certs")
730 ("SSL_CERT_FILE" . "/etc/ssl/certs/ca-certificates.crt")
731 ("GIT_SSL_CAINFO" . "/etc/ssl/certs/ca-certificates.crt")
732
733 ;; 'GTK_DATA_PREFIX' must name one directory where GTK+ themes are
734 ;; searched for.
735 ("GTK_DATA_PREFIX" . "/run/current-system/profile")
736
737 ;; By default, applications that use D-Bus, such as Emacs, abort at startup
738 ;; when /etc/machine-id is missing. Make sure these warnings are non-fatal.
739 ("DBUS_FATAL_WARNINGS" . "0")
740
741 ;; XXX: Normally we wouldn't need to do this, but our glibc@2.23 package
742 ;; used to look things up in 'PREFIX/lib/locale' instead of
743 ;; '/run/current-system/locale' as was intended. Keep this hack around so
744 ;; that people who still have glibc@2.23-using packages in their profiles
745 ;; can use them correctly.
746 ;; TODO: Remove when glibc@2.23 is long gone.
747 ("GUIX_LOCPATH" . "/run/current-system/locale")))
748
749 (define %setuid-programs
750 ;; Default set of setuid-root programs.
751 (let ((shadow (@ (gnu packages admin) shadow)))
752 (list (file-append shadow "/bin/passwd")
753 (file-append shadow "/bin/su")
754 (file-append shadow "/bin/newuidmap")
755 (file-append shadow "/bin/newgidmap")
756 (file-append inetutils "/bin/ping")
757 (file-append inetutils "/bin/ping6")
758 (file-append sudo "/bin/sudo")
759 (file-append fuse "/bin/fusermount"))))
760
761 (define %sudoers-specification
762 ;; Default /etc/sudoers contents: 'root' and all members of the 'wheel'
763 ;; group can do anything. See
764 ;; <http://www.sudo.ws/sudo/man/1.8.10/sudoers.man.html>.
765 ;; TODO: Add a declarative API.
766 (plain-file "sudoers" "\
767 root ALL=(ALL) ALL
768 %wheel ALL=(ALL) ALL\n"))
769
770 (define* (operating-system-activation-script os #:key container?)
771 "Return the activation script for OS---i.e., the code that \"activates\" the
772 stateful part of OS, including user accounts and groups, special directories,
773 etc."
774 (let* ((services (operating-system-services os #:container? container?))
775 (activation (fold-services services
776 #:target-type activation-service-type)))
777 (activation-service->script activation)))
778
779 (define* (operating-system-boot-script os #:key container?)
780 "Return the boot script for OS---i.e., the code started by the initrd once
781 we're running in the final root. When CONTAINER? is true, skip all
782 hardware-related operations as necessary when booting a Linux container."
783 (let* ((services (operating-system-services os #:container? container?))
784 (boot (fold-services services #:target-type boot-service-type)))
785 ;; BOOT is the script as a monadic value.
786 (service-value boot)))
787
788 (define (operating-system-user-accounts os)
789 "Return the list of user accounts of OS."
790 (let* ((services (operating-system-services os))
791 (account (fold-services services
792 #:target-type account-service-type)))
793 (filter user-account?
794 (service-value account))))
795
796 (define (operating-system-shepherd-service-names os)
797 "Return the list of Shepherd service names for OS."
798 (append-map shepherd-service-provision
799 (service-value
800 (fold-services (operating-system-services os)
801 #:target-type
802 shepherd-root-service-type))))
803
804 (define* (operating-system-derivation os #:key container?)
805 "Return a derivation that builds OS."
806 (let* ((services (operating-system-services os #:container? container?))
807 (system (fold-services services)))
808 ;; SYSTEM contains the derivation as a monadic value.
809 (service-value system)))
810
811 (define* (operating-system-profile os #:key container?)
812 "Return a derivation that builds the system profile of OS."
813 (mlet* %store-monad
814 ((services -> (operating-system-services os #:container? container?))
815 (profile (fold-services services
816 #:target-type profile-service-type)))
817 (match profile
818 (("profile" profile)
819 (return profile)))))
820
821 (define (operating-system-root-file-system os)
822 "Return the root file system of OS."
823 (find (match-lambda
824 (($ <file-system> device title "/") #t)
825 (x #f))
826 (operating-system-file-systems os)))
827
828 (define (operating-system-initrd-file os)
829 "Return a gexp denoting the initrd file of OS."
830 (define boot-file-systems
831 (filter file-system-needed-for-boot?
832 (operating-system-file-systems os)))
833
834 (define mapped-devices
835 (operating-system-boot-mapped-devices os))
836
837 (define make-initrd
838 (operating-system-initrd os))
839
840 (mlet %store-monad ((initrd (make-initrd boot-file-systems
841 #:linux (operating-system-kernel os)
842 #:mapped-devices mapped-devices)))
843 (return (file-append initrd "/initrd"))))
844
845 (define (locale-name->definition* name)
846 "Variant of 'locale-name->definition' that raises an error upon failure."
847 (match (locale-name->definition name)
848 (#f
849 (raise (condition
850 (&message
851 (message (format #f (G_ "~a: invalid locale name") name))))))
852 (def def)))
853
854 (define (operating-system-locale-directory os)
855 "Return the directory containing the locales compiled for the definitions
856 listed in OS. The C library expects to find it under
857 /run/current-system/locale."
858 (define name
859 (operating-system-locale os))
860
861 (define definitions
862 ;; While we're at it, check whether NAME is defined and add it if needed.
863 (if (member name (map locale-definition-name
864 (operating-system-locale-definitions os)))
865 (operating-system-locale-definitions os)
866 (cons (locale-name->definition* name)
867 (operating-system-locale-definitions os))))
868
869 (locale-directory definitions
870 #:libcs (operating-system-locale-libcs os)))
871
872 (define (kernel->boot-label kernel)
873 "Return a label for the bootloader menu entry that boots KERNEL."
874 (string-append "GNU with "
875 (string-titlecase (package-name kernel)) " "
876 (package-version kernel)
877 " (beta)"))
878
879 (define (store-file-system file-systems)
880 "Return the file system object among FILE-SYSTEMS that contains the store."
881 (match (filter (lambda (fs)
882 (and (file-system-mount? fs)
883 (not (memq 'bind-mount (file-system-flags fs)))
884 (string-prefix? (file-system-mount-point fs)
885 (%store-prefix))))
886 file-systems)
887 ((and candidates (head . tail))
888 (reduce (lambda (fs1 fs2)
889 (if (> (string-length (file-system-mount-point fs1))
890 (string-length (file-system-mount-point fs2)))
891 fs1
892 fs2))
893 head
894 candidates))))
895
896 (define (operating-system-store-file-system os)
897 "Return the file system that contains the store of OS."
898 (store-file-system (operating-system-file-systems os)))
899
900 (define* (operating-system-bootcfg os #:optional (old-entries '()))
901 "Return the bootloader configuration file for OS. Use OLD-ENTRIES
902 (which is a list of <menu-entry>) to populate the \"old entries\" menu."
903 (mlet* %store-monad
904 ((system (operating-system-derivation os))
905 (root-fs -> (operating-system-root-file-system os))
906 (root-device -> (file-system-device root-fs))
907 (params (operating-system-boot-parameters os system root-device))
908 (entry -> (boot-parameters->menu-entry params))
909 (bootloader-conf -> (operating-system-bootloader os)))
910 ((bootloader-configuration-file-generator
911 (bootloader-configuration-bootloader bootloader-conf))
912 bootloader-conf (list entry) #:old-entries old-entries)))
913
914 (define (fs->boot-device fs)
915 "Given FS, a <file-system> object, return a value suitable for use as the
916 device in a <menu-entry>."
917 (case (file-system-title fs)
918 ((uuid label device) (file-system-device fs))
919 (else #f)))
920
921 (define (operating-system-boot-parameters os system.drv root-device)
922 "Return a monadic <boot-parameters> record that describes the boot parameters
923 of OS. SYSTEM.DRV is either a derivation or #f. If it's a derivation, adds
924 kernel arguments for that derivation to <boot-parameters>."
925 (mlet* %store-monad
926 ((initrd (operating-system-initrd-file os))
927 (store -> (operating-system-store-file-system os))
928 (bootloader -> (bootloader-configuration-bootloader
929 (operating-system-bootloader os)))
930 (bootloader-name -> (bootloader-name bootloader))
931 (label -> (kernel->boot-label (operating-system-kernel os))))
932 (return (boot-parameters
933 (label label)
934 (root-device root-device)
935 (kernel (operating-system-kernel-file os))
936 (kernel-arguments
937 (if system.drv
938 (operating-system-kernel-arguments os system.drv root-device)
939 (operating-system-user-kernel-arguments os)))
940 (initrd initrd)
941 (bootloader-name bootloader-name)
942 (store-device (fs->boot-device store))
943 (store-mount-point (file-system-mount-point store))))))
944
945 (define (device->sexp device)
946 "Serialize DEVICE as an sexp (really, as an object with a read syntax.)"
947 (match device
948 ((? uuid? uuid)
949 `(uuid ,(uuid-type uuid) ,(uuid-bytevector uuid)))
950 (_
951 device)))
952
953 (define* (operating-system-boot-parameters-file os #:optional (system.drv #f))
954 "Return a file that describes the boot parameters of OS. The primary use of
955 this file is the reconstruction of GRUB menu entries for old configurations.
956 SYSTEM.DRV is optional. If given, adds kernel arguments for that system to the
957 returned file (since the returned file is then usually stored into the
958 content-addressed \"system\" directory, it's usually not a good idea
959 to give it because the content hash would change by the content hash
960 being stored into the \"parameters\" file)."
961 (mlet* %store-monad ((root -> (operating-system-root-file-system os))
962 (device -> (file-system-device root))
963 (params (operating-system-boot-parameters os
964 system.drv
965 device)))
966 (gexp->file "parameters"
967 #~(boot-parameters
968 (version 0)
969 (label #$(boot-parameters-label params))
970 (root-device
971 #$(device->sexp
972 (boot-parameters-root-device params)))
973 (kernel #$(boot-parameters-kernel params))
974 (kernel-arguments
975 #$(boot-parameters-kernel-arguments params))
976 (initrd #$(boot-parameters-initrd params))
977 (bootloader-name #$(boot-parameters-bootloader-name params))
978 (store
979 (device
980 #$(device->sexp (boot-parameters-store-device params)))
981 (mount-point #$(boot-parameters-store-mount-point params))))
982 #:set-load-path? #f)))
983
984 (define-gexp-compiler (operating-system-compiler (os <operating-system>)
985 system target)
986 ((store-lift
987 (lambda (store)
988 ;; XXX: This is not super elegant but we can't pass SYSTEM and TARGET to
989 ;; 'operating-system-derivation'.
990 (run-with-store store (operating-system-derivation os)
991 #:system system
992 #:target target)))))
993
994 ;;; system.scm ends here