diff --git a/hosts/common/programs/default.nix b/hosts/common/programs/default.nix index 841132b2..8530d0d6 100644 --- a/hosts/common/programs/default.nix +++ b/hosts/common/programs/default.nix @@ -90,6 +90,7 @@ ./tangram.nix ./tor-browser.nix ./tuba.nix + ./unl0kr ./vlc.nix ./waybar ./waylock.nix diff --git a/hosts/modules/gui/unl0kr/default.nix b/hosts/common/programs/unl0kr/default.nix similarity index 56% rename from hosts/modules/gui/unl0kr/default.nix rename to hosts/common/programs/unl0kr/default.nix index 012197d3..6220c87e 100644 --- a/hosts/modules/gui/unl0kr/default.nix +++ b/hosts/common/programs/unl0kr/default.nix @@ -1,7 +1,8 @@ { config, lib, pkgs, ... }: let - cfg = config.sane.gui.unl0kr; - tty = "tty${builtins.toString cfg.vt}"; + cfg = config.sane.programs.unl0kr; + + tty = "tty${builtins.toString cfg.config.vt}"; redirect-tty = pkgs.static-nix-shell.mkPython3Bin { pname = "redirect-tty"; src = ./.; @@ -25,66 +26,80 @@ let redirect-tty "/dev/${tty}" unl0kr & # login -p: preserve environment - login -p ${cfg.user} + login -p ${cfg.config.user} ''; }; in { - options = with lib; { - sane.gui.unl0kr.enable = mkOption { - type = types.bool; - default = false; - description = '' - whether to launch unl0kr at boot. - unl0kr takes the role of a greeter, presenting a virtual keyboard to the framebuffer - and allowing password auth via either keyboard, mouse, or touch. - ''; - }; - sane.gui.unl0kr.vt = mkOption { - type = types.int; - default = 1; - }; - sane.gui.unl0kr.user = mkOption { - type = types.str; - default = "colin"; - }; - sane.gui.unl0kr.afterLogin = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - shell code to run after a successful login (via .profile). - ''; - }; - sane.gui.unl0kr.delay = mkOption { - type = types.int; - default = 3; - description = '' - seconds to wait between successful login and running the `afterLogin` command. - this is a safety mechanism, to allow users an exit in case DE is broken. - ''; - }; - sane.gui.unl0kr.package = mkOption { - type = types.package; - default = pkgs.unl0kr; - }; - sane.gui.unl0kr.launcher = mkOption { - type = types.package; - default = launcher; - description = '' - script to tie `unl0kr` and `login` together. - exposed for debugging. - ''; + sane.programs.unl0kr = { + configOption = with lib; mkOption { + default = {}; + type = types.submodule { + options.autostart = mkOption { + type = types.bool; + default = true; + description = '' + whether to launch unl0kr at boot. + unl0kr takes the role of a greeter, presenting a virtual keyboard to the framebuffer + and allowing password auth via either keyboard, mouse, or touch. + ''; + }; + options.vt = mkOption { + type = types.int; + default = 1; + }; + options.user = mkOption { + type = types.str; + # TODO: derive this from sane.programs...enableFor.user.* info + default = "colin"; + }; + options.afterLogin = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + shell code to run after a successful login (via .profile). + ''; + }; + options.delay = mkOption { + type = types.int; + default = 3; + description = '' + seconds to wait between successful login and running the `afterLogin` command. + this is a safety mechanism, to allow users an exit in case DE is broken. + ''; + }; + options.launcher = mkOption { + type = types.package; + default = launcher; + description = '' + script to tie `unl0kr` and `login` together. + exposed for debugging. + ''; + }; + }; }; + + + # lib.mkAfter so that launching the DE happens *after* any other .profile setup. + # alternatively, we could recurse: exec a new login shell with some env-var signalling to not launch the DE, + # run with `-c "{cfg.afterLogin}"` + fs.".profile".symlink.text = lib.mkAfter (lib.optionalString (cfg.config.afterLogin != null) '' + # if already running a desktop environment, or if running from ssh, then `tty` will show /dev/pts/NN. + if [ "$(tty)" = "/dev/${tty}" ]; then + echo 'launching default session in ${builtins.toString cfg.config.delay}s' + sleep ${builtins.toString cfg.config.delay} && exec ${cfg.config.afterLogin} + fi + ''); }; - config = lib.mkIf cfg.enable { + systemd = lib.mkIf cfg.enabled { # prevent nixos-rebuild from killing us after a redeploy - systemd.services."autovt@${tty}".enable = false; - systemd.services.unl0kr = { + services."autovt@${tty}".enable = false; + services.unl0kr = { # --skip-login is funny here: it *doesn't* skip the login; rather it has getty not try to read the username for itself # and instead launch --login-program *immediately* # N.B.: exec paths here must be absolute. neither systemd nor agetty query PATH. - serviceConfig.ExecStart = "${pkgs.util-linux}/bin/agetty --login-program '${cfg.launcher}/bin/unl0kr-login' --noclear --skip-login --keep-baud ${tty} 115200,38400,9600 $TERM"; + serviceConfig.ExecStart = "${pkgs.util-linux}/bin/agetty --login-program '${cfg.config.launcher}/bin/unl0kr-login' --noclear --skip-login --keep-baud ${tty} 115200,38400,9600 $TERM"; serviceConfig.Type = "simple"; serviceConfig.Restart = "always"; @@ -105,26 +120,17 @@ in restartIfChanged = false; }; - systemd.defaultUnit = "graphical.target"; - - # lib.mkAfter so that launching the DE happens *after* any other .profile setup. - # alternatively, we could recurse: exec a new login shell with some env-var signalling to not launch the DE, - # run with `-c "{cfg.afterLogin}"` - sane.users."${cfg.user}".fs.".profile".symlink.text = lib.mkAfter (lib.optionalString (cfg.afterLogin != null) '' - # if already running a desktop environment, or if running from ssh, then `tty` will show /dev/pts/NN. - if [ "$(tty)" = "/dev/${tty}" ]; then - echo 'launching default session in ${builtins.toString cfg.delay}s' - sleep ${builtins.toString cfg.delay} && exec ${cfg.afterLogin} - fi - ''); + defaultUnit = "graphical.target"; + }; + security.loginDefs.settings = lib.mkIf cfg.enabled { # see: `man login.defs` # disable timeout for `login` program. # LOGIN_TIMEOUT=0 lets me pipe input into `login` and not worry about the pipe randomly dying. - security.loginDefs.settings.LOGIN_TIMEOUT = 0; + LOGIN_TIMEOUT = 0; # LOGIN_RETRIES=1 ensures that if the password is wrong, then login exits and the whole service restarts so unl0kr re-appears. # docs mention `UNIX_MAX_RETRIES` setting within pam_unix (hardcoded to 3): seems that's an upper-limit to this value, but no lower limit. - security.loginDefs.settings.LOGIN_RETRIES = 1; - security.loginDefs.settings.FAIL_DELAY = 1; #< delay this long after failed loging before allowing retry + LOGIN_RETRIES = 1; + FAIL_DELAY = 1; #< delay this long after failed loging before allowing retry }; } diff --git a/hosts/modules/gui/unl0kr/redirect-tty b/hosts/common/programs/unl0kr/redirect-tty similarity index 100% rename from hosts/modules/gui/unl0kr/redirect-tty rename to hosts/common/programs/unl0kr/redirect-tty diff --git a/hosts/modules/gui/default.nix b/hosts/modules/gui/default.nix index 788fbaaa..c2c6c4c1 100644 --- a/hosts/modules/gui/default.nix +++ b/hosts/modules/gui/default.nix @@ -14,7 +14,6 @@ in ./sway ./sxmo ./theme - ./unl0kr ]; sane.programs.gameApps = declPackageSet [ diff --git a/hosts/modules/gui/sway/default.nix b/hosts/modules/gui/sway/default.nix index 64679db8..650eb4cc 100644 --- a/hosts/modules/gui/sway/default.nix +++ b/hosts/modules/gui/sway/default.nix @@ -172,6 +172,8 @@ in # xdg-desktop-portal-wlr provides portals for screenshots/screen sharing "xdg-desktop-portal-wlr" "xdg-terminal-exec" # used by sway config + ] ++ lib.optionals cfg.useGreeter [ + "unl0kr" ]; secrets.".config/sane-sway/snippets.txt" = ../../../../secrets/common/snippets.txt.bin; @@ -233,10 +235,8 @@ in # sane.gui.gtk.icon-theme = lib.mkDefault "rose-pine-dawn"; # 2.5/5 coverage on moby # sane.gui.gtk.icon-theme = lib.mkDefault "Flat-Remix-Grey-Light"; # requires qtbase - sane.gui.unl0kr = lib.mkIf cfg.useGreeter { - enable = true; + sane.programs.unl0kr.config = lib.mkIf cfg.useGreeter { afterLogin = "sway"; - user = "colin"; }; # swap in these lines to use `greetd`+`gtkgreet` instead: