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