base.scm 144 KB

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