This guide explains how to set up a USB-based kill switch for Qubes OS that locks your screen immediately and shuts down your system shortly after a specific USB device is removed.
It’s similar to BusKill, but purpose-built for Qubes OS.
ONLY TESTED FOR XFCE ENVIRONMENT WITH THE XFCE SCREENSAVER
What it does:
- Monitors a chosen USB device (flash drive, hardware token, etc.)
- Locks screen immediately if device is disconnected
- Shuts down after a set delay if screen remains locked
- Resumes monitoring if you unlock before shutdown
Prerequisites
- Qubes OS (tested on 4.2.4)
- A USB device to act as your “key”
- Basic terminal knowledge
Installation
1. Create Script Directory
mkdir -p ~/Scripts
cd ~/Scripts
2. Create the Scripts
SelectUSB.sh – Choose USB device to monitor
#!/bin/bash
ConfigDir="$HOME/Scripts"
mkdir -p "$ConfigDir"
ListDevices() {
echo "===== Available USB Block Devices ====="
Devices=()
Types=()
Index=1
while IFS= read -r Line; do
BackendDevice=$(echo "$Line" | awk '{print $1}')
Description=$(echo "$Line" | cut -d' ' -f3-)
Devices+=("$BackendDevice")
Types+=("block")
echo "$Index) $BackendDevice - $Description"
((Index++))
done < <(qvm-block list 2>/dev/null | tail -n +2)
echo
echo "===== Available Raw USB Devices ====="
while IFS= read -r Line; do
BackendDevice=$(echo "$Line" | awk '{print $1}')
Description=$(echo "$Line" | cut -d' ' -f3-)
Devices+=("$BackendDevice")
Types+=("usb")
echo "$Index) $BackendDevice - $Description"
((Index++))
done < <(qvm-usb list 2>/dev/null | tail -n +2)
}
ChooseDevice() {
while true; do
clear
echo "USB Kill Switch - Device Selection"
echo "=================================="
ListDevices
echo
echo "Enter number to select device, 'r' to refresh, or 'q' to quit:"
read -rp "> " Choice
case "$Choice" in
"r"|"R") continue ;;
"q"|"Q") exit 0 ;;
*)
if [[ "$Choice" =~ ^[0-9]+$ ]] && (( Choice >= 1 && Choice <= ${#Devices[@]} )); then
SelectedDevice="${Devices[$((Choice-1))]}"
MonitorType="${Types[$((Choice-1))]}"
MonitorVM=$(echo "$SelectedDevice" | cut -d':' -f1)
MonitorDevice=$(echo "$SelectedDevice" | cut -d':' -f2)
echo
echo "Selected: $MonitorDevice from $MonitorVM (type: $MonitorType)"
echo "Press Enter to confirm..."
read
break
else
echo "Invalid choice! Try again."
sleep 2
fi
;;
esac
done
}
echo "Starting USB Kill Switch setup..."
ChooseDevice
echo "MonitorType=$MonitorType" > "$ConfigDir/USBDevice.conf"
echo "MonitorVM=$MonitorVM" >> "$ConfigDir/USBDevice.conf"
echo "MonitorDevice=$MonitorDevice" >> "$ConfigDir/USBDevice.conf"
echo "Configuration saved. Starting USB Kill Switch service..."
systemctl --user start monitor-drive-usbkill.service
echo "USB Kill Switch is now active!"
sleep 3
Tip:
If you want this selector to appear automatically after login (e.g., so you can choose your USB key every session), create a .desktop
file in ~/.config/autostart
:
[Desktop Entry]
Type=Application
Name=USB Kill Switch Setup
Exec=xfce4-terminal --command "/home/user/Scripts/SelectUSB.sh"
Terminal=true
X-GNOME-Autostart-enabled=true
Replace /home/user
with your actual username.
USBKill.sh – Main monitoring daemon
#!/bin/bash
ConfigDir="$HOME/Scripts"
ConfigFile="$ConfigDir/USBDevice.conf"
if [[ ! -f "$ConfigFile" ]]; then
echo "ERROR: No USB device configured."
echo "Please run SelectUSB.sh first."
exit 1
fi
source "$ConfigFile"
ShutdownTimeout=10
CheckInterval=0.5
DisconnectedTime=0
LogMessage() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | systemd-cat -t usbkill
}
IsDeviceConnected() {
if [[ "$MonitorType" == "block" ]]; then
qvm-block list "$MonitorVM" 2>/dev/null | grep -q "$MonitorDevice"
else
qvm-usb list "$MonitorVM" 2>/dev/null | grep -q "$MonitorDevice"
fi
}
IsScreenLocked() {
xscreensaver-command -time 2>/dev/null | grep -q "screen locked"
}
LockScreen() {
if ! IsScreenLocked; then
LogMessage "Locking screen due to USB disconnect"
xflock4 &
fi
}
LogMessage "USB Kill Switch started - Monitoring $MonitorType device $MonitorDevice on $MonitorVM"
while true; do
if [[ $DisconnectedTime -eq 0 ]]; then
if ! IsDeviceConnected; then
DisconnectedTime=$(date +%s)
LogMessage "USB device disconnected"
LockScreen
fi
else
CurrentTime=$(date +%s)
ElapsedTime=$((CurrentTime - DisconnectedTime))
if ! IsScreenLocked; then
LogMessage "Screen unlocked — stopping service"
systemctl --user stop monitor-drive-usb.service
xfce4-terminal -x "$ConfigDir/SelectUSB.sh"
exit 0
fi
if [[ $ElapsedTime -ge $ShutdownTimeout ]]; then
LogMessage "Timeout reached — shutting down"
shutdown now
exit 0
fi
fi
sleep $CheckInterval
done
3. Set Permissions
chmod +x ~/Scripts/*.sh
4. Create Systemd Service
File: ~/.config/systemd/user/monitor-drive-usbkill.service
[Unit]
Description=USB Kill Switch Monitor
After=graphical-session.target
Wants=graphical-session.target
[Service]
Type=simple
ExecStart=%h/Scripts/USBKill.sh
Restart=on-failure
RestartSec=10
Environment=DISPLAY=:0
[Install]
WantedBy=default.target
Usage
- Run:
~/Scripts/SelectUSB.sh
- Pick your USB key
- Service runs automatically and monitors the device
Customization
ShutdownTimeout=30
– seconds before shutdownCheckInterval=0.5
– polling interval in seconds
Troubleshooting
- Check logs:
journalctl --user -u monitor-drive-usbkill.service --no-pager
- Make sure
xscreensaver
is running for screen lock
Uninstall
systemctl --user stop monitor-drive-usbkill.service
rm -rf ~/Scripts/
rm ~/.config/systemd/user/monitor-drive-usbkill.service
systemctl --user daemon-reload