at 24.11-pre 9.0 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 cfg = config.services.displayManager; 5 6 installedSessions = pkgs.runCommand "desktops" 7 { # trivial derivation 8 preferLocalBuild = true; 9 allowSubstitutes = false; 10 } 11 '' 12 mkdir -p "$out/share/"{xsessions,wayland-sessions} 13 14 ${lib.concatMapStrings (pkg: '' 15 for n in ${lib.concatStringsSep " " pkg.providedSessions}; do 16 if ! test -f ${pkg}/share/wayland-sessions/$n.desktop -o \ 17 -f ${pkg}/share/xsessions/$n.desktop; then 18 echo "Couldn't find provided session name, $n.desktop, in session package ${pkg.name}:" 19 echo " ${pkg}" 20 return 1 21 fi 22 done 23 24 if test -d ${pkg}/share/xsessions; then 25 ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions 26 fi 27 if test -d ${pkg}/share/wayland-sessions; then 28 ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/wayland-sessions $out/share/wayland-sessions 29 fi 30 '') cfg.sessionPackages} 31 ''; 32in 33{ 34 options = { 35 services.displayManager = { 36 enable = lib.mkEnableOption "systemd's display-manager service"; 37 38 preStart = lib.mkOption { 39 type = lib.types.lines; 40 default = ""; 41 example = "rm -f /var/log/my-display-manager.log"; 42 description = "Script executed before the display manager is started."; 43 }; 44 45 execCmd = lib.mkOption { 46 type = lib.types.str; 47 example = lib.literalExpression ''"''${pkgs.lightdm}/bin/lightdm"''; 48 description = "Command to start the display manager."; 49 }; 50 51 environment = lib.mkOption { 52 type = with lib.types; attrsOf unspecified; 53 default = {}; 54 description = "Additional environment variables needed by the display manager."; 55 }; 56 57 hiddenUsers = lib.mkOption { 58 type = with lib.types; listOf str; 59 default = [ "nobody" ]; 60 description = '' 61 A list of users which will not be shown in the display manager. 62 ''; 63 }; 64 65 logToFile = lib.mkOption { 66 type = lib.types.bool; 67 default = false; 68 description = '' 69 Whether the display manager redirects the output of the 70 session script to {file}`~/.xsession-errors`. 71 ''; 72 }; 73 74 logToJournal = lib.mkOption { 75 type = lib.types.bool; 76 default = true; 77 description = '' 78 Whether the display manager redirects the output of the 79 session script to the systemd journal. 80 ''; 81 }; 82 83 # Configuration for automatic login. Common for all DM. 84 autoLogin = lib.mkOption { 85 type = lib.types.submodule ({ config, options, ... }: { 86 options = { 87 enable = lib.mkOption { 88 type = lib.types.bool; 89 default = config.user != null; 90 defaultText = lib.literalExpression "config.${options.user} != null"; 91 description = '' 92 Automatically log in as {option}`autoLogin.user`. 93 ''; 94 }; 95 96 user = lib.mkOption { 97 type = with lib.types; nullOr str; 98 default = null; 99 description = '' 100 User to be used for the automatic login. 101 ''; 102 }; 103 }; 104 }); 105 106 default = {}; 107 description = '' 108 Auto login configuration attrset. 109 ''; 110 }; 111 112 defaultSession = lib.mkOption { 113 type = lib.types.nullOr lib.types.str // { 114 description = "session name"; 115 check = d: 116 lib.assertMsg (d != null -> (lib.types.str.check d && lib.elem d cfg.sessionData.sessionNames)) '' 117 Default graphical session, '${d}', not found. 118 Valid names for 'services.displayManager.defaultSession' are: 119 ${lib.concatStringsSep "\n " cfg.sessionData.sessionNames} 120 ''; 121 }; 122 default = null; 123 example = "gnome"; 124 description = '' 125 Graphical session to pre-select in the session chooser (only effective for GDM, LightDM and SDDM). 126 127 On GDM, LightDM and SDDM, it will also be used as a session for auto-login. 128 ''; 129 }; 130 131 sessionData = lib.mkOption { 132 description = "Data exported for display managers convenience"; 133 internal = true; 134 default = {}; 135 }; 136 137 sessionPackages = lib.mkOption { 138 type = lib.types.listOf (lib.types.package // { 139 description = "package with provided sessions"; 140 check = p: lib.assertMsg 141 (lib.types.package.check p && p ? providedSessions 142 && p.providedSessions != [] && lib.all lib.isString p.providedSessions) 143 '' 144 Package, '${p.name}', did not specify any session names, as strings, in 145 'passthru.providedSessions'. This is required when used as a session package. 146 147 The session names can be looked up in: 148 ${p}/share/xsessions 149 ${p}/share/wayland-sessions 150 ''; 151 }); 152 default = []; 153 description = '' 154 A list of packages containing x11 or wayland session files to be passed to the display manager. 155 ''; 156 }; 157 }; 158 }; 159 160 imports = [ 161 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "autoLogin" ] [ "services" "displayManager" "autoLogin" ]) 162 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "defaultSession" ] [ "services" "displayManager" "defaultSession" ]) 163 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "hiddenUsers" ] [ "services" "displayManager" "hiddenUsers" ]) 164 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "environment" ] [ "services" "displayManager" "environment" ]) 165 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "execCmd" ] [ "services" "displayManager" "execCmd" ]) 166 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logToFile" ] [ "services" "displayManager" "logToFile" ]) 167 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logToJournal" ] [ "services" "displayManager" "logToJournal" ]) 168 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "preStart" ] [ "services" "displayManager" "preStart" ]) 169 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "sessionData" ] [ "services" "displayManager" "sessionData" ]) 170 (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "sessionPackages" ] [ "services" "displayManager" "sessionPackages" ]) 171 ]; 172 173 config = lib.mkIf cfg.enable { 174 assertions = [ 175 { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null; 176 message = '' 177 services.displayManager.autoLogin.enable requires services.displayManager.autoLogin.user to be set 178 ''; 179 } 180 ]; 181 182 # Make xsessions and wayland sessions available in XDG_DATA_DIRS 183 # as some programs have behavior that depends on them being present 184 environment.sessionVariables.XDG_DATA_DIRS = lib.mkIf (cfg.sessionPackages != [ ]) [ 185 "${cfg.sessionData.desktops}/share" 186 ]; 187 188 services.displayManager.sessionData = { 189 desktops = installedSessions; 190 sessionNames = lib.concatMap (p: p.providedSessions) cfg.sessionPackages; 191 # We do not want to force users to set defaultSession when they have only single DE. 192 autologinSession = 193 if cfg.defaultSession != null then 194 cfg.defaultSession 195 else if cfg.sessionData.sessionNames != [] then 196 lib.head cfg.sessionData.sessionNames 197 else 198 null; 199 }; 200 201 # so that the service won't be enabled when only startx is used 202 systemd.services.display-manager.enable = 203 let dmConf = config.services.xserver.displayManager; 204 noDmUsed = !(dmConf.gdm.enable 205 || cfg.sddm.enable 206 || dmConf.xpra.enable 207 || dmConf.lightdm.enable); 208 in lib.mkIf noDmUsed (lib.mkDefault false); 209 210 systemd.services.display-manager = { 211 description = "Display Manager"; 212 after = [ "acpid.service" "systemd-logind.service" "systemd-user-sessions.service" ]; 213 restartIfChanged = false; 214 215 environment = lib.optionalAttrs config.hardware.opengl.setLdLibraryPath { 216 LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ]; 217 } // cfg.environment; 218 219 preStart = cfg.preStart; 220 script = lib.mkIf (config.systemd.services.display-manager.enable == true) cfg.execCmd; 221 222 # Stop restarting if the display manager stops (crashes) 2 times 223 # in one minute. Starting X typically takes 3-4s. 224 startLimitIntervalSec = 30; 225 startLimitBurst = 3; 226 serviceConfig = { 227 Restart = "always"; 228 RestartSec = "200ms"; 229 SyslogIdentifier = "display-manager"; 230 }; 231 }; 232 }; 233}