diff --git a/hosts/fenixpc/fenix.nix b/hosts/fenixpc/fenix.nix index 5425a00..36e1f23 100644 --- a/hosts/fenixpc/fenix.nix +++ b/hosts/fenixpc/fenix.nix @@ -87,5 +87,9 @@ in settings.folders.PhotoArchive.enabled = true; settings.folders.books.enabled = true; }; + yubilock = { + enable = true; + autoRestore = true; + }; }; } diff --git a/modules/hm/yubilock.nix b/modules/hm/yubilock.nix new file mode 100644 index 0000000..eb9ba6c --- /dev/null +++ b/modules/hm/yubilock.nix @@ -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 + ]; + }; +} diff --git a/quirks/yubilock.nix b/quirks/yubilock.nix deleted file mode 100644 index a16ef8a..0000000 --- a/quirks/yubilock.nix +++ /dev/null @@ -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" - ''; -}