xorg.scm 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 Andy Wingo <wingo@igalia.com>
  3. ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
  4. ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
  5. ;;; Copyright © 2018, 2019 Timothy Sample <samplet@ngyro.com>
  6. ;;; Copyright © 2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  7. ;;; Copyright © 2019 Tim Gesthuizen <tim.gesthuizen@yahoo.de>
  8. ;;; Copyright © 2020 shtwzrd <shtwzrd@protonmail.com>
  9. ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
  10. ;;; Copyright © 2020 Alex Griffin <a@ajgrf.com>
  11. ;;;
  12. ;;; This file is part of GNU Guix.
  13. ;;;
  14. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  15. ;;; under the terms of the GNU General Public License as published by
  16. ;;; the Free Software Foundation; either version 3 of the License, or (at
  17. ;;; your option) any later version.
  18. ;;;
  19. ;;; GNU Guix is distributed in the hope that it will be useful, but
  20. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  21. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. ;;; GNU General Public License for more details.
  23. ;;;
  24. ;;; You should have received a copy of the GNU General Public License
  25. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  26. (define-module (gnu services xorg)
  27. #:use-module (gnu artwork)
  28. #:use-module (gnu services)
  29. #:use-module (gnu services shepherd)
  30. #:use-module (gnu system pam)
  31. #:use-module (gnu system keyboard)
  32. #:use-module (gnu services base)
  33. #:use-module (gnu services dbus)
  34. #:use-module (gnu packages base)
  35. #:use-module (gnu packages guile)
  36. #:use-module (gnu packages xorg)
  37. #:use-module (gnu packages fonts)
  38. #:use-module (gnu packages gl)
  39. #:use-module (gnu packages glib)
  40. #:use-module (gnu packages display-managers)
  41. #:use-module (gnu packages freedesktop)
  42. #:use-module (gnu packages gnustep)
  43. #:use-module (gnu packages gnome)
  44. #:use-module (gnu packages admin)
  45. #:use-module (gnu packages bash)
  46. #:use-module (gnu system shadow)
  47. #:use-module (guix build-system trivial)
  48. #:use-module (guix gexp)
  49. #:use-module (guix store)
  50. #:use-module (guix packages)
  51. #:use-module (guix derivations)
  52. #:use-module (guix records)
  53. #:use-module (guix deprecation)
  54. #:use-module (srfi srfi-1)
  55. #:use-module (srfi srfi-9)
  56. #:use-module (srfi srfi-26)
  57. #:use-module (ice-9 match)
  58. #:export (xorg-configuration
  59. xorg-configuration?
  60. xorg-configuration-modules
  61. xorg-configuration-fonts
  62. xorg-configuration-drivers
  63. xorg-configuration-resolutions
  64. xorg-configuration-extra-config
  65. xorg-configuration-server
  66. xorg-configuration-server-arguments
  67. %default-xorg-modules
  68. %default-xorg-fonts
  69. %default-xorg-server-arguments
  70. xorg-wrapper
  71. xorg-start-command
  72. xinitrc
  73. xorg-server-service-type
  74. %default-slim-theme
  75. %default-slim-theme-name
  76. slim-configuration
  77. slim-configuration?
  78. slim-configuration-slim
  79. slim-configuration-allow-empty-passwords?
  80. slim-configuration-auto-login?
  81. slim-configuration-default-user
  82. slim-configuration-theme
  83. slim-configuration-theme-name
  84. slim-configuration-xauth
  85. slim-configuration-shepherd
  86. slim-configuration-auto-login-session
  87. slim-configuration-xorg
  88. slim-configuration-display
  89. slim-configuration-vt
  90. slim-configuration-sessreg
  91. slim-service-type
  92. screen-locker
  93. screen-locker?
  94. screen-locker-service-type
  95. screen-locker-service
  96. localed-configuration
  97. localed-configuration?
  98. localed-service-type
  99. gdm-configuration
  100. gdm-service-type
  101. handle-xorg-configuration
  102. set-xorg-configuration))
  103. ;;; Commentary:
  104. ;;;
  105. ;;; Services that relate to the X Window System.
  106. ;;;
  107. ;;; Code:
  108. (define %default-xorg-modules
  109. ;; Default list of modules loaded by the server. When multiple drivers
  110. ;; match, the first one in the list is loaded.
  111. (list xf86-video-vesa
  112. xf86-video-fbdev
  113. xf86-video-amdgpu
  114. xf86-video-ati
  115. xf86-video-cirrus
  116. xf86-video-intel
  117. xf86-video-mach64
  118. xf86-video-nouveau
  119. xf86-video-nv
  120. xf86-video-sis
  121. ;; Libinput is the new thing and is recommended over evdev/synaptics:
  122. ;; <http://who-t.blogspot.fr/2015/01/xf86-input-libinput-compatibility-with.html>.
  123. xf86-input-libinput
  124. xf86-input-evdev
  125. xf86-input-keyboard
  126. xf86-input-mouse
  127. xf86-input-synaptics))
  128. (define %default-xorg-fonts
  129. ;; Default list of fonts available to the X server.
  130. (list (file-append font-alias "/share/fonts/X11/75dpi")
  131. (file-append font-alias "/share/fonts/X11/100dpi")
  132. (file-append font-alias "/share/fonts/X11/misc")
  133. (file-append font-alias "/share/fonts/X11/cyrillic")
  134. (file-append font-misc-misc ;default fonts for xterm
  135. "/share/fonts/X11/misc")
  136. (file-append font-adobe75dpi "/share/fonts/X11/75dpi")))
  137. (define %default-xorg-server-arguments
  138. ;; Default command-line arguments for X.
  139. '("-nolisten" "tcp"))
  140. ;; Configuration of an Xorg server.
  141. (define-record-type* <xorg-configuration>
  142. xorg-configuration make-xorg-configuration
  143. xorg-configuration?
  144. (modules xorg-configuration-modules ;list of packages
  145. ; filter out modules not supported on current system
  146. (default (filter
  147. (lambda (p)
  148. (member (%current-system)
  149. (package-supported-systems p)))
  150. %default-xorg-modules)))
  151. (fonts xorg-configuration-fonts ;list of packges
  152. (default %default-xorg-fonts))
  153. (drivers xorg-configuration-drivers ;list of strings
  154. (default '()))
  155. (resolutions xorg-configuration-resolutions ;list of tuples
  156. (default '()))
  157. (keyboard-layout xorg-configuration-keyboard-layout ;#f | <keyboard-layout>
  158. (default #f))
  159. (extra-config xorg-configuration-extra-config ;list of strings
  160. (default '()))
  161. (server xorg-configuration-server ;package
  162. (default xorg-server))
  163. (server-arguments xorg-configuration-server-arguments ;list of strings
  164. (default %default-xorg-server-arguments)))
  165. (define (xorg-configuration->file config)
  166. "Compute an Xorg configuration file corresponding to CONFIG, an
  167. <xorg-configuration> record."
  168. (let ((xorg-server (xorg-configuration-server config)))
  169. (define all-modules
  170. ;; 'xorg-server' provides 'fbdevhw.so' etc.
  171. (append (xorg-configuration-modules config)
  172. (list xorg-server)))
  173. (define build
  174. #~(begin
  175. (use-modules (ice-9 match)
  176. (srfi srfi-1)
  177. (srfi srfi-26))
  178. (call-with-output-file #$output
  179. (lambda (port)
  180. (define drivers
  181. '#$(xorg-configuration-drivers config))
  182. (define (device-section driver)
  183. (string-append "
  184. Section \"Device\"
  185. Identifier \"device-" driver "\"
  186. Driver \"" driver "\"
  187. EndSection"))
  188. (define (screen-section driver resolutions)
  189. (string-append "
  190. Section \"Screen\"
  191. Identifier \"screen-" driver "\"
  192. Device \"device-" driver "\"
  193. SubSection \"Display\"
  194. Modes "
  195. (string-join (map (match-lambda
  196. ((x y)
  197. (string-append "\"" (number->string x)
  198. "x" (number->string y) "\"")))
  199. resolutions)) "
  200. EndSubSection
  201. EndSection"))
  202. (define (input-class-section layout variant model options)
  203. (string-append "
  204. Section \"InputClass\"
  205. Identifier \"evdev keyboard catchall\"
  206. MatchIsKeyboard \"on\"
  207. Option \"XkbLayout\" " (object->string layout)
  208. (if variant
  209. (string-append " Option \"XkbVariant\" \""
  210. variant "\"")
  211. "")
  212. (if model
  213. (string-append " Option \"XkbModel\" \""
  214. model "\"")
  215. "")
  216. (match options
  217. (()
  218. "")
  219. (_
  220. (string-append " Option \"XkbOptions\" \""
  221. (string-join options ",") "\""))) "
  222. MatchDevicePath \"/dev/input/event*\"
  223. Driver \"evdev\"
  224. EndSection\n"))
  225. (define (expand modules)
  226. ;; Append to MODULES the relevant /lib/xorg/modules
  227. ;; sub-directories.
  228. (append-map (lambda (module)
  229. (filter-map (lambda (directory)
  230. (let ((full (string-append module
  231. directory)))
  232. (and (file-exists? full)
  233. full)))
  234. '("/lib/xorg/modules/drivers"
  235. "/lib/xorg/modules/input"
  236. "/lib/xorg/modules/multimedia"
  237. "/lib/xorg/modules/extensions")))
  238. modules))
  239. (display "Section \"Files\"\n" port)
  240. (for-each (lambda (font)
  241. (format port " FontPath \"~a\"~%" font))
  242. '#$(xorg-configuration-fonts config))
  243. (for-each (lambda (module)
  244. (format port
  245. " ModulePath \"~a\"~%"
  246. module))
  247. (append (expand '#$all-modules)
  248. ;; For fbdevhw.so and so on.
  249. (list #$(file-append xorg-server
  250. "/lib/xorg/modules"))))
  251. (display "EndSection\n" port)
  252. (display "
  253. Section \"ServerFlags\"
  254. Option \"AllowMouseOpenFail\" \"on\"
  255. EndSection\n" port)
  256. (display (string-join (map device-section drivers) "\n")
  257. port)
  258. (newline port)
  259. (display (string-join
  260. (map (cut screen-section <>
  261. '#$(xorg-configuration-resolutions config))
  262. drivers)
  263. "\n")
  264. port)
  265. (newline port)
  266. (let ((layout #$(and=> (xorg-configuration-keyboard-layout config)
  267. keyboard-layout-name))
  268. (variant #$(and=> (xorg-configuration-keyboard-layout config)
  269. keyboard-layout-variant))
  270. (model #$(and=> (xorg-configuration-keyboard-layout config)
  271. keyboard-layout-model))
  272. (options '#$(and=> (xorg-configuration-keyboard-layout config)
  273. keyboard-layout-options)))
  274. (when layout
  275. (display (input-class-section layout variant model options)
  276. port)
  277. (newline port)))
  278. (for-each (lambda (config)
  279. (display config port))
  280. '#$(xorg-configuration-extra-config config))))))
  281. (computed-file "xserver.conf" build)))
  282. (define (xorg-configuration-directory modules)
  283. "Return a directory that contains the @code{.conf} files for X.org that
  284. includes the @code{share/X11/xorg.conf.d} directories of each package listed
  285. in @var{modules}."
  286. (with-imported-modules '((guix build utils))
  287. (computed-file "xorg.conf.d"
  288. #~(begin
  289. (use-modules (guix build utils)
  290. (srfi srfi-1))
  291. (define files
  292. (append-map (lambda (module)
  293. (find-files (string-append
  294. module
  295. "/share/X11/xorg.conf.d")
  296. "\\.conf$"))
  297. (list #$@modules)))
  298. (mkdir #$output)
  299. (for-each (lambda (file)
  300. (symlink file
  301. (string-append #$output "/"
  302. (basename file))))
  303. files)
  304. #t))))
  305. (define* (xorg-wrapper #:optional (config (xorg-configuration)))
  306. "Return a derivation that builds a script to start the X server with the
  307. given @var{config}. The resulting script should be used in place of
  308. @code{/usr/bin/X}."
  309. (define exp
  310. ;; Write a small wrapper around the X server.
  311. #~(begin
  312. (setenv "XORG_DRI_DRIVER_PATH" (string-append #$mesa "/lib/dri"))
  313. (setenv "XKB_BINDIR" (string-append #$xkbcomp "/bin"))
  314. (let ((X (string-append #$(xorg-configuration-server config) "/bin/X")))
  315. (apply execl X X
  316. "-xkbdir" (string-append #$xkeyboard-config "/share/X11/xkb")
  317. "-config" #$(xorg-configuration->file config)
  318. "-configdir" #$(xorg-configuration-directory
  319. (xorg-configuration-modules config))
  320. (cdr (command-line))))))
  321. (program-file "X-wrapper" exp))
  322. (define* (xorg-start-command #:optional (config (xorg-configuration)))
  323. "Return a @code{startx} script in which the modules, fonts, etc. specified
  324. in @var{config}, are available. The result should be used in place of
  325. @code{startx}."
  326. (define X
  327. (xorg-wrapper config))
  328. (define exp
  329. ;; Write a small wrapper around the X server.
  330. #~(apply execl #$X #$X ;; Second #$X is for argv[0].
  331. "-logverbose" "-verbose" "-terminate"
  332. #$@(xorg-configuration-server-arguments config)
  333. (cdr (command-line))))
  334. (program-file "startx" exp))
  335. (define* (xinitrc #:key fallback-session)
  336. "Return a system-wide xinitrc script that starts the specified X session,
  337. which should be passed to this script as the first argument. If not, the
  338. @var{fallback-session} will be used or, if @var{fallback-session} is false, a
  339. desktop session from the system or user profile will be used."
  340. (define builder
  341. #~(begin
  342. (use-modules (ice-9 match)
  343. (ice-9 regex)
  344. (ice-9 ftw)
  345. (ice-9 rdelim)
  346. (srfi srfi-1)
  347. (srfi srfi-26))
  348. (define (close-all-fdes)
  349. ;; Close all the open file descriptors except 0 to 2.
  350. (let loop ((fd 3))
  351. (when (< fd 4096) ;FIXME: use sysconf + _SC_OPEN_MAX
  352. (false-if-exception (close-fdes fd))
  353. (loop (+ 1 fd)))))
  354. (define (exec-from-login-shell command . args)
  355. ;; Run COMMAND from a login shell so that it gets to see the same
  356. ;; environment variables that one gets when logging in on a tty, for
  357. ;; instance.
  358. (let* ((pw (getpw (getuid)))
  359. (shell (passwd:shell pw)))
  360. ;; Close any open file descriptors. This is all the more
  361. ;; important that SLiM itself exec's us directly without closing
  362. ;; its own file descriptors!
  363. (close-all-fdes)
  364. ;; The '--login' option is supported at least by Bash and zsh.
  365. (execl shell shell "--login" "-c"
  366. (string-join (cons command args)))))
  367. (define system-profile
  368. "/run/current-system/profile")
  369. (define user-profile
  370. (and=> (getpw (getuid))
  371. (lambda (pw)
  372. (string-append (passwd:dir pw) "/.guix-profile"))))
  373. (define (xsession-command desktop-file)
  374. ;; Read from DESKTOP-FILE its X session command and return it as a
  375. ;; list.
  376. (define exec-regexp
  377. (make-regexp "^[[:blank:]]*Exec=(.*)$"))
  378. (call-with-input-file desktop-file
  379. (lambda (port)
  380. (let loop ()
  381. (match (read-line port)
  382. ((? eof-object?) #f)
  383. ((= (cut regexp-exec exec-regexp <>) result)
  384. (if result
  385. (string-tokenize (match:substring result 1))
  386. (loop))))))))
  387. (define (find-session profile)
  388. ;; Return an X session command from PROFILE or #f if none was found.
  389. (let ((directory (string-append profile "/share/xsessions")))
  390. (match (scandir directory
  391. (cut string-suffix? ".desktop" <>))
  392. ((or () #f)
  393. #f)
  394. ((sessions ...)
  395. (any xsession-command
  396. (map (cut string-append directory "/" <>)
  397. sessions))))))
  398. (let* ((home (getenv "HOME"))
  399. (xsession-file (string-append home "/.xsession"))
  400. (session (match (command-line)
  401. ((_)
  402. #$(if fallback-session
  403. #~(list #$fallback-session)
  404. #f))
  405. ((_ x ..1)
  406. x))))
  407. (if (file-exists? xsession-file)
  408. ;; Run ~/.xsession when it exists.
  409. (apply exec-from-login-shell xsession-file
  410. (or session '()))
  411. ;; Otherwise, start the specified session or a fallback.
  412. (apply exec-from-login-shell
  413. (or session
  414. (find-session user-profile)
  415. (find-session system-profile)))))))
  416. (program-file "xinitrc" builder))
  417. (define-syntax handle-xorg-configuration
  418. (syntax-rules ()
  419. "Generate the `compose' and `extend' entries of a login manager
  420. `service-type' to handle specifying the `xorg-configuration' through
  421. a `service-extension', as used by `set-xorg-configuration'."
  422. ((_ configuration-record service-type-definition)
  423. (service-type
  424. (inherit service-type-definition)
  425. (compose (lambda (extensions)
  426. (match extensions
  427. (() #f)
  428. ((config . _) config))))
  429. (extend (lambda (config xorg-configuration)
  430. (if xorg-configuration
  431. (configuration-record
  432. (inherit config)
  433. (xorg-configuration xorg-configuration))
  434. config)))))))
  435. (define (xorg-server-profile-service config)
  436. ;; XXX: profile-service-type only accepts <package> objects.
  437. (list
  438. (package
  439. (name "xorg-wrapper")
  440. (version (package-version xorg-server))
  441. (source (xorg-wrapper config))
  442. (build-system trivial-build-system)
  443. (arguments
  444. '(#:modules ((guix build utils))
  445. #:builder
  446. (begin
  447. (use-modules (guix build utils))
  448. (let* ((source (assoc-ref %build-inputs "source"))
  449. (out (assoc-ref %outputs "out"))
  450. (bin (string-append out "/bin")))
  451. (mkdir-p bin)
  452. (symlink source (string-append bin "/X"))
  453. (symlink source (string-append bin "/Xorg"))
  454. #t))))
  455. (home-page (package-home-page xorg-server))
  456. (synopsis (package-synopsis xorg-server))
  457. (description (package-description xorg-server))
  458. (license (package-license xorg-server)))))
  459. (define xorg-server-service-type
  460. (service-type
  461. (name 'xorg-server)
  462. (extensions
  463. (list (service-extension profile-service-type
  464. xorg-server-profile-service)))
  465. (default-value (xorg-configuration))
  466. (description "Add @command{X} to the system profile, to be used with
  467. @command{sx} or @command{xinit}.")))
  468. ;;;
  469. ;;; SLiM log-in manager.
  470. ;;;
  471. (define %default-slim-theme
  472. ;; Theme based on work by Felipe López.
  473. (file-append %artwork-repository "/slim"))
  474. (define %default-slim-theme-name
  475. ;; This must be the name of the sub-directory in %DEFAULT-SLIM-THEME that
  476. ;; contains the actual theme files.
  477. "1.x")
  478. (define-record-type* <slim-configuration>
  479. slim-configuration make-slim-configuration
  480. slim-configuration?
  481. (slim slim-configuration-slim
  482. (default slim))
  483. (allow-empty-passwords? slim-configuration-allow-empty-passwords?
  484. (default #t))
  485. (auto-login? slim-configuration-auto-login?
  486. (default #f))
  487. (default-user slim-configuration-default-user
  488. (default ""))
  489. (theme slim-configuration-theme
  490. (default %default-slim-theme))
  491. (theme-name slim-configuration-theme-name
  492. (default %default-slim-theme-name))
  493. (xauth slim-configuration-xauth
  494. (default xauth))
  495. (shepherd slim-configuration-shepherd
  496. (default shepherd))
  497. (auto-login-session slim-configuration-auto-login-session
  498. (default #f))
  499. (xorg-configuration slim-configuration-xorg
  500. (default (xorg-configuration)))
  501. (display slim-configuration-display
  502. (default ":0"))
  503. (vt slim-configuration-vt
  504. (default "vt7"))
  505. (sessreg slim-configuration-sessreg
  506. (default sessreg)))
  507. (define (slim-pam-service config)
  508. "Return a PAM service for @command{slim}."
  509. (list (unix-pam-service
  510. "slim"
  511. #:login-uid? #t
  512. #:allow-empty-passwords?
  513. (slim-configuration-allow-empty-passwords? config))))
  514. (define (slim-shepherd-service config)
  515. (let* ((xinitrc (xinitrc #:fallback-session
  516. (slim-configuration-auto-login-session config)))
  517. (xauth (slim-configuration-xauth config))
  518. (startx (xorg-start-command (slim-configuration-xorg config)))
  519. (display (slim-configuration-display config))
  520. (vt (slim-configuration-vt config))
  521. (shepherd (slim-configuration-shepherd config))
  522. (theme-name (slim-configuration-theme-name config))
  523. (sessreg (slim-configuration-sessreg config))
  524. (lockfile (string-append "/var/run/slim-" vt ".lock")))
  525. (define slim.cfg
  526. (mixed-text-file "slim.cfg" "
  527. default_path /run/current-system/profile/bin
  528. default_xserver " startx "
  529. display_name " display "
  530. xserver_arguments " vt "
  531. xauth_path " xauth "/bin/xauth
  532. authfile /var/run/slim-" vt ".auth
  533. lockfile " lockfile "
  534. logfile /var/log/slim-" vt ".log
  535. # The login command. '%session' is replaced by the chosen session name, one
  536. # of the names specified in the 'sessions' setting: 'wmaker', 'xfce', etc.
  537. login_cmd exec " xinitrc " %session
  538. sessiondir /run/current-system/profile/share/xsessions
  539. session_msg session (F1 to change):
  540. sessionstart_cmd " sessreg "/bin/sessreg -a -l $DISPLAY %user
  541. sessionstop_cmd " sessreg "/bin/sessreg -d -l $DISPLAY %user
  542. halt_cmd " shepherd "/sbin/halt
  543. reboot_cmd " shepherd "/sbin/reboot\n"
  544. (if (slim-configuration-auto-login? config)
  545. (string-append "auto_login yes\ndefault_user "
  546. (slim-configuration-default-user config) "\n")
  547. "")
  548. (if theme-name
  549. (string-append "current_theme " theme-name "\n")
  550. "")))
  551. (define theme
  552. (slim-configuration-theme config))
  553. (list (shepherd-service
  554. (documentation "Xorg display server")
  555. (provision (append
  556. ;; For compatibility, also provide 'xorg-server'.
  557. (if (string=? vt "vt7")
  558. '(xorg-server)
  559. '())
  560. (list (symbol-append 'xorg-server-
  561. (string->symbol vt)))))
  562. (requirement '(user-processes host-name udev))
  563. (start
  564. #~(lambda ()
  565. ;; A stale lock file can prevent SLiM from starting, so remove it to
  566. ;; be on the safe side.
  567. (false-if-exception (delete-file lockfile))
  568. (fork+exec-command
  569. (list (string-append #$(slim-configuration-slim config)
  570. "/bin/slim")
  571. "-nodaemon")
  572. #:environment-variables
  573. (list (string-append "SLIM_CFGFILE=" #$slim.cfg)
  574. #$@(if theme
  575. (list #~(string-append "SLIM_THEMESDIR=" #$theme))
  576. #~())))))
  577. (stop #~(make-kill-destructor))
  578. (respawn? #t)))))
  579. (define slim-service-type
  580. (handle-xorg-configuration slim-configuration
  581. (service-type (name 'slim)
  582. (extensions
  583. (list (service-extension shepherd-root-service-type
  584. slim-shepherd-service)
  585. (service-extension pam-root-service-type
  586. slim-pam-service)
  587. ;; Unconditionally add xterm to the system profile, to
  588. ;; avoid bad surprises.
  589. (service-extension profile-service-type
  590. (const (list xterm)))))
  591. (default-value (slim-configuration))
  592. (description
  593. "Run the SLiM graphical login manager for X11."))))
  594. ;;;
  595. ;;; Screen lockers & co.
  596. ;;;
  597. (define-record-type <screen-locker>
  598. (screen-locker name program empty?)
  599. screen-locker?
  600. (name screen-locker-name) ;string
  601. (program screen-locker-program) ;gexp
  602. (empty? screen-locker-allows-empty-passwords?)) ;Boolean
  603. (define screen-locker-pam-services
  604. (match-lambda
  605. (($ <screen-locker> name _ empty?)
  606. (list (unix-pam-service name
  607. #:allow-empty-passwords? empty?)))))
  608. (define screen-locker-setuid-programs
  609. (compose list screen-locker-program))
  610. (define screen-locker-service-type
  611. (service-type (name 'screen-locker)
  612. (extensions
  613. (list (service-extension pam-root-service-type
  614. screen-locker-pam-services)
  615. (service-extension setuid-program-service-type
  616. screen-locker-setuid-programs)))
  617. (description
  618. "Allow the given program to be used as a screen locker for
  619. the graphical server by making it setuid-root, so it can authenticate users,
  620. and by creating a PAM service for it.")))
  621. (define* (screen-locker-service package
  622. #:optional
  623. (program (package-name package))
  624. #:key allow-empty-passwords?)
  625. "Add @var{package}, a package for a screen locker or screen saver whose
  626. command is @var{program}, to the set of setuid programs and add a PAM entry
  627. for it. For example:
  628. @lisp
  629. (screen-locker-service xlockmore \"xlock\")
  630. @end lisp
  631. makes the good ol' XlockMore usable."
  632. (service screen-locker-service-type
  633. (screen-locker program
  634. (file-append package "/bin/" program)
  635. allow-empty-passwords?)))
  636. ;;;
  637. ;;; Locale service.
  638. ;;;
  639. (define-record-type* <localed-configuration>
  640. localed-configuration make-localed-configuration
  641. localed-configuration?
  642. (localed localed-configuration-localed
  643. (default localed))
  644. (keyboard-layout localed-configuration-keyboard-layout
  645. (default #f)))
  646. (define (localed-dbus-service config)
  647. "Return the 'localed' D-Bus service for @var{config}, a
  648. @code{<localed-configuration>} record."
  649. (define keyboard-layout
  650. (localed-configuration-keyboard-layout config))
  651. ;; The primary purpose of 'localed' is to tell GDM what the "current" Xorg
  652. ;; keyboard layout is. If 'localed' is missing, or if it's unable to
  653. ;; determine the current XKB layout, then GDM forcefully installs its
  654. ;; default XKB config (US English). Here we communicate the configured
  655. ;; layout through environment variables.
  656. (if keyboard-layout
  657. (let* ((layout (keyboard-layout-name keyboard-layout))
  658. (variant (keyboard-layout-variant keyboard-layout))
  659. (model (keyboard-layout-model keyboard-layout))
  660. (options (keyboard-layout-options keyboard-layout)))
  661. (list (wrapped-dbus-service
  662. (localed-configuration-localed config)
  663. "libexec/localed/localed"
  664. `(("GUIX_XKB_LAYOUT" ,layout)
  665. ,@(if variant
  666. `(("GUIX_XKB_VARIANT" ,variant))
  667. '())
  668. ,@(if model
  669. `(("GUIX_XKB_MODEL" ,model))
  670. '())
  671. ,@(if (null? options)
  672. '()
  673. `(("GUIX_XKB_OPTIONS"
  674. ,(string-join options ","))))))))
  675. '()))
  676. (define localed-service-type
  677. (let ((package (lambda (config)
  678. ;; Don't bother if the user didn't specify any keyboard
  679. ;; layout.
  680. (if (localed-configuration-keyboard-layout config)
  681. (list (localed-configuration-localed config))
  682. '()))))
  683. (service-type (name 'localed)
  684. (extensions
  685. (list (service-extension dbus-root-service-type
  686. localed-dbus-service)
  687. (service-extension udev-service-type package)
  688. (service-extension polkit-service-type package)
  689. ;; Add 'localectl' to the profile.
  690. (service-extension profile-service-type package)))
  691. ;; This service can be extended, typically by the X login
  692. ;; manager, to communicate the chosen Xorg keyboard layout.
  693. (compose (lambda (extensions)
  694. (find keyboard-layout? extensions)))
  695. (extend (lambda (config keyboard-layout)
  696. (localed-configuration
  697. (inherit config)
  698. (keyboard-layout keyboard-layout))))
  699. (description
  700. "Run the locale daemon, @command{localed}, which can be used
  701. to control the system locale and keyboard mapping from user programs such as
  702. the GNOME desktop environment.")
  703. (default-value (localed-configuration)))))
  704. ;;;
  705. ;;; GNOME Desktop Manager.
  706. ;;;
  707. (define %gdm-accounts
  708. (list (user-group (name "gdm") (system? #t))
  709. (user-account
  710. (name "gdm")
  711. (group "gdm")
  712. (supplementary-groups '("video"))
  713. (system? #t)
  714. (comment "GNOME Display Manager user")
  715. (home-directory "/var/lib/gdm")
  716. (shell (file-append shadow "/sbin/nologin")))))
  717. (define %gdm-activation
  718. ;; Ensure /var/lib/gdm is owned by the "gdm" user. This is normally the
  719. ;; case but could be wrong if the "gdm" user was created, then removed, and
  720. ;; then recreated under a different UID/GID: <https://bugs.gnu.org/37423>.
  721. (with-imported-modules '((guix build utils))
  722. #~(begin
  723. (use-modules (guix build utils))
  724. (let* ((gdm (getpwnam "gdm"))
  725. (uid (passwd:uid gdm))
  726. (gid (passwd:gid gdm))
  727. (st (stat "/var/lib/gdm" #f)))
  728. ;; Recurse into /var/lib/gdm only if it has wrong ownership.
  729. (when (and st
  730. (or (not (= uid (stat:uid st)))
  731. (not (= gid (stat:gid st)))))
  732. (for-each (lambda (file)
  733. (chown file uid gid))
  734. (find-files "/var/lib/gdm"
  735. #:directories? #t)))))))
  736. (define dbus-daemon-wrapper
  737. (program-file
  738. "gdm-dbus-wrapper"
  739. #~(begin
  740. (use-modules (srfi srfi-26))
  741. (define system-profile
  742. "/run/current-system/profile")
  743. (define user-profile
  744. (and=> (getpw (getuid))
  745. (lambda (pw)
  746. (string-append (passwd:dir pw) "/.guix-profile"))))
  747. ;; If we are able to find the user's profile, we can add it to
  748. ;; the search paths set below. We need to do this so that D-Bus
  749. ;; can start services installed by the user. This allows
  750. ;; applications that require session D-Bus services (e.g,
  751. ;; 'evolution') to work even if those services are only available
  752. ;; in the user's profile. See <https://bugs.gnu.org/35267>.
  753. (define profiles
  754. (if user-profile
  755. (list user-profile system-profile)
  756. (list system-profile)))
  757. (setenv "XDG_CONFIG_DIRS"
  758. (string-join (map (cut string-append <> "/etc/xdg") profiles)
  759. ":"))
  760. (setenv "XDG_DATA_DIRS"
  761. (string-join (map (cut string-append <> "/share") profiles)
  762. ":"))
  763. (apply execl (string-append #$dbus "/bin/dbus-daemon")
  764. (program-arguments)))))
  765. (define-record-type* <gdm-configuration>
  766. gdm-configuration make-gdm-configuration
  767. gdm-configuration?
  768. (gdm gdm-configuration-gdm (default gdm))
  769. (allow-empty-passwords? gdm-configuration-allow-empty-passwords? (default #t))
  770. (auto-login? gdm-configuration-auto-login? (default #f))
  771. (dbus-daemon gdm-configuration-dbus-daemon (default dbus-daemon-wrapper))
  772. (debug? gdm-configuration-debug? (default #f))
  773. (default-user gdm-configuration-default-user (default #f))
  774. (gnome-shell-assets gdm-configuration-gnome-shell-assets
  775. (default (list adwaita-icon-theme font-cantarell)))
  776. (xorg-configuration gdm-configuration-xorg
  777. (default (xorg-configuration)))
  778. (x-session gdm-configuration-x-session
  779. (default (xinitrc))))
  780. (define (gdm-configuration-file config)
  781. (mixed-text-file "gdm-custom.conf"
  782. "[daemon]\n"
  783. "#User=gdm\n"
  784. "#Group=gdm\n"
  785. (if (gdm-configuration-auto-login? config)
  786. (string-append
  787. "AutomaticLoginEnable=true\n"
  788. "AutomaticLogin="
  789. (or (gdm-configuration-default-user config)
  790. (error "missing default user for auto-login"))
  791. "\n")
  792. (string-append
  793. "AutomaticLoginEnable=false\n"
  794. "#AutomaticLogin=\n"))
  795. "#TimedLoginEnable=false\n"
  796. "#TimedLogin=\n"
  797. "#TimedLoginDelay=0\n"
  798. ;; Disable initial system setup inside GDM.
  799. ;; Whatever settings are set there should already be
  800. ;; taken care of through `guix system'.
  801. ;; See also
  802. ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=39281>.
  803. "InitialSetupEnable=false\n"
  804. ;; Enable me once X is working.
  805. "WaylandEnable=false\n"
  806. "\n"
  807. "[debug]\n"
  808. "Enable=" (if (gdm-configuration-debug? config)
  809. "true"
  810. "false") "\n"
  811. "\n"
  812. "[security]\n"
  813. "#DisallowTCP=true\n"
  814. "#AllowRemoteAutoLogin=false\n"))
  815. (define (gdm-pam-service config)
  816. "Return a PAM service for @command{gdm}."
  817. (list
  818. (pam-service
  819. (inherit (unix-pam-service "gdm-autologin"
  820. #:login-uid? #t))
  821. (auth (list (pam-entry
  822. (control "optional")
  823. (module (file-append (gdm-configuration-gdm config)
  824. "/lib/security/pam_gdm.so")))
  825. (pam-entry
  826. (control "sufficient")
  827. (module "pam_permit.so")))))
  828. (pam-service
  829. (inherit (unix-pam-service "gdm-launch-environment"))
  830. (auth (list (pam-entry
  831. (control "required")
  832. (module "pam_permit.so")))))
  833. (unix-pam-service "gdm-password"
  834. #:login-uid? #t
  835. #:allow-empty-passwords?
  836. (gdm-configuration-allow-empty-passwords? config))))
  837. (define (gdm-shepherd-service config)
  838. (list (shepherd-service
  839. (documentation "Xorg display server (GDM)")
  840. (provision '(xorg-server))
  841. (requirement '(dbus-system user-processes host-name udev))
  842. (start #~(lambda ()
  843. (fork+exec-command
  844. (list #$(file-append (gdm-configuration-gdm config)
  845. "/bin/gdm"))
  846. #:environment-variables
  847. (list (string-append
  848. "GDM_CUSTOM_CONF="
  849. #$(gdm-configuration-file config))
  850. (string-append
  851. "GDM_DBUS_DAEMON="
  852. #$(gdm-configuration-dbus-daemon config))
  853. (string-append
  854. "GDM_X_SERVER="
  855. #$(xorg-wrapper
  856. (gdm-configuration-xorg config)))
  857. (string-append
  858. "GDM_X_SESSION="
  859. #$(gdm-configuration-x-session config))
  860. (string-append
  861. "XDG_DATA_DIRS="
  862. ((lambda (ls) (string-join ls ":"))
  863. (map (lambda (path)
  864. (string-append path "/share"))
  865. ;; XXX: Remove gnome-shell below when GDM
  866. ;; can depend on GNOME Shell directly.
  867. (cons #$gnome-shell
  868. '#$(gdm-configuration-gnome-shell-assets
  869. config)))))))))
  870. (stop #~(make-kill-destructor))
  871. (respawn? #t))))
  872. (define gdm-service-type
  873. (handle-xorg-configuration gdm-configuration
  874. (service-type (name 'gdm)
  875. (extensions
  876. (list (service-extension shepherd-root-service-type
  877. gdm-shepherd-service)
  878. (service-extension activation-service-type
  879. (const %gdm-activation))
  880. (service-extension account-service-type
  881. (const %gdm-accounts))
  882. (service-extension pam-root-service-type
  883. gdm-pam-service)
  884. (service-extension profile-service-type
  885. gdm-configuration-gnome-shell-assets)
  886. (service-extension dbus-root-service-type
  887. (compose list
  888. gdm-configuration-gdm))
  889. (service-extension localed-service-type
  890. (compose
  891. xorg-configuration-keyboard-layout
  892. gdm-configuration-xorg))))
  893. (default-value (gdm-configuration))
  894. (description
  895. "Run the GNOME Desktop Manager (GDM), a program that allows
  896. you to log in in a graphical session, whether or not you use GNOME."))))
  897. (define* (set-xorg-configuration config
  898. #:optional
  899. (login-manager-service-type
  900. gdm-service-type))
  901. "Tell the log-in manager (of type @var{login-manager-service-type}) to use
  902. @var{config}, an <xorg-configuration> record."
  903. (simple-service 'set-xorg-configuration
  904. login-manager-service-type
  905. config))
  906. ;;; xorg.scm ends here