License:Unlicense
Duress password is integrated at two authentication points: the lightdm display manager for system login, and the xscreensaver lock screen for session unlock. This ensures the duress action can be triggered both at initial boot authentication and when unlocking an existing session.
See this guide for creating a duress nuke-password for a LUKS-encrypted disk: Hidden “nuke” duress-password to LUKS-encrypted disk. Qubes OS LUKS self-destruct module
Make backups of all your VMs beforehand.
Download this repository in dvm:
git clone https://github.com/nuvious/pam-duress.git
then add it to a ZIP archive, for example pam.zip
Send it to dom0 and extract archive
qvm-run --pass-io dispXXX 'cat /home/user/pam.zip' > pam.zip
unzip pam.zip
Run these commands to build the module in dom0 and create duress-password:
sudo qubes-dom0-update gcc gcc-c++ make cmake automake pam-devel openssl-devel
cd pam-duress
make
sudo make install PAM_DIR=/usr/lib64/security
make clean
mkdir -p ~/.duress
sudo mkdir -p /etc/duress.d
Create a scripts with two scenarios:
1. Scenario: Delete some VMs and delete this script itself:
cat > ~/remove_vm.sh << 'EOF'
#!/bin/bash
if ! [ -w /run/qubesd.sock ] && [ -z "$DURESS_REEXEC" ]; then
exec sg qubes "DURESS_REEXEC=1 $0 $*"
fi
export PATH="/usr/bin:/usr/sbin:/bin:/sbin:$PATH"
# Add the names of VMs to be deleted here 'test_vm'
/usr/bin/qvm-remove --force test_vm
EOF
chmod +x ~/remove_vm.sh
(
Add the names of VMs to be deleted here ‘test_vm’)
2. Scenario: Total system destruction:
cat > ~/remove_qubes.sh << 'EOF'
#!/bin/bash
# WARNING: This script irreversibly destroys data. Use only for duress password.
if ! [ -w /run/qubesd.sock ] && [ -z "$DURESS_REEXEC" ]; then
exec sg qubes "DURESS_REEXEC=1 $0 $*"
fi
export PATH="/usr/bin:/usr/sbin:/bin:/sbin:$PATH"
# ========== PHASE 0: REMOVE RAM-WIPE MODULE ==========
RAM_WIPE_DIR="/usr/lib/dracut/modules.d/40ram-wipe"
if [ -d "$RAM_WIPE_DIR" ]; then
echo "[*] Removing ram-wipe dracut module to prevent shutdown stall..."
rm -rf "$RAM_WIPE_DIR"
fi
# ========== PHASE 1: DESTROY LUKS HEADER ==========
LUKS_DEV=""
for dev in /dev/nvme0n1p3 /dev/sda2 /dev/vda2 /dev/mapper/luks-*; do
cryptsetup isLuks "$dev" 2>/dev/null && LUKS_DEV="$dev" && break
done
if [ -n "$LUKS_DEV" ]; then
echo "[*] Erasing LUKS header on $LUKS_DEV..."
if cryptsetup luksErase --batch-mode "$LUKS_DEV" 2>/dev/null; then
echo "[*] LUKS header destroyed. Triggering emergency reboot..."
echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger
xl debug-keys R 2>/dev/null || true
exit 0
fi
fi
# ========== PHASE 2: FALLBACK - DESTROY ALL VMs + CORRUPT LVM ==========
echo "[!] LUKS erase failed or not found. Executing fallback destruction..."
echo "[*] Removing all qubes..."
qvm-remove --all -f 2>/dev/null || true
echo "[*] Corrupting LVM metadata..."
vgremove -ff qubes_dom0 2>/dev/null || true
for pv in /dev/nvme0n1p3 /dev/sda2 /dev/vda2; do
[ -b "$pv" ] && dd if=/dev/urandom of="$pv" bs=1M count=4 conv=notrunc 2>/dev/null && break
done
# ========== PHASE 3: INSTANT REBOOT ==========
echo "[*] Triggering emergency reboot..."
echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger
xl debug-keys R 2>/dev/null || true
EOF
chmod +x ~/remove_qubes.sh
Then add scripts in duress module:
cat > ~/.duress/remove_passwd.sh << 'EOF'
#!/bin/sh
/home/user/remove_vm.sh
rm -rf /home/user/remove_vm.sh
rm -rf /var/log/qubes
EOF
cat > ~/.duress/remove_passwd2.sh << 'EOF'
#!/bin/sh
/home/user/remove_qubes.sh
EOF
then
chmod 500 ~/.duress/remove_passwd.sh
chmod 500 ~/.duress/remove_passwd2.sh
duress_sign ~/.duress/remove_passwd.sh
add alternative password for destroying VMs
duress_sign ~/.duress/remove_passwd2.sh
add alternative password for destroying system
and then:
chmod 400 ~/.duress/remove_passwd.sh.sha256
chmod 400 ~/.duress/remove_passwd2.sh.sha256
Check:
ls -la ~/.duress/
Module created.
Now we need to modify this file /etc/pam.d/system-auth
sudo nano /etc/system-auth
Add this line
auth sufficient pam_duress.so
so that the first 6 auth-lines look like this:
auth required pam_env.so
auth required pam_faildelay.so delay=2000000
auth sufficient pam_fprintd.so
auth sufficient pam_unix.so nullok
auth sufficient pam_duress.so
auth required pam_deny.so
then click Ctrl + C and Ctrl + X
Done.
Now first duress password will remove some VMs.
Second duress password will destroy and forcibly shutdown the system. It should protect against forensics (disk will become unreadable).
See also this guides:
- Hidden “nuke” duress-password to LUKS-encrypted disk. Qubes OS LUKS self-destruct module
- Encrypted AppVMs and Templates. Encrypted pool. Secret vault in a LUKS-Pool. Paranoid security
- Qubes OS live mode. dom0 in RAM. Non-persistent Boot. RAM-Wipe. Protection against forensics. Tails mode. Hardening dom0. Root read‑only. Paranoid Security. Ephemeral Encryption