aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 David Craven <david@craven.ch>
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019 Jesse Gildersleve <jessejohngildersleve@protonmail.com>
;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
;;; Copyright © 2023, 2024 Zheng Junjie <873216071@qq.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu services sddm)
  #:use-module (gnu packages admin)
  #:use-module (gnu packages display-managers)
  #:use-module (gnu packages freedesktop)
  #:use-module (gnu packages xorg)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module (gnu services xorg)
  #:use-module (gnu system pam)
  #:use-module (gnu system shadow)
  #:use-module (guix gexp)
  #:use-module (guix records)
  #:use-module (guix deprecation)
  #:use-module (guix utils)
  #:use-module (guix packages)
  #:export (sddm-configuration
            sddm-configuration?
            sddm-service-type
            sddm-service))

(define-record-type* <sddm-configuration>
  sddm-configuration      make-sddm-configuration
  sddm-configuration?
  (sddm                   sddm-configuration-sddm
                          (default sddm))

  ;; [General]
  ;; valid values are x11 and wayland
  ;; currently doesn't do anything is enabled by wayland greeter PR
  (display-server         sddm-configuration-display-server
                          (default "x11"))
  ;; valid values are on, off or none
  (numlock                sddm-configuration-numlock
                          (default "on"))
  (halt-command           sddm-configuration-halt-command
                          (default (file-append shepherd "/sbin/halt")))
  (reboot-command         sddm-configuration-reboot-command
                          (default (file-append shepherd "/sbin/reboot")))

  ;; [Theme]
  ;; valid values are elarun, maldives or maya
  (theme                  sddm-configuration-theme
                          (default "maldives"))
  (themes-directory       sddm-configuration-themes-directory
                          (default "/run/current-system/profile/share/sddm/themes"))
  (faces-directory        sddm-configuration-faces-directory
                          (default "/run/current-system/profile/share/sddm/faces"))

  ;; [Users]
  (default-path           sddm-configuration-default-path
                          (default "/run/current-system/profile/bin"))
  (minimum-uid            sddm-configuration-minimum-uid
                          (default 1000))
  (maximum-uid            sddm-configuration-maximum-uid
                          (default 2000))
  (remember-last-user?    sddm-configuration-remember-last-user?
                          (default #t))
  (remember-last-session? sddm-configuration-remember-last-session?
                          (default #t))
  (hide-users             sddm-configuration-hide-users
                          (default ""))
  (hide-shells            sddm-configuration-hide-shells
                          (default (file-append shadow "/sbin/nologin")))

  ;; [Wayland]
  (session-command        sddm-configuration-session-command
                          (default (file-append sddm "/share/sddm/scripts/wayland-session")))
  (sessions-directory     sddm-configuration-sessions-directory
                          (default "/run/current-system/profile/share/wayland-sessions"))
  ;; [X11]
  (xorg-configuration     sddm-configuration-xorg
                          (default (xorg-configuration)))
  (xauth-path             sddm-configuration-xauth-path
                          (default (file-append xauth "/bin/xauth")))
  (xephyr-path            sddm-configuration-xephyr-path
                          (default (file-append xorg-server "/bin/Xephyr")))
  (xdisplay-start         sddm-configuration-xdisplay-start
                          (default (file-append sddm "/share/sddm/scripts/Xsetup")))
  (xdisplay-stop          sddm-configuration-xdisplay-stop
                          (default (file-append sddm "/share/sddm/scripts/Xstop")))
  (xsession-command       sddm-configuration-xsession-command
                          (default (xinitrc)))
  (xsessions-directory    sddm-configuration-xsessions-directory
                          (default "/run/current-system/profile/share/xsessions"))
  (minimum-vt             sddm-configuration-minimum-vt
                          (default 7))

  ;; [Autologin]
  (auto-login-user        sddm-configuration-auto-login-user
                          (default ""))
  ;; valid values are xfce.desktop gnome.desktop weston.desktop hawaii.desktop
  (auto-login-session     sddm-configuration-auto-login-session
                          (default ""))
  (relogin?               sddm-configuration-relogin?
                          (default #f)))

(define (sddm-configuration-file config)
  (mixed-text-file "sddm.conf" "
[General]
DisplayServer="        (sddm-configuration-display-server config)              "
Numlock="              (sddm-configuration-numlock config)                     "
HaltCommand="          (sddm-configuration-halt-command config)                "
RebootCommand="        (sddm-configuration-reboot-command config)              "

[Users]
DefaultPath="          (sddm-configuration-default-path config)                "
MinimumUid="           (number->string (sddm-configuration-minimum-uid config))"
MaximumUid="           (number->string (sddm-configuration-maximum-uid config))"
RememberLastUser="     (if (sddm-configuration-remember-last-user? config)
                           "true" "false")                                     "
RememberLastSession="  (if (sddm-configuration-remember-last-session? config)
                           "true" "false")                                     "
HideUsers="            (sddm-configuration-hide-users config)                  "
Hideshells="           (sddm-configuration-hide-shells config)                 "

[Theme]
Current="              (sddm-configuration-theme config)                       "
ThemeDir="             (sddm-configuration-themes-directory config)            "
FacesDir="             (sddm-configuration-faces-directory config)             "

[Wayland]
SessionCommand="       (sddm-configuration-session-command config)             "
SessionDir="           (sddm-configuration-sessions-directory config)          "

[X11]
ServerPath="           (xorg-start-command (sddm-configuration-xorg config))   "
XauthPath="            (sddm-configuration-xauth-path config)                  "
XephyrPath="           (sddm-configuration-xephyr-path config)                 "
DisplayCommand="       (sddm-configuration-xdisplay-start config)              "
DisplayStopCommand="   (sddm-configuration-xdisplay-stop config)               "
SessionCommand="       (sddm-configuration-xsession-command config)            "
SessionDir="           (sddm-configuration-xsessions-directory config)         "
MinimumVT="            (number->string (sddm-configuration-minimum-vt config)) "
ServerArguments="      (string-join
                        (xorg-configuration-server-arguments
                         (sddm-configuration-xorg config)))           "

[Autologin]
User="                 (sddm-configuration-auto-login-user config)             "
Session="              (sddm-configuration-auto-login-session config)          "
Relogin="              (if (sddm-configuration-relogin? config)
                           "true" "false")                                     "
"))

(define (sddm-shepherd-service config)
  "Return a <shepherd-service> for sddm with CONFIG."

  (define sddm (sddm-configuration-sddm config))
  (define qt6? (version-prefix?
                "6"
                (package-version (lookup-package-input sddm "qtbase"))))

  (define sddm-command
    #~(list (string-append #$sddm "/bin/sddm")))

  (list (shepherd-service
         (documentation "SDDM display manager.")
         (requirement '(user-processes elogind pam))
         (provision '(xorg-server display-manager))
         (start #~(make-forkexec-constructor
                   #$sddm-command
                   ;; some theme need icon,qml,data so add path to env.
                   #:environment-variables
                   (cons*
                    "XDG_DATA_DIRS=/run/current-system/profile/share"
                    "XDG_CONFIG_DIRS=/run/current-system/profile/etc/xdg"
                    #$(string-append "QT_PLUGIN_PATH=/run/current-system/profile/lib/qt"
                                     (if qt6? "6" "5")
                                     "/plugins")
                    #$(string-append "QML" (if qt6? "" "2")
                                     "_IMPORT_PATH=/run/current-system/profile/lib/qt"
                                     (if qt6? "6" "5") "/qml")
                    (default-environment-variables))))
         (stop #~(make-kill-destructor)))))

(define (sddm-etc-service config)
  (list `("sddm.conf" ,(sddm-configuration-file config))))

(define (sddm-pam-service config)
  "Return a PAM service for @command{sddm}."
  (pam-service
   (name "sddm")
   (auth
    (list
     (pam-entry
      (control "requisite")
      (module "pam_nologin.so"))
     (pam-entry
      (control "required")
      (module "pam_env.so"))
     (pam-entry
      (control "required")
      (module "pam_succeed_if.so")
      (arguments (list (string-append "uid >= "
                                      (number->string (sddm-configuration-minimum-uid config)))
                       "quiet")))
     ;; should be factored out into system-auth
     (pam-entry
      (control "required")
      (module "pam_unix.so"))))
   (account
    (list
     ;; should be factored out into system-account
     (pam-entry
      (control "required")
      (module "pam_unix.so"))))
   (password
    (list
     ;; should be factored out into system-password
     (pam-entry
      (control "required")
      (module "pam_unix.so")
      (arguments (list "sha512" "shadow" "try_first_pass")))))
   (session
    (list
     ;; lfs has a required pam_limits.so
     ;; should be factored out into system-session
     (pam-entry
      (control "required")
      (module "pam_unix.so"))))))

(define (sddm-greeter-pam-service)
  "Return a PAM service for @command{sddm-greeter}."
  (pam-service
   (name "sddm-greeter")
   (auth
    (list
     ;; Load environment from /etc/environment and ~/.pam_environment
     (pam-entry
      (control "required")
      (module "pam_env.so"))
     ;; Always let the greeter start without authentication
     (pam-entry
      (control "required")
      (module "pam_permit.so"))))
   (account
    (list
     ;; No action required for account management
     (pam-entry
      (control "required")
      (module "pam_permit.so"))))
   (password
    (list
     ;; Can't change password
     (pam-entry
      (control "required")
      (module "pam_deny.so"))))
   (session
    (list
     ;; Setup session
     (pam-entry
      (control "required")
      (module "pam_unix.so"))))))

(define (sddm-autologin-pam-service config)
  "Return a PAM service for @command{sddm-autologin}"
  (pam-service
   (name "sddm-autologin")
   (auth
    (list
     (pam-entry
      (control "requisite")
      (module "pam_nologin.so"))
     (pam-entry
      (control "required")
      (module "pam_succeed_if.so")
      (arguments (list (string-append "uid >= "
                                      (number->string (sddm-configuration-minimum-uid config)))
                       "quiet")))
     (pam-entry
      (control "required")
      (module "pam_permit.so"))))
   (account
    (list
     (pam-entry
      (control "include")
      (module "sddm"))))
   (password
    (list
     (pam-entry
      (control "required")
      (module "pam_deny.so"))))
   (session
    (list
     (pam-entry
      (control "include")
      (module "sddm"))))))

(define (sddm-pam-services config)
  (list (sddm-pam-service config)
        (sddm-greeter-pam-service)
        (sddm-autologin-pam-service config)))

(define %sddm-accounts
  (list (user-group (name "sddm") (system? #t))
        (user-account
         (name "sddm")
         (group "sddm")
         (system? #t)
         (comment "SDDM user")
         (home-directory "/var/lib/sddm")
         (shell (file-append shadow "/sbin/nologin")))))

;; Add default themes to profile
(define sddm-profile-service
  (compose list sddm-configuration-sddm))

(define sddm-service-type
  (handle-xorg-configuration sddm-configuration
    (service-type (name 'sddm)
                  (extensions
                    (list (service-extension shepherd-root-service-type
                                             sddm-shepherd-service)
                          (service-extension etc-service-type
                                             sddm-etc-service)
                          (service-extension pam-root-service-type
                                             sddm-pam-services)
                          (service-extension account-service-type
                                             (const %sddm-accounts))
                          (service-extension profile-service-type
                                             sddm-profile-service)
                          (service-extension localed-service-type
                                             (compose
                                              xorg-configuration-keyboard-layout
                                              sddm-configuration-xorg))))
                  (default-value (sddm-configuration))
                  (description
                   "Run SDDM, a display and log-in manager for X11 and
Wayland."))))
if it was actually installed. Reported by peanutbutterandc on #guix. Tobias Geerinckx-Rice 2020-05-23guix-install.sh: Fix ‘systemctl not found’ error message at probe....* etc/guix-install.sh (chk_init_sys): Redirect systemctl errors to /dev/null. Signed-off-by: Tobias Geerinckx-Rice <me@tobias.gr> Vincent Legoll 2020-05-23guix-install.sh: Add xz to requirements....* etc/guix-install.sh (REQUIRE): Add xz to requirements list. Signed-off-by: Tobias Geerinckx-Rice <me@tobias.gr> Vincent Legoll 2020-05-17etc: Install mount unit only if it exists....This follows up on 1a1faa78b0498fbb71f1533beb4b65817c1d3f2a, and avoids the (non-fatal) error seen in <https://issues.guix.gnu.org/41356>. /gnu/store will remain writable on new foreign distribution installations until the next release. * etc/guix-install.sh (sys_enable_guix_daemon): Check for ‘gnu-store.mount’ presence before trying to cp it. Update forgotten copyright header. Tobias Geerinckx-Rice 2020-05-16etc: Add a systemd unit to bind-mount @storedir@ read-only....* etc/gnu-store.mount.in: New file. * nix/local.mk (nodist_systemdservice_DATA): Add it. (etc/%.mount): New rule for it. * etc/guix-install.sh (sys_enable_guix_daemon): Install it. * doc/guix.texi (Binary Installation): Document it. * .gitignore: Ignore changes to it. Tobias Geerinckx-Rice 2020-03-22guix-install.sh: /etc/profile.d/guix.sh sources ~/.guix-profile/etc/profile....* etc/guix-install.sh (sys_create_init_profile): Source ~/.guix-profile/etc/profile instead of running 'guix package --search-paths=prefix' Ludovic Courtès 2020-03-22guix-install.sh: Add a trailing colon to 'INFOPATH'....Fixes <https://bugs.gnu.org/39984>. Suggested by Adam Porter <adam@alphapapa.net>. * etc/guix-install.sh (sys_create_init_profile): Add a trailing colon to 'INFOPATH'. Ludovic Courtès 2020-03-11guix-install.sh: Install SysV init script....* etc/guix-install.sh (sys_enable_guix_daemon): Install SysV init script. Danny Milosavljevic 2020-01-26guix-install.sh: Correctly treat empty or unset $XDG_DATA_DIRS...If $XDG_DATA_DIRS is unset, default value of "/usr/local/share:/usr/share" is used according to XDG Base Directory Specification. However, /etc/profile.d/guix.sh treats this value as empty list when appending its own directory, so after installing Guix on the system, launchers such as Rofi stop searching for .desktop files in /usr/share/applications/ and can't launch applications other than those installed with Guix. This patch fixes the bug in generated /etc/profile.d/guix.sh * etc/guix-install.sh (sys_create_init_profile): Use default value of /usr/local/share:/usr/share/ before appending if $XDG_DATA_DIRS is not set. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Alexander Krotov 2020-01-26guix-install.sh: Create /etc/profile.d if it does not exist...* etc/guix-install.sh (sys_create_init_profile): Add code to create /etc/profile.d if it somehow does not exist; the function still carries on because it is possible that /etc/profile is still configured to read the *.sh files from /etc/profile.d, if they exist. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Prafulla Giri 2020-01-26guix-install.sh: Export INFOPATH to contain updated guix info-pages...* etc/guix-install.sh (sys_create_init_profile): Export INFOPATH to include the updated info-pages from ~/.config/guix/current/share/info. This also makes sure that both /usr/bin/info and $GUIX_PROFILE/bin/info can read guix info pages without throwing "no menu item 'guix' in node dir(Top)" error. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Prafulla Giri 2020-01-17guix-install.sh: Create an init profile during installation...Create an init profile (/etc/profile.d/guix.sh) during installation for better integration with foreign distros. This file, read by login-shells sets a few environment variables (PATH, GUIX_PROFILE, GUIX_LOCALE, along with XDG_DATA_DIRS) and makes guix-installed packages readily available for the users. Other environment variables, as listed by `guix package --search-paths=prefix`, are also exported. Checks are in place to prevent the init profile from needlessly polluting the user's environment. * etc/guix-install.sh (sys_create_init_profile): New function to create /etc/profile.d/guix.sh init profile. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Prafulla Giri 2019-12-04guix-install.sh: Use a deterministic umask....Users with strict umasks (e.g. 0077) would end up with an unreadable /gnu (mode 0700) and no way to run guix. Reported by A. <@aaap:matrix.org> on #guix. * etc/guix-install.sh (main): Set umask before installing anything. Tobias Geerinckx-Rice 2019-09-05guix-install.sh: Work around locale issues in 'guix-daemon.service'....* etc/guix-install.sh (sys_enable_guix_daemon): Modify 'guix-daemon.service' to work around locale issues not fixed in 1.0.1. Ludovic Courtès 2019-07-08guix-install.sh: Don't initialise ~/.gnupg....* etc/guix-install.sh (chk_gpg_keyring): Call gpg with ‘--dry-run’. Tobias Geerinckx-Rice 2019-07-08guix-install.sh: Check for PGP key separately....* etc/guix-install.sh (chk_gpg_keyring): New function to handle the public key check previously stuffed into chk_require. (main): Call it. Tobias Geerinckx-Rice 2019-07-08guix-install.sh: Add missing ‘local’ declaration....* etc/guix-install.sh (chk_require): Make $c local. Tobias Geerinckx-Rice 2019-07-08guix-install.sh: Treat REQUIRE as the array it is....Don't flatten it into a string only to split it again later. * etc/guix-install.sh (chk_require): Iterate over array elements, not string tokens. (main): Pass $REQUIRE as an array of arguments. Tobias Geerinckx-Rice 2019-07-01etc: Do not recommend use of SKS key servers....* etc/guix-install.sh: Recommend downloading the GPG key from Savannah. Ricardo Wurmus 2019-06-29guix-install.sh: Don't authorise hydra.gnu.org....* etc/guix-install.sh (sys_authorize_build_farms): Authorise only ci.guix.gnu.org and make all references to it singular. Tobias Geerinckx-Rice