1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.xserver.displayManager;
8 gnome3 = config.environment.gnome3.packageSet;
9 gdm = gnome3.gdm;
10
11in
12
13{
14
15 ###### interface
16
17 options = {
18
19 services.xserver.displayManager.gdm = {
20
21 enable = mkEnableOption ''
22 GDM as the display manager.
23 <emphasis>GDM in NixOS is not well-tested with desktops other
24 than GNOME, so use with caution, as it could render the
25 system unusable.</emphasis>
26 '';
27
28 debug = mkEnableOption ''
29 debugging messages in GDM
30 '';
31
32 autoLogin = mkOption {
33 default = {};
34 description = ''
35 Auto login configuration attrset.
36 '';
37
38 type = types.submodule {
39 options = {
40 enable = mkOption {
41 type = types.bool;
42 default = false;
43 description = ''
44 Automatically log in as the sepecified <option>autoLogin.user</option>.
45 '';
46 };
47
48 user = mkOption {
49 type = types.nullOr types.str;
50 default = null;
51 description = ''
52 User to be used for the autologin.
53 '';
54 };
55
56 delay = mkOption {
57 type = types.int;
58 default = 0;
59 description = ''
60 Seconds of inactivity after which the autologin will be performed.
61 '';
62 };
63
64 };
65 };
66 };
67
68 };
69
70 };
71
72
73 ###### implementation
74
75 config = mkIf cfg.gdm.enable {
76
77 assertions = [
78 { assertion = cfg.gdm.autoLogin.enable -> cfg.gdm.autoLogin.user != null;
79 message = "GDM auto-login requires services.xserver.displayManager.gdm.autoLogin.user to be set";
80 }
81 ];
82
83 services.xserver.displayManager.slim.enable = false;
84
85 users.extraUsers.gdm =
86 { name = "gdm";
87 uid = config.ids.uids.gdm;
88 group = "gdm";
89 home = "/run/gdm";
90 description = "GDM user";
91 };
92
93 users.extraGroups.gdm.gid = config.ids.gids.gdm;
94
95 services.xserver.displayManager.job =
96 {
97 environment = {
98 GDM_X_SERVER = "${cfg.xserverBin} ${cfg.xserverArgs}";
99 GDM_SESSIONS_DIR = "${cfg.session.desktops}";
100 XDG_CONFIG_DIRS = "${gnome3.gnome_settings_daemon}/etc/xdg";
101 # Find the mouse
102 XCURSOR_PATH = "~/.icons:${config.system.path}/share/icons";
103 };
104 execCmd = "exec ${gdm}/bin/gdm";
105 };
106
107 # Because sd_login_monitor_new requires /run/systemd/machines
108 systemd.services.display-manager.wants = [ "systemd-machined.service" ];
109 systemd.services.display-manager.after = [ "systemd-machined.service" ];
110
111 systemd.services.display-manager.path = [ gnome3.gnome_shell gnome3.caribou pkgs.xorg.xhost pkgs.dbus_tools ];
112
113 services.dbus.packages = [ gdm ];
114
115 programs.dconf.profiles.gdm = "${gdm}/share/dconf/profile/gdm";
116
117 # Use AutomaticLogin if delay is zero, because it's immediate.
118 # Otherwise with TimedLogin with zero seconds the prompt is still
119 # presented and there's a little delay.
120 environment.etc."gdm/custom.conf".text = ''
121 [daemon]
122 ${optionalString cfg.gdm.autoLogin.enable (
123 if cfg.gdm.autoLogin.delay > 0 then ''
124 TimedLoginEnable=true
125 TimedLogin=${cfg.gdm.autoLogin.user}
126 TimedLoginDelay=${toString cfg.gdm.autoLogin.delay}
127 '' else ''
128 AutomaticLoginEnable=true
129 AutomaticLogin=${cfg.gdm.autoLogin.user}
130 '')
131 }
132
133 [security]
134
135 [xdmcp]
136
137 [greeter]
138
139 [chooser]
140
141 [debug]
142 ${optionalString cfg.gdm.debug "Enable=true"}
143 '';
144
145 # GDM LFS PAM modules, adapted somehow to NixOS
146 security.pam.services = {
147 gdm-launch-environment.text = ''
148 auth required pam_succeed_if.so audit quiet_success user = gdm
149 auth optional pam_permit.so
150
151 account required pam_succeed_if.so audit quiet_success user = gdm
152 account sufficient pam_unix.so
153
154 password required pam_deny.so
155
156 session required pam_succeed_if.so audit quiet_success user = gdm
157 session required pam_env.so envfile=${config.system.build.pamEnvironment}
158 session optional ${pkgs.systemd}/lib/security/pam_systemd.so
159 session optional pam_keyinit.so force revoke
160 session optional pam_permit.so
161 '';
162
163 gdm.text = ''
164 auth requisite pam_nologin.so
165 auth required pam_env.so envfile=${config.system.build.pamEnvironment}
166
167 auth required pam_succeed_if.so uid >= 1000 quiet
168 auth optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
169 auth ${if config.security.pam.enableEcryptfs then "required" else "sufficient"} pam_unix.so nullok likeauth
170 ${optionalString config.security.pam.enableEcryptfs
171 "auth required ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
172
173 ${optionalString (! config.security.pam.enableEcryptfs)
174 "auth required pam_deny.so"}
175
176 account sufficient pam_unix.so
177
178 password requisite pam_unix.so nullok sha512
179 ${optionalString config.security.pam.enableEcryptfs
180 "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
181
182 session required pam_env.so envfile=${config.system.build.pamEnvironment}
183 session required pam_unix.so
184 ${optionalString config.security.pam.enableEcryptfs
185 "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
186 session required pam_loginuid.so
187 session optional ${pkgs.systemd}/lib/security/pam_systemd.so
188 session optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start
189 '';
190
191 gdm-password.text = ''
192 auth requisite pam_nologin.so
193 auth required pam_env.so envfile=${config.system.build.pamEnvironment}
194
195 auth required pam_succeed_if.so uid >= 1000 quiet
196 auth optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
197 auth ${if config.security.pam.enableEcryptfs then "required" else "sufficient"} pam_unix.so nullok likeauth
198 ${optionalString config.security.pam.enableEcryptfs
199 "auth required ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
200 ${optionalString (! config.security.pam.enableEcryptfs)
201 "auth required pam_deny.so"}
202
203 account sufficient pam_unix.so
204
205 password requisite pam_unix.so nullok sha512
206 ${optionalString config.security.pam.enableEcryptfs
207 "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
208
209 session required pam_env.so envfile=${config.system.build.pamEnvironment}
210 session required pam_unix.so
211 ${optionalString config.security.pam.enableEcryptfs
212 "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
213 session required pam_loginuid.so
214 session optional ${pkgs.systemd}/lib/security/pam_systemd.so
215 session optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start
216 '';
217
218 gdm-autologin.text = ''
219 auth requisite pam_nologin.so
220
221 auth required pam_succeed_if.so uid >= 1000 quiet
222 auth required pam_permit.so
223
224 account sufficient pam_unix.so
225
226 password requisite pam_unix.so nullok sha512
227
228 session optional pam_keyinit.so revoke
229 session required pam_env.so envfile=${config.system.build.pamEnvironment}
230 session required pam_unix.so
231 session required pam_loginuid.so
232 session optional ${pkgs.systemd}/lib/security/pam_systemd.so
233 '';
234
235 };
236
237 };
238
239}