1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 dmcfg = config.services.xserver.displayManager; 8 xEnv = config.systemd.services."display-manager".environment; 9 cfg = dmcfg.lightdm; 10 11 inherit (pkgs) stdenv lightdm writeScript writeText; 12 13 # lightdm runs with clearenv(), but we need a few things in the enviornment for X to startup 14 xserverWrapper = writeScript "xserver-wrapper" 15 '' 16 #! ${pkgs.bash}/bin/bash 17 ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} 18 19 display=$(echo "$@" | xargs -n 1 | grep -P ^:\\d\$ | head -n 1 | sed s/^://) 20 if [ -z "$display" ] 21 then additionalArgs=":0 -logfile /var/log/X.0.log" 22 else additionalArgs="-logfile /var/log/X.$display.log" 23 fi 24 25 exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs} $additionalArgs "$@" 26 ''; 27 28 usersConf = writeText "users.conf" 29 '' 30 [UserList] 31 minimum-uid=500 32 hidden-users=${concatStringsSep " " dmcfg.hiddenUsers} 33 hidden-shells=/run/current-system/sw/bin/nologin 34 ''; 35 36 lightdmConf = writeText "lightdm.conf" 37 '' 38 [LightDM] 39 greeter-user = ${config.users.extraUsers.lightdm.name} 40 greeters-directory = ${cfg.greeter.package} 41 sessions-directory = ${dmcfg.session.desktops} 42 43 [Seat:*] 44 xserver-command = ${xserverWrapper} 45 session-wrapper = ${dmcfg.session.script} 46 greeter-session = ${cfg.greeter.name} 47 ${cfg.extraSeatDefaults} 48 ''; 49in 50{ 51 # Note: the order in which lightdm greeter modules are imported 52 # here determines the default: later modules (if enable) are 53 # preferred. 54 imports = [ 55 ./lightdm-greeters/gtk.nix 56 ]; 57 58 options = { 59 60 services.xserver.displayManager.lightdm = { 61 62 enable = mkOption { 63 type = types.bool; 64 default = false; 65 description = '' 66 Whether to enable lightdm as the display manager. 67 ''; 68 }; 69 70 greeter = { 71 package = mkOption { 72 type = types.package; 73 description = '' 74 The LightDM greeter to login via. The package should be a directory 75 containing a .desktop file matching the name in the 'name' option. 76 ''; 77 78 }; 79 name = mkOption { 80 type = types.string; 81 description = '' 82 The name of a .desktop file in the directory specified 83 in the 'package' option. 84 ''; 85 }; 86 }; 87 88 background = mkOption { 89 type = types.str; 90 default = "${pkgs.nixos-artwork}/share/artwork/gnome/Gnome_Dark.png"; 91 description = '' 92 The background image or color to use. 93 ''; 94 }; 95 96 extraSeatDefaults = mkOption { 97 type = types.lines; 98 default = ""; 99 example = '' 100 greeter-show-manual-login=true 101 ''; 102 description = "Extra lines to append to SeatDefaults section."; 103 }; 104 105 }; 106 }; 107 108 config = mkIf cfg.enable { 109 services.xserver.displayManager.slim.enable = false; 110 111 services.xserver.displayManager.job = { 112 logsXsession = true; 113 114 # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH 115 execCmd = '' 116 export PATH=${lightdm}/sbin:$PATH 117 exec ${lightdm}/sbin/lightdm --log-dir=/var/log --run-dir=/run 118 ''; 119 }; 120 121 environment.etc."lightdm/lightdm.conf".source = lightdmConf; 122 environment.etc."lightdm/users.conf".source = usersConf; 123 124 services.dbus.enable = true; 125 services.dbus.packages = [ lightdm ]; 126 127 security.pam.services.lightdm = { 128 allowNullPassword = true; 129 startSession = true; 130 }; 131 security.pam.services.lightdm-greeter = { 132 allowNullPassword = true; 133 startSession = true; 134 text = '' 135 auth required pam_env.so envfile=${config.system.build.pamEnvironment} 136 auth required pam_permit.so 137 138 account required pam_permit.so 139 140 password required pam_deny.so 141 142 session required pam_env.so envfile=${config.system.build.pamEnvironment} 143 session required pam_unix.so 144 session optional ${pkgs.systemd}/lib/security/pam_systemd.so 145 ''; 146 }; 147 148 users.extraUsers.lightdm = { 149 createHome = true; 150 home = "/var/lib/lightdm-data"; 151 group = "lightdm"; 152 uid = config.ids.uids.lightdm; 153 }; 154 155 users.extraGroups.lightdm.gid = config.ids.gids.lightdm; 156 services.xserver.tty = null; # We might start multiple X servers so let the tty increment themselves.. 157 services.xserver.display = null; # We specify our own display (and logfile) in xserver-wrapper up there 158 }; 159}