@@ -49,6 +49,7 @@
#:use-module (gnu system pam)
#:use-module (gnu packages glib)
#:use-module (gnu packages admin)
+ #:use-module (gnu packages bash)
#:use-module (gnu packages cups)
#:use-module (gnu packages freedesktop)
#:use-module (gnu packages gnome)
@@ -1239,6 +1240,215 @@ or setting its password with passwd.")))
seatd-shepherd-service)))
(default-value (seatd-configuration))))
+
+;;;
+;;; greetd-service-type -- minimal and flexible login manager daemon
+;;;
+
+(define-record-type* <greetd-agreety-session>
+ greetd-agreety-session make-greetd-agreety-session
+ greetd-agreety-session?
+ (package greetd-agreety-command-package (default bash))
+ (command-bin greetd-agreety-command-bin (default "/bin/bash"))
+ (command-args greetd-agreety-command-args (default '("-l")))
+ (extra-env greetd-agreety-extra-env (default '()))
+ (command-generator greetd-agreety-command-generator))
+
+(define greetd-agreety-tty-session-command
+ (match-lambda
+ (($ <greetd-agreety-session> pkg command-bin command-args extra-env)
+ (program-file
+ "agreety-tty-session-command"
+ #~(begin
+ (use-modules (ice-9 match))
+ (let* ((abs-cmd-bin #$(file-append pkg command-bin)))
+ (for-each
+ (match-lambda ((var . val) (setenv var val)))
+ (quote (#$@extra-env)))
+ (apply execl abs-cmd-bin abs-cmd-bin
+ (list #$@command-args))))))))
+
+(define greetd-agreety-tty-xdg-session-command
+ (match-lambda
+ (($ <greetd-agreety-session> package command-bin command-args extra-env)
+ (program-file
+ "agreety-tty-xdg-session-command"
+ #~(begin
+ (use-modules (ice-9 popen) (ice-9 rdelim) (ice-9 match))
+ (let*
+ ((username (getenv "USER"))
+ (useruid (passwd:uid (getpwuid username)))
+ (useruid (number->string useruid))
+ (abs-cmd-bin #$(file-append package command-bin)))
+ (setenv "XDG_SESSION_TYPE" "tty")
+ (setenv "XDG_RUNTIME_DIR" (string-append "/run/user/" useruid))
+ (for-each
+ (match-lambda ((var . val) (setenv var val)))
+ (quote (#$@extra-env)))
+ (apply execl abs-cmd-bin abs-cmd-bin
+ (list #$@command-args))))))))
+
+(define greetd-agreety-tty-session
+ (greetd-agreety-session
+ (command-generator greetd-agreety-tty-session-command)))
+
+(define greetd-agreety-tty-xdg-session
+ (greetd-agreety-session
+ (command-generator greetd-agreety-tty-xdg-session-command)))
+
+(define-record-type* <greetd-terminal-configuration>
+ greetd-terminal-configuration make-greetd-terminal-configuration
+ greetd-terminal-configuration?
+ (greetd greetd-package (default greetd))
+ (config-file-name greetd-config-file-name (thunked)
+ (default (default-config-file-name this-record)))
+ (terminal-vt greetd-terminal-vt (default "7"))
+ (default-session-user greetd-default-session-user (default "greeter"))
+ (default-session-command greetd-default-session-command
+ (default greetd-agreety-tty-xdg-session)))
+
+(define (default-config-file-name config)
+ (string-join (list "config-" (greetd-terminal-vt config) ".toml") ""))
+
+(define make-greetd-terminal-default-session-command
+ (match-lambda
+ (($ <greetd-terminal-configuration> greetd _ _ _ default-session-command)
+ (cond ((greetd-agreety-session? default-session-command)
+ (let*
+ ((generator (greetd-agreety-command-generator
+ default-session-command))
+ (command (apply generator (list default-session-command)))
+ (agreety-bin (file-append greetd "/bin/agreety")))
+ (program-file
+ "agreety-command"
+ #~(execl #$agreety-bin #$agreety-bin "-c" #$command))))
+ (else (program-file "agreety-command-exit" #~(exit #f)))))))
+
+(define (make-greetd-terminal-configuration-file config)
+ (let*
+ ((config-file-name (greetd-config-file-name config))
+ (terminal-vt (greetd-terminal-vt config))
+ (default-session-user (greetd-default-session-user config))
+ (default-session-command (make-greetd-terminal-default-session-command config)))
+ (mixed-text-file
+ config-file-name
+ "[terminal]\n"
+ "vt = " terminal-vt "\n"
+ "[default_session]\n"
+ "user = " default-session-user "\n"
+ "command = " default-session-command "\n")))
+
+(define %default-motd
+ (plain-file "motd" "This is the GNU operating system, welcome!\n\n"))
+
+(define %greetd-accounts
+ (list (user-account (name "greeter") (group "wheel") (system? #t))))
+
+(define %greetd-file-systems
+ (list (file-system
+ (device "none")
+ (mount-point "/run/greetd/pam_mount")
+ (type "tmpfs")
+ (check? #f)
+ (flags '(no-suid no-dev no-exec))
+ (options "mode=0755")
+ (create-mount-point? #t))))
+
+(define %greetd-pam-mount-rules
+ `((debug (@ (enable "0")))
+ (volume (@ (sgrp "users")
+ (fstype "tmpfs")
+ (mountpoint "/run/user/%(USERUID)")
+ (options "noexec,nosuid,nodev,size=1g,mode=0700,uid=%(USERUID),gid=%(USERGID)")))
+ (logout (@ (wait "0")
+ (hup "0")
+ (term "yes")
+ (kill "no")))
+ (mkmountpoint (@ (enable "1") (remove "true")))))
+
+(define-record-type* <greetd-configuration>
+ greetd-configuration make-greetd-configuration
+ greetd-configuration?
+ (motd greetd-motd (default %default-motd))
+ (allow-empty-passwords? greetd-allow-empty-passwords? (default #t))
+ (terminals greetd-terminals (default '())))
+
+(define (make-greetd-pam-mount-conf-file config)
+ (computed-file
+ "greetd_pam_mount.conf.xml"
+ #~(begin
+ (use-modules (sxml simple))
+ (call-with-output-file #$output
+ (lambda (port)
+ (sxml->xml
+ '(*TOP*
+ (*PI* xml "version='1.0' encoding='utf-8'")
+ (pam_mount
+ #$@%greetd-pam-mount-rules
+ (pmvarrun
+ #$(file-append greetd-pam-mount
+ "/sbin/pmvarrun -u '%(USER)' -o '%(OPERATION)'"))))
+ port))))))
+
+(define (greetd-etc-service config)
+ `(("security/greetd_pam_mount.conf.xml"
+ ,(make-greetd-pam-mount-conf-file config))))
+
+(define (greetd-pam-service config)
+ (define optional-pam-mount
+ (pam-entry
+ (control "optional")
+ (module #~(string-append #$greetd-pam-mount "/lib/security/pam_mount.so"))))
+
+ (list
+ (unix-pam-service "greetd"
+ #:login-uid? #t
+ #:allow-empty-passwords?
+ (greetd-allow-empty-passwords? config)
+ #:motd
+ (greetd-motd config))
+ (lambda (pam)
+ (if (member (pam-service-name pam)
+ '("login" "greetd" "su" "slim" "gdm-password"))
+ (pam-service
+ (inherit pam)
+ (auth (append (pam-service-auth pam)
+ (list optional-pam-mount)))
+ (session (append (pam-service-session pam)
+ (list optional-pam-mount))))
+ pam))))
+
+(define (greetd-shepherd-services config)
+ (map
+ (lambda (tc)
+ (let*
+ ((greetd-bin (file-append (greetd-package tc) "/sbin/greetd"))
+ (greetd-conf (make-greetd-terminal-configuration-file tc))
+ (greetd-vt (greetd-terminal-vt tc)))
+ (shepherd-service
+ (requirement '(user-processes host-name udev virtual-terminal))
+ (provision (list (symbol-append
+ 'term-tty
+ (string->symbol (greetd-terminal-vt tc)))))
+ (start #~(make-forkexec-constructor
+ (list #$greetd-bin "-c" #$greetd-conf)
+ #:log-file
+ (string-append "/tmp/greetd." #$greetd-vt ".log")))
+ (stop #~(make-kill-destructor)))))
+ (greetd-terminals config)))
+
+(define greetd-service-type
+ (service-type
+ (name 'greetd)
+ (extensions
+ (list
+ (service-extension account-service-type (const %greetd-accounts))
+ (service-extension file-system-service-type (const %greetd-file-systems))
+ (service-extension etc-service-type greetd-etc-service)
+ (service-extension pam-root-service-type greetd-pam-service)
+ (service-extension shepherd-root-service-type greetd-shepherd-services)))
+ (default-value (greetd-configuration))))
+
;;;
;;; The default set of desktop services.