nixos/ly: init module

Vonfry 0849e0fe 45b9a988

Changed files
+202 -2
nixos
doc
manual
release-notes
modules
services
display-managers
x11
tests
+5
nixos/doc/manual/release-notes/rl-2411.section.md
···
- NixOS now has support for *automatic boot assessment* (see [here](https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT/)) for detailed description of the feature) for `systemd-boot` users. Available as [boot.loader.systemd-boot.bootCounting](#opt-boot.loader.systemd-boot.bootCounting.enable).
+
- A new display-manager `services.displayManager.ly` was added.
+
It is a tui based replacement of sddm and lightdm for window manager users.
+
Users can use it by `services.displayManager.ly.enable` and config it by
+
`services.displayManager.ly.settings` to generate `/etc/ly/config.ini`
+
## New Services {#sec-release-24.11-new-services}
- [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr), proxy server to bypass Cloudflare protection. Available as [services.flaresolverr](#opt-services.flaresolverr.enable) service.
+1
nixos/modules/module-list.nix
···
./services/display-managers/default.nix
./services/display-managers/greetd.nix
./services/display-managers/sddm.nix
+
./services/display-managers/ly.nix
./services/editors/emacs.nix
./services/editors/haste.nix
./services/editors/infinoted.nix
+2 -1
nixos/modules/services/display-managers/default.nix
···
noDmUsed = !(dmConf.gdm.enable
|| cfg.sddm.enable
|| dmConf.xpra.enable
-
|| dmConf.lightdm.enable);
+
|| dmConf.lightdm.enable
+
|| cfg.ly.enable);
in lib.mkIf noDmUsed (lib.mkDefault false);
systemd.services.display-manager = {
+147
nixos/modules/services/display-managers/ly.nix
···
+
{
+
config,
+
lib,
+
pkgs,
+
...
+
}:
+
+
let
+
dmcfg = config.services.displayManager;
+
xcfg = config.services.xserver;
+
xdmcfg = xcfg.displayManager;
+
cfg = config.services.displayManager.ly;
+
xEnv = config.systemd.services.display-manager.environment;
+
+
ly = cfg.package;
+
+
iniFmt = pkgs.formats.iniWithGlobalSection { };
+
+
inherit (lib)
+
concatMapStrings
+
attrNames
+
getAttr
+
mkIf
+
mkOption
+
mkEnableOption
+
mkPackageOption
+
;
+
+
xserverWrapper = pkgs.writeShellScript "xserver-wrapper" ''
+
${concatMapStrings (n: ''
+
export ${n}="${getAttr n xEnv}"
+
'') (attrNames xEnv)}
+
exec systemd-cat -t xserver-wrapper ${xdmcfg.xserverBin} ${toString xdmcfg.xserverArgs} "$@"
+
'';
+
+
defaultConfig = {
+
shutdown_cmd = "/run/current-system/systemd/bin/systemctl poweroff";
+
restart_cmd = "/run/current-system/systemd/bin/systemctl reboot";
+
tty = 2;
+
service_name = "ly";
+
path = "/run/current-system/sw/bin";
+
term_reset_cmd = "${pkgs.ncurses}/bin/tput reset";
+
term_restore_cursor_cmd = "${pkgs.ncurses}/bin/tput cnorm";
+
mcookie_cmd = "/run/current-system/sw/bin/mcookie";
+
waylandsessions = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
+
wayland_cmd = dmcfg.sessionData.wrapper;
+
xsessions = "${dmcfg.sessionData.desktops}/share/xsessions";
+
xauth_cmd = lib.optionalString xcfg.enable "${pkgs.xorg.xauth}/bin/xauth";
+
x_cmd = lib.optionalString xcfg.enable xserverWrapper;
+
x_cmd_setup = dmcfg.sessionData.wrapper;
+
};
+
+
finalConfig = defaultConfig // cfg.settings;
+
+
cfgFile = iniFmt.generate "config.ini" { globalSection = finalConfig; };
+
+
in
+
{
+
options = {
+
services.displayManager.ly = {
+
enable = mkEnableOption "ly as the display manager";
+
+
package = mkPackageOption pkgs [ "ly" ] { };
+
+
settings = mkOption {
+
type =
+
with lib.types;
+
attrsOf (oneOf [
+
str
+
int
+
bool
+
]);
+
default = { };
+
example = {
+
load = false;
+
save = false;
+
};
+
description = ''
+
Extra settings merged in and overwriting defaults in config.ini.
+
'';
+
};
+
};
+
};
+
+
config = mkIf cfg.enable {
+
+
assertions = [
+
{
+
assertion = !dmcfg.autoLogin.enable;
+
message = ''
+
ly doesn't support auto login.
+
'';
+
}
+
];
+
+
security.pam.services.ly = {
+
startSession = true;
+
unixAuth = true;
+
};
+
+
environment = {
+
etc."ly/config.ini".source = cfgFile;
+
systemPackages = [ ly ];
+
+
pathsToLink = [ "/share/ly" ];
+
};
+
+
services = {
+
dbus.packages = [ ly ];
+
+
displayManager = {
+
enable = true;
+
execCmd = "exec /run/current-system/sw/bin/ly";
+
};
+
+
xserver = {
+
# To enable user switching, allow ly to allocate TTYs/displays dynamically.
+
tty = null;
+
display = null;
+
};
+
};
+
+
systemd = {
+
# We're not using the upstream unit, so copy these:
+
# https://github.com/fairyglade/ly/blob/master/res/ly.service
+
services.display-manager = {
+
after = [
+
"systemd-user-sessions.service"
+
"plymouth-quit-wait.service"
+
"getty@tty${toString finalConfig.tty}.service"
+
];
+
+
conflicts = [ "getty@tty7.service" ];
+
+
serviceConfig = {
+
Type = "idle";
+
StandardInput = "tty";
+
TTYPath = "/dev/tty${toString finalConfig.tty}";
+
TTYReset = "yes";
+
TTYVHangup = "yes";
+
};
+
};
+
};
+
};
+
+
meta.maintainers = with lib.maintainers; [ vonfry ];
+
}
+2 -1
nixos/modules/services/x11/xserver.nix
···
|| dmConf.xpra.enable
|| dmConf.sx.enable
|| dmConf.startx.enable
-
|| config.services.greetd.enable);
+
|| config.services.greetd.enable
+
|| config.services.displayManager.ly.enable);
in mkIf (default) (mkDefault true);
services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ];
+1
nixos/tests/all-tests.nix
···
lomiri-filemanager-app = runTest ./lomiri-filemanager-app.nix;
lomiri-system-settings = handleTest ./lomiri-system-settings.nix {};
lorri = handleTest ./lorri/default.nix {};
+
ly = handleTest ./ly.nix {};
maddy = discoverTests (import ./maddy { inherit handleTest; });
maestral = handleTest ./maestral.nix {};
magic-wormhole-mailbox-server = handleTest ./magic-wormhole-mailbox-server.nix {};
+44
nixos/tests/ly.nix
···
+
import ./make-test-python.nix (
+
{ ... }:
+
+
{
+
name = "ly";
+
+
nodes.machine =
+
{ ... }:
+
{
+
imports = [ ./common/user-account.nix ];
+
services.displayManager.ly = {
+
enable = true;
+
settings = {
+
load = false;
+
save = false;
+
};
+
};
+
services.xserver.enable = true;
+
services.displayManager.defaultSession = "none+icewm";
+
services.xserver.windowManager.icewm.enable = true;
+
};
+
+
testScript =
+
{ nodes, ... }:
+
let
+
user = nodes.machine.users.users.alice;
+
in
+
''
+
start_all()
+
machine.wait_until_tty_matches("2", "password:")
+
machine.send_key("ctrl-alt-f2")
+
machine.sleep(1)
+
machine.screenshot("ly")
+
machine.send_chars("alice")
+
machine.send_key("tab")
+
machine.send_chars("${user.password}")
+
machine.send_key("ret")
+
machine.wait_for_file("/run/user/${toString user.uid}/lyxauth")
+
machine.succeed("xauth merge /run/user/${toString user.uid}/lyxauth")
+
machine.wait_for_window("^IceWM ")
+
machine.screenshot("icewm")
+
'';
+
}
+
)