fix(idle): don't lock before an encrypted hibernate (was: unlock after)
The previous nomarchy-hibernate-unlock ran `pkill hyprlock` after a hibernate resume, but killing a Wayland session-lock client without releasing the lock trips hyprlock's "go to a tty" crash failsafe -- the compositor keeps the screen locked for safety. So resume showed a hyprlock error screen instead of unlocking. Fix it the right way: never engage the lock before an encrypted hibernate (the LUKS passphrase at resume is the gate). Replace the post-resume unlock with a nomarchy-lock-before-sleep unit that takes over hypridle's before_sleep_cmd: it locks on the RAM-resume sleeps (suspend / hybrid-sleep / suspend-then-hibernate) always, and on hibernate.target only when the disk is unencrypted. idle.nix drops before_sleep_cmd accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -123,23 +123,32 @@ in
|
||||
|
||||
networking.networkmanager.enable = lib.mkDefault true;
|
||||
|
||||
# No double-unlock on hibernate. hypridle locks hyprlock before every
|
||||
# sleep (right for suspend), but a hibernate resume is already gated by
|
||||
# the LUKS passphrase entered at boot — so the user would type a password
|
||||
# twice. Once we're back from an *encrypted* hibernate, drop the now-
|
||||
# redundant hyprlock. Ordered After the hibernate service, so it runs
|
||||
# post-resume; pulled in only by hibernate.target (suspend, and the
|
||||
# RAM-resume phase of suspend-then-hibernate, stay locked — they have no
|
||||
# passphrase gate). Gated on LUKS: an unencrypted hibernate keeps its lock.
|
||||
systemd.services.nomarchy-hibernate-unlock =
|
||||
lib.mkIf (builtins.attrNames config.boot.initrd.luks.devices != [ ]) {
|
||||
description = "Dismiss hyprlock after resuming from an encrypted hibernate";
|
||||
after = [ "systemd-hibernate.service" ];
|
||||
wantedBy = [ "hibernate.target" ];
|
||||
# No double-unlock on hibernate. Locking the session before sleep is
|
||||
# right for suspend (resumes from RAM, no other gate), but an encrypted
|
||||
# hibernate already resumes through the LUKS passphrase — a hyprlock on
|
||||
# top is a second password. And we can't just drop the lock after the
|
||||
# resume: a Wayland session-lock whose client dies without releasing
|
||||
# trips hyprlock's "go to a tty" crash failsafe (the compositor keeps the
|
||||
# screen locked for safety). So don't lock before an encrypted hibernate
|
||||
# in the first place. hypridle can't tell suspend from hibernate, hence a
|
||||
# system unit hooked to the sleep targets: it locks on the RAM-resume
|
||||
# sleeps always, and on hibernate only when the disk is unencrypted (no
|
||||
# LUKS gate to rely on). Replaces hypridle's old before_sleep_cmd.
|
||||
systemd.services.nomarchy-lock-before-sleep =
|
||||
let
|
||||
encrypted = builtins.attrNames config.boot.initrd.luks.devices != [ ];
|
||||
# Sleeps whose normal resume is from RAM — always lock these.
|
||||
ramTargets = [ "suspend.target" "hybrid-sleep.target" "suspend-then-hibernate.target" ];
|
||||
ramServices = [ "systemd-suspend.service" "systemd-hybrid-sleep.service" "systemd-suspend-then-hibernate.service" ];
|
||||
in
|
||||
{
|
||||
description = "Lock the session before sleep (skipped for an encrypted hibernate)";
|
||||
before = ramServices ++ lib.optional (!encrypted) "systemd-hibernate.service";
|
||||
wantedBy = ramTargets ++ lib.optional (!encrypted) "hibernate.target";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
# `-`: a missing hyprlock (idle disabled, or not locked) isn't a failure.
|
||||
ExecStart = "-${pkgs.procps}/bin/pkill -x hyprlock";
|
||||
# Plural: a system unit has no session of its own to lock.
|
||||
ExecStart = "${config.systemd.package}/bin/loginctl lock-sessions";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user