at 23.11-pre 11 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 xcfg = config.services.xserver; 8 dmcfg = xcfg.displayManager; 9 xEnv = config.systemd.services.display-manager.environment; 10 cfg = dmcfg.lightdm; 11 sessionData = dmcfg.sessionData; 12 13 setSessionScript = pkgs.callPackage ./account-service-util.nix { }; 14 15 inherit (pkgs) lightdm writeScript writeText; 16 17 # lightdm runs with clearenv(), but we need a few things in the environment for X to startup 18 xserverWrapper = writeScript "xserver-wrapper" 19 '' 20 #! ${pkgs.bash}/bin/bash 21 ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} 22 23 display=$(echo "$@" | xargs -n 1 | grep -P ^:\\d\$ | head -n 1 | sed s/^://) 24 if [ -z "$display" ] 25 then additionalArgs=":0 -logfile /var/log/X.0.log" 26 else additionalArgs="-logfile /var/log/X.$display.log" 27 fi 28 29 exec ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} $additionalArgs "$@" 30 ''; 31 32 usersConf = writeText "users.conf" 33 '' 34 [UserList] 35 minimum-uid=1000 36 hidden-users=${concatStringsSep " " dmcfg.hiddenUsers} 37 hidden-shells=/run/current-system/sw/bin/nologin 38 ''; 39 40 lightdmConf = writeText "lightdm.conf" 41 '' 42 [LightDM] 43 ${optionalString cfg.greeter.enable '' 44 greeter-user = ${config.users.users.lightdm.name} 45 greeters-directory = ${cfg.greeter.package} 46 ''} 47 sessions-directory = ${dmcfg.sessionData.desktops}/share/xsessions:${dmcfg.sessionData.desktops}/share/wayland-sessions 48 ${cfg.extraConfig} 49 50 [Seat:*] 51 xserver-command = ${xserverWrapper} 52 session-wrapper = ${dmcfg.sessionData.wrapper} 53 ${optionalString cfg.greeter.enable '' 54 greeter-session = ${cfg.greeter.name} 55 ''} 56 ${optionalString dmcfg.autoLogin.enable '' 57 autologin-user = ${dmcfg.autoLogin.user} 58 autologin-user-timeout = ${toString cfg.autoLogin.timeout} 59 autologin-session = ${sessionData.autologinSession} 60 ''} 61 ${optionalString (dmcfg.setupCommands != "") '' 62 display-setup-script=${pkgs.writeScript "lightdm-display-setup" '' 63 #!${pkgs.bash}/bin/bash 64 ${dmcfg.setupCommands} 65 ''} 66 ''} 67 ${cfg.extraSeatDefaults} 68 ''; 69 70in 71{ 72 meta = with lib; { 73 maintainers = with maintainers; [ ] ++ teams.pantheon.members; 74 }; 75 76 # Note: the order in which lightdm greeter modules are imported 77 # here determines the default: later modules (if enable) are 78 # preferred. 79 imports = [ 80 ./lightdm-greeters/gtk.nix 81 ./lightdm-greeters/mini.nix 82 ./lightdm-greeters/enso-os.nix 83 ./lightdm-greeters/pantheon.nix 84 ./lightdm-greeters/tiny.nix 85 ./lightdm-greeters/slick.nix 86 ./lightdm-greeters/mobile.nix 87 (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "enable" ] [ 88 "services" 89 "xserver" 90 "displayManager" 91 "autoLogin" 92 "enable" 93 ]) 94 (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "user" ] [ 95 "services" 96 "xserver" 97 "displayManager" 98 "autoLogin" 99 "user" 100 ]) 101 ]; 102 103 options = { 104 105 services.xserver.displayManager.lightdm = { 106 107 enable = mkOption { 108 type = types.bool; 109 default = false; 110 description = lib.mdDoc '' 111 Whether to enable lightdm as the display manager. 112 ''; 113 }; 114 115 greeter = { 116 enable = mkOption { 117 type = types.bool; 118 default = true; 119 description = lib.mdDoc '' 120 If set to false, run lightdm in greeterless mode. This only works if autologin 121 is enabled and autoLogin.timeout is zero. 122 ''; 123 }; 124 package = mkOption { 125 type = types.package; 126 description = lib.mdDoc '' 127 The LightDM greeter to login via. The package should be a directory 128 containing a .desktop file matching the name in the 'name' option. 129 ''; 130 131 }; 132 name = mkOption { 133 type = types.str; 134 description = lib.mdDoc '' 135 The name of a .desktop file in the directory specified 136 in the 'package' option. 137 ''; 138 }; 139 }; 140 141 extraConfig = mkOption { 142 type = types.lines; 143 default = ""; 144 example = '' 145 user-authority-in-system-dir = true 146 ''; 147 description = lib.mdDoc "Extra lines to append to LightDM section."; 148 }; 149 150 background = mkOption { 151 type = types.either types.path (types.strMatching "^#[0-9]\{6\}$"); 152 # Manual cannot depend on packages, we are actually setting the default in config below. 153 defaultText = literalExpression "pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath"; 154 description = lib.mdDoc '' 155 The background image or color to use. 156 ''; 157 }; 158 159 extraSeatDefaults = mkOption { 160 type = types.lines; 161 default = ""; 162 example = '' 163 greeter-show-manual-login=true 164 ''; 165 description = lib.mdDoc "Extra lines to append to SeatDefaults section."; 166 }; 167 168 # Configuration for automatic login specific to LightDM 169 autoLogin.timeout = mkOption { 170 type = types.int; 171 default = 0; 172 description = lib.mdDoc '' 173 Show the greeter for this many seconds before automatic login occurs. 174 ''; 175 }; 176 177 }; 178 }; 179 180 config = mkIf cfg.enable { 181 182 assertions = [ 183 { assertion = xcfg.enable; 184 message = '' 185 LightDM requires services.xserver.enable to be true 186 ''; 187 } 188 { assertion = dmcfg.autoLogin.enable -> sessionData.autologinSession != null; 189 message = '' 190 LightDM auto-login requires that services.xserver.displayManager.defaultSession is set. 191 ''; 192 } 193 { assertion = !cfg.greeter.enable -> (dmcfg.autoLogin.enable && cfg.autoLogin.timeout == 0); 194 message = '' 195 LightDM can only run without greeter if automatic login is enabled and the timeout for it 196 is set to zero. 197 ''; 198 } 199 ]; 200 201 # Keep in sync with the defaultText value from the option definition. 202 services.xserver.displayManager.lightdm.background = mkDefault pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath; 203 204 # Set default session in session chooser to a specified values – basically ignore session history. 205 # Auto-login is already covered by a config value. 206 services.xserver.displayManager.job.preStart = optionalString (!dmcfg.autoLogin.enable && dmcfg.defaultSession != null) '' 207 ${setSessionScript}/bin/set-session ${dmcfg.defaultSession} 208 ''; 209 210 # setSessionScript needs session-files in XDG_DATA_DIRS 211 services.xserver.displayManager.job.environment.XDG_DATA_DIRS = "${dmcfg.sessionData.desktops}/share/"; 212 213 # setSessionScript wants AccountsService 214 systemd.services.display-manager.wants = [ 215 "accounts-daemon.service" 216 ]; 217 218 # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH 219 services.xserver.displayManager.job.execCmd = '' 220 export PATH=${lightdm}/sbin:$PATH 221 exec ${lightdm}/sbin/lightdm 222 ''; 223 224 # Replaces getty 225 systemd.services.display-manager.conflicts = [ 226 "getty@tty7.service" 227 # TODO: Add "plymouth-quit.service" so LightDM can control when plymouth 228 # quits. Currently this breaks switching to configurations with plymouth. 229 ]; 230 231 # Pull in dependencies of services we replace. 232 systemd.services.display-manager.after = [ 233 "rc-local.service" 234 "systemd-machined.service" 235 "systemd-user-sessions.service" 236 "getty@tty7.service" 237 "user.slice" 238 ]; 239 240 # user.slice needs to be present 241 systemd.services.display-manager.requires = [ 242 "user.slice" 243 ]; 244 245 # lightdm stops plymouth so when it fails make sure plymouth stops. 246 systemd.services.display-manager.onFailure = [ 247 "plymouth-quit.service" 248 ]; 249 250 systemd.services.display-manager.serviceConfig = { 251 BusName = "org.freedesktop.DisplayManager"; 252 IgnoreSIGPIPE = "no"; 253 # This allows lightdm to pass the LUKS password through to PAM. 254 # login keyring is unlocked automatic when autologin is used. 255 KeyringMode = "shared"; 256 KillMode = "mixed"; 257 StandardError = "inherit"; 258 }; 259 260 environment.etc."lightdm/lightdm.conf".source = lightdmConf; 261 environment.etc."lightdm/users.conf".source = usersConf; 262 263 services.dbus.enable = true; 264 services.dbus.packages = [ lightdm ]; 265 266 # lightdm uses the accounts daemon to remember language/window-manager per user 267 services.accounts-daemon.enable = true; 268 269 # Enable the accounts daemon to find lightdm's dbus interface 270 environment.systemPackages = [ lightdm ]; 271 272 security.polkit.enable = true; 273 274 security.pam.services.lightdm.text = '' 275 auth substack login 276 account include login 277 password substack login 278 session include login 279 ''; 280 281 security.pam.services.lightdm-greeter.text = '' 282 auth required pam_succeed_if.so audit quiet_success user = lightdm 283 auth optional pam_permit.so 284 285 account required pam_succeed_if.so audit quiet_success user = lightdm 286 account sufficient pam_unix.so 287 288 password required pam_deny.so 289 290 session required pam_succeed_if.so audit quiet_success user = lightdm 291 session required pam_env.so conffile=/etc/pam/environment readenv=0 292 session optional ${config.systemd.package}/lib/security/pam_systemd.so 293 session optional pam_keyinit.so force revoke 294 session optional pam_permit.so 295 ''; 296 297 security.pam.services.lightdm-autologin.text = '' 298 auth requisite pam_nologin.so 299 300 auth required pam_succeed_if.so uid >= 1000 quiet 301 auth required pam_permit.so 302 303 account sufficient pam_unix.so 304 305 password requisite pam_unix.so nullok yescrypt 306 307 session optional pam_keyinit.so revoke 308 session include login 309 ''; 310 311 users.users.lightdm = { 312 home = "/var/lib/lightdm"; 313 group = "lightdm"; 314 uid = config.ids.uids.lightdm; 315 }; 316 317 systemd.tmpfiles.rules = [ 318 "d /run/lightdm 0711 lightdm lightdm -" 319 "d /var/cache/lightdm 0711 root lightdm -" 320 "d /var/lib/lightdm 1770 lightdm lightdm -" 321 "d /var/lib/lightdm-data 1775 lightdm lightdm -" 322 "d /var/log/lightdm 0711 root lightdm -" 323 ]; 324 325 users.groups.lightdm.gid = config.ids.gids.lightdm; 326 services.xserver.tty = null; # We might start multiple X servers so let the tty increment themselves.. 327 services.xserver.display = null; # We specify our own display (and logfile) in xserver-wrapper up there 328 }; 329}