Use clever yubilock

This commit is contained in:
2025-11-16 02:29:56 +03:00
parent b4afe2581e
commit 0316fb2b6c
3 changed files with 171 additions and 11 deletions

View File

@@ -87,5 +87,9 @@ in
settings.folders.PhotoArchive.enabled = true; settings.folders.PhotoArchive.enabled = true;
settings.folders.books.enabled = true; settings.folders.books.enabled = true;
}; };
yubilock = {
enable = true;
autoRestore = true;
};
}; };
} }

167
modules/hm/yubilock.nix Normal file
View File

@@ -0,0 +1,167 @@
# Stealed from https://github.com/guttermonk/yubilock
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.yubilock;
# Script paths - users should copy scripts to their ~/.config/waybar/scripts/
yubilockScript = pkgs.writeShellScript "yubilock" ''
STATE_FILE="$HOME/.cache/yubilock-state"
LOG_FILE="$HOME/.cache/yubilock.log"
PID_FILE="$HOME/.cache/yubilock.pid"
# Function to check if a YubiKey is currently plugged in
check_yubikey() {
if ${pkgs.usbutils}/bin/lsusb | ${pkgs.gnugrep}/bin/grep -i "yubikey" > /dev/null; then
return 0 # device is present
else
return 1 # device is not present
fi
}
# Function to lock the screen
lock_screen() {
# Using loginctl for systemd-based systems
${pkgs.systemd}/bin/loginctl lock-session
echo "Screen locked at $(date)" >> "$LOG_FILE"
}
# Create state file if it doesn't exist
if [ ! -f "$STATE_FILE" ]; then
echo "off" > "$STATE_FILE"
fi
# Record PID for later termination
echo "$$" > "$PID_FILE"
# Main monitoring loop
echo "YubiKey monitoring started at $(date)" >> "$LOG_FILE"
while true; do
# Check if monitoring is still enabled
if [ "$(cat "$STATE_FILE")" != "on" ]; then
echo "YubiKey monitoring stopped at $(date)" >> "$LOG_FILE"
exit 0
fi
if check_yubikey; then
echo "YubiKey detected at $(date)" >> "$LOG_FILE"
# Wait until the YubiKey is removed
while check_yubikey && [ "$(cat "$STATE_FILE")" = "on" ]; do
sleep 1
done
# If we exited because service was disabled, exit gracefully
if [ "$(cat "$STATE_FILE")" != "on" ]; then
echo "YubiKey monitoring stopped at $(date)" >> "$LOG_FILE"
exit 0
fi
echo "YubiKey removed at $(date)" >> "$LOG_FILE"
lock_screen
else
echo "No YubiKey detected. Checking again in 10 seconds..." >> "$LOG_FILE"
# Check less frequently to reduce system load
sleep 10
fi
done
'';
yubilockRestoreScript = pkgs.writeShellScript "yubilock-restore" ''
STATE_FILE="$HOME/.cache/yubilock-state"
LOG_FILE="$HOME/.cache/yubilock-restore.log"
echo "[$(date)] Checking yubilock state on login" >> "$LOG_FILE"
# Create state file if it doesn't exist
if [ ! -f "$STATE_FILE" ]; then
echo "off" > "$STATE_FILE"
echo "[$(date)] No state file found, defaulting to off" >> "$LOG_FILE"
exit 0
fi
# Read the saved state
saved_state=$(cat "$STATE_FILE")
echo "[$(date)] Saved state: $saved_state" >> "$LOG_FILE"
# If it was enabled before, re-enable it
if [ "$saved_state" = "on" ]; then
if ! ${pkgs.systemd}/bin/systemctl --user is-active yubilock.service > /dev/null 2>&1; then
echo "[$(date)] Restoring yubilock service" >> "$LOG_FILE"
${pkgs.systemd}/bin/systemctl --user start yubilock.service
echo "[$(date)] Yubilock service restored" >> "$LOG_FILE"
else
echo "[$(date)] Yubilock service already running" >> "$LOG_FILE"
fi
fi
'';
in
{
options.services.yubilock = {
enable = mkEnableOption "YubiKey screen lock monitor";
autoRestore = mkOption {
type = types.bool;
default = true;
description = ''
Automatically restore yubilock state on login.
If enabled, the yubilock service will be restarted on login
if it was running when you last logged out.
'';
};
};
config = mkIf cfg.enable {
# Systemd user service for yubilock
systemd.user.services.yubilock = {
Unit = {
Description = "YubiKey lock screen monitor";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
Type = "simple";
ExecStart = "${yubilockScript}";
Restart = "on-failure";
RestartSec = "5s";
# Ensure state persists
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p %h/.cache";
# Clean state on stop
ExecStopPost = "${pkgs.bash}/bin/bash -c 'echo off > %h/.cache/yubilock-state'";
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
# Systemd user service to restore yubilock state on login
systemd.user.services.yubilock-restore = mkIf cfg.autoRestore {
Unit = {
Description = "Restore YubiKey monitor state on login";
After = [ "graphical-session.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${yubilockRestoreScript}";
RemainAfterExit = false;
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
# Ensure required packages are available
home.packages = with pkgs; [
usbutils # for lsusb command
];
};
}

View File

@@ -1,11 +0,0 @@
{ pkgs, ... }:
{
services.udev.extraRules = ''
ACTION=="remove",\
ENV{ID_BUS}=="usb",\
ENV{ID_MODEL_ID}=="0407",\
ENV{ID_VENDOR_ID}=="1050",\
ENV{ID_VENDOR}=="Yubico",\
RUN+="${pkgs.systemd}/bin/loginctl lock-sessions"
'';
}