diff --git a/nixos/modules/services/ttys/getty.nix b/nixos/modules/services/ttys/getty.nix index 01d2858602b6..73db27519aa5 100644 --- a/nixos/modules/services/ttys/getty.nix +++ b/nixos/modules/services/ttys/getty.nix @@ -132,6 +132,12 @@ in ###### implementation config = mkIf config.console.enable { + assertions = [ + { + assertion = cfg.loginOptions != null -> cfg.autologinUser == null; + message = "services.getty.autoLoginUser has no effect when services.getty.loginOptions is set."; + } + ]; # Note: this is set here rather than up there so that changing # nixos.label would not rebuild manual pages services.getty.greetingLine = mkDefault ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>''; diff --git a/nixos/modules/services/ttys/kmscon.nix b/nixos/modules/services/ttys/kmscon.nix index 70d3e15e6e36..eee6a41f7de4 100644 --- a/nixos/modules/services/ttys/kmscon.nix +++ b/nixos/modules/services/ttys/kmscon.nix @@ -17,28 +17,80 @@ let cfg = config.services.kmscon; - autologinArg = lib.optionalString (cfg.autologinUser != null) "-f ${cfg.autologinUser}"; + gettyCfg = config.services.getty; configDir = pkgs.writeTextFile { name = "kmscon-config"; destination = "/kmscon.conf"; text = cfg.extraConfig; }; + + baseLoginOptions = "-p -- \\u"; + + agettyCmd = + enableAutologin: + "${lib.getExe' pkgs.util-linux "agetty"} ${ + lib.escapeShellArgs ( + [ + "--login-program" + (toString gettyCfg.loginProgram) + "--login-options" + # these options are passed as a single parameter + "${lib.optionalString enableAutologin "-f "}${baseLoginOptions}" + ] + ++ lib.optionals enableAutologin [ + "--autologin" + gettyCfg.autologinUser + ] + ++ gettyCfg.extraArgs + ++ [ + "--8bits" + "--noclear" + "--" + "-" + ] + ) + } $TERM"; + + loginScript = pkgs.writers.writeDash "kmscon-login" '' + kms_tty= + active_tty_file=/sys/class/tty/tty0/active + if [ -f "$active_tty_file" ]; then + read -r kms_tty < "$active_tty_file" + fi + + ${lib.optionalString (gettyCfg.autologinUser != null && gettyCfg.autologinOnce) '' + autologged="/run/kmscon.autologged" + if [ "$kms_tty" = tty1 ] && [ ! -f "$autologged" ]; then + touch "$autologged" + exec ${agettyCmd true} + fi + ''} + + exec ${agettyCmd (gettyCfg.autologinUser != null && !gettyCfg.autologinOnce)} + ''; in { + imports = [ + (lib.mkRemovedOptionModule [ "services" "kmscon" "autologinUser" ] '' + Autologin is now handled by the agetty module. + + Check `services.getty.autologinUser` instead. + '') + ]; + options = { services.kmscon = { enable = mkEnableOption '' - kmscon as the virtual console instead of gettys. - kmscon is a kms/dri-based userspace virtual terminal implementation. - It supports a richer feature set than the standard linux console VT, - including full unicode support, and when the video card supports drm - should be much faster + Use kmscon instead of autovt. + + Kmscon is a simple terminal emulator based on linux kernel mode setting (KMS). + It is an attempt to replace the in-kernel VT implementation with a userspace console. ''; package = mkPackageOption pkgs "kmscon" { }; - hwRender = mkEnableOption "3D hardware acceleration to render the console"; + hwRender = mkEnableOption "hardware acceleration + DRM backend"; fonts = mkOption { description = "Fonts used by kmscon, in order of priority."; @@ -63,8 +115,13 @@ in nullOr (nonEmptyListOf fontType); }; - useXkbConfig = mkEnableOption "" // { - description = "Whether to configure keymap from xserver keyboard settings."; + useXkbConfig = mkEnableOption "configure keymap from xserver keyboard settings."; + + term = mkOption { + description = "Value for the TERM environment variable."; + type = types.nullOr types.str; + default = null; + example = "xterm-256color"; }; extraConfig = mkOption { @@ -80,33 +137,39 @@ in default = ""; example = "--term xterm-256color"; }; - - autologinUser = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Username of the account that will be automatically logged in at the console. - If unspecified, a login prompt is shown as usual. - ''; - }; }; }; config = mkIf cfg.enable { + assertions = [ + { + assertion = gettyCfg.loginOptions == null; + message = "services.getty.loginOptions is not supported when services.kmscon is enabled."; + } + ]; + + environment.systemPackages = [ cfg.package ]; systemd.packages = [ cfg.package ]; systemd.services."kmsconvt@" = { - after = [ - "systemd-logind.service" - "systemd-vconsole-setup.service" - ]; - requires = [ "systemd-logind.service" ]; - serviceConfig.ExecStart = [ - "" - '' - ${cfg.package}/bin/kmscon "--vt=%I" ${cfg.extraOptions} --seats=seat0 --no-switchvt --configdir ${configDir} --login -- ${pkgs.shadow}/bin/login -p ${autologinArg} - '' + "" # override upstream default with an empty ExecStart + (builtins.concatStringsSep " " ( + [ + "${cfg.package}/bin/kmscon" + "--configdir" + configDir + "--vt=%I" + "--no-switchvt" + "--login" + ] + ++ lib.optional (cfg.extraOptions != "") cfg.extraOptions + ++ [ + "--" + loginScript + ] + + )) ]; restartIfChanged = false; @@ -115,9 +178,6 @@ in systemd.suppressedSystemUnits = [ "autovt@.service" ]; - systemd.services.systemd-vconsole-setup.enable = false; - systemd.services.reload-systemd-vconsole-setup.enable = false; - services.kmscon.extraConfig = let xkb = optionals cfg.useXkbConfig ( @@ -134,15 +194,20 @@ in ) config.services.xserver.xkb ) ); - render = optionals cfg.hwRender [ - "drm" - "hwaccel" - ]; + render = + if cfg.hwRender then + [ + "drm" + "hwaccel" + ] + else + [ "no-drm" ]; fonts = optional (cfg.fonts != null) "font-name=${lib.concatMapStringsSep ", " (f: f.name) cfg.fonts}"; + term = optional (cfg.term != null) "term=${cfg.term}"; in - lib.concatLines (xkb ++ render ++ fonts); + lib.concatLines (xkb ++ render ++ fonts ++ term); hardware.graphics.enable = mkIf cfg.hwRender true; @@ -151,4 +216,9 @@ in packages = map (f: f.package) cfg.fonts; }; }; + + meta.maintainers = with lib.maintainers; [ + hustlerone + ccicnce113424 + ]; } diff --git a/nixos/tests/kmscon.nix b/nixos/tests/kmscon.nix index cb20274c6ece..1c67a16af2ba 100644 --- a/nixos/tests/kmscon.nix +++ b/nixos/tests/kmscon.nix @@ -5,7 +5,6 @@ nodes.machine = { pkgs, - lib, ... }: { @@ -13,6 +12,8 @@ ./common/user-account.nix ]; + services.getty.autologinUser = "alice"; + services.kmscon = { enable = true; hwRender = true; @@ -22,6 +23,7 @@ package = pkgs.nerd-fonts.jetbrains-mono; } ]; + term = "xterm-256color"; package = pkgs.kmscon; }; }; @@ -29,15 +31,9 @@ enableOCR = true; testScript = '' - machine.wait_for_unit("multi-user.target") + machine.start() with subtest("ensure we can open a tty"): - machine.wait_for_text("machine login:") - - machine.send_chars("alice\n") - machine.wait_for_text("Password:") - - machine.send_chars("foobar\n") machine.wait_for_text("alice@machine") machine.send_chars("echo $TERM | tee /tmp/term.txt\n")