1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 dmcfg = config.services.displayManager;
10 xcfg = config.services.xserver;
11 xdmcfg = xcfg.displayManager;
12 cfg = config.services.displayManager.ly;
13 xEnv = config.systemd.services.display-manager.environment;
14
15 ly = cfg.package;
16
17 iniFmt = pkgs.formats.iniWithGlobalSection { };
18
19 inherit (lib)
20 concatMapStrings
21 attrNames
22 getAttr
23 mkIf
24 mkOption
25 mkEnableOption
26 mkPackageOption
27 ;
28
29 xserverWrapper = pkgs.writeShellScript "xserver-wrapper" ''
30 ${concatMapStrings (n: ''
31 export ${n}="${getAttr n xEnv}"
32 '') (attrNames xEnv)}
33 exec systemd-cat -t xserver-wrapper ${xdmcfg.xserverBin} ${toString xdmcfg.xserverArgs} "$@"
34 '';
35
36 defaultConfig = {
37 shutdown_cmd = "/run/current-system/systemd/bin/systemctl poweroff";
38 restart_cmd = "/run/current-system/systemd/bin/systemctl reboot";
39 tty = 2;
40 service_name = "ly";
41 path = "/run/current-system/sw/bin";
42 term_reset_cmd = "${pkgs.ncurses}/bin/tput reset";
43 term_restore_cursor_cmd = "${pkgs.ncurses}/bin/tput cnorm";
44 mcookie_cmd = "/run/current-system/sw/bin/mcookie";
45 waylandsessions = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
46 wayland_cmd = dmcfg.sessionData.wrapper;
47 xsessions = "${dmcfg.sessionData.desktops}/share/xsessions";
48 xauth_cmd = lib.optionalString xcfg.enable "${pkgs.xorg.xauth}/bin/xauth";
49 x_cmd = lib.optionalString xcfg.enable xserverWrapper;
50 x_cmd_setup = dmcfg.sessionData.wrapper;
51 };
52
53 finalConfig = defaultConfig // cfg.settings;
54
55 cfgFile = iniFmt.generate "config.ini" { globalSection = finalConfig; };
56
57in
58{
59 options = {
60 services.displayManager.ly = {
61 enable = mkEnableOption "ly as the display manager";
62
63 package = mkPackageOption pkgs [ "ly" ] { };
64
65 settings = mkOption {
66 type =
67 with lib.types;
68 attrsOf (oneOf [
69 str
70 int
71 bool
72 ]);
73 default = { };
74 example = {
75 load = false;
76 save = false;
77 };
78 description = ''
79 Extra settings merged in and overwriting defaults in config.ini.
80 '';
81 };
82 };
83 };
84
85 config = mkIf cfg.enable {
86
87 assertions = [
88 {
89 assertion = !dmcfg.autoLogin.enable;
90 message = ''
91 ly doesn't support auto login.
92 '';
93 }
94 ];
95
96 security.pam.services.ly = {
97 startSession = true;
98 unixAuth = true;
99 enableGnomeKeyring = lib.mkDefault config.services.gnome.gnome-keyring.enable;
100 };
101
102 environment = {
103 etc."ly/config.ini".source = cfgFile;
104 systemPackages = [ ly ];
105
106 pathsToLink = [ "/share/ly" ];
107 };
108
109 services = {
110 dbus.packages = [ ly ];
111
112 displayManager = {
113 enable = true;
114 execCmd = "exec /run/current-system/sw/bin/ly";
115 };
116
117 xserver = {
118 # To enable user switching, allow ly to allocate TTYs/displays dynamically.
119 tty = null;
120 display = null;
121 };
122 };
123
124 systemd = {
125 # We're not using the upstream unit, so copy these:
126 # https://github.com/fairyglade/ly/blob/master/res/ly.service
127 services.display-manager = {
128 after = [
129 "systemd-user-sessions.service"
130 "plymouth-quit-wait.service"
131 "getty@tty${toString finalConfig.tty}.service"
132 ];
133
134 conflicts = [ "getty@tty7.service" ];
135
136 serviceConfig = {
137 Type = "idle";
138 StandardInput = "tty";
139 TTYPath = "/dev/tty${toString finalConfig.tty}";
140 TTYReset = "yes";
141 TTYVHangup = "yes";
142 };
143 };
144 };
145 };
146
147 meta.maintainers = with lib.maintainers; [ vonfry ];
148}