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}