system.scm 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 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. ;;; Copyright © 2019 Meiyo Peng <meiyo.peng@gmail.com>
  8. ;;; Copyright © 2019, 2020 Miguel Ángel Arruga Vivas <rosen644835@gmail.com>
  9. ;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
  10. ;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
  11. ;;; Copyright © 2020 Florian Pelz <pelzflorian@pelzflorian.de>
  12. ;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  13. ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <jannek@gnu.org>
  14. ;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
  15. ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
  16. ;;; Copyright © 2021 raid5atemyhomework <raid5atemyhomework@protonmail.com>
  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. (define-module (gnu system)
  33. #:use-module (guix inferior)
  34. #:use-module (guix store)
  35. #:use-module (guix monads)
  36. #:use-module (guix gexp)
  37. #:use-module (guix records)
  38. #:use-module (guix packages)
  39. #:use-module (guix derivations)
  40. #:use-module (guix profiles)
  41. #:use-module ((guix utils) #:select (substitute-keyword-arguments))
  42. #:use-module (guix i18n)
  43. #:use-module (guix diagnostics)
  44. #:use-module (gnu packages admin)
  45. #:use-module (gnu packages base)
  46. #:use-module (gnu packages bash)
  47. #:use-module (gnu packages compression)
  48. #:use-module (gnu packages cross-base)
  49. #:use-module (gnu packages cryptsetup)
  50. #:use-module (gnu packages disk)
  51. #:use-module (gnu packages file-systems)
  52. #:use-module (gnu packages firmware)
  53. #:use-module (gnu packages gawk)
  54. #:use-module (gnu packages guile)
  55. #:use-module (gnu packages guile-xyz)
  56. #:use-module (gnu packages hurd)
  57. #:use-module (gnu packages less)
  58. #:use-module (gnu packages linux)
  59. #:use-module (gnu packages man)
  60. #:use-module (gnu packages nano)
  61. #:use-module (gnu packages nvi)
  62. #:use-module (gnu packages package-management)
  63. #:use-module (gnu packages pciutils)
  64. #:use-module (gnu packages texinfo)
  65. #:use-module (gnu packages text-editors)
  66. #:use-module (gnu packages wget)
  67. #:use-module (gnu services)
  68. #:use-module (gnu services shepherd)
  69. #:use-module (gnu services base)
  70. #:use-module (gnu bootloader)
  71. #:use-module (gnu system shadow)
  72. #:use-module (gnu system nss)
  73. #:use-module (gnu system locale)
  74. #:use-module (gnu system pam)
  75. #:use-module (gnu system linux-initrd)
  76. #:use-module (gnu system uuid)
  77. #:use-module (gnu system file-systems)
  78. #:use-module (gnu system mapped-devices)
  79. #:use-module (ice-9 match)
  80. #:use-module (srfi srfi-1)
  81. #:use-module (srfi srfi-26)
  82. #:use-module (srfi srfi-34)
  83. #:use-module (srfi srfi-35)
  84. #:use-module (rnrs bytevectors)
  85. #:export (operating-system
  86. operating-system?
  87. this-operating-system
  88. operating-system-bootloader
  89. operating-system-services
  90. operating-system-essential-services
  91. operating-system-default-essential-services
  92. operating-system-user-services
  93. operating-system-packages
  94. operating-system-host-name
  95. operating-system-hosts-file
  96. operating-system-hurd
  97. operating-system-kernel
  98. operating-system-kernel-file
  99. operating-system-kernel-arguments
  100. operating-system-label
  101. operating-system-default-label
  102. operating-system-initrd-modules
  103. operating-system-initrd
  104. operating-system-users
  105. operating-system-groups
  106. operating-system-issue
  107. operating-system-timezone
  108. operating-system-locale
  109. operating-system-locale-definitions
  110. operating-system-locale-libcs
  111. operating-system-mapped-devices
  112. operating-system-file-systems
  113. operating-system-store-file-system
  114. operating-system-user-mapped-devices
  115. operating-system-boot-mapped-devices
  116. operating-system-bootloader-crypto-devices
  117. operating-system-activation-script
  118. operating-system-user-accounts
  119. operating-system-shepherd-service-names
  120. operating-system-user-kernel-arguments
  121. operating-system-firmware
  122. operating-system-keyboard-layout
  123. operating-system-name-service-switch
  124. operating-system-pam-services
  125. operating-system-setuid-programs
  126. operating-system-skeletons
  127. operating-system-sudoers-file
  128. operating-system-swap-devices
  129. operating-system-kernel-loadable-modules
  130. operating-system-location
  131. operating-system-derivation
  132. operating-system-profile
  133. operating-system-bootcfg
  134. operating-system-etc-directory
  135. operating-system-locale-directory
  136. operating-system-boot-script
  137. operating-system-uuid
  138. system-linux-image-file-name
  139. operating-system-with-gc-roots
  140. operating-system-with-provenance
  141. hurd-default-essential-services
  142. boot-parameters
  143. boot-parameters?
  144. boot-parameters-label
  145. boot-parameters-root-device
  146. boot-parameters-bootloader-name
  147. boot-parameters-bootloader-menu-entries
  148. boot-parameters-store-crypto-devices
  149. boot-parameters-store-device
  150. boot-parameters-store-directory-prefix
  151. boot-parameters-store-mount-point
  152. boot-parameters-locale
  153. boot-parameters-kernel
  154. boot-parameters-kernel-arguments
  155. boot-parameters-initrd
  156. boot-parameters-multiboot-modules
  157. read-boot-parameters
  158. read-boot-parameters-file
  159. boot-parameters->menu-entry
  160. local-host-aliases
  161. %root-account
  162. %setuid-programs
  163. %sudoers-specification
  164. %base-packages
  165. %base-packages-interactive
  166. %base-packages-linux
  167. %base-packages-networking
  168. %base-packages-disk-utilities
  169. %base-packages-utils
  170. %base-firmware
  171. %default-kernel-arguments))
  172. ;;; Commentary:
  173. ;;;
  174. ;;; This module supports whole-system configuration.
  175. ;;;
  176. ;;; Code:
  177. (define (bootable-kernel-arguments system root-device)
  178. "Return a list of kernel arguments (gexps) to boot SYSTEM from ROOT-DEVICE."
  179. (list (string-append "--root="
  180. ;; Note: Always use the DCE format because that's what
  181. ;; (gnu build linux-boot) expects for the '--root'
  182. ;; kernel command-line option.
  183. (file-system-device->string root-device
  184. #:uuid-type 'dce))
  185. #~(string-append "--system=" #$system)
  186. #~(string-append "--load=" #$system "/boot")))
  187. ;; System-wide configuration.
  188. ;; TODO: Add per-field docstrings/stexi.
  189. (define-record-type* <operating-system> operating-system
  190. make-operating-system
  191. operating-system?
  192. this-operating-system
  193. (kernel operating-system-kernel ; package
  194. (default linux-libre))
  195. (kernel-loadable-modules operating-system-kernel-loadable-modules
  196. (default '())) ; list of packages
  197. (kernel-arguments operating-system-user-kernel-arguments
  198. (default %default-kernel-arguments)) ; list of gexps/strings
  199. (hurd operating-system-hurd
  200. (default #f)) ; package
  201. (bootloader operating-system-bootloader) ; <bootloader-configuration>
  202. (label operating-system-label ; string
  203. (thunked)
  204. (default (operating-system-default-label this-operating-system)))
  205. (keyboard-layout operating-system-keyboard-layout ;#f | <keyboard-layout>
  206. (default #f))
  207. (initrd operating-system-initrd ; (list fs) -> file-like
  208. (default base-initrd))
  209. (initrd-modules operating-system-initrd-modules ; list of strings
  210. (thunked) ; it's system-dependent
  211. (default %base-initrd-modules))
  212. (firmware operating-system-firmware ; list of packages
  213. (default %base-firmware))
  214. (host-name operating-system-host-name) ; string
  215. (hosts-file operating-system-hosts-file ; file-like | #f
  216. (default #f))
  217. (mapped-devices operating-system-mapped-devices ; list of <mapped-device>
  218. (default '()))
  219. (file-systems operating-system-file-systems) ; list of fs
  220. (swap-devices operating-system-swap-devices ; list of strings
  221. (default '()))
  222. (users operating-system-users ; list of user accounts
  223. (default %base-user-accounts))
  224. (groups operating-system-groups ; list of user groups
  225. (default %base-groups))
  226. (skeletons operating-system-skeletons ; list of name/file-like value
  227. (default (default-skeletons)))
  228. (issue operating-system-issue ; string
  229. (default %default-issue))
  230. (packages operating-system-packages ; list of (PACKAGE OUTPUT...)
  231. (default %base-packages)) ; or just PACKAGE
  232. (timezone operating-system-timezone) ; string
  233. (locale operating-system-locale ; string
  234. (default "en_US.utf8"))
  235. (locale-definitions operating-system-locale-definitions ; list of <locale-definition>
  236. (default %default-locale-definitions))
  237. (locale-libcs operating-system-locale-libcs ; list of <packages>
  238. (default %default-locale-libcs))
  239. (name-service-switch operating-system-name-service-switch ; <name-service-switch>
  240. (default %default-nss))
  241. (essential-services operating-system-essential-services ; list of services
  242. (thunked)
  243. (default (operating-system-default-essential-services
  244. this-operating-system)))
  245. (services operating-system-user-services ; list of services
  246. (default %base-services))
  247. (pam-services operating-system-pam-services ; list of PAM services
  248. (default (base-pam-services)))
  249. (setuid-programs operating-system-setuid-programs
  250. (default %setuid-programs)) ; list of string-valued gexps
  251. (sudoers-file operating-system-sudoers-file ; file-like
  252. (default %sudoers-specification))
  253. (location operating-system-location ; <location>
  254. (default (and=> (current-source-location)
  255. source-properties->location))
  256. (innate)))
  257. (define (operating-system-kernel-arguments os root-device)
  258. "Return all the kernel arguments, including the ones not specified
  259. directly by the user."
  260. (append (bootable-kernel-arguments os root-device)
  261. (operating-system-user-kernel-arguments os)))
  262. ;;;
  263. ;;; Boot parameters
  264. ;;;
  265. (define-record-type* <boot-parameters>
  266. boot-parameters make-boot-parameters boot-parameters?
  267. (label boot-parameters-label)
  268. ;; Because we will use the 'store-device' to create the GRUB search command,
  269. ;; the 'store-device' has slightly different semantics than 'root-device'.
  270. ;; The 'store-device' can be a file system uuid, a file system label, or #f,
  271. ;; but it cannot be a device file name such as "/dev/sda3", since GRUB would
  272. ;; not understand that. The 'root-device', on the other hand, corresponds
  273. ;; exactly to the device field of the <file-system> object representing the
  274. ;; OS's root file system, so it might be a device file name like
  275. ;; "/dev/sda3". The 'store-directory-prefix' field contains #f or the store
  276. ;; file name inside the 'store-device' as it is seen by GRUB, e.g. it would
  277. ;; contain "/storefs" if the store is located in that subvolume of a btrfs
  278. ;; partition.
  279. (root-device boot-parameters-root-device)
  280. (bootloader-name boot-parameters-bootloader-name)
  281. (bootloader-menu-entries ;list of <menu-entry>
  282. boot-parameters-bootloader-menu-entries)
  283. (store-device boot-parameters-store-device)
  284. (store-mount-point boot-parameters-store-mount-point)
  285. (store-directory-prefix boot-parameters-store-directory-prefix)
  286. (store-crypto-devices boot-parameters-store-crypto-devices
  287. (default '()))
  288. (locale boot-parameters-locale)
  289. (kernel boot-parameters-kernel)
  290. (kernel-arguments boot-parameters-kernel-arguments)
  291. (initrd boot-parameters-initrd)
  292. (multiboot-modules boot-parameters-multiboot-modules))
  293. (define (ensure-not-/dev device)
  294. "If DEVICE starts with a slash, return #f. This is meant to filter out
  295. Linux device names such as /dev/sda, and to preserve GRUB device names and
  296. file system labels."
  297. (if (and (string? device) (string-prefix? "/" device))
  298. #f
  299. device))
  300. (define (read-boot-parameters port)
  301. "Read boot parameters from PORT and return the corresponding
  302. <boot-parameters> object or #f if the format is unrecognized."
  303. (define device-sexp->device
  304. (match-lambda
  305. (('uuid (? symbol? type) (? bytevector? bv))
  306. (bytevector->uuid bv type))
  307. (('file-system-label (? string? label))
  308. (file-system-label label))
  309. ((? bytevector? bv) ;old format
  310. (bytevector->uuid bv 'dce))
  311. ((? string? device)
  312. (if (string-contains device ":/")
  313. device ; nfs-root
  314. ;; It used to be that we would not distinguish between labels and
  315. ;; device names. Try to infer the right thing here.
  316. (if (string-prefix? "/" device)
  317. device
  318. (file-system-label device))))))
  319. (define uuid-sexp->uuid
  320. (match-lambda
  321. (('uuid (? symbol? type) (? bytevector? bv))
  322. (bytevector->uuid bv type))
  323. (x
  324. (warning (G_ "unrecognized uuid ~a at '~a'~%") x (port-filename port))
  325. #f)))
  326. (match (read port)
  327. (('boot-parameters ('version 0)
  328. ('label label) ('root-device root)
  329. ('kernel kernel)
  330. rest ...)
  331. (boot-parameters
  332. (label label)
  333. (root-device (device-sexp->device root))
  334. (bootloader-name
  335. (match (assq 'bootloader-name rest)
  336. ((_ args) args)
  337. (#f 'grub))) ; for compatibility reasons.
  338. (bootloader-menu-entries
  339. (match (assq 'bootloader-menu-entries rest)
  340. ((_ entries) (map sexp->menu-entry entries))
  341. (#f '())))
  342. ;; In the past, we would store the directory name of linux instead of
  343. ;; the absolute file name of its image. Detect that and correct it.
  344. (kernel (if (string=? kernel (direct-store-path kernel))
  345. (string-append kernel "/"
  346. (system-linux-image-file-name))
  347. kernel))
  348. (kernel-arguments
  349. (match (assq 'kernel-arguments rest)
  350. ((_ args) args)
  351. (#f '()))) ;the old format
  352. (initrd
  353. (match (assq 'initrd rest)
  354. (('initrd ('string-append directory file)) ;the old format
  355. (string-append directory file))
  356. (('initrd (? string? file))
  357. file)
  358. (#f #f)))
  359. (multiboot-modules
  360. (match (assq 'multiboot-modules rest)
  361. ((_ args) args)
  362. (#f '())))
  363. (locale
  364. (match (assq 'locale rest)
  365. ((_ locale) locale)
  366. (#f #f)))
  367. (store-device
  368. ;; Linux device names like "/dev/sda1" are not suitable GRUB device
  369. ;; identifiers, so we just filter them out.
  370. (ensure-not-/dev
  371. (match (assq 'store rest)
  372. (('store ('device #f) _ ...)
  373. root-device)
  374. (('store ('device device) _ ...)
  375. (device-sexp->device device))
  376. (_ ;the old format
  377. root-device))))
  378. (store-directory-prefix
  379. (match (assq 'store rest)
  380. (('store . store-data)
  381. (match (assq 'directory-prefix store-data)
  382. (('directory-prefix prefix) prefix)
  383. ;; No directory-prefix found.
  384. (_ #f)))
  385. (_
  386. ;; No store found, old format.
  387. #f)))
  388. (store-crypto-devices
  389. (match (assq 'store rest)
  390. (('store . store-data)
  391. (match (assq 'crypto-devices store-data)
  392. (('crypto-devices (devices ...))
  393. (map uuid-sexp->uuid devices))
  394. (('crypto-devices dev)
  395. (warning (G_ "unrecognized crypto-devices ~S at '~a'~%")
  396. dev (port-filename port))
  397. '())
  398. (_
  399. ;; No crypto-devices found.
  400. '())))
  401. (_
  402. ;; No store found, old format.
  403. '())))
  404. (store-mount-point
  405. (match (assq 'store rest)
  406. (('store ('device _) ('mount-point mount-point) _ ...)
  407. mount-point)
  408. (_ ;the old format
  409. "/")))))
  410. (x ;unsupported format
  411. (warning (G_ "unrecognized boot parameters at '~a'~%")
  412. (port-filename port))
  413. #f)))
  414. (define (read-boot-parameters-file system)
  415. "Read boot parameters from SYSTEM's (system or generation) \"parameters\"
  416. file and returns the corresponding <boot-parameters> object or #f if the
  417. format is unrecognized.
  418. The object has its kernel-arguments extended in order to make it bootable."
  419. (let* ((file (string-append system "/parameters"))
  420. (params (call-with-input-file file read-boot-parameters))
  421. (root (boot-parameters-root-device params)))
  422. (boot-parameters
  423. (inherit params)
  424. (kernel-arguments (append (bootable-kernel-arguments system root)
  425. (boot-parameters-kernel-arguments params))))))
  426. (define (boot-parameters->menu-entry conf)
  427. (let* ((kernel (boot-parameters-kernel conf))
  428. (multiboot-modules (boot-parameters-multiboot-modules conf))
  429. (multiboot? (pair? multiboot-modules)))
  430. (menu-entry
  431. (label (boot-parameters-label conf))
  432. (device (boot-parameters-store-device conf))
  433. (device-mount-point (boot-parameters-store-mount-point conf))
  434. (linux (and (not multiboot?) kernel))
  435. (linux-arguments (if (not multiboot?)
  436. (boot-parameters-kernel-arguments conf)
  437. '()))
  438. (initrd (boot-parameters-initrd conf))
  439. (multiboot-kernel (and multiboot? kernel))
  440. (multiboot-arguments (if multiboot?
  441. (boot-parameters-kernel-arguments conf)
  442. '()))
  443. (multiboot-modules (if multiboot?
  444. (boot-parameters-multiboot-modules conf)
  445. '())))))
  446. ;;;
  447. ;;; Services.
  448. ;;;
  449. (define (non-boot-file-system-service os)
  450. "Return the file system service for the file systems of OS that are not
  451. marked as 'needed-for-boot'."
  452. (define file-systems
  453. (remove file-system-needed-for-boot?
  454. (operating-system-file-systems os)))
  455. (define mapped-devices-for-boot
  456. (operating-system-boot-mapped-devices os))
  457. (define (device-mappings fs)
  458. (let ((device (file-system-device fs)))
  459. (if (string? device) ;title is 'device
  460. (filter (lambda (md)
  461. (any (cut string=? device <>)
  462. (map (cut string-append "/dev/mapper" <>)
  463. (mapped-device-targets md))))
  464. (operating-system-mapped-devices os))
  465. '())))
  466. (define (add-dependencies fs)
  467. ;; Add the dependencies due to device mappings to FS.
  468. (file-system
  469. (inherit fs)
  470. (dependencies
  471. (delete-duplicates
  472. (remove (cut member <> mapped-devices-for-boot)
  473. (append (device-mappings fs)
  474. (file-system-dependencies fs)))
  475. eq?))))
  476. (service file-system-service-type
  477. (map add-dependencies file-systems)))
  478. (define (mapped-device-users device file-systems)
  479. "Return the subset of FILE-SYSTEMS that use DEVICE."
  480. (let ((targets (map (cut string-append "/dev/mapper/" <>)
  481. (mapped-device-targets device))))
  482. (filter (lambda (fs)
  483. (or (member device (file-system-dependencies fs))
  484. (and (string? (file-system-device fs))
  485. (any (cut string=? (file-system-device fs) <>) targets))))
  486. file-systems)))
  487. (define (operating-system-user-mapped-devices os)
  488. "Return the subset of mapped devices that can be installed in
  489. user-land--i.e., those not needed during boot."
  490. (let ((devices (operating-system-mapped-devices os))
  491. (file-systems (operating-system-file-systems os)))
  492. (filter (lambda (md)
  493. (let ((users (mapped-device-users md file-systems)))
  494. (not (any file-system-needed-for-boot? users))))
  495. devices)))
  496. (define (operating-system-boot-mapped-devices os)
  497. "Return the subset of mapped devices that must be installed during boot,
  498. from the initrd."
  499. (let ((devices (operating-system-mapped-devices os))
  500. (file-systems (operating-system-file-systems os)))
  501. (filter (lambda (md)
  502. (let ((users (mapped-device-users md file-systems)))
  503. (any file-system-needed-for-boot? users)))
  504. devices)))
  505. (define (operating-system-bootloader-crypto-devices os)
  506. "Return the subset of mapped devices that the bootloader must open.
  507. Only devices specified by uuid are supported."
  508. (define (valid-crypto-device? dev)
  509. (or (uuid? dev)
  510. (begin
  511. (warning (G_ "\
  512. mapped-device '~a' may not be mounted by the bootloader.~%")
  513. dev)
  514. #f)))
  515. (filter-map (match-lambda
  516. ((and (= mapped-device-type type)
  517. (= mapped-device-source source))
  518. (and (eq? luks-device-mapping type)
  519. (valid-crypto-device? source)
  520. source))
  521. (_ #f))
  522. ;; XXX: Ordering is important, we trust the returned one.
  523. (operating-system-boot-mapped-devices os)))
  524. (define (device-mapping-services os)
  525. "Return the list of device-mapping services for OS as a list."
  526. (map device-mapping-service
  527. (operating-system-user-mapped-devices os)))
  528. (define (swap-services os)
  529. "Return the list of swap services for OS."
  530. (map swap-service (operating-system-swap-devices os)))
  531. (define* (system-linux-image-file-name #:optional
  532. (target (or (%current-target-system)
  533. (%current-system))))
  534. "Return the basename of the kernel image file for TARGET."
  535. (cond
  536. ((string-prefix? "arm" target) "zImage")
  537. ((string-prefix? "mips" target) "vmlinuz")
  538. ((string-prefix? "aarch64" target) "Image")
  539. (else "bzImage")))
  540. (define (operating-system-kernel-file os)
  541. "Return an object representing the absolute file name of the kernel image of
  542. OS."
  543. (if (operating-system-hurd os)
  544. (file-append (operating-system-kernel os) "/boot/gnumach")
  545. (file-append (operating-system-kernel os)
  546. "/" (system-linux-image-file-name))))
  547. (define %default-modprobe-blacklist
  548. ;; List of kernel modules to blacklist by default.
  549. '("usbmouse" ;races with bcm5974, see <https://bugs.gnu.org/35574>
  550. "usbkbd")) ;races with usbhid, see <https://issues.guix.gnu.org/35574#18>
  551. (define %default-kernel-arguments
  552. ;; Default arguments passed to the kernel.
  553. (list (string-append "modprobe.blacklist="
  554. (string-join %default-modprobe-blacklist ","))
  555. "quiet"))
  556. (define* (operating-system-directory-base-entries os)
  557. "Return the basic entries of the 'system' directory of OS for use as the
  558. value of the SYSTEM-SERVICE-TYPE service."
  559. (let* ((locale (operating-system-locale-directory os))
  560. (kernel (operating-system-kernel os))
  561. (hurd (operating-system-hurd os))
  562. (initrd (and (not hurd) (operating-system-initrd-file os)))
  563. (params (operating-system-boot-parameters-file os)))
  564. `(,@(if hurd
  565. `(("hurd" ,hurd)
  566. ("kernel" ,kernel))
  567. '())
  568. ("parameters" ,params)
  569. ,@(if initrd `(("initrd" ,initrd)) '())
  570. ("locale" ,locale)))) ;used by libc
  571. (define (operating-system-default-essential-services os)
  572. "Return the list of essential services for OS. These are special services
  573. that implement part of what's declared in OS are responsible for low-level
  574. bookkeeping."
  575. (define known-fs
  576. (map file-system-mount-point (operating-system-file-systems os)))
  577. (let* ((mappings (device-mapping-services os))
  578. (root-fs (root-file-system-service))
  579. (other-fs (non-boot-file-system-service os))
  580. (swaps (swap-services os))
  581. (procs (service user-processes-service-type))
  582. (host-name (host-name-service (operating-system-host-name os)))
  583. (entries (operating-system-directory-base-entries os)))
  584. (cons* (service system-service-type entries)
  585. (service linux-builder-service-type
  586. (linux-builder-configuration
  587. (kernel (operating-system-kernel os))
  588. (modules (operating-system-kernel-loadable-modules os))))
  589. %boot-service
  590. ;; %SHEPHERD-ROOT-SERVICE must come last so that the gexp that
  591. ;; execs shepherd comes last in the boot script (XXX). Likewise,
  592. ;; the cleanup service must come first so that its gexp runs before
  593. ;; activation code.
  594. (service cleanup-service-type #f)
  595. %activation-service
  596. %shepherd-root-service
  597. (pam-root-service (operating-system-pam-services os))
  598. (account-service (append (operating-system-accounts os)
  599. (operating-system-groups os))
  600. (operating-system-skeletons os))
  601. (operating-system-etc-service os)
  602. (service fstab-service-type
  603. (filter file-system-needed-for-boot?
  604. (operating-system-file-systems os)))
  605. (session-environment-service
  606. (operating-system-environment-variables os))
  607. host-name procs root-fs
  608. (service setuid-program-service-type
  609. (operating-system-setuid-programs os))
  610. (service profile-service-type
  611. (operating-system-packages os))
  612. other-fs
  613. (append mappings swaps
  614. ;; Add the firmware service.
  615. (list %linux-bare-metal-service
  616. (service firmware-service-type
  617. (operating-system-firmware os)))))))
  618. (define (hurd-default-essential-services os)
  619. (let ((entries (operating-system-directory-base-entries os)))
  620. (list (service system-service-type entries)
  621. %boot-service
  622. %hurd-startup-service
  623. %activation-service
  624. %shepherd-root-service
  625. (service user-processes-service-type)
  626. (account-service (append (operating-system-accounts os)
  627. (operating-system-groups os))
  628. (operating-system-skeletons os))
  629. (root-file-system-service)
  630. (service file-system-service-type '())
  631. (service fstab-service-type
  632. (filter file-system-needed-for-boot?
  633. (operating-system-file-systems os)))
  634. (pam-root-service (operating-system-pam-services os))
  635. (operating-system-etc-service os)
  636. (service setuid-program-service-type
  637. (operating-system-setuid-programs os))
  638. (service profile-service-type (operating-system-packages os)))))
  639. (define* (operating-system-services os)
  640. "Return all the services of OS, including \"essential\" services."
  641. (instantiate-missing-services
  642. (append (operating-system-user-services os)
  643. (operating-system-essential-services os))))
  644. (define (operating-system-with-gc-roots os roots)
  645. "Return a variant of OS where ROOTS are registered as GC roots."
  646. (operating-system
  647. (inherit os)
  648. ;; We use this procedure for the installation OS, which already defines GC
  649. ;; roots. Add ROOTS to those.
  650. (services (cons (simple-service 'extra-root
  651. gc-root-service-type roots)
  652. (operating-system-user-services os)))))
  653. (define (operating-system-configuration-file os)
  654. "Return the configuration file of OS, based on its 'location' field, or #f
  655. if it could not be determined."
  656. (let ((file (and=> (operating-system-location os)
  657. location-file)))
  658. (and file
  659. (or (and (string-prefix? "/" file) file)
  660. (search-path %load-path file)))))
  661. (define* (operating-system-with-provenance os
  662. #:optional
  663. (config-file
  664. (operating-system-configuration-file
  665. os)))
  666. "Return a variant of OS that stores its own provenance information,
  667. including CONFIG-FILE, if available. This is achieved by adding an instance
  668. of PROVENANCE-SERVICE-TYPE to its services."
  669. (operating-system
  670. (inherit os)
  671. (services (cons (service provenance-service-type config-file)
  672. (operating-system-user-services os)))))
  673. ;;;
  674. ;;; /etc.
  675. ;;;
  676. (define %base-firmware
  677. ;; Firmware usable by default.
  678. (list ath9k-htc-firmware
  679. openfwwf-firmware))
  680. (define %base-packages-utils
  681. ;; Default set of utilities packages.
  682. (cons* procps psmisc which
  683. (@ (gnu packages admin) shadow) ;for 'passwd'
  684. guile-3.0-latest
  685. ;; The packages below are also in %FINAL-INPUTS, so take them from
  686. ;; there to avoid duplication.
  687. (list bash coreutils findutils grep sed
  688. diffutils patch gawk tar gzip bzip2 xz lzip)))
  689. (define %base-packages-linux
  690. ;; Default set of linux specific packages.
  691. (list pciutils usbutils
  692. util-linux+udev
  693. ;; Get 'insmod' & co. from kmod, not module-init-tools, since udev
  694. ;; already depends on it anyway.
  695. kmod eudev))
  696. (define %base-packages-interactive
  697. ;; Default set of common interactive packages.
  698. (list less mg nano
  699. nvi
  700. man-db
  701. info-reader ;the standalone Info reader (no Perl)
  702. bash-completion
  703. kbd
  704. ;; The 'sudo' command is already in %SETUID-PROGRAMS, but we also
  705. ;; want the other commands and the man pages (notably because
  706. ;; auto-completion in Emacs shell relies on man pages.)
  707. sudo
  708. guile-readline guile-colorized))
  709. (define %base-packages-networking
  710. ;; Default set of networking packages.
  711. (list inetutils isc-dhcp
  712. iproute
  713. wget
  714. ;; wireless-tools is deprecated in favor of iw, but it's still what
  715. ;; many people are familiar with, so keep it around.
  716. iw wireless-tools))
  717. (define %base-packages-disk-utilities
  718. ;; A well-rounded set of packages for interacting with disks, partitions
  719. ;; and filesystems.
  720. (list parted gptfdisk ddrescue
  721. ;; We used to provide fdisk from GNU fdisk, but as of version 2.0.0a
  722. ;; it pulls Guile 1.8, which takes unreasonable space; furthermore
  723. ;; util-linux's fdisk is already available, in %base-packages-linux.
  724. cryptsetup mdadm
  725. dosfstools
  726. btrfs-progs
  727. f2fs-tools
  728. jfsutils))
  729. (define %base-packages
  730. ;; Default set of packages globally visible. It should include anything
  731. ;; required for basic administrator tasks.
  732. (append (list e2fsprogs)
  733. %base-packages-interactive
  734. %base-packages-linux
  735. %base-packages-networking
  736. %base-packages-utils))
  737. (define %default-issue
  738. ;; Default contents for /etc/issue.
  739. "
  740. This is the GNU system. Welcome.\n")
  741. (define (local-host-aliases host-name)
  742. "Return aliases for HOST-NAME, to be used in /etc/hosts."
  743. (string-append "127.0.0.1 localhost " host-name "\n"
  744. "::1 localhost " host-name "\n"))
  745. (define (default-/etc/hosts host-name)
  746. "Return the default /etc/hosts file."
  747. (plain-file "hosts" (local-host-aliases host-name)))
  748. (define (validated-sudoers-file file)
  749. "Return a copy of FILE, a sudoers file, after checking that it is
  750. syntactically correct."
  751. (computed-file "sudoers"
  752. (with-imported-modules '((guix build utils))
  753. #~(begin
  754. (use-modules (guix build utils))
  755. (invoke #+(file-append sudo "/sbin/visudo")
  756. "--check" "--file" #$file)
  757. (copy-file #$file #$output)))))
  758. (define* (operating-system-etc-service os)
  759. "Return a <service> that builds a directory containing the static part of
  760. the /etc directory."
  761. (let* ((login.defs
  762. (plain-file "login.defs"
  763. (string-append
  764. "# Default paths for non-login shells started by su(1).\n"
  765. "ENV_PATH /run/setuid-programs:"
  766. "/run/current-system/profile/bin:"
  767. "/run/current-system/profile/sbin\n"
  768. "ENV_SUPATH /run/setuid-programs:"
  769. "/run/current-system/profile/bin:"
  770. "/run/current-system/profile/sbin\n")))
  771. (hurd (operating-system-hurd os))
  772. (issue (plain-file "issue" (operating-system-issue os)))
  773. (nsswitch (operating-system-name-service-switch os))
  774. (nsswitch (and nsswitch
  775. (plain-file "nsswitch.conf"
  776. (name-service-switch->string nsswitch))))
  777. (sudoers (operating-system-sudoers-file os))
  778. ;; Startup file for POSIX-compliant login shells, which set system-wide
  779. ;; environment variables.
  780. (profile (mixed-text-file "profile" "\
  781. # Crucial variables that could be missing in the profiles' 'etc/profile'
  782. # because they would require combining both profiles.
  783. # FIXME: See <http://bugs.gnu.org/20255>.
  784. export MANPATH=$HOME/.guix-profile/share/man:/run/current-system/profile/share/man
  785. export INFOPATH=$HOME/.guix-profile/share/info:/run/current-system/profile/share/info
  786. export XDG_DATA_DIRS=$HOME/.guix-profile/share:/run/current-system/profile/share
  787. export XDG_CONFIG_DIRS=$HOME/.guix-profile/etc/xdg:/run/current-system/profile/etc/xdg
  788. # Make sure libXcursor finds cursors installed into user or system profiles. See <http://bugs.gnu.org/24445>
  789. export XCURSOR_PATH=$HOME/.icons:$HOME/.guix-profile/share/icons:/run/current-system/profile/share/icons
  790. # Ignore the default value of 'PATH'.
  791. unset PATH
  792. # Load the system profile's settings.
  793. GUIX_PROFILE=/run/current-system/profile ; \\
  794. . /run/current-system/profile/etc/profile
  795. # Since 'lshd' does not use pam_env, /etc/environment must be explicitly
  796. # loaded when someone logs in via SSH. See <http://bugs.gnu.org/22175>.
  797. # We need 'PATH' to be defined here, for 'cat' and 'cut'. Do this before
  798. # reading the user's 'etc/profile' to allow variables to be overridden.
  799. if [ -f /etc/environment -a -n \"$SSH_CLIENT\" \\
  800. -a -z \"$LINUX_MODULE_DIRECTORY\" ]
  801. then
  802. . /etc/environment
  803. export `cat /etc/environment | cut -d= -f1`
  804. fi
  805. # Arrange so that ~/.config/guix/current comes first.
  806. for profile in \"$HOME/.guix-profile\" \"$HOME/.config/guix/current\"
  807. do
  808. if [ -f \"$profile/etc/profile\" ]
  809. then
  810. # Load the user profile's settings.
  811. GUIX_PROFILE=\"$profile\" ; \\
  812. . \"$profile/etc/profile\"
  813. else
  814. # At least define this one so that basic things just work
  815. # when the user installs their first package.
  816. export PATH=\"$profile/bin:$PATH\"
  817. fi
  818. done
  819. # Prepend setuid programs.
  820. export PATH=/run/setuid-programs:$PATH
  821. # Arrange so that ~/.config/guix/current/share/info comes first.
  822. export INFOPATH=\"$HOME/.config/guix/current/share/info:$INFOPATH\"
  823. # Set the umask, notably for users logging in via 'lsh'.
  824. # See <http://bugs.gnu.org/22650>.
  825. umask 022
  826. # Allow Hunspell-based applications (IceCat, LibreOffice, etc.) to
  827. # find dictionaries.
  828. export DICPATH=\"$HOME/.guix-profile/share/hunspell:/run/current-system/profile/share/hunspell\"
  829. # Allow GStreamer-based applications to find plugins.
  830. export GST_PLUGIN_PATH=\"$HOME/.guix-profile/lib/gstreamer-1.0\"
  831. if [ -n \"$BASH_VERSION\" -a -f /etc/bashrc ]
  832. then
  833. # Load Bash-specific initialization code.
  834. . /etc/bashrc
  835. fi
  836. "))
  837. (bashrc (plain-file "bashrc" "\
  838. # Bash-specific initialization.
  839. # The 'bash-completion' package.
  840. if [ -f /run/current-system/profile/etc/profile.d/bash_completion.sh ]
  841. then
  842. # Bash-completion sources ~/.bash_completion. It installs a dynamic
  843. # completion loader that searches its own completion files as well
  844. # as those in ~/.guix-profile and /run/current-system/profile.
  845. source /run/current-system/profile/etc/profile.d/bash_completion.sh
  846. fi\n")))
  847. (etc-service
  848. `(("services" ,(file-append net-base "/etc/services"))
  849. ("protocols" ,(file-append net-base "/etc/protocols"))
  850. ("rpc" ,(file-append net-base "/etc/rpc"))
  851. ("login.defs" ,#~#$login.defs)
  852. ("issue" ,#~#$issue)
  853. ,@(if nsswitch `(("nsswitch.conf" ,#~#$nsswitch)) '())
  854. ("profile" ,#~#$profile)
  855. ("bashrc" ,#~#$bashrc)
  856. ("hosts" ,#~#$(or (operating-system-hosts-file os)
  857. (default-/etc/hosts (operating-system-host-name os))))
  858. ;; Write the operating-system-host-name to /etc/hostname to prevent
  859. ;; NetworkManager from changing the system's hostname when connecting
  860. ;; to certain networks. Some discussion at
  861. ;; https://lists.gnu.org/archive/html/help-guix/2017-09/msg00037.html
  862. ("hostname" ,(plain-file "hostname" (operating-system-host-name os)))
  863. ;; Some programs (e.g., GLib) look at /etc/timezone to find the
  864. ;; name of the current timezone. For details, see
  865. ;; https://lists.gnu.org/archive/html/guix-devel/2019-07/msg00166.html
  866. ("timezone" ,(plain-file "timezone" (operating-system-timezone os)))
  867. ("localtime" ,(file-append tzdata "/share/zoneinfo/"
  868. (operating-system-timezone os)))
  869. ,@(if sudoers
  870. `(("sudoers" ,(validated-sudoers-file sudoers)))
  871. '())
  872. ,@(if hurd
  873. `(("login" ,(file-append hurd "/etc/login"))
  874. ("motd" ,(file-append hurd "/etc/motd"))
  875. ("ttys" ,(file-append hurd "/etc/ttys")))
  876. '())))))
  877. (define %root-account
  878. ;; Default root account.
  879. (user-account
  880. (name "root")
  881. (password "")
  882. (uid 0) (group "root")
  883. (comment "System administrator")
  884. (home-directory "/root")))
  885. (define (operating-system-accounts os)
  886. "Return the user accounts for OS, including an obligatory 'root' account,
  887. and excluding accounts requested by services."
  888. ;; Make sure there's a root account.
  889. (if (find (lambda (user)
  890. (and=> (user-account-uid user) zero?))
  891. (operating-system-users os))
  892. (operating-system-users os)
  893. (cons %root-account (operating-system-users os))))
  894. (define (maybe-string->file file-name thing)
  895. "If THING is a string, return a <plain-file> with THING as its content.
  896. Otherwise just return THING.
  897. This is for backward-compatibility of fields that used to be strings and are
  898. now file-like objects.."
  899. (match thing
  900. ((? string?)
  901. (warning (G_ "using a string for file '~a' is deprecated; \
  902. use 'plain-file' instead~%")
  903. file-name)
  904. (plain-file file-name thing))
  905. (x
  906. x)))
  907. (define (maybe-file->monadic file-name thing)
  908. "If THING is a value in %STORE-MONAD, return it as is; otherwise return
  909. THING in the %STORE-MONAD.
  910. This is for backward-compatibility of fields that used to be monadic values
  911. and are now file-like objects."
  912. (with-monad %store-monad
  913. (match thing
  914. ((? procedure?)
  915. (warning (G_ "using a monadic value for '~a' is deprecated; \
  916. use 'plain-file' instead~%")
  917. file-name)
  918. thing)
  919. (x
  920. (return x)))))
  921. (define (operating-system-etc-directory os)
  922. "Return that static part of the /etc directory of OS."
  923. (etc-directory
  924. (fold-services (operating-system-services os)
  925. #:target-type etc-service-type)))
  926. (define (operating-system-environment-variables os)
  927. "Return the environment variables of OS for
  928. @var{session-environment-service-type}, to be used in @file{/etc/environment}."
  929. `(("LANG" . ,(operating-system-locale os))
  930. ;; Note: No need to set 'TZ' since (1) we provide /etc/localtime, and (2)
  931. ;; it doesn't work for setuid binaries. See <https://bugs.gnu.org/29212>.
  932. ("TZDIR" . ,(file-append tzdata "/share/zoneinfo"))
  933. ;; Tell 'modprobe' & co. where to look for modules.
  934. ("LINUX_MODULE_DIRECTORY" . "/run/booted-system/kernel/lib/modules")
  935. ;; These variables are honored by OpenSSL (libssl) and Git.
  936. ("SSL_CERT_DIR" . "/etc/ssl/certs")
  937. ("SSL_CERT_FILE" . "/etc/ssl/certs/ca-certificates.crt")
  938. ("GIT_SSL_CAINFO" . "/etc/ssl/certs/ca-certificates.crt")
  939. ;; 'GTK_DATA_PREFIX' must name one directory where GTK+ themes are
  940. ;; searched for.
  941. ("GTK_DATA_PREFIX" . "/run/current-system/profile")
  942. ;; By default, applications that use D-Bus, such as Emacs, abort at startup
  943. ;; when /etc/machine-id is missing. Make sure these warnings are non-fatal.
  944. ("DBUS_FATAL_WARNINGS" . "0")
  945. ;; XXX: Normally we wouldn't need to do this, but our glibc@2.23 package
  946. ;; used to look things up in 'PREFIX/lib/locale' instead of
  947. ;; '/run/current-system/locale' as was intended. Keep this hack around so
  948. ;; that people who still have glibc@2.23-using packages in their profiles
  949. ;; can use them correctly.
  950. ;; TODO: Remove when glibc@2.23 is long gone.
  951. ("GUIX_LOCPATH" . "/run/current-system/locale")))
  952. (define %setuid-programs
  953. ;; Default set of setuid-root programs.
  954. (let ((shadow (@ (gnu packages admin) shadow)))
  955. (list (file-append shadow "/bin/passwd")
  956. (file-append shadow "/bin/sg")
  957. (file-append shadow "/bin/su")
  958. (file-append shadow "/bin/newgrp")
  959. (file-append shadow "/bin/newuidmap")
  960. (file-append shadow "/bin/newgidmap")
  961. (file-append inetutils "/bin/ping")
  962. (file-append inetutils "/bin/ping6")
  963. (file-append sudo "/bin/sudo")
  964. (file-append sudo "/bin/sudoedit")
  965. (file-append fuse "/bin/fusermount")
  966. ;; To allow mounts with the "user" option, "mount" and "umount" must
  967. ;; be setuid-root.
  968. (file-append util-linux "/bin/mount")
  969. (file-append util-linux "/bin/umount"))))
  970. (define %sudoers-specification
  971. ;; Default /etc/sudoers contents: 'root' and all members of the 'wheel'
  972. ;; group can do anything. See
  973. ;; <http://www.sudo.ws/sudo/man/1.8.10/sudoers.man.html>.
  974. ;; TODO: Add a declarative API.
  975. (plain-file "sudoers" "\
  976. root ALL=(ALL) ALL
  977. %wheel ALL=(ALL) ALL\n"))
  978. (define* (operating-system-activation-script os)
  979. "Return the activation script for OS---i.e., the code that \"activates\" the
  980. stateful part of OS, including user accounts and groups, special directories,
  981. etc."
  982. (let* ((services (operating-system-services os))
  983. (activation (fold-services services
  984. #:target-type activation-service-type)))
  985. (activation-service->script activation)))
  986. (define* (operating-system-boot-script os)
  987. "Return the boot script for OS---i.e., the code started by the initrd once
  988. we're running in the final root."
  989. (let* ((services (operating-system-services os))
  990. (boot (fold-services services #:target-type boot-service-type)))
  991. (service-value boot)))
  992. (define (operating-system-user-accounts os)
  993. "Return the list of user accounts of OS."
  994. (let* ((services (operating-system-services os))
  995. (account (fold-services services
  996. #:target-type account-service-type)))
  997. (filter user-account?
  998. (service-value account))))
  999. (define (operating-system-shepherd-service-names os)
  1000. "Return the list of Shepherd service names for OS."
  1001. (append-map shepherd-service-provision
  1002. (shepherd-configuration-services
  1003. (service-value
  1004. (fold-services (operating-system-services os)
  1005. #:target-type
  1006. shepherd-root-service-type)))))
  1007. (define* (operating-system-derivation os)
  1008. "Return a derivation that builds OS."
  1009. (let* ((services (operating-system-services os))
  1010. (system (fold-services services)))
  1011. ;; SYSTEM contains the derivation as a monadic value.
  1012. (service-value system)))
  1013. (define* (operating-system-profile os)
  1014. "Return a derivation that builds the system profile of OS."
  1015. (mlet* %store-monad
  1016. ((services -> (operating-system-services os))
  1017. (profile (fold-services services
  1018. #:target-type profile-service-type)))
  1019. (match profile
  1020. (("profile" profile)
  1021. (return profile)))))
  1022. (define (operating-system-root-file-system os)
  1023. "Return the root file system of OS."
  1024. (or (find (lambda (fs)
  1025. (string=? "/" (file-system-mount-point fs)))
  1026. (operating-system-file-systems os))
  1027. (raise (condition
  1028. (&message (message "missing root file system"))
  1029. (&error-location
  1030. (location (operating-system-location os)))))))
  1031. (define (operating-system-initrd-file os)
  1032. "Return a gexp denoting the initrd file of OS."
  1033. (define boot-file-systems
  1034. (filter file-system-needed-for-boot?
  1035. (operating-system-file-systems os)))
  1036. (define mapped-devices
  1037. (operating-system-boot-mapped-devices os))
  1038. (define make-initrd
  1039. (operating-system-initrd os))
  1040. (make-initrd boot-file-systems
  1041. #:linux (operating-system-kernel os)
  1042. #:linux-modules
  1043. (operating-system-initrd-modules os)
  1044. #:mapped-devices mapped-devices
  1045. #:keyboard-layout (operating-system-keyboard-layout os)))
  1046. (define* (operating-system-uuid os #:optional (type 'dce))
  1047. "Compute UUID object with a deterministic \"UUID\" for OS, of the given
  1048. TYPE (one of 'iso9660 or 'dce). Return a UUID object."
  1049. ;; Note: For this to be deterministic, we must not hash things that contains
  1050. ;; (directly or indirectly) procedures, for example. That rules out
  1051. ;; anything that contains gexps, thunk or delayed record fields, etc.
  1052. (define service-name
  1053. (compose service-type-name service-kind))
  1054. (define (file-system-digest fs)
  1055. ;; Return a hashable digest that does not contain 'dependencies' since
  1056. ;; this field can contain procedures.
  1057. (let ((device (file-system-device fs)))
  1058. (list (file-system-mount-point fs)
  1059. (file-system-type fs)
  1060. (file-system-device->string device)
  1061. (file-system-options fs))))
  1062. (if (eq? type 'iso9660)
  1063. (let ((pad (compose (cut string-pad <> 2 #\0)
  1064. number->string))
  1065. (h (hash (map service-name (operating-system-services os))
  1066. 3600)))
  1067. (bytevector->uuid
  1068. (string->iso9660-uuid
  1069. (string-append "1970-01-01-"
  1070. (pad (hash (operating-system-host-name os) 24)) "-"
  1071. (pad (quotient h 60)) "-"
  1072. (pad (modulo h 60)) "-"
  1073. (pad (hash (map file-system-digest
  1074. (operating-system-file-systems os))
  1075. 100))))
  1076. 'iso9660))
  1077. (bytevector->uuid
  1078. (uint-list->bytevector
  1079. (list (hash (map file-system-digest
  1080. (operating-system-file-systems os))
  1081. (- (expt 2 32) 1))
  1082. (hash (operating-system-host-name os)
  1083. (- (expt 2 32) 1))
  1084. (hash (map service-name (operating-system-services os))
  1085. (- (expt 2 32) 1))
  1086. (hash (map file-system-digest (operating-system-file-systems os))
  1087. (- (expt 2 32) 1)))
  1088. (endianness little)
  1089. 4)
  1090. type)))
  1091. (define (locale-name->definition* name)
  1092. "Variant of 'locale-name->definition' that raises an error upon failure."
  1093. (match (locale-name->definition name)
  1094. (#f
  1095. (raise (formatted-message (G_ "~a: invalid locale name") name)))
  1096. (def def)))
  1097. (define (operating-system-locale-directory os)
  1098. "Return the directory containing the locales compiled for the definitions
  1099. listed in OS. The C library expects to find it under
  1100. /run/current-system/locale."
  1101. (define name
  1102. (operating-system-locale os))
  1103. (define definitions
  1104. ;; While we're at it, check whether NAME is defined and add it if needed.
  1105. (if (member name (map locale-definition-name
  1106. (operating-system-locale-definitions os)))
  1107. (operating-system-locale-definitions os)
  1108. (cons (locale-name->definition* name)
  1109. (operating-system-locale-definitions os))))
  1110. (locale-directory definitions
  1111. #:libcs (operating-system-locale-libcs os)))
  1112. (define* (kernel->boot-label kernel #:key hurd)
  1113. "Return a label for the bootloader menu entry that boots KERNEL."
  1114. (cond ((package? hurd)
  1115. (string-append "GNU with the "
  1116. (string-titlecase (package-name hurd)) " "
  1117. (package-version hurd)))
  1118. ((package? kernel)
  1119. (string-append "GNU with "
  1120. (string-titlecase (package-name kernel)) " "
  1121. (package-version kernel)))
  1122. ((inferior-package? kernel)
  1123. (string-append "GNU with "
  1124. (string-titlecase (inferior-package-name kernel)) " "
  1125. (inferior-package-version kernel)))
  1126. (else "GNU")))
  1127. (define (operating-system-default-label os)
  1128. "Return the default label for OS, as it will appear in the bootloader menu
  1129. entry."
  1130. (kernel->boot-label (operating-system-kernel os)
  1131. #:hurd (operating-system-hurd os)))
  1132. (define (store-file-system file-systems)
  1133. "Return the file system object among FILE-SYSTEMS that contains the store."
  1134. (match (filter (lambda (fs)
  1135. (and (file-system-mount? fs)
  1136. (not (memq 'bind-mount (file-system-flags fs)))
  1137. (string-prefix? (file-system-mount-point fs)
  1138. (%store-prefix))))
  1139. file-systems)
  1140. ((and candidates (head . tail))
  1141. (reduce (lambda (fs1 fs2)
  1142. (if (> (string-length (file-system-mount-point fs1))
  1143. (string-length (file-system-mount-point fs2)))
  1144. fs1
  1145. fs2))
  1146. head
  1147. candidates))))
  1148. (define (operating-system-store-file-system os)
  1149. "Return the file system that contains the store of OS."
  1150. (store-file-system (operating-system-file-systems os)))
  1151. (define* (operating-system-bootcfg os #:optional (old-entries '()))
  1152. "Return the bootloader configuration file for OS. Use OLD-ENTRIES,
  1153. a list of <menu-entry>, to populate the \"old entries\" menu."
  1154. (let* ((file-systems (operating-system-file-systems os))
  1155. (root-fs (operating-system-root-file-system os))
  1156. (root-device (file-system-device root-fs))
  1157. (locale (operating-system-locale os))
  1158. (crypto-devices (operating-system-bootloader-crypto-devices os))
  1159. (params (operating-system-boot-parameters
  1160. os root-device
  1161. #:system-kernel-arguments? #t))
  1162. (entry (boot-parameters->menu-entry params))
  1163. (bootloader-conf (operating-system-bootloader os)))
  1164. (define generate-config-file
  1165. (bootloader-configuration-file-generator
  1166. (bootloader-configuration-bootloader bootloader-conf)))
  1167. (generate-config-file bootloader-conf (list entry)
  1168. #:old-entries old-entries
  1169. #:locale locale
  1170. #:store-crypto-devices crypto-devices
  1171. #:store-directory-prefix
  1172. (btrfs-store-subvolume-file-name file-systems))))
  1173. (define (operating-system-multiboot-modules os)
  1174. (if (operating-system-hurd os) (hurd-multiboot-modules os) '()))
  1175. (define (hurd-multiboot-modules os)
  1176. (let* ((hurd (operating-system-hurd os))
  1177. (root-file-system-command
  1178. (list (file-append hurd "/hurd/ext2fs.static")
  1179. "ext2fs"
  1180. "--multiboot-command-line='${kernel-command-line}'"
  1181. "--host-priv-port='${host-port}'"
  1182. "--device-master-port='${device-port}'"
  1183. "--exec-server-task='${exec-task}'"
  1184. "--store-type=typed"
  1185. "--x-xattr-translator-records"
  1186. "'${root}'" "'$(task-create)'" "'$(task-resume)'"))
  1187. (target (%current-target-system))
  1188. (libc (if target
  1189. (with-parameters ((%current-target-system #f))
  1190. ;; TODO: cross-libc has extra patches for the Hurd;
  1191. ;; remove in next rebuild cycle
  1192. (cross-libc target))
  1193. glibc))
  1194. (exec-server-command
  1195. (list (file-append libc "/lib/ld.so.1") "exec"
  1196. (file-append hurd "/hurd/exec") "'$(exec-task=task-create)'")))
  1197. (list root-file-system-command exec-server-command)))
  1198. (define* (operating-system-boot-parameters os root-device
  1199. #:key system-kernel-arguments?)
  1200. "Return a monadic <boot-parameters> record that describes the boot
  1201. parameters of OS. When SYSTEM-KERNEL-ARGUMENTS? is true, add kernel arguments
  1202. such as '--root' and '--load' to <boot-parameters>."
  1203. (let* ((initrd (and (not (operating-system-hurd os))
  1204. (operating-system-initrd-file os)))
  1205. (store (operating-system-store-file-system os))
  1206. (file-systems (operating-system-file-systems os))
  1207. (crypto-devices (operating-system-bootloader-crypto-devices os))
  1208. (locale (operating-system-locale os))
  1209. (bootloader (bootloader-configuration-bootloader
  1210. (operating-system-bootloader os)))
  1211. (bootloader-name (bootloader-name bootloader))
  1212. (label (operating-system-label os))
  1213. (multiboot-modules (operating-system-multiboot-modules os)))
  1214. (boot-parameters
  1215. (label label)
  1216. (root-device root-device)
  1217. (kernel (operating-system-kernel-file os))
  1218. (kernel-arguments
  1219. (if system-kernel-arguments?
  1220. (operating-system-kernel-arguments os root-device)
  1221. (operating-system-user-kernel-arguments os)))
  1222. (initrd initrd)
  1223. (multiboot-modules multiboot-modules)
  1224. (bootloader-name bootloader-name)
  1225. (bootloader-menu-entries
  1226. (bootloader-configuration-menu-entries (operating-system-bootloader os)))
  1227. (locale locale)
  1228. (store-device (ensure-not-/dev (file-system-device store)))
  1229. (store-directory-prefix (btrfs-store-subvolume-file-name file-systems))
  1230. (store-crypto-devices crypto-devices)
  1231. (store-mount-point (file-system-mount-point store)))))
  1232. (define (device->sexp device)
  1233. "Serialize DEVICE as an sexp (really, as an object with a read syntax.)"
  1234. (match device
  1235. ((? uuid? uuid)
  1236. `(uuid ,(uuid-type uuid) ,(uuid-bytevector uuid)))
  1237. ((? file-system-label? label)
  1238. `(file-system-label ,(file-system-label->string label)))
  1239. (_
  1240. device)))
  1241. (define* (operating-system-boot-parameters-file os
  1242. #:key system-kernel-arguments?)
  1243. "Return a file that describes the boot parameters of OS. The primary use of
  1244. this file is the reconstruction of GRUB menu entries for old configurations.
  1245. When SYSTEM-KERNEL-ARGUMENTS? is true, add kernel arguments such as '--root'
  1246. and '--load' to the returned file (since the returned file is then usually
  1247. stored into the content-addressed \"system\" directory, it's usually not a
  1248. good idea to give it because the content hash would change by the content hash
  1249. being stored into the \"parameters\" file)."
  1250. (let* ((root (operating-system-root-file-system os))
  1251. (device (file-system-device root))
  1252. (params (operating-system-boot-parameters
  1253. os device
  1254. #:system-kernel-arguments?
  1255. system-kernel-arguments?)))
  1256. (scheme-file "parameters"
  1257. #~(boot-parameters
  1258. (version 0)
  1259. (label #$(boot-parameters-label params))
  1260. (root-device
  1261. #$(device->sexp
  1262. (boot-parameters-root-device params)))
  1263. (kernel #$(boot-parameters-kernel params))
  1264. (kernel-arguments
  1265. #$(boot-parameters-kernel-arguments params))
  1266. #$@(if (boot-parameters-initrd params)
  1267. #~((initrd #$(boot-parameters-initrd params)))
  1268. #~())
  1269. #$@(if (pair? (boot-parameters-multiboot-modules params))
  1270. #~((multiboot-modules
  1271. #$(boot-parameters-multiboot-modules params)))
  1272. #~())
  1273. (bootloader-name #$(boot-parameters-bootloader-name params))
  1274. (bootloader-menu-entries
  1275. #$(map menu-entry->sexp
  1276. (or (and=> (operating-system-bootloader os)
  1277. bootloader-configuration-menu-entries)
  1278. '())))
  1279. (locale #$(boot-parameters-locale params))
  1280. (store
  1281. (device
  1282. #$(device->sexp (boot-parameters-store-device params)))
  1283. (mount-point #$(boot-parameters-store-mount-point
  1284. params))
  1285. (directory-prefix
  1286. #$(boot-parameters-store-directory-prefix params))
  1287. (crypto-devices
  1288. #$(map device->sexp
  1289. (boot-parameters-store-crypto-devices params)))))
  1290. #:set-load-path? #f)))
  1291. (define-gexp-compiler (operating-system-compiler (os <operating-system>)
  1292. system target)
  1293. ((store-lift
  1294. (lambda (store)
  1295. ;; XXX: This is not super elegant but we can't pass SYSTEM and TARGET to
  1296. ;; 'operating-system-derivation'.
  1297. (run-with-store store (operating-system-derivation os)
  1298. #:system system
  1299. #:target target)))))
  1300. ;;; system.scm ends here