1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 xcfg = config.services.xserver; 8 dmcfg = xcfg.displayManager; 9 cfg = dmcfg.sddm; 10 xEnv = config.systemd.services."display-manager".environment; 11 12 inherit (pkgs) sddm; 13 14 xserverWrapper = pkgs.writeScript "xserver-wrapper" '' 15 #!/bin/sh 16 ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} 17 exec systemd-cat ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} "$@" 18 ''; 19 20 Xsetup = pkgs.writeScript "Xsetup" '' 21 #!/bin/sh 22 ${cfg.setupScript} 23 ''; 24 25 Xstop = pkgs.writeScript "Xstop" '' 26 #!/bin/sh 27 ${cfg.stopScript} 28 ''; 29 30 cfgFile = pkgs.writeText "sddm.conf" '' 31 [General] 32 HaltCommand=${pkgs.systemd}/bin/systemctl poweroff 33 RebootCommand=${pkgs.systemd}/bin/systemctl reboot 34 ${optionalString cfg.autoNumlock '' 35 Numlock=on 36 ''} 37 38 [Theme] 39 Current=${cfg.theme} 40 ThemeDir=/run/current-system/sw/share/sddm/themes 41 FacesDir=/run/current-system/sw/share/sddm/faces 42 43 [Users] 44 MaximumUid=${toString config.ids.uids.nixbld} 45 HideUsers=${concatStringsSep "," dmcfg.hiddenUsers} 46 HideShells=/run/current-system/sw/bin/nologin 47 48 [X11] 49 MinimumVT=${toString (if xcfg.tty != null then xcfg.tty else 7)} 50 ServerPath=${xserverWrapper} 51 XephyrPath=${pkgs.xorg.xorgserver.out}/bin/Xephyr 52 SessionCommand=${dmcfg.session.script} 53 SessionDir=${dmcfg.session.desktops} 54 XauthPath=${pkgs.xorg.xauth}/bin/xauth 55 DisplayCommand=${Xsetup} 56 DisplayStopCommand=${Xstop} 57 58 ${optionalString cfg.autoLogin.enable '' 59 [Autologin] 60 User=${cfg.autoLogin.user} 61 Session=${defaultSessionName}.desktop 62 Relogin=${boolToString cfg.autoLogin.relogin} 63 ''} 64 65 ${cfg.extraConfig} 66 ''; 67 68 defaultSessionName = 69 let 70 dm = xcfg.desktopManager.default; 71 wm = xcfg.windowManager.default; 72 in dm + optionalString (wm != "none") ("+" + wm); 73 74in 75{ 76 options = { 77 78 services.xserver.displayManager.sddm = { 79 enable = mkOption { 80 type = types.bool; 81 default = false; 82 description = '' 83 Whether to enable sddm as the display manager. 84 ''; 85 }; 86 87 extraConfig = mkOption { 88 type = types.lines; 89 default = ""; 90 example = '' 91 [Autologin] 92 User=john 93 Session=plasma.desktop 94 ''; 95 description = '' 96 Extra lines appended to the configuration of SDDM. 97 ''; 98 }; 99 100 theme = mkOption { 101 type = types.str; 102 default = ""; 103 description = '' 104 Greeter theme to use. 105 ''; 106 }; 107 108 autoNumlock = mkOption { 109 type = types.bool; 110 default = false; 111 description = '' 112 Enable numlock at login. 113 ''; 114 }; 115 116 setupScript = mkOption { 117 type = types.str; 118 default = ""; 119 example = '' 120 # workaround for using NVIDIA Optimus without Bumblebee 121 xrandr --setprovideroutputsource modesetting NVIDIA-0 122 xrandr --auto 123 ''; 124 description = '' 125 A script to execute when starting the display server. 126 ''; 127 }; 128 129 stopScript = mkOption { 130 type = types.str; 131 default = ""; 132 description = '' 133 A script to execute when stopping the display server. 134 ''; 135 }; 136 137 autoLogin = mkOption { 138 default = {}; 139 description = '' 140 Configuration for automatic login. 141 ''; 142 143 type = types.submodule { 144 options = { 145 enable = mkOption { 146 type = types.bool; 147 default = false; 148 description = '' 149 Automatically log in as <option>autoLogin.user</option>. 150 ''; 151 }; 152 153 user = mkOption { 154 type = types.nullOr types.str; 155 default = null; 156 description = '' 157 User to be used for the automatic login. 158 ''; 159 }; 160 161 relogin = mkOption { 162 type = types.bool; 163 default = false; 164 description = '' 165 If true automatic login will kick in again on session exit (logout), otherwise it 166 will only log in automatically when the display-manager is started. 167 ''; 168 }; 169 }; 170 }; 171 }; 172 173 }; 174 175 }; 176 177 config = mkIf cfg.enable { 178 179 assertions = [ 180 { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null; 181 message = '' 182 SDDM auto-login requires services.xserver.displayManager.sddm.autoLogin.user to be set 183 ''; 184 } 185 { assertion = cfg.autoLogin.enable -> elem defaultSessionName dmcfg.session.names; 186 message = '' 187 SDDM auto-login requires that services.xserver.desktopManager.default and 188 services.xserver.windowMananger.default are set to valid values. The current 189 default session: ${defaultSessionName} is not valid. 190 ''; 191 } 192 ]; 193 194 services.xserver.displayManager.slim.enable = false; 195 196 services.xserver.displayManager.job = { 197 logsXsession = true; 198 199 environment = { 200 # Load themes from system environment 201 QT_PLUGIN_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtPluginPrefix; 202 QML2_IMPORT_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtQmlPrefix; 203 204 XDG_DATA_DIRS = "/run/current-system/sw/share"; 205 }; 206 207 execCmd = "exec /run/current-system/sw/bin/sddm"; 208 }; 209 210 security.pam.services = { 211 sddm = { 212 allowNullPassword = true; 213 startSession = true; 214 }; 215 216 sddm-greeter.text = '' 217 auth required pam_succeed_if.so audit quiet_success user = sddm 218 auth optional pam_permit.so 219 220 account required pam_succeed_if.so audit quiet_success user = sddm 221 account sufficient pam_unix.so 222 223 password required pam_deny.so 224 225 session required pam_succeed_if.so audit quiet_success user = sddm 226 session required pam_env.so envfile=${config.system.build.pamEnvironment} 227 session optional ${pkgs.systemd}/lib/security/pam_systemd.so 228 session optional pam_keyinit.so force revoke 229 session optional pam_permit.so 230 ''; 231 232 sddm-autologin.text = '' 233 auth requisite pam_nologin.so 234 auth required pam_succeed_if.so uid >= 1000 quiet 235 auth required pam_permit.so 236 237 account include sddm 238 239 password include sddm 240 241 session include sddm 242 ''; 243 }; 244 245 users.extraUsers.sddm = { 246 createHome = true; 247 home = "/var/lib/sddm"; 248 group = "sddm"; 249 uid = config.ids.uids.sddm; 250 }; 251 252 environment.etc."sddm.conf".source = cfgFile; 253 254 users.extraGroups.sddm.gid = config.ids.gids.sddm; 255 256 environment.systemPackages = [ sddm ]; 257 services.dbus.packages = [ sddm ]; 258 259 # To enable user switching, allow sddm to allocate TTYs/displays dynamically. 260 services.xserver.tty = null; 261 services.xserver.display = null; 262 }; 263}