nixos/settings/auth.nix

93 lines
3.8 KiB
Nix
Raw Normal View History

# Authenticate before creating the desktop; keep its lock separate from the bar.
{ config, lib, pkgs, ... }:
let
enabled = lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ];
theme = config.home-manager.users.fred.xdg.configFile."quickshell/Theme.qml".text;
bundle = name: shell: pkgs.linkFarm name [
{ name = "shell.qml"; path = shell; }
{ name = "AuthView.qml"; path = ./quickshell/AuthView.qml; }
{ name = "Theme.qml"; path = pkgs.writeText "Theme.qml" theme; }
{ name = "qmldir"; path = pkgs.writeText "qmldir" "singleton Theme 1.0 Theme.qml\nAuthView 1.0 AuthView.qml\n"; }
];
greeter = bundle "fred-greeter" ./quickshell/Greeter.qml;
locker = bundle "fred-lock" ./quickshell/SessionLock.qml;
session = pkgs.writeShellScript "hyprland-session" ''
exec ${config.programs.hyprland.package}/bin/start-hyprland >/dev/null 2>&1
'';
lockCommand = pkgs.writeShellApplication {
name = "fred-lock";
runtimeInputs = [ pkgs.systemd pkgs.coreutils pkgs.quickshell ];
text = builtins.readFile ../scripts/lock-session.sh;
};
in {
config = lib.mkIf enabled {
system.build.auth = pkgs.linkFarm "fred-auth" [
{ name = "greeter"; path = greeter; }
{ name = "lock"; path = locker; }
{ name = "bin"; path = "${lockCommand}/bin"; }
];
services.greetd = {
enable = true;
greeterManagesPlymouth = true;
settings.default_session = {
user = "greeter";
command = toString (pkgs.writeShellScript "fred-greeter" ''
export FRED_SESSION_COMMAND=${session}
export FRED_GREETER=1
export QML2_IMPORT_PATH=${pkgs.qt6.qt5compat}/lib/qt-6/qml
export XKB_DEFAULT_LAYOUT=gb,no
export XKB_DEFAULT_OPTIONS=${lib.escapeShellArg ("grp:win_space_toggle" + lib.optionalString (config.networking.hostName == "FredOS-Gaming") ",altwin:swap_lalt_lwin")}
exec ${pkgs.dbus}/bin/dbus-run-session -- ${pkgs.cage}/bin/cage -s -- ${pkgs.quickshell}/bin/qs -p ${greeter}
'');
};
};
security.pam.services.greetd.allowNullPassword = lib.mkForce false;
security.pam.services.fred-lock = { allowNullPassword = false; };
environment.systemPackages = [ lockCommand ];
home-manager.users.fred.systemd.user.services.quickshell-lock = {
Unit = {
Description = "Independent Quickshell session lock";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
StartLimitIntervalSec = 0;
};
Service = {
ExecStart = "${pkgs.quickshell}/bin/qs -p ${locker}";
Environment = [ "QML2_IMPORT_PATH=${pkgs.qt6.qt5compat}/lib/qt-6/qml" ];
Restart = "always";
RestartSec = 1;
TimeoutStartSec = 5;
};
# No WantedBy: greetd already authenticated the new desktop session.
};
systemd.services.lock-before-sleep = {
description = "Require a confirmed session lock before sleep";
before = [ "sleep.target" ];
requiredBy = [ "sleep.target" ];
serviceConfig = {
Type = "oneshot";
User = "fred";
TimeoutStartSec = "20s";
};
script = ''
set -euo pipefail
export HOME=/home/fred
export XDG_RUNTIME_DIR=/run/user/$(${pkgs.coreutils}/bin/id -u)
# A greeter has no desktop to lock. Query logind, not a potentially
# stale user target, and fail closed if querying logind fails.
sessions=$(${pkgs.systemd}/bin/loginctl list-sessions --no-legend --no-pager)
fred_uid=$(${pkgs.coreutils}/bin/id -u)
while read -r session uid _; do
[ "$uid" = "$fred_uid" ] || continue
type=$(${pkgs.systemd}/bin/loginctl show-session "$session" -p Type --value)
if [ "$type" = wayland ] || [ "$type" = x11 ]; then
exec ${lockCommand}/bin/fred-lock
fi
done <<< "$sessions"
'';
};
};
}