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