1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2014-2022 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
4 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
5 ;;; Copyright © 2016 Sou Bunnbu <iyzsong@gmail.com>
6 ;;; Copyright © 2017, 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
7 ;;; Copyright © 2017 Nikita <nikita@n0.is>
8 ;;; Copyright © 2018, 2020 Efraim Flashner <efraim@flashner.co.il>
9 ;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
10 ;;; Copyright © 2017, 2019 Christopher Baines <mail@cbaines.net>
11 ;;; Copyright © 2019 Tim Gesthuizen <tim.gesthuizen@yahoo.de>
12 ;;; Copyright © 2019 David Wilson <david@daviwil.com>
13 ;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
14 ;;; Copyright © 2020 Reza Alizadeh Majd <r.majd@pantherx.org>
15 ;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
16 ;;; Copyright © 2021, 2022 muradm <mail@muradm.net>
18 ;;; This file is part of GNU Guix.
20 ;;; GNU Guix is free software; you can redistribute it and/or modify it
21 ;;; under the terms of the GNU General Public License as published by
22 ;;; the Free Software Foundation; either version 3 of the License, or (at
23 ;;; your option) any later version.
25 ;;; GNU Guix is distributed in the hope that it will be useful, but
26 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
27 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 ;;; GNU General Public License for more details.
30 ;;; You should have received a copy of the GNU General Public License
31 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
33 (define-module (gnu services desktop)
34 #:use-module (gnu services)
35 #:use-module (gnu services shepherd)
36 #:use-module (gnu services base)
37 #:use-module (gnu services dbus)
38 #:use-module (gnu services avahi)
39 #:use-module (gnu services xorg)
40 #:use-module (gnu services networking)
41 #:use-module (gnu services sound)
42 #:use-module ((gnu system file-systems)
43 #:select (%control-groups
46 #:autoload (gnu services sddm) (sddm-service-type)
47 #:use-module (gnu system)
48 #:use-module (gnu system setuid)
49 #:use-module (gnu system shadow)
50 #:use-module (gnu system uuid)
51 #:use-module (gnu system pam)
52 #:use-module (gnu packages glib)
53 #:use-module (gnu packages admin)
54 #:use-module (gnu packages cups)
55 #:use-module (gnu packages freedesktop)
56 #:use-module (gnu packages gnome)
57 #:use-module (gnu packages xfce)
58 #:use-module (gnu packages avahi)
59 #:use-module (gnu packages xdisorg)
60 #:use-module (gnu packages scanner)
61 #:use-module (gnu packages suckless)
62 #:use-module (gnu packages linux)
63 #:use-module (gnu packages libusb)
64 #:use-module (gnu packages lxqt)
65 #:use-module (gnu packages mate)
66 #:use-module (gnu packages nfs)
67 #:use-module (gnu packages enlightenment)
68 #:use-module (guix deprecation)
69 #:use-module (guix records)
70 #:use-module (guix packages)
71 #:use-module (guix store)
72 #:use-module (guix ui)
73 #:use-module (guix utils)
74 #:use-module (guix gexp)
75 #:use-module (srfi srfi-1)
76 #:use-module (ice-9 format)
77 #:use-module (ice-9 match)
78 #:export (<upower-configuration>
81 upower-configuration-upower
82 upower-configuration-watts-up-pro?
83 upower-configuration-poll-batteries?
84 upower-configuration-ignore-lid?
85 upower-configuration-use-percentage-for-policy?
86 upower-configuration-percentage-low
87 upower-configuration-percentage-critical
88 upower-configuration-percentage-action
89 upower-configuration-time-low
90 upower-configuration-time-critical
91 upower-configuration-time-action
92 upower-configuration-critical-power-action
104 geoclue-configuration
105 geoclue-configuration?
106 %standard-geoclue-applications
110 bluetooth-service-type
111 bluetooth-configuration
112 bluetooth-configuration?
115 elogind-configuration
116 elogind-configuration?
121 gdm-file-system-service
123 %fontconfig-file-system
124 fontconfig-file-system-service
126 accountsservice-service-type
127 accountsservice-service
129 cups-pk-helper-service-type
132 gnome-desktop-configuration
133 gnome-desktop-configuration?
134 gnome-desktop-service
135 gnome-desktop-service-type
137 mate-desktop-configuration
138 mate-desktop-configuration?
140 mate-desktop-service-type
142 lxqt-desktop-configuration
143 lxqt-desktop-configuration?
144 lxqt-desktop-service-type
146 xfce-desktop-configuration
147 xfce-desktop-configuration?
149 xfce-desktop-service-type
151 x11-socket-directory-service
153 enlightenment-desktop-configuration
154 enlightenment-desktop-configuration?
155 enlightenment-desktop-service-type
157 inputattach-configuration
158 inputattach-configuration?
159 inputattach-service-type
163 gnome-keyring-configuration
164 gnome-keyring-configuration?
165 gnome-keyring-service-type
174 ;;; This module contains service definitions for a "desktop" environment.
184 (if value "true\n" "false\n"))
186 (define (package-direct-input-selector input)
188 (match (assoc-ref (package-direct-inputs package) input)
189 ((package . _) package))))
194 ;;; Upower D-Bus service.
197 (define-record-type* <upower-configuration>
198 upower-configuration make-upower-configuration
199 upower-configuration?
200 (upower upower-configuration-upower
202 (watts-up-pro? upower-configuration-watts-up-pro?
204 (poll-batteries? upower-configuration-poll-batteries?
206 (ignore-lid? upower-configuration-ignore-lid?
208 (use-percentage-for-policy? upower-configuration-use-percentage-for-policy?
210 (percentage-low upower-configuration-percentage-low
212 (percentage-critical upower-configuration-percentage-critical
214 (percentage-action upower-configuration-percentage-action
216 (time-low upower-configuration-time-low
218 (time-critical upower-configuration-time-critical
220 (time-action upower-configuration-time-action
222 (critical-power-action upower-configuration-critical-power-action
223 (default 'hybrid-sleep)))
225 (define* upower-configuration-file
226 ;; Return an upower-daemon configuration file.
228 (($ <upower-configuration> upower
229 watts-up-pro? poll-batteries? ignore-lid? use-percentage-for-policy?
230 percentage-low percentage-critical percentage-action time-low
231 time-critical time-action critical-power-action)
232 (plain-file "UPower.conf"
235 "EnableWattsUpPro=" (bool watts-up-pro?)
236 "NoPollBatteries=" (bool (not poll-batteries?))
237 "IgnoreLid=" (bool ignore-lid?)
238 "UsePercentageForPolicy=" (bool use-percentage-for-policy?)
239 "PercentageLow=" (number->string percentage-low) "\n"
240 "PercentageCritical=" (number->string percentage-critical) "\n"
241 "PercentageAction=" (number->string percentage-action) "\n"
242 "TimeLow=" (number->string time-low) "\n"
243 "TimeCritical=" (number->string time-critical) "\n"
244 "TimeAction=" (number->string time-action) "\n"
245 "CriticalPowerAction=" (match critical-power-action
246 ('hybrid-sleep "HybridSleep")
247 ('hibernate "Hibernate")
248 ('power-off "PowerOff"))
251 (define %upower-activation
253 (use-modules (guix build utils))
254 (mkdir-p "/var/lib/upower")))
256 (define (upower-dbus-service config)
257 (list (wrapped-dbus-service (upower-configuration-upower config)
259 `(("UPOWER_CONF_FILE_NAME"
260 ,(upower-configuration-file config))))))
262 (define (upower-shepherd-service config)
263 "Return a shepherd service for UPower with CONFIG."
264 (let ((upower (upower-configuration-upower config))
265 (config (upower-configuration-file config)))
266 (list (shepherd-service
267 (documentation "Run the UPower power and battery monitor.")
268 (provision '(upower-daemon))
269 (requirement '(dbus-system udev))
271 (start #~(make-forkexec-constructor
272 (list (string-append #$upower "/libexec/upowerd"))
273 #:environment-variables
274 (list (string-append "UPOWER_CONF_FILE_NAME="
276 (stop #~(make-kill-destructor))))))
278 (define upower-service-type
279 (let ((upower-package (compose list upower-configuration-upower)))
280 (service-type (name 'upower)
282 "Run @command{upowerd}}, a system-wide monitor for power
283 consumption and battery levels, with the given configuration settings. It
284 implements the @code{org.freedesktop.UPower} D-Bus interface, and is notably
287 (list (service-extension dbus-root-service-type
289 (service-extension shepherd-root-service-type
290 upower-shepherd-service)
291 (service-extension activation-service-type
292 (const %upower-activation))
293 (service-extension udev-service-type
296 ;; Make the 'upower' command visible.
297 (service-extension profile-service-type
299 (default-value (upower-configuration)))))
303 ;;; GeoClue D-Bus service.
307 (define-record-type* <geoclue-configuration>
308 geoclue-configuration make-geoclue-configuration
309 geoclue-configuration?
310 (geoclue geoclue-configuration-geoclue
312 (whitelist geoclue-configuration-whitelist)
313 (wifi-geolocation-url geoclue-configuration-wifi-geolocation-url)
314 (submit-data? geoclue-configuration-submit-data?)
315 (wifi-submission-url geoclue-configuration-wifi-submission-url)
316 (submission-nick geoclue-configuration-submission-nick)
317 (applications geoclue-configuration-applications))
319 (define* (geoclue-application name #:key (allowed? #t) system? (users '()))
320 "Configure default GeoClue access permissions for an application. NAME is
321 the Desktop ID of the application, without the .desktop part. If ALLOWED? is
322 true, the application will have access to location information by default.
323 The boolean SYSTEM? value indicates that an application is a system component
324 or not. Finally USERS is a list of UIDs of all users for which this
325 application is allowed location info access. An empty users list means all
329 "allowed=" (bool allowed?)
330 "system=" (bool system?)
331 "users=" (string-join users ";") "\n"))
333 (define %standard-geoclue-applications
334 (list (geoclue-application "gnome-datetime-panel" #:system? #t)
335 (geoclue-application "epiphany" #:system? #f)
336 (geoclue-application "firefox" #:system? #f)))
338 (define* (geoclue-configuration-file config)
339 "Return a geoclue configuration file."
340 (plain-file "geoclue.conf"
344 (string-join (geoclue-configuration-whitelist config)
347 "url=" (geoclue-configuration-wifi-geolocation-url config) "\n"
348 "submit-data=" (bool (geoclue-configuration-submit-data? config))
350 (geoclue-configuration-wifi-submission-url config) "\n"
352 (geoclue-configuration-submission-nick config)
354 (string-join (geoclue-configuration-applications config)
357 (define (geoclue-dbus-service config)
358 (list (wrapped-dbus-service (geoclue-configuration-geoclue config)
360 `(("GEOCLUE_CONFIG_FILE"
361 ,(geoclue-configuration-file config))))))
363 (define %geoclue-accounts
364 (list (user-group (name "geoclue") (system? #t))
369 (comment "GeoClue daemon user")
370 (home-directory "/var/empty")
371 (shell "/run/current-system/profile/sbin/nologin"))))
373 (define geoclue-service-type
374 (service-type (name 'geoclue)
376 (list (service-extension dbus-root-service-type
377 geoclue-dbus-service)
378 (service-extension account-service-type
379 (const %geoclue-accounts))))
380 (description "Run the @command{geoclue} location service.
381 This service provides a D-Bus interface to allow applications to request
382 access to a user's physical location, and optionally to add information to
383 online location databases.")))
385 (define* (geoclue-service #:key (geoclue geoclue)
387 (wifi-geolocation-url
388 ;; Mozilla geolocation service:
389 "https://location.services.mozilla.com/v1/geolocate?key=geoclue")
392 "https://location.services.mozilla.com/v1/submit?key=geoclue")
393 (submission-nick "geoclue")
394 (applications %standard-geoclue-applications))
395 "Return a service that runs the @command{geoclue} location service. This
396 service provides a D-Bus interface to allow applications to request access to
397 a user's physical location, and optionally to add information to online
398 location databases. By default, only the GNOME date-time panel and the Icecat
399 and Epiphany web browsers are able to ask for the user's location, and in the
400 case of Icecat and Epiphany, both will ask the user for permission first. See
401 @uref{https://wiki.freedesktop.org/www/Software/GeoClue/, the geoclue web
402 site} for more information."
403 (service geoclue-service-type
404 (geoclue-configuration
406 (whitelist whitelist)
407 (wifi-geolocation-url wifi-geolocation-url)
408 (submit-data? submit-data?)
409 (wifi-submission-url wifi-submission-url)
410 (submission-nick submission-nick)
411 (applications applications))))
418 (define-record-type* <bluetooth-configuration>
419 bluetooth-configuration make-bluetooth-configuration
420 bluetooth-configuration?
421 (bluez bluetooth-configuration-bluez (default bluez))
424 (name bluetooth-configuration-name (default "BlueZ"))
425 (class bluetooth-configuration-class (default #x000000))
426 (discoverable-timeout
427 bluetooth-configuration-discoverable-timeout (default 180))
428 (always-pairable? bluetooth-configuration-always-pairable? (default #f))
429 (pairable-timeout bluetooth-configuration-pairable-timeout (default 0))
431 ;;; MAYBE: Exclude into separate <device-id> record-type?
432 (device-id bluetooth-configuration-device-id (default #f))
433 (reverse-service-discovery?
434 bluetooth-configuration-reverse-service-discovery (default #t))
435 (name-resolving? bluetooth-configuration-name-resolving? (default #t))
436 (debug-keys? bluetooth-configuration-debug-keys? (default #f))
439 ;;; 'dual, 'bredr, 'le
440 (controller-mode bluetooth-configuration-controller-mode (default 'dual))
443 ;;; 'off, 'single, 'multiple
444 (multi-profile bluetooth-configuration-multi-profile (default 'off))
445 (fast-connectable? bluetooth-configuration-fast-connectable? (default #f))
448 ;;; for LE mode: 'off, 'network/on, 'device
449 ;;; for Dual mode: 'off, 'network/on', 'device, 'limited-network, 'limited-device
450 ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n68
451 (privacy bluetooth-configuration-privacy (default 'off))
454 ;;; 'never, 'confirm, 'always
455 (just-works-repairing
456 bluetooth-configuration-just-works-repairing (default 'never))
457 (temporary-timeout bluetooth-configuration-temporary-timeout (default 30))
458 (refresh-discovery? bluetooth-configuration-refresh-discovery (default #t))
460 ;;; Possible values: #t, #f, (uuid <uuid>)
462 ;;; d4992530-b9ec-469f-ab01-6c481c47da1c (BlueZ Experimental Debug)
463 ;;; 671b10b5-42c0-4696-9227-eb28d1b049d6 (BlueZ Experimental Simultaneous Central and Peripheral)
464 ;;; 15c0a148-c273-11ea-b3de-0242ac130004 (BlueZ Experimental LL privacy)
465 ;;; 330859bc-7506-492d-9370-9a6f0614037f (BlueZ Experimental Bluetooth Quality Report)
466 ;;; a6695ace-ee7f-4fb9-881a-5fac66c629af (BlueZ Experimental Offload Codecs)
467 ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n110
468 (experimental bluetooth-configuration-experimental (default #f))
469 (remote-name-request-retry-delay
470 bluetooth-configuration-remote-name-request-retry-delay (default 300))
473 (page-scan-type bluetooth-configuration-page-scan-type (default #f))
474 (page-scan-interval bluetooth-configuration-page-scan-interval (default #f))
475 (page-scan-window bluetooth-configuration-page-scan-window (default #f))
476 (inquiry-scan-type bluetooth-configuration-inquiry-scan-type (default #f))
477 (inquiry-scan-interval bluetooth-configuration-inquiry-scan-interval (default #f))
478 (inquiry-scan-window bluetooth-configuration-inquiry-scan-window (default #f))
479 (link-supervision-timeout bluetooth-configuration-link-supervision-timeout (default #f))
480 (page-timeout bluetooth-configuration-page-timeout (default #f))
481 (min-sniff-interval bluetooth-configuration-min-sniff-interval (default #f))
482 (max-sniff-interval bluetooth-configuration-max-sniff-interval (default #f))
485 (min-advertisement-interval
486 bluetooth-configuration-min-advertisement-interval (default #f))
487 (max-advertisement-interval
488 bluetooth-configuration-max-advertisement-interval (default #f))
489 (multi-advertisement-rotation-interval
490 bluetooth-configuration-multi-advertisement-rotation-interval (default #f))
491 (scan-interval-auto-connect
492 bluetooth-configuration-scan-interval-auto-connect (default #f))
493 (scan-window-auto-connect
494 bluetooth-configuration-scan-window-auto-connect (default #f))
495 (scan-interval-suspend
496 bluetooth-configuration-scan-interval-suspend (default #f))
498 bluetooth-configuration-scan-window-suspend (default #f))
499 (scan-interval-discovery
500 bluetooth-configuration-scan-interval-discovery (default #f))
501 (scan-window-discovery
502 bluetooth-configuration-scan-window-discovery (default #f))
503 (scan-interval-adv-monitor
504 bluetooth-configuration-scan-interval-adv-monitor (default #f))
505 (scan-window-adv-monitor
506 bluetooth-configuration-scan-window-adv-monitor (default #f))
507 (scan-interval-connect
508 bluetooth-configuration-scan-interval-connect (default #f))
510 bluetooth-configuration-scan-window-connect (default #f))
511 (min-connection-interval
512 bluetooth-configuration-min-connection-interval (default #f))
513 (max-connection-interval
514 bluetooth-configuration-max-connection-interval (default #f))
516 bluetooth-configuration-connection-latency (default #f))
517 (connection-supervision-timeout
518 bluetooth-configuration-connection-supervision-timeout (default #f))
520 bluetooth-configuration-autoconnect-timeout (default #f))
521 (adv-mon-allowlist-scan-duration
522 bluetooth-configuration-adv-mon-allowlist-scan-duration (default 300))
523 (adv-mon-no-filter-scan-duration
524 bluetooth-configuration-adv-mon-no-filter-scan-duration (default 500))
525 (enable-adv-mon-interleave-scan?
526 bluetooth-configuration-enable-adv-mon-interleave-scan (default #t))
529 ;;; Possible values: 'yes, 'no, 'always
530 (cache bluetooth-configuration-cache (default 'always))
532 ;;; Possible values: 7 ... 16, 0 (don't care)
533 (key-size bluetooth-configuration-key-size (default 0))
535 ;;; Possible values: 23 ... 517
536 (exchange-mtu bluetooth-configuration-exchange-mtu (default 517))
538 ;;; Possible values: 1 ... 5
539 (att-channels bluetooth-configuration-att-channels (default 3))
542 ;;; Possible values: 'basic, 'ertm
543 (session-mode bluetooth-configuration-session-mode (default 'basic))
545 ;;; Possible values: 'basic, 'streaming
546 (stream-mode bluetooth-configuration-stream-mode (default 'basic))
549 (reconnect-uuids bluetooth-configuration-reconnect-uuids (default '()))
550 (reconnect-attempts bluetooth-configuration-reconnect-attempts (default 7))
551 (reconnect-intervals bluetooth-configuration-reconnect-intervals
552 (default (list 1 2 4 8 16 32 64)))
553 (auto-enable? bluetooth-configuration-auto-enable? (default #f))
554 (resume-delay bluetooth-configuration-resume-delay (default 2))
559 ;;; "N = 0x00" ... "N = 0xFF"
560 ;;; Source: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/main.conf#n286
561 (rssi-sampling-period bluetooth-configuration-rssi-sampling-period
564 (define (bluetooth-configuration-file config)
565 "Return a configuration file for the systemd bluetooth service, as a string."
568 "\nName = " (bluetooth-configuration-name config)
569 "\nClass = " (string-append
571 (format #f "~6,'0x" (bluetooth-configuration-class config)))
572 "\nDiscoverableTimeout = " (number->string
573 (bluetooth-configuration-discoverable-timeout
575 "\nAlwaysPairable = " (bool (bluetooth-configuration-always-pairable?
577 "\nPairableTimeout = " (number->string
578 (bluetooth-configuration-pairable-timeout
580 (if (bluetooth-configuration-device-id config)
581 (string-append "\nDeviceID = " (bluetooth-configuration-device-id config))
583 "\nReverseServiceDiscovery = " (bool
584 (bluetooth-configuration-reverse-service-discovery
586 "\nNameResolving = " (bool (bluetooth-configuration-name-resolving? config))
587 "\nDebugKeys = " (bool (bluetooth-configuration-debug-keys? config))
588 "\nControllerMode = " (symbol->string
589 (bluetooth-configuration-controller-mode config))
590 "\nMultiProfile = " (symbol->string (bluetooth-configuration-multi-profile
592 "\nFastConnectable = " (bool (bluetooth-configuration-fast-connectable? config))
593 "\nPrivacy = " (symbol->string (bluetooth-configuration-privacy config))
594 "\nJustWorksRepairing = " (symbol->string
595 (bluetooth-configuration-just-works-repairing config))
596 "\nTemporaryTimeout = " (number->string
597 (bluetooth-configuration-temporary-timeout config))
598 "\nRefreshDiscovery = " (bool (bluetooth-configuration-refresh-discovery config))
599 "\nExperimental = " (let ((experimental (bluetooth-configuration-experimental config)))
600 (cond ((or (eq? experimental #t)
601 (eq? experimental #f)) (bool experimental))
602 ((list? experimental)
603 (string-join (map uuid->string experimental) ","))))
604 "\nRemoteNameRequestRetryDelay = " (number->string
605 (bluetooth-configuration-remote-name-request-retry-delay
608 (if (bluetooth-configuration-page-scan-type config)
611 (number->string (bluetooth-configuration-page-scan-type config)))
613 (if (bluetooth-configuration-page-scan-interval config)
615 "\nPageScanInterval = "
616 (number->string (bluetooth-configuration-page-scan-interval config)))
618 (if (bluetooth-configuration-page-scan-window config)
620 "\nPageScanWindow = "
621 (number->string (bluetooth-configuration-page-scan-window config)))
623 (if (bluetooth-configuration-inquiry-scan-type config)
625 "\nInquiryScanType = "
626 (number->string (bluetooth-configuration-inquiry-scan-type config)))
628 (if (bluetooth-configuration-inquiry-scan-interval config)
630 "\nInquiryScanInterval = "
631 (number->string (bluetooth-configuration-inquiry-scan-interval config)))
633 (if (bluetooth-configuration-inquiry-scan-window config)
635 "\nInquiryScanWindow = "
636 (number->string (bluetooth-configuration-inquiry-scan-window config)))
638 (if (bluetooth-configuration-link-supervision-timeout config)
640 "\nLinkSupervisionTimeout = "
641 (number->string (bluetooth-configuration-link-supervision-timeout config)))
643 (if (bluetooth-configuration-page-timeout config)
646 (number->string (bluetooth-configuration-page-timeout config)))
648 (if (bluetooth-configuration-min-sniff-interval config)
650 "\nMinSniffInterval = "
651 (number->string (bluetooth-configuration-min-sniff-interval config)))
653 (if (bluetooth-configuration-max-sniff-interval config)
655 "\nMaxSniffInterval = "
656 (number->string (bluetooth-configuration-max-sniff-interval config)))
660 (if (bluetooth-configuration-min-advertisement-interval config)
662 "\nMinAdvertisementInterval = "
663 (number->string (bluetooth-configuration-min-advertisement-interval config)))
665 (if (bluetooth-configuration-max-advertisement-interval config)
667 "\nMaxAdvertisementInterval = "
668 (number->string (bluetooth-configuration-max-advertisement-interval config)))
670 (if (bluetooth-configuration-multi-advertisement-rotation-interval config)
672 "\nMultiAdvertisementRotationInterval = "
674 (bluetooth-configuration-multi-advertisement-rotation-interval config)))
676 (if (bluetooth-configuration-scan-interval-auto-connect config)
678 "\nScanIntervalAutoConnect = "
679 (number->string (bluetooth-configuration-scan-interval-auto-connect config)))
681 (if (bluetooth-configuration-scan-window-auto-connect config)
683 "\nScanWindowAutoConnect = "
684 (number->string (bluetooth-configuration-scan-window-auto-connect config)))
686 (if (bluetooth-configuration-scan-interval-suspend config)
688 "\nScanIntervalSuspend = "
689 (number->string (bluetooth-configuration-scan-interval-suspend config)))
691 (if (bluetooth-configuration-scan-window-suspend config)
693 "\nScanWindowSuspend = "
694 (number->string (bluetooth-configuration-scan-window-suspend config)))
696 (if (bluetooth-configuration-scan-interval-discovery config)
698 "\nScanIntervalDiscovery = "
699 (number->string (bluetooth-configuration-scan-interval-discovery config)))
701 (if (bluetooth-configuration-scan-window-discovery config)
703 "\nScanWindowDiscovery = "
704 (number->string (bluetooth-configuration-scan-window-discovery config)))
706 (if (bluetooth-configuration-scan-interval-adv-monitor config)
708 "\nScanIntervalAdvMonitor = "
709 (number->string (bluetooth-configuration-scan-interval-adv-monitor config)))
711 (if (bluetooth-configuration-scan-window-adv-monitor config)
713 "\nScanWindowAdvMonitor = "
714 (number->string (bluetooth-configuration-scan-window-adv-monitor config)))
716 (if (bluetooth-configuration-scan-interval-connect config)
718 "\nScanIntervalConnect = "
719 (number->string (bluetooth-configuration-scan-interval-connect config)))
721 (if (bluetooth-configuration-scan-window-connect config)
723 "\nScanWindowConnect = "
724 (number->string (bluetooth-configuration-scan-window-connect config)))
726 (if (bluetooth-configuration-min-connection-interval config)
728 "\nMinConnectionInterval = "
729 (number->string (bluetooth-configuration-min-connection-interval config)))
731 (if (bluetooth-configuration-max-connection-interval config)
733 "\nMaxConnectionInterval = "
734 (number->string (bluetooth-configuration-max-connection-interval config)))
736 (if (bluetooth-configuration-connection-latency config)
738 "\nConnectionLatency = "
739 (number->string (bluetooth-configuration-connection-latency config)))
741 (if (bluetooth-configuration-connection-supervision-timeout config)
743 "\nConnectionSupervisionTimeout = "
744 (number->string (bluetooth-configuration-connection-supervision-timeout config)))
746 (if (bluetooth-configuration-autoconnect-timeout config)
748 "\nAutoconnecttimeout = "
749 (number->string (bluetooth-configuration-autoconnect-timeout config)))
751 "\nAdvMonAllowlistScanDuration = " (number->string
752 (bluetooth-configuration-adv-mon-allowlist-scan-duration
754 "\nAdvMonNoFilterScanDuration = " (number->string
755 (bluetooth-configuration-adv-mon-no-filter-scan-duration
757 "\nEnableAdvMonInterleaveScan = " (number->string
759 (bluetooth-configuration-enable-adv-mon-interleave-scan
764 "\nCache = " (symbol->string (bluetooth-configuration-cache config))
765 "\nKeySize = " (number->string (bluetooth-configuration-key-size config))
766 "\nExchangeMTU = " (number->string (bluetooth-configuration-exchange-mtu config))
767 "\nChannels = " (number->string (bluetooth-configuration-att-channels config))
770 "\nSessionMode = " (symbol->string (bluetooth-configuration-session-mode config))
771 "\nStreamMode = " (symbol->string (bluetooth-configuration-stream-mode config))
774 (let ((uuids (bluetooth-configuration-reconnect-uuids config)))
775 (if (not (eq? '() uuids))
777 "\nReconnectUUIDs = "
778 (string-join (map uuid->string uuids) ","))
780 "\nReconnectAttempts = " (number->string
781 (bluetooth-configuration-reconnect-attempts config))
782 "\nReconnectIntervals = " (string-join
784 (bluetooth-configuration-reconnect-intervals
787 "\nAutoEnable = " (bool (bluetooth-configuration-auto-enable?
789 "\nResumeDelay = " (number->string (bluetooth-configuration-resume-delay config))
792 "\nRSSISamplingPeriod = " (string-append
795 (bluetooth-configuration-rssi-sampling-period config)))))
797 (define (bluetooth-directory config)
798 (computed-file "etc-bluetooth"
802 (call-with-output-file "main.conf"
804 (display #$(bluetooth-configuration-file config)
807 (define (bluetooth-shepherd-service config)
808 "Return a shepherd service for @command{bluetoothd}."
810 (provision '(bluetooth))
811 (requirement '(dbus-system udev))
812 (documentation "Run the bluetoothd daemon.")
813 (start #~(make-forkexec-constructor
814 (list #$(file-append (bluetooth-configuration-bluez config)
815 "/libexec/bluetooth/bluetoothd"))))
816 (stop #~(make-kill-destructor))))
818 (define bluetooth-service-type
822 (list (service-extension dbus-root-service-type
823 (compose list bluetooth-configuration-bluez))
824 (service-extension udev-service-type
825 (compose list bluetooth-configuration-bluez))
826 (service-extension etc-service-type
829 ,(bluetooth-directory config)))))
830 (service-extension shepherd-root-service-type
831 (compose list bluetooth-shepherd-service))))
832 (default-value (bluetooth-configuration))
833 (description "Run the @command{bluetoothd} daemon, which manages all the
834 Bluetooth devices and provides a number of D-Bus interfaces.")))
836 (define* (bluetooth-service #:key (bluez bluez) (auto-enable? #f))
837 "Return a service that runs the @command{bluetoothd} daemon, which manages
838 all the Bluetooth devices and provides a number of D-Bus interfaces. When
839 AUTO-ENABLE? is true, the bluetooth controller is powered automatically at
842 Users need to be in the @code{lp} group to access the D-Bus service.
844 (service bluetooth-service-type
845 (bluetooth-configuration
847 (auto-enable? auto-enable?))))
851 ;;; Colord D-Bus service.
854 (define %colord-activation
856 (use-modules (guix build utils))
857 (mkdir-p "/var/lib/colord")
858 (let ((user (getpwnam "colord")))
859 (chown "/var/lib/colord"
860 (passwd:uid user) (passwd:gid user)))))
862 (define %colord-accounts
863 (list (user-group (name "colord") (system? #t))
868 (comment "colord daemon user")
869 (home-directory "/var/empty")
870 (shell (file-append shadow "/sbin/nologin")))))
872 (define colord-service-type
873 (service-type (name 'colord)
875 (list (service-extension account-service-type
876 (const %colord-accounts))
877 (service-extension activation-service-type
878 (const %colord-activation))
880 ;; Colord is a D-Bus service that dbus-daemon can
882 (service-extension dbus-root-service-type list)
884 ;; Colord provides "color device" rules for udev.
885 (service-extension udev-service-type list)
887 ;; It provides polkit "actions".
888 (service-extension polkit-service-type list)))
889 (default-value colord)
891 "Run @command{colord}, a system service with a D-Bus
892 interface to manage the color profiles of input and output devices such as
893 screens and scanners.")))
900 (define-record-type* <udisks-configuration>
901 udisks-configuration make-udisks-configuration
902 udisks-configuration?
903 (udisks udisks-configuration-udisks
906 (define %udisks-activation
907 (with-imported-modules '((guix build utils))
909 (use-modules (guix build utils))
911 (let ((run-dir "/var/run/udisks2"))
913 (chmod run-dir #o700)))))
915 (define udisks-service-type
916 (let ((udisks-package (lambda (config)
917 (list (udisks-configuration-udisks config)))))
918 (service-type (name 'udisks)
920 (list (service-extension polkit-service-type
922 (service-extension dbus-root-service-type
924 (service-extension udev-service-type
926 (service-extension activation-service-type
927 (const %udisks-activation))
929 ;; Profile 'udisksctl' & co. in the system profile.
930 (service-extension profile-service-type
932 (description "Run UDisks, a @dfn{disk management} daemon
933 that provides user interfaces with notifications and ways to mount/unmount
934 disks. Programs that talk to UDisks include the @command{udisksctl} command,
935 part of UDisks, and GNOME Disks."))))
937 (define* (udisks-service #:key (udisks udisks))
938 "Return a service for @uref{http://udisks.freedesktop.org/docs/latest/,
939 UDisks}, a @dfn{disk management} daemon that provides user interfaces with
940 notifications and ways to mount/unmount disks. Programs that talk to UDisks
941 include the @command{udisksctl} command, part of UDisks, and GNOME Disks."
942 (service udisks-service-type
943 (udisks-configuration (udisks udisks))))
947 ;;; Elogind login and seat management service.
950 (define-record-type* <elogind-configuration> elogind-configuration
951 make-elogind-configuration
952 elogind-configuration?
953 (elogind elogind-package
955 (kill-user-processes? elogind-kill-user-processes?
957 (kill-only-users elogind-kill-only-users
959 (kill-exclude-users elogind-kill-exclude-users
961 (inhibit-delay-max-seconds elogind-inhibit-delay-max-seconds
963 (handle-power-key elogind-handle-power-key
965 (handle-suspend-key elogind-handle-suspend-key
967 (handle-hibernate-key elogind-handle-hibernate-key
968 ;; (default 'hibernate)
969 ;; XXX Ignore it for now, since we don't
970 ;; yet handle resume-from-hibernation in
973 (handle-lid-switch elogind-handle-lid-switch
975 (handle-lid-switch-docked elogind-handle-lid-switch-docked
977 (handle-lid-switch-external-power elogind-handle-lid-switch-external-power
978 (default *unspecified*))
979 (power-key-ignore-inhibited? elogind-power-key-ignore-inhibited?
981 (suspend-key-ignore-inhibited? elogind-suspend-key-ignore-inhibited?
983 (hibernate-key-ignore-inhibited? elogind-hibernate-key-ignore-inhibited?
985 (lid-switch-ignore-inhibited? elogind-lid-switch-ignore-inhibited?
987 (holdoff-timeout-seconds elogind-holdoff-timeout-seconds
989 (idle-action elogind-idle-action
991 (idle-action-seconds elogind-idle-action-seconds
993 (runtime-directory-size-percent elogind-runtime-directory-size-percent
995 (runtime-directory-size elogind-runtime-directory-size
997 (remove-ipc? elogind-remove-ipc?
1000 (suspend-state elogind-suspend-state
1001 (default '("mem" "standby" "freeze")))
1002 (suspend-mode elogind-suspend-mode
1004 (hibernate-state elogind-hibernate-state
1005 (default '("disk")))
1006 (hibernate-mode elogind-hibernate-mode
1007 (default '("platform" "shutdown")))
1008 (hybrid-sleep-state elogind-hybrid-sleep-state
1009 (default '("disk")))
1010 (hybrid-sleep-mode elogind-hybrid-sleep-mode
1012 '("suspend" "platform" "shutdown"))))
1014 (define (elogind-configuration-file config)
1019 (_ (error "expected #t or #f, instead got:" x))))
1020 (define char-set:user-name
1021 (string->char-set "abcdefghijklmnopqrstuvwxyz0123456789_-"))
1022 (define (valid-list? l pred)
1023 (and-map (lambda (x) (string-every pred x)) l))
1024 (define (user-name-list users)
1025 (unless (valid-list? users char-set:user-name)
1026 (error "invalid user list" users))
1027 (string-join users " "))
1028 (define (enum val allowed)
1029 (unless (memq val allowed)
1030 (error "invalid value" val allowed))
1031 (symbol->string val))
1032 (define (non-negative-integer x)
1033 (unless (exact-integer? x) (error "not an integer" x))
1034 (when (negative? x) (error "negative number not allowed" x))
1036 (define handle-actions
1037 '(ignore poweroff reboot halt kexec suspend hibernate hybrid-sleep lock))
1038 (define (handle-action x)
1039 (if (unspecified? x)
1040 x ;let the unspecified value go through
1041 (enum x handle-actions)))
1042 (define (sleep-list tokens)
1043 (unless (valid-list? tokens char-set:user-name)
1044 (error "invalid sleep list" tokens))
1045 (string-join tokens " "))
1046 (define-syntax ini-file-clause
1048 ;; Produce an empty line when encountering an unspecified value. This
1049 ;; is better than an empty string value, which can, in some cases, cause
1050 ;; warnings such as "Failed to parse handle action setting".
1051 ((_ config (prop (parser getter)))
1052 (let ((value (parser (getter config))))
1053 (if (unspecified? value)
1055 (string-append prop "=" value "\n"))))
1057 (if (unspecified? str)
1059 (string-append str "\n")))))
1060 (define-syntax-rule (ini-file config file clause ...)
1061 (plain-file file (string-append (ini-file-clause config clause) ...)))
1063 config "logind.conf"
1065 ("KillUserProcesses" (yesno elogind-kill-user-processes?))
1066 ("KillOnlyUsers" (user-name-list elogind-kill-only-users))
1067 ("KillExcludeUsers" (user-name-list elogind-kill-exclude-users))
1068 ("InhibitDelayMaxSec" (non-negative-integer elogind-inhibit-delay-max-seconds))
1069 ("HandlePowerKey" (handle-action elogind-handle-power-key))
1070 ("HandleSuspendKey" (handle-action elogind-handle-suspend-key))
1071 ("HandleHibernateKey" (handle-action elogind-handle-hibernate-key))
1072 ("HandleLidSwitch" (handle-action elogind-handle-lid-switch))
1073 ("HandleLidSwitchDocked" (handle-action elogind-handle-lid-switch-docked))
1074 ("HandleLidSwitchExternalPower" (handle-action elogind-handle-lid-switch-external-power))
1075 ("PowerKeyIgnoreInhibited" (yesno elogind-power-key-ignore-inhibited?))
1076 ("SuspendKeyIgnoreInhibited" (yesno elogind-suspend-key-ignore-inhibited?))
1077 ("HibernateKeyIgnoreInhibited" (yesno elogind-hibernate-key-ignore-inhibited?))
1078 ("LidSwitchIgnoreInhibited" (yesno elogind-lid-switch-ignore-inhibited?))
1079 ("HoldoffTimeoutSec" (non-negative-integer elogind-holdoff-timeout-seconds))
1080 ("IdleAction" (handle-action elogind-idle-action))
1081 ("IdleActionSec" (non-negative-integer elogind-idle-action-seconds))
1082 ("RuntimeDirectorySize"
1085 (match (elogind-runtime-directory-size-percent config)
1086 (#f (non-negative-integer (elogind-runtime-directory-size config)))
1087 (percent (string-append (non-negative-integer percent) "%"))))))
1088 ("RemoveIPC" (yesno elogind-remove-ipc?))
1090 ("SuspendState" (sleep-list elogind-suspend-state))
1091 ("SuspendMode" (sleep-list elogind-suspend-mode))
1092 ("HibernateState" (sleep-list elogind-hibernate-state))
1093 ("HibernateMode" (sleep-list elogind-hibernate-mode))
1094 ("HybridSleepState" (sleep-list elogind-hybrid-sleep-state))
1095 ("HybridSleepMode" (sleep-list elogind-hybrid-sleep-mode))))
1097 (define (elogind-dbus-service config)
1098 "Return a @file{org.freedesktop.login1.service} file that tells D-Bus how to
1099 \"start\" elogind. In practice though, our elogind is started when booting by
1100 shepherd. Thus, the @code{Exec} line of this @file{.service} file does not
1101 explain how to start elogind; instead, it spawns a wrapper that waits for the
1102 @code{elogind} shepherd service. This avoids a race condition where both
1103 @command{shepherd} and @command{dbus-daemon} would attempt to start elogind."
1104 ;; For more info on the elogind startup race, see
1105 ;; <https://issues.guix.gnu.org/55444>.
1108 (elogind-package config))
1111 (program-file "elogind-dbus-shepherd-sync"
1112 (with-imported-modules '((gnu services herd))
1114 (use-modules (gnu services herd)
1117 (guard (c ((service-not-found-error? c)
1118 (format (current-error-port)
1119 "no elogind shepherd service~%")
1121 ((shepherd-error? c)
1122 (format (current-error-port)
1123 "elogind shepherd service not \
1126 (wait-for-service 'elogind))))))
1129 (with-imported-modules '((guix build utils))
1131 (use-modules (guix build utils)
1134 (define service-directory
1135 "/share/dbus-1/system-services")
1137 (mkdir-p (dirname (string-append #$output service-directory)))
1138 (copy-recursively (string-append #$elogind service-directory)
1139 (string-append #$output service-directory))
1140 (symlink (string-append #$elogind "/etc") ;for etc/dbus-1
1141 (string-append #$output "/etc"))
1143 ;; Replace the "Exec=" line of the 'org.freedesktop.login1.service'
1144 ;; file with one that refers to WRAPPER instead of elogind.
1145 (match (find-files #$output "\\.service$")
1148 (("Exec[[:blank:]]*=.*" _)
1149 (string-append "Exec=" #$wrapper "\n"))))))))
1151 (list (computed-file "elogind-dbus-service-wrapper" build)))
1153 (define (pam-extension-procedure config)
1154 "Return an extension for PAM-ROOT-SERVICE-TYPE that ensures that all the PAM
1155 services use 'pam_elogind.so', a module that allows elogind to keep track of
1156 logged-in users (run 'loginctl' to see elogind's world view of users and
1160 (control "required")
1161 (module (file-append (elogind-package config)
1162 "/lib/security/pam_elogind.so"))))
1167 (session (cons pam-elogind (pam-service-session pam)))))))
1169 (define (elogind-shepherd-service config)
1170 "Return a Shepherd service to start elogind according to @var{config}."
1171 (list (shepherd-service
1172 (requirement '(dbus-system))
1173 (provision '(elogind))
1174 (start #~(make-forkexec-constructor
1175 (list #$(file-append (elogind-package config)
1176 "/libexec/elogind/elogind"))
1177 #:environment-variables
1178 (list (string-append "ELOGIND_CONF_FILE="
1179 #$(elogind-configuration-file
1181 (stop #~(make-kill-destructor)))))
1183 (define elogind-service-type
1184 (service-type (name 'elogind)
1186 (list (service-extension dbus-root-service-type
1187 elogind-dbus-service)
1188 (service-extension udev-service-type
1189 (compose list elogind-package))
1190 (service-extension polkit-service-type
1191 (compose list elogind-package))
1193 ;; Start elogind from the Shepherd rather than waiting
1194 ;; for bus activation. This ensures that it can handle
1195 ;; events like lid close, etc.
1196 (service-extension shepherd-root-service-type
1197 elogind-shepherd-service)
1199 ;; Provide the 'loginctl' command.
1200 (service-extension profile-service-type
1201 (compose list elogind-package))
1203 ;; Extend PAM with pam_elogind.so.
1204 (service-extension pam-root-service-type
1205 pam-extension-procedure)
1207 ;; We need /run/user, /run/systemd, etc.
1208 (service-extension file-system-service-type
1209 (const %elogind-file-systems))))
1210 (default-value (elogind-configuration))
1211 (description "Run the @command{elogind} login and seat
1212 management service. The @command{elogind} service integrates with PAM to
1213 allow other system components to know the set of logged-in users as well as
1214 their session types (graphical, console, remote, etc.). It can also clean up
1215 after users when they log out.")))
1217 (define* (elogind-service #:key (config (elogind-configuration)))
1218 "Return a service that runs the @command{elogind} login and seat management
1219 service. The @command{elogind} service integrates with PAM to allow other
1220 system components to know the set of logged-in users as well as their session
1221 types (graphical, console, remote, etc.). It can also clean up after users
1223 (service elogind-service-type config))
1227 ;;; Fontconfig and other desktop file-systems.
1230 (define %fontconfig-file-system
1233 (mount-point "/var/cache/fontconfig")
1235 (flags '(read-only))
1238 (define %gdm-file-system
1241 (mount-point "/var/lib/gdm")
1245 ;; The global fontconfig cache directory can sometimes contain stale entries,
1246 ;; possibly referencing fonts that have been GC'd, so mount it read-only.
1247 ;; As mentioned https://debbugs.gnu.org/cgi/bugreport.cgi?bug=36924#8 and
1248 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=38046#10 and elsewhere.
1249 (define fontconfig-file-system-service
1250 (simple-service 'fontconfig-file-system
1251 file-system-service-type
1252 (list %fontconfig-file-system)))
1254 ;; Avoid stale caches and stale user IDs being reused between system
1255 ;; reconfigurations, which would crash GDM and render the system unusable.
1256 ;; GDM doesn't require persisting anything valuable there anyway.
1257 (define gdm-file-system-service
1258 (simple-service 'gdm-file-system
1259 file-system-service-type
1260 (list %gdm-file-system)))
1264 ;;; AccountsService service.
1267 (define %accountsservice-activation
1269 (use-modules (guix build utils))
1270 (mkdir-p "/var/lib/AccountsService")))
1272 (define accountsservice-service-type
1273 (service-type (name 'accountsservice)
1275 (list (service-extension activation-service-type
1276 (const %accountsservice-activation))
1277 (service-extension dbus-root-service-type list)
1278 (service-extension polkit-service-type list)))
1279 (default-value accountsservice)
1280 (description "Run AccountsService, a system service available
1281 over D-Bus that can list available accounts, change their passwords, and so
1282 on. AccountsService integrates with PolicyKit to enable unprivileged users to
1283 acquire the capability to modify their system configuration.")))
1285 (define* (accountsservice-service #:key (accountsservice accountsservice))
1286 "Return a service that runs AccountsService, a system service that
1287 can list available accounts, change their passwords, and so on.
1288 AccountsService integrates with PolicyKit to enable unprivileged users to
1289 acquire the capability to modify their system configuration.
1290 @uref{https://www.freedesktop.org/wiki/Software/AccountsService/, the
1291 accountsservice web site} for more information."
1292 (service accountsservice-service-type accountsservice))
1296 ;;; cups-pk-helper service.
1299 (define cups-pk-helper-service-type
1301 (name 'cups-pk-helper)
1303 "PolicyKit helper to configure CUPS with fine-grained privileges.")
1305 (list (service-extension dbus-root-service-type list)
1306 (service-extension polkit-service-type list)))
1307 (default-value cups-pk-helper)))
1311 ;;; Scanner access via SANE.
1314 (define %sane-accounts
1315 ;; The '60-libsane.rules' udev rules refers to the "scanner" group.
1316 (list (user-group (name "scanner") (system? #t))))
1318 (define sane-service-type
1322 "This service provides access to scanners @i{via}
1323 @uref{http://www.sane-project.org, SANE} by installing the necessary udev
1325 (default-value sane-backends-minimal)
1327 (list (service-extension udev-service-type list)
1328 (service-extension account-service-type
1329 (const %sane-accounts))))))
1334 ;;; GNOME desktop service.
1337 (define-record-type* <gnome-desktop-configuration> gnome-desktop-configuration
1338 make-gnome-desktop-configuration
1339 gnome-desktop-configuration?
1340 (gnome gnome-package (default gnome)))
1342 (define (gnome-packages config packages)
1343 "Return the list of GNOME dependencies from CONFIG which names are part of
1344 the given PACKAGES list."
1345 (let ((gnome (gnome-package config)))
1347 ((package-direct-input-selector name) gnome))
1350 (define (gnome-udev-rules config)
1351 "Return the list of GNOME dependencies that provide udev rules."
1352 (gnome-packages config '("gnome-settings-daemon")))
1354 (define (gnome-polkit-settings config)
1355 "Return the list of GNOME dependencies that provide polkit actions and
1357 (gnome-packages config
1358 '("gnome-settings-daemon"
1359 "gnome-control-center"
1360 "gnome-system-monitor"
1363 (define gnome-desktop-service-type
1365 (name 'gnome-desktop)
1367 (list (service-extension udev-service-type
1369 (service-extension polkit-service-type
1370 gnome-polkit-settings)
1371 (service-extension profile-service-type
1374 (default-value (gnome-desktop-configuration))
1375 (description "Run the GNOME desktop environment.")))
1377 (define-deprecated (gnome-desktop-service #:key (config
1378 (gnome-desktop-configuration)))
1379 gnome-desktop-service-type
1380 "Return a service that adds the @code{gnome} package to the system profile,
1381 and extends polkit with the actions from @code{gnome-settings-daemon}."
1382 (service gnome-desktop-service-type config))
1384 ;; MATE Desktop service.
1385 ;; TODO: Add mate-screensaver.
1387 (define-record-type* <mate-desktop-configuration> mate-desktop-configuration
1388 make-mate-desktop-configuration
1389 mate-desktop-configuration?
1390 (mate-package mate-package (default mate)))
1392 (define (mate-polkit-extension config)
1393 "Return the list of packages for CONFIG's MATE package that extend polkit."
1394 (let ((mate (mate-package config)))
1395 (map (lambda (input)
1396 ((package-direct-input-selector input) mate))
1397 '("mate-system-monitor" ;kill, renice processes
1398 "mate-settings-daemon" ;date/time settings
1399 "mate-power-manager" ;modify brightness
1400 "mate-control-center" ;RandR, display properties FIXME
1401 "mate-applets")))) ;CPU frequency scaling
1403 (define mate-desktop-service-type
1405 (name 'mate-desktop)
1407 (list (service-extension polkit-service-type
1408 mate-polkit-extension)
1409 (service-extension profile-service-type
1412 (default-value (mate-desktop-configuration))
1413 (description "Run the MATE desktop environment.")))
1415 (define-deprecated (mate-desktop-service #:key
1417 (mate-desktop-configuration)))
1418 mate-desktop-service-type
1419 "Return a service that adds the @code{mate} package to the system profile,
1420 and extends polkit with the actions from @code{mate-settings-daemon}."
1421 (service mate-desktop-service-type config))
1425 ;;; XFCE desktop service.
1428 (define-record-type* <xfce-desktop-configuration> xfce-desktop-configuration
1429 make-xfce-desktop-configuration
1430 xfce-desktop-configuration?
1431 (xfce xfce-package (default xfce)))
1433 (define (xfce-polkit-settings config)
1434 "Return the list of XFCE dependencies that provide polkit actions and
1436 (let ((xfce (xfce-package config)))
1438 ((package-direct-input-selector name) xfce))
1440 "xfce4-power-manager"))))
1442 (define xfce-desktop-service-type
1444 (name 'xfce-desktop)
1446 (list (service-extension polkit-service-type
1447 xfce-polkit-settings)
1448 (service-extension profile-service-type
1449 (compose list xfce-package))))
1450 (default-value (xfce-desktop-configuration))
1451 (description "Run the Xfce desktop environment.")))
1453 (define-deprecated (xfce-desktop-service #:key (config
1454 (xfce-desktop-configuration)))
1455 xfce-desktop-service-type
1456 "Return a service that adds the @code{xfce} package to the system profile,
1457 and extends polkit with the ability for @code{thunar} to manipulate the file
1458 system as root from within a user session, after the user has authenticated
1459 with the administrator's password."
1460 (service xfce-desktop-service-type config))
1464 ;;; Lxqt desktop service.
1467 (define-record-type* <lxqt-desktop-configuration> lxqt-desktop-configuration
1468 make-lxqt-desktop-configuration
1469 lxqt-desktop-configuration?
1473 (define (lxqt-polkit-settings config)
1474 "Return the list of LXQt dependencies that provide polkit actions and
1476 (let ((lxqt (lxqt-package config)))
1478 ((package-direct-input-selector name) lxqt))
1481 (define lxqt-desktop-service-type
1483 (name 'lxqt-desktop)
1485 (list (service-extension polkit-service-type
1486 lxqt-polkit-settings)
1487 (service-extension profile-service-type
1488 (compose list lxqt-package))))
1489 (default-value (lxqt-desktop-configuration))
1490 (description "Run LXQt desktop environment.")))
1494 ;;; X11 socket directory service
1497 (define x11-socket-directory-service
1498 ;; Return a service that creates /tmp/.X11-unix. When using X11, libxcb
1499 ;; takes care of creating that directory. However, when using XWayland, we
1500 ;; need to create beforehand. Thus, create it unconditionally here.
1501 (simple-service 'x11-socket-directory
1502 activation-service-type
1503 (with-imported-modules '((guix build utils))
1505 (use-modules (guix build utils))
1506 (let ((directory "/tmp/.X11-unix"))
1508 (chmod directory #o1777))))))
1511 ;;; Enlightenment desktop service.
1514 (define-record-type* <enlightenment-desktop-configuration>
1515 enlightenment-desktop-configuration make-enlightenment-desktop-configuration
1516 enlightenment-desktop-configuration?
1518 (enlightenment enlightenment-package
1519 (default enlightenment)))
1521 (define (enlightenment-setuid-programs enlightenment-desktop-configuration)
1522 (match-record enlightenment-desktop-configuration
1523 <enlightenment-desktop-configuration>
1525 (map file-like->setuid-program
1526 (list (file-append enlightenment
1527 "/lib/enlightenment/utils/enlightenment_sys")
1528 (file-append enlightenment
1529 "/lib/enlightenment/utils/enlightenment_system")
1530 (file-append enlightenment
1531 "/lib/enlightenment/utils/enlightenment_ckpasswd")))))
1533 (define enlightenment-desktop-service-type
1535 (name 'enlightenment-desktop)
1537 (list (service-extension dbus-root-service-type
1539 (package-direct-input-selector
1541 enlightenment-package))
1542 (service-extension setuid-program-service-type
1543 enlightenment-setuid-programs)
1544 (service-extension profile-service-type
1546 enlightenment-package))))
1547 (default-value (enlightenment-desktop-configuration))
1549 "Return a service that adds the @code{enlightenment} package to the system
1550 profile, and extends dbus with the ability for @code{efl} to generate
1551 thumbnails and makes setuid the programs which enlightenment needs to function
1556 ;;; inputattach-service-type
1559 (define-record-type* <inputattach-configuration>
1560 inputattach-configuration
1561 make-inputattach-configuration
1562 inputattach-configuration?
1563 (device-type inputattach-configuration-device-type
1565 (device inputattach-configuration-device
1566 (default "/dev/ttyS0"))
1567 (baud-rate inputattach-configuration-baud-rate
1569 (log-file inputattach-configuration-log-file
1572 (define inputattach-shepherd-service
1574 (($ <inputattach-configuration> type device baud-rate log-file)
1575 (let ((args (append (if baud-rate
1576 (list "--baud" (number->string baud-rate))
1578 (list (string-append "--" type)
1580 (list (shepherd-service
1581 (provision '(inputattach))
1582 (requirement '(udev))
1583 (documentation "inputattach daemon")
1584 (start #~(make-forkexec-constructor
1585 (cons (string-append #$inputattach
1588 #:log-file #$log-file))
1589 (stop #~(make-kill-destructor))))))))
1591 (define inputattach-service-type
1595 (list (service-extension shepherd-root-service-type
1596 inputattach-shepherd-service)))
1597 (default-value (inputattach-configuration))
1598 (description "Return a service that runs inputattach on a device and
1599 dispatches events from it.")))
1603 ;;; gnome-keyring-service-type
1606 (define-record-type* <gnome-keyring-configuration> gnome-keyring-configuration
1607 make-gnome-keyring-configuration
1608 gnome-keyring-configuration?
1609 (keyring gnome-keyring-package (default gnome-keyring))
1610 (pam-services gnome-keyring-pam-services (default '(("gdm-password" . login)
1611 ("passwd" . passwd)))))
1613 (define (pam-gnome-keyring config)
1614 (define (%pam-keyring-entry . arguments)
1616 (control "optional")
1617 (module (file-append (gnome-keyring-package config)
1618 "/lib/security/pam_gnome_keyring.so"))
1619 (arguments arguments)))
1623 (case (assoc-ref (gnome-keyring-pam-services config)
1624 (pam-service-name service))
1628 (auth (append (pam-service-auth service)
1629 (list (%pam-keyring-entry))))
1630 (session (append (pam-service-session service)
1631 (list (%pam-keyring-entry "auto_start"))))))
1635 (password (append (pam-service-password service)
1636 (list (%pam-keyring-entry))))))
1639 (define gnome-keyring-service-type
1641 (name 'gnome-keyring)
1643 (service-extension pam-root-service-type pam-gnome-keyring)))
1644 (default-value (gnome-keyring-configuration))
1645 (description "Return a service, that adds the @code{gnome-keyring} package
1646 to the system profile and extends PAM with entries using
1647 @code{pam_gnome_keyring.so}, unlocking a user's login keyring when they log in
1648 or setting its password with passwd.")))
1652 ;;; polkit-wheel-service -- Allow wheel group to perform admin actions
1655 (define polkit-wheel
1658 `(("share/polkit-1/rules.d/wheel.rules"
1661 "polkit.addAdminRule(function(action, subject) {
1662 return [\"unix-group:wheel\"];
1666 (define polkit-wheel-service
1667 (simple-service 'polkit-wheel polkit-service-type (list polkit-wheel)))
1671 ;;; seatd-service-type -- minimal seat management daemon
1674 (define (seatd-group-sanitizer group-or-name)
1675 (match group-or-name
1676 ((? user-group? group) group)
1677 ((? string? group-name) (user-group (name group-name) (system? #t)))
1678 (_ (leave (G_ "seatd: '~a' is not a valid group~%") group-or-name))))
1680 (define-record-type* <seatd-configuration> seatd-configuration
1681 make-seatd-configuration
1682 seatd-configuration?
1683 (seatd seatd-package (default seatd))
1684 (group seatd-group ; string | <user-group>
1686 (sanitize seatd-group-sanitizer))
1687 (socket seatd-socket (default "/run/seatd.sock"))
1688 (logfile seatd-logfile (default "/var/log/seatd.log"))
1689 (loglevel seatd-loglevel (default "info")))
1691 (define (seatd-shepherd-service config)
1692 (list (shepherd-service
1693 (documentation "Minimal seat management daemon")
1695 ;; TODO: once cgroups is separate dependency
1696 ;; here we should depend on it rather than elogind
1697 (provision '(seatd elogind))
1698 (start #~(make-forkexec-constructor
1699 (list #$(file-append (seatd-package config) "/bin/seatd")
1700 "-g" #$(user-group-name (seatd-group config)))
1701 #:environment-variables
1702 (list (string-append "SEATD_LOGLEVEL="
1703 #$(seatd-loglevel config))
1704 (string-append "SEATD_DEFAULTPATH="
1705 #$(seatd-socket config)))
1706 #:log-file #$(seatd-logfile config)))
1707 (stop #~(make-kill-destructor)))))
1709 (define seatd-accounts
1710 (match-lambda (($ <seatd-configuration> _ group) (list group))))
1712 (define seatd-environment
1714 (($ <seatd-configuration> _ _ socket)
1715 `(("SEATD_SOCK" . ,socket)))))
1717 (define seatd-service-type
1720 (description "Seat management takes care of mediating access
1721 to shared devices (graphics, input), without requiring the
1722 applications needing access to be root.")
1725 (service-extension account-service-type seatd-accounts)
1726 (service-extension session-environment-service-type seatd-environment)
1727 ;; TODO: once cgroups is separate dependency we should not mount it here
1728 ;; for now it is mounted here, because elogind mounts it
1729 (service-extension file-system-service-type (const %control-groups))
1730 (service-extension shepherd-root-service-type seatd-shepherd-service)))
1731 (default-value (seatd-configuration))))
1735 ;;; The default set of desktop services.
1738 (define* (desktop-services-for-system #:optional
1739 (system (or (%current-target-system)
1740 (%current-system))))
1741 ;; List of services typically useful for a "desktop" use case.
1743 ;; Since GDM depends on Rust (gdm -> gnome-shell -> gjs -> mozjs -> rust)
1744 ;; and Rust is currently unavailable on non-x86_64 platforms, default to
1745 ;; SDDM there (FIXME).
1746 (cons* (if (string-prefix? "x86_64" system)
1747 (service gdm-service-type)
1748 (service sddm-service-type))
1750 ;; Screen lockers are a pretty useful thing and these are small.
1751 (screen-locker-service slock)
1752 (screen-locker-service xlockmore "xlock")
1754 ;; Add udev rules for MTP devices so that non-root users can access
1756 (simple-service 'mtp udev-service-type (list libmtp))
1757 ;; Add udev rules for scanners.
1758 (service sane-service-type)
1759 ;; Add polkit rules, so that non-root users in the wheel group can
1760 ;; perform administrative tasks (similar to "sudo").
1761 polkit-wheel-service
1763 ;; Allow desktop users to also mount NTFS and NFS file systems
1765 (simple-service 'mount-setuid-helpers setuid-program-service-type
1766 (map (lambda (program)
1769 (list (file-append nfs-utils "/sbin/mount.nfs")
1770 (file-append ntfs-3g "/sbin/mount.ntfs-3g"))))
1772 ;; This is a volatile read-write file system mounted at /var/lib/gdm,
1773 ;; to avoid GDM stale cache and permission issues.
1774 gdm-file-system-service
1776 ;; The global fontconfig cache directory can sometimes contain
1777 ;; stale entries, possibly referencing fonts that have been GC'd,
1778 ;; so mount it read-only.
1779 fontconfig-file-system-service
1781 ;; NetworkManager and its applet.
1782 (service network-manager-service-type)
1783 (service wpa-supplicant-service-type) ;needed by NetworkManager
1784 (simple-service 'network-manager-applet
1785 profile-service-type
1786 (list network-manager-applet))
1787 (service modem-manager-service-type)
1788 (service usb-modeswitch-service-type)
1790 ;; The D-Bus clique.
1791 (service avahi-service-type)
1793 (service upower-service-type)
1794 (accountsservice-service)
1795 (service cups-pk-helper-service-type)
1796 (service colord-service-type)
1798 (service polkit-service-type)
1802 (service ntp-service-type)
1804 x11-socket-directory-service
1806 (service pulseaudio-service-type)
1807 (service alsa-service-type)
1811 (define-syntax %desktop-services
1812 (identifier-syntax (desktop-services-for-system)))
1814 ;;; desktop.scm ends here