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}