base.scm 122 KB

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