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}