feat(terra): replace tuigreet with a quickshell greeter

greetd now runs a throwaway Hyprland hosting dotfiles/quickshell/greeter.qml,
configured per host via homelab.greeter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 23:34:10 +02:00
co-authored by Claude Opus 5
parent 4adb59808f
commit f3dddc9150
10 changed files with 857 additions and 6 deletions
+76
View File
@@ -0,0 +1,76 @@
{ config, lib, pkgs, ... }:
# greetd greeter: a throwaway Hyprland running quickshell's greeter.qml as the
# `greeter` user. Hyprland must exit after the login so greetd can start the
# real session, hence the exit dispatch once qs returns.
let
cfg = config.homelab.greeter;
hyprland = config.programs.hyprland.package;
toLua = lib.generators.toLua { };
shellDir = ../../dotfiles/quickshell;
session = pkgs.writeShellScript "greeter-session" ''
${lib.getExe pkgs.quickshell} -p ${shellDir}/greeter.qml
${hyprland}/bin/hyprctl dispatch 'hl.dsp.exit()'
'';
hyprConfig = pkgs.writeText "greeter-hyprland.lua" ''
${lib.concatMapStrings (m: "hl.monitor(${toLua m})\n") cfg.monitors}
hl.config(${toLua {
input = { kb_layout = cfg.keyboardLayout; numlock_by_default = true; };
animations.enabled = false;
misc = {
disable_hyprland_logo = true;
disable_splash_rendering = true;
background_color = "rgb(0a0a0a)";
};
ecosystem = { no_update_news = true; no_donation_nag = true; };
}})
hl.env("QS_GREETER_OUTPUT", ${toLua cfg.primaryOutput})
hl.env("QS_GREETER_USER", ${toLua cfg.defaultUser})
hl.env("QS_GREETER_HOST", ${toLua config.networking.hostName})
hl.env("QS_GREETER_SESSION", "start-hyprland")
hl.on("hyprland.start", function()
hl.exec_cmd("${session}")
end)
'';
in
{
options.homelab.greeter = {
monitors = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [ ];
description = "hl.monitor() tables; reuse the user's so outputs line up.";
};
primaryOutput = lib.mkOption {
type = lib.types.str;
default = "";
description = "Output that gets the login panel (others get the backdrop only).";
};
defaultUser = lib.mkOption {
type = lib.types.str;
default = "";
};
keyboardLayout = lib.mkOption {
type = lib.types.str;
default = "us";
};
};
config = {
services.greetd = {
enable = true;
settings.default_session.command =
"${hyprland}/bin/start-hyprland -- --config ${hyprConfig}";
};
# Hyprland and quickshell want a writable $HOME for cache/state.
users.users.greeter = {
home = "/var/lib/greeter";
createHome = true;
};
};
}