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.override { x11Support = cfg.x11Support; };
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 service_name = "ly";
40 path = "/run/current-system/sw/bin";
41 term_reset_cmd = "${pkgs.ncurses}/bin/tput reset";
42 term_restore_cursor_cmd = "${pkgs.ncurses}/bin/tput cnorm";
43 waylandsessions = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
44 xsessions = "${dmcfg.sessionData.desktops}/share/xsessions";
45 xauth_cmd = lib.optionalString xcfg.enable "${pkgs.xorg.xauth}/bin/xauth";
46 x_cmd = lib.optionalString xcfg.enable xserverWrapper;
47 setup_cmd = dmcfg.sessionData.wrapper;
48 };
49
50 finalConfig = defaultConfig // cfg.settings;
51
52 cfgFile = iniFmt.generate "config.ini" { globalSection = finalConfig; };
53
54in
55{
56 options = {
57 services.displayManager.ly = {
58 enable = mkEnableOption "ly as the display manager";
59 x11Support = mkOption {
60 description = "Whether to enable support for X11";
61 type = lib.types.bool;
62 default = true;
63 };
64
65 package = mkPackageOption pkgs [ "ly" ] { };
66
67 settings = mkOption {
68 type =
69 with lib.types;
70 attrsOf (oneOf [
71 str
72 int
73 bool
74 ]);
75 default = { };
76 example = {
77 load = false;
78 save = false;
79 };
80 description = ''
81 Extra settings merged in and overwriting defaults in config.ini.
82 '';
83 };
84 };
85 };
86
87 config = mkIf cfg.enable {
88
89 assertions = [
90 {
91 assertion = !dmcfg.autoLogin.enable;
92 message = ''
93 ly doesn't support auto login.
94 '';
95 }
96 ];
97
98 security.pam.services.ly = {
99 startSession = true;
100 unixAuth = true;
101 enableGnomeKeyring = lib.mkDefault config.services.gnome.gnome-keyring.enable;
102 };
103
104 environment = {
105 etc."ly/config.ini".source = cfgFile;
106 systemPackages = [ ly ];
107
108 pathsToLink = [ "/share/ly" ];
109 };
110
111 services = {
112 dbus.packages = [ ly ];
113
114 displayManager = {
115 enable = true;
116 execCmd = "exec /run/current-system/sw/bin/ly";
117
118 # Set this here instead of 'defaultConfig' so users get eval
119 # errors when they change it.
120 ly.settings.tty = 1;
121 };
122
123 xserver = {
124 # To enable user switching, allow ly to allocate displays dynamically.
125 display = null;
126 };
127 };
128
129 systemd = {
130 # We're not using the upstream unit, so copy these:
131 # https://github.com/fairyglade/ly/blob/master/res/ly.service
132 services.display-manager = {
133 after = [
134 "systemd-user-sessions.service"
135 "plymouth-quit-wait.service"
136 ];
137
138 serviceConfig = {
139 Type = "idle";
140 StandardInput = "tty";
141 TTYPath = "/dev/tty${toString finalConfig.tty}";
142 TTYReset = "yes";
143 TTYVHangup = "yes";
144 };
145 };
146 };
147 };
148
149 meta.maintainers = with lib.maintainers; [ vonfry ];
150}