1{ config, lib, pkgs, utils, ... }:
2
3with lib;
4
5let
6 cfg = config.services.logind;
7
8 logindHandlerType = types.enum [
9 "ignore" "poweroff" "reboot" "halt" "kexec" "suspend"
10 "hibernate" "hybrid-sleep" "suspend-then-hibernate" "lock"
11 ];
12in
13{
14 options = {
15 services.logind.extraConfig = mkOption {
16 default = "";
17 type = types.lines;
18 example = "IdleAction=lock";
19 description = lib.mdDoc ''
20 Extra config options for systemd-logind. See
21 [
22 logind.conf(5)](https://www.freedesktop.org/software/systemd/man/logind.conf.html) for available options.
23 '';
24 };
25
26 services.logind.killUserProcesses = mkOption {
27 default = false;
28 type = types.bool;
29 description = lib.mdDoc ''
30 Specifies whether the processes of a user should be killed
31 when the user logs out. If true, the scope unit corresponding
32 to the session and all processes inside that scope will be
33 terminated. If false, the scope is "abandoned" (see
34 [systemd.scope(5)](https://www.freedesktop.org/software/systemd/man/systemd.scope.html#)), and processes are not killed.
35
36 See [logind.conf(5)](https://www.freedesktop.org/software/systemd/man/logind.conf.html#KillUserProcesses=)
37 for more details.
38 '';
39 };
40
41 services.logind.lidSwitch = mkOption {
42 default = "suspend";
43 example = "ignore";
44 type = logindHandlerType;
45
46 description = lib.mdDoc ''
47 Specifies what to be done when the laptop lid is closed.
48 '';
49 };
50
51 services.logind.lidSwitchDocked = mkOption {
52 default = "ignore";
53 example = "suspend";
54 type = logindHandlerType;
55
56 description = lib.mdDoc ''
57 Specifies what to be done when the laptop lid is closed
58 and another screen is added.
59 '';
60 };
61
62 services.logind.lidSwitchExternalPower = mkOption {
63 default = cfg.lidSwitch;
64 defaultText = literalExpression "services.logind.lidSwitch";
65 example = "ignore";
66 type = logindHandlerType;
67
68 description = lib.mdDoc ''
69 Specifies what to do when the laptop lid is closed and the system is
70 on external power. By default use the same action as specified in
71 services.logind.lidSwitch.
72 '';
73 };
74 };
75
76 config = {
77 systemd.additionalUpstreamSystemUnits = [
78 "systemd-logind.service"
79 "autovt@.service"
80 "systemd-user-sessions.service"
81 ] ++ optionals config.systemd.package.withImportd [
82 "dbus-org.freedesktop.import1.service"
83 ] ++ optionals config.systemd.package.withMachined [
84 "dbus-org.freedesktop.machine1.service"
85 ] ++ optionals config.systemd.package.withPortabled [
86 "dbus-org.freedesktop.portable1.service"
87 ] ++ [
88 "dbus-org.freedesktop.login1.service"
89 "user@.service"
90 "user-runtime-dir@.service"
91 ];
92
93 environment.etc = {
94 "systemd/logind.conf".text = ''
95 [Login]
96 KillUserProcesses=${if cfg.killUserProcesses then "yes" else "no"}
97 HandleLidSwitch=${cfg.lidSwitch}
98 HandleLidSwitchDocked=${cfg.lidSwitchDocked}
99 HandleLidSwitchExternalPower=${cfg.lidSwitchExternalPower}
100 ${cfg.extraConfig}
101 '';
102 };
103
104 # Restarting systemd-logind breaks X11
105 # - upstream commit: https://cgit.freedesktop.org/xorg/xserver/commit/?id=dc48bd653c7e101
106 # - systemd announcement: https://github.com/systemd/systemd/blob/22043e4317ecd2bc7834b48a6d364de76bb26d91/NEWS#L103-L112
107 # - this might be addressed in the future by xorg
108 #systemd.services.systemd-logind.restartTriggers = [ config.environment.etc."systemd/logind.conf".source ];
109 systemd.services.systemd-logind.restartIfChanged = false;
110 systemd.services.systemd-logind.stopIfChanged = false;
111
112 # The user-runtime-dir@ service is managed by systemd-logind we should not touch it or else we break the users' sessions.
113 systemd.services."user-runtime-dir@".stopIfChanged = false;
114 systemd.services."user-runtime-dir@".restartIfChanged = false;
115 };
116}