1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.greetd;
9 tty = "tty1";
10 settingsFormat = pkgs.formats.toml { };
11in
12{
13 imports = [
14 (lib.mkRemovedOptionModule [
15 "services"
16 "greetd"
17 "vt"
18 ] "The VT is now fixed to VT1.")
19 ];
20
21 options.services.greetd = {
22 enable = lib.mkEnableOption "greetd, a minimal and flexible login manager daemon";
23
24 package = lib.mkPackageOption pkgs "greetd" { };
25
26 settings = lib.mkOption {
27 type = settingsFormat.type;
28 example = lib.literalExpression ''
29 {
30 default_session = {
31 command = "''${pkgs.greetd}/bin/agreety --cmd sway";
32 };
33 }
34 '';
35 description = ''
36 greetd configuration ([documentation](https://man.sr.ht/~kennylevinsen/greetd/))
37 as a Nix attribute set.
38 '';
39 };
40
41 greeterManagesPlymouth = lib.mkOption {
42 type = lib.types.bool;
43 internal = true;
44 default = false;
45 description = ''
46 Don't configure the greetd service to wait for Plymouth to exit.
47
48 Enable this if the greeter you're using can manage Plymouth itself to provide a smoother handoff.
49 '';
50 };
51
52 restart = lib.mkOption {
53 type = lib.types.bool;
54 default = !(cfg.settings ? initial_session);
55 defaultText = lib.literalExpression "!(config.services.greetd.settings ? initial_session)";
56 description = ''
57 Whether to restart greetd when it terminates (e.g. on failure).
58 This is usually desirable so a user can always log in, but should be disabled when using 'settings.initial_session' (autologin),
59 because every greetd restart will trigger the autologin again.
60 '';
61 };
62
63 useTextGreeter = lib.mkOption {
64 type = lib.types.bool;
65 default = false;
66 description = ''
67 Whether the greeter uses text-based user interfaces (For example, tuigreet).
68
69 When set to true, some systemd service configuration will be adjusted to avoid systemd boot messages interrupt TUI.
70 '';
71 };
72 };
73 config = lib.mkIf cfg.enable {
74
75 services.greetd.settings.terminal.vt = 1;
76 services.greetd.settings.default_session.user = lib.mkDefault "greeter";
77
78 security.pam.services.greetd = {
79 allowNullPassword = true;
80 startSession = true;
81 enableGnomeKeyring = lib.mkDefault config.services.gnome.gnome-keyring.enable;
82 };
83
84 # This prevents nixos-rebuild from killing greetd by activating getty again
85 systemd.services."autovt@${tty}".enable = false;
86
87 # Enable desktop session data
88 services.displayManager.enable = lib.mkDefault true;
89
90 systemd.services.greetd = {
91 aliases = [ "display-manager.service" ];
92
93 unitConfig = {
94 Wants = [
95 "systemd-user-sessions.service"
96 ];
97 After = [
98 "systemd-user-sessions.service"
99 "getty@${tty}.service"
100 ]
101 ++ lib.optionals (!cfg.greeterManagesPlymouth) [
102 "plymouth-quit-wait.service"
103 ];
104 Conflicts = [
105 "getty@${tty}.service"
106 ];
107 };
108
109 serviceConfig = {
110 ExecStart = "${lib.getExe cfg.package} --config ${settingsFormat.generate "greetd.toml" cfg.settings}";
111
112 Restart = lib.mkIf cfg.restart "on-success";
113
114 # Defaults from greetd upstream configuration
115 IgnoreSIGPIPE = false;
116 SendSIGHUP = true;
117 TimeoutStopSec = "30s";
118 KeyringMode = "shared";
119
120 Type = "idle";
121 }
122 // (lib.optionalAttrs cfg.useTextGreeter {
123 StandardInput = "tty";
124 StandardOutput = "tty";
125 # Without this errors will spam on screen
126 StandardError = "journal";
127
128 # Without these bootlogs will spam on screen
129 TTYPath = "/dev/tty1";
130 TTYReset = true;
131 TTYVHangup = true;
132 TTYVTDisallocate = true;
133 });
134
135 # Don't kill a user session when using nixos-rebuild
136 restartIfChanged = false;
137
138 wantedBy = [ "graphical.target" ];
139 };
140
141 systemd.defaultUnit = "graphical.target";
142
143 # Create directories potentially required by supported greeters
144 # See https://github.com/NixOS/nixpkgs/issues/248323
145 systemd.tmpfiles.rules = [
146 "d '/var/cache/tuigreet' - greeter greeter - -"
147 ];
148
149 users.users.greeter = {
150 isSystemUser = true;
151 group = "greeter";
152 };
153
154 users.groups.greeter = { };
155 };
156
157 meta.maintainers = with lib.maintainers; [ queezle ];
158}