This script adds two new options to the GRUB menu for safely launching live modes. You will get two ways to launch dom0 in RAM for protection against forensics:
- Qubes Overlay-Live Mode â dom0 in tmpfs overlay
- Qubes Zram-Live Mode â dom0 in zram block device
This script also adds the RamâWipe module to wipe memory after shutdown. This tool is used by Tails and Kicksecure / Whonix to wipe memory for protection against forensics and cold boot attack.
You will see new entries after shutdown Qubes ![]()
This script also creates an ultraâhardened dom0 in live modes: root readâonly, swap is disabled, strong hardening mount, strong kernel hardening (kernel hardening from Secureblue). It protects the system from any hacker or malware attacks.
This script also creates two hardened Amnesic DVMs with ephemeral encryption! These are basic VMs for protection against forensics:
- Directories
/home/userand/usr/localare bind-mounted from volatile/tmpfor isolated use and reducing session traces, then session data will be permanently destroyed after the dvm shutdown! Ephemeral encryption protects your data even if a forensic analyst gains access to the decrypted, running dom0! - Both DVMs have the kernel options
init_on_free=1andinit_on_alloc=1for paranoid security and to protect against the leakage of passwords and private data (Secureblue and Tails have these kernel options by default). Now no app can leak your passwords or private data! - Both DVMs also have protection against dom0-timezone leak. It protects against the creation of a your unique system fingerprint!
This guide solves the old problems:
1 implement live boot by porting grub-live to Qubes - amnesia / non-persistent boot / anti-forensics
2 DisposableVMs: support for in-RAM execution only (for anti-forensics
3 Reduce leakage of disposable VM content and history into dom0 filesystem
4 Wipe RAM after shutdown
OverlayâLive Mode is very fast and maximally secure. Overlay is used in Tails and Kicksecure/Whonix. It also makes efficient use of memory for the dom0 RAM disk (you have 100% free space on dom0).
ZramâLive Mode starts slowly, uses more CPU power, but saves RAM dramatically (~ 2Ă compared to OverlayâLive) when creating large RAMâAppVMs. It is perfect for running large VMs (Temolate copy or Standalone qube) in RAM for tests new packages / apps.
Both live modes significantly increase dom0 security:
Root mount in readâonly mode,
dom0 operates in the ultra-hardened live-mode,
Ephemeral encryption for private data.
RAM-wipe always and everywhere.
Now your private data are protected from forensic analysis. Volatile private data and ephemeral encryption protect your data even if a forensic analyst gains access to the decrypted, running dom0. Xen wipes memory for VMs, and
init_on_free=1withinit_on_alloc=1wipe memory for apps in amnesicâlive DVMs. Dom0 Live with isolation and strong hardening is securely shielded from any hacks. Even if a genius attacker gets into dom0, he wonât be able to make any persistent changes because your root is mounted readâonly, and a reboot will wipe out the attacker! You have the most powerful system protection: xen-isolation, robust hardening, a readâonly root, ephemeral encryption, non-persistent live mode with ram-wipe.
This also works great for experiments in Qubes or for beginners who want to learn without fear of breaking anything - all changes disappear after a reboot. It will extend the lifespan of your SSD.
Donât worry about installing these modes - default Qubes boot wonât be affected at all and wonât change! I created this scenario to be as safe as possible and isolated from the default Qubes boot:
The new GRUB options are added to/etc/grub.d/40_custom(so it donât modify your/etc/default/grub).
The new sysctl options start only in live modes.
The new dracut live modules start only in live modes.
The new ephemeral DVMs donât affect the operation or settings of the default DVMs.
Swap is disabled only in live modes.
Simple script for automatically determine the optimal LiveâDisk size and creating Dracut Modules, Custom GRUB, Amnesic Live DVMs
Make a backup before you run script ![]()
You just need:
Save the script into txt, for example, with name live.sh in /home/user/
Make the file executable. Run in terminal sudo chmod +x live.sh or tick the box in File Properties â Permissions â Program:
Copy file to dom0. Run it in dom0 terminal qvm-run --pass-io <qube-name> 'cat /home/user/live.sh' > live.sh
Run it with sudo sudo ./live.sh
#!/bin/bash
# Qubes Dom0 Live Boot and RAM-Wipe
# â ïž Make backup before running! Run as root: sudo ./live.sh
set -e # Exit on any error
#BOOT_UUID
BOOT_UUID=$(findmnt -n -o UUID /boot 2>/dev/null || echo "AUTO_BOOT_NOT_FOUND")
if [ "$BOOT_UUID" = "AUTO_BOOT_NOT_FOUND" ]; then
BOOT_UUID=$(blkid -s UUID -o value -d $(findmnt -n -o SOURCE /boot 2>/dev/null))
fi
# LUKS_UUID
LUKS_DEVICE=$(blkid -t TYPE="crypto_LUKS" -o device 2>/dev/null | head -n1 || echo "")
if [ -n "$LUKS_DEVICE" ]; then
LUKS_UUID=$(sudo cryptsetup luksUUID "$LUKS_DEVICE" 2>/dev/null)
else
LUKS_UUID="AUTO_LUKS_NOT_FOUND"
fi
# Latest XEN_PATH
XEN_PATH=$(ls /boot/xen*.gz 2>/dev/null | sort -V | tail -1 | xargs basename 2>/dev/null || echo "/xen-4.19.4.gz")
# Latest kernel/initramfs
LATEST_KERNEL=$(ls /boot/vmlinuz-*qubes*.x86_64 2>/dev/null | grep -E 'qubes\.fc[0-9]+' | sort -V | tail -1 | xargs basename)
LATEST_INITRAMFS=$(echo "/initramfs-${LATEST_KERNEL#vmlinuz-}.img")
# Max memory dom0
system_total_mb=$(xl info | grep total_memory | awk '{print $3}')
if [ -n "$system_total_mb" ] && [ "$system_total_mb" -gt 0 ] 2>/dev/null; then
# 80% total_memory
DOM0_MAX_MB=$((system_total_mb * 80 / 100))
DOM0_MAX_GB=$((DOM0_MAX_MB / 1024))
DOM0_MAX_RAM="dom0_mem=max:${DOM0_MAX_MB}M"
DOM0_MAX_GBG="${DOM0_MAX_GB}G"
else
DOM0_MAX_RAM="dom0_mem=max:10240M"
DOM0_MAX_GB="10"
DOM0_MAX_GBG="10G"
fi
# qubes_dom0-root
Qubes_Root=$(findmnt -n -o SOURCE /)
echo "=== Qubes Dom0 Live Boot Setup ==="
# Disable Dom0 Swap and Add Sysctl Hardening:
cat > /home/user/.config/swapoff.sh << 'EOF'
#!/bin/bash
sleep 2
if findmnt -n -o SOURCE / | grep -qE "(overlay|/dev/zram0)"; then
sudo systemctl stop dev-zram0.swap systemd-zram-setup@zram0.service
sudo systemctl disable dev-zram0.swap systemd-zram-setup@zram0.service
sudo systemctl mask dev-zram0.swap systemd-zram-setup@zram0.service
sudo swapoff /dev/zram0
sudo swapoff -a
sudo sed -i '/[[:space:]]\+swap[[:space:]]\+/s/^/#/' /etc/fstab
sudo sed -i '/[[:space:]]\+none[[:space:]]\+swap[[:space:]]\+/s/^/#/' /etc/fstab
sudo sed -i '/[[:space:]]\?\/dev\/.*[[:space:]]\+swap[[:space:]]\+/s/^/#/' /etc/fstab
sudo sysctl -w kernel.sysrq=0
sudo sysctl -w kernel.perf_event_paranoid=3
sudo sysctl -w kernel.kptr_restrict=2
sudo sysctl -w kernel.panic=5
sudo sysctl -w fs.protected_regular=2
sudo sysctl -w fs.protected_fifos=2
sudo sysctl -w kernel.printk="3 3 3 3"
sudo sysctl -w kernel.kexec_load_disabled=1
sudo sysctl -w kernel.io_uring_disabled=2
qvm-pool set vm-pool -o ephemeral_volatile=True
qvm-pool set varlibqubes -o ephemeral_volatile=True
fi
EOF
chmod 755 /home/user/.config/swapoff.sh
cat > /home/user/.config/autostart/swapoff.desktop << 'EOF'
[Desktop Entry]
Encoding=UTF-8
Version=0.9.4
Type=Application
Name=swapoff
Comment=
Exec=/home/user/.config/swapoff.sh
OnlyShowIn=XFCE;
RunHook=0
StartupNotify=false
Terminal=false
Hidden=false
EOF
# Create Dracut directories
echo "Creating Dracut modules..."
mkdir -p /usr/lib/dracut/modules.d/90ramboot
mkdir -p /usr/lib/dracut/modules.d/90overlayfs-root
# Create 90ramboot/module-setup.sh
cat > /usr/lib/dracut/modules.d/90ramboot/module-setup.sh << 'EOF'
#!/usr/bin/bash
check() {
return 0
}
depends() {
return 0
}
install() {
inst_simple "$moddir/zram-mount.sh"
inst_hook cleanup 00 "$moddir/zram-mount.sh"
}
EOF
chmod 755 /usr/lib/dracut/modules.d/90ramboot/module-setup.sh
# Create 90overlayfs-root/module-setup.sh
cat > /usr/lib/dracut/modules.d/90overlayfs-root/module-setup.sh << 'EOF'
#!/bin/bash
check() {
[ -d /lib/modules/$kernel/kernel/fs/overlayfs ] || return 1
}
depends() {
return 0
}
installkernel() {
hostonly='' instmods overlay
}
install() {
inst_hook pre-pivot 10 "$moddir/overlay-mount.sh"
}
EOF
chmod 755 /usr/lib/dracut/modules.d/90overlayfs-root/module-setup.sh
# Create overlay-mount.sh
cat > /usr/lib/dracut/modules.d/90overlayfs-root/overlay-mount.sh << 'EOF'
#!/bin/sh
. /lib/dracut-lib.sh
if ! getargbool 0 rootovl ; then
return
fi
modprobe overlay
mount -o remount,nolock,noatime $NEWROOT
mkdir -p /live/image
mount --bind $NEWROOT /live/image
umount $NEWROOT
mkdir /cow
mount -n -t tmpfs -o mode=0755,size=100%,nr_inodes=500k,noexec,nodev,nosuid,noatime,nodiratime tmpfs /cow
mkdir /cow/work /cow/rw
mount -t overlay -o noatime,nodiratime,volatile,lowerdir=/live/image,upperdir=/cow/rw,workdir=/cow/work,default_permissions,relatime overlay $NEWROOT
mkdir -p $NEWROOT/live/cow
mkdir -p $NEWROOT/live/image
mount --bind /cow/rw $NEWROOT/live/cow
umount /cow
mount --bind /live/image $NEWROOT/live/image
umount /live/image
umount $NEWROOT/live/cow
EOF
chmod 755 /usr/lib/dracut/modules.d/90overlayfs-root/overlay-mount.sh
# Create zram-mount.sh
cat > /usr/lib/dracut/modules.d/90ramboot/zram-mount.sh << EOF
#!/bin/sh
. /lib/dracut-lib.sh
if ! getargbool 0 rootzram ; then
return
fi
mkdir /mnt
umount /sysroot
mount -o ro $Qubes_Root /mnt
modprobe zram
echo $DOM0_MAX_GBG > /sys/block/zram0/disksize
/mnt/usr/sbin/mkfs.ext2 /dev/zram0
mount -o nodev,nosuid,noatime,nodiratime /dev/zram0 /sysroot
cp -a /mnt/* /sysroot
umount /mnt
exit 0
EOF
chmod 755 /usr/lib/dracut/modules.d/90ramboot/zram-mount.sh
# Create ramboot dracut.conf
cat > /etc/dracut.conf.d/ramboot.conf << 'EOF'
add_drivers+=" zram "
add_dracutmodules+=" ramboot "
EOF
# Create module directory
mkdir -p /usr/lib/dracut/modules.d/40ram-wipe/
# Create module-setup.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/module-setup.sh << 'EOF'
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.
# called by dracut
check() {
require_binaries sync || return 1
require_binaries sleep || return 1
require_binaries dmsetup || return 1
return 0
}
# called by dracut
depends() {
return 0
}
# called by dracut
install() {
inst_simple "/usr/libexec/ram-wipe/ram-wipe-lib.sh" "/lib/ram-wipe-lib.sh"
inst_multiple sync
inst_multiple sleep
inst_multiple dmsetup
inst_hook shutdown 40 "$moddir/wipe-ram.sh"
inst_hook cleanup 80 "$moddir/wipe-ram-needshutdown.sh"
}
# called by dracut
installkernel() {
return 0
}
EOF
chmod +x /usr/lib/dracut/modules.d/40ram-wipe/module-setup.sh
# Create wipe-ram-needshutdown.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram-needshutdown.sh << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.
type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
. /lib/ram-wipe-lib.sh
ram_wipe_check_needshutdown() {
## 'local' is unavailable in 'sh'.
#local kernel_wiperam_setting
kernel_wiperam_setting="$(getarg wiperam)"
if [ "$kernel_wiperam_setting" = "skip" ]; then
force_echo "wipe-ram-needshutdown.sh: Skip, because wiperam=skip kernel parameter detected, OK."
return 0
fi
true "wipe-ram-needshutdown.sh: Calling dracut function need_shutdown to drop back into initramfs at shutdown, OK."
need_shutdown
return 0
}
ram_wipe_check_needshutdown
EOF
chmod +x /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram-needshutdown.sh
# Create wipe-ram.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram.sh << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.
## Credits:
## First version by @friedy10.
## https://github.com/friedy10/dracut/blob/master/modules.d/40sdmem/wipe.sh
## Use '.' and not 'source' in 'sh'.
. /lib/ram-wipe-lib.sh
drop_caches() {
sync
## https://gitlab.tails.boum.org/tails/tails/-/blob/master/config/chroot_local-includes/usr/local/lib/initramfs-pre-shutdown-hook
### Ensure any remaining disk cache is erased by Linux' memory poisoning
echo 3 > /proc/sys/vm/drop_caches
sync
}
ram_wipe() {
## 'local' is unavailable in 'sh'.
#local kernel_wiperam_setting dmsetup_actual_output dmsetup_expected_output
## getarg returns the last parameter only.
kernel_wiperam_setting="$(getarg wiperam)"
if [ "$kernel_wiperam_setting" = "skip" ]; then
force_echo "wipe-ram.sh: Skip, because wiperam=skip kernel parameter detected, OK."
return 0
fi
force_echo "wipe-ram.sh: RAM extraction attack defense... Starting RAM wipe pass during shutdown..."
drop_caches
force_echo "wipe-ram.sh: RAM wipe pass completed, OK."
## In theory might be better to check this beforehand, but the test is
## really fast.
force_echo "wipe-ram.sh: Checking if there are still mounted encrypted disks..."
## TODO: use 'timeout'?
dmsetup_actual_output="$(dmsetup ls --target crypt 2>&1)"
dmsetup_expected_output="No devices found"
if [ "$dmsetup_actual_output" = "$dmsetup_expected_output" ]; then
force_echo "wipe-ram.sh: Success, there are no more mounted encrypted disks, OK."
elif [ "$dmsetup_actual_output" = "" ]; then
force_echo "wipe-ram.sh: Success, there are no more mounted encrypted disks, OK."
else
## dracut should unmount the root encrypted disk cryptsetup luksClose during shutdown
## https://github.com/dracutdevs/dracut/issues/1888
force_echo "\\
wipe-ram.sh: There are still mounted encrypted disks! RAM wipe incomplete!
debugging information:
dmsetup_expected_output: '$dmsetup_expected_output'
dmsetup_actual_output: '$dmsetup_actual_output'"
## How else could the user be informed that something is wrong?
sleep 5
fi
}
ram_wipe
EOF
chmod +x /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram.sh
# Create ram-wipe dracut.conf.d
cat > /usr/lib/dracut/dracut.conf.d/30-ram-wipe.conf << 'EOF'
add_dracutmodules+=" ram-wipe "
EOF
# Create ram-wipe-lib.sh
mkdir -p /usr/libexec/ram-wipe
cat > /usr/libexec/ram-wipe/ram-wipe-lib.sh << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.
## Based on:
## /usr/lib/dracut/modules.d/99base/dracut-lib.sh
if [ -z "$DRACUT_SYSTEMD" ]; then
force_echo() {
echo "<28>dracut INFO: $*" > /dev/kmsg
echo "dracut INFO: $*" >&2
}
else
force_echo() {
echo "INFO: $*" >&2
}
fi
EOF
chmod +x /usr/libexec/ram-wipe/ram-wipe-lib.sh
# Update INITRAMFS
dracut --verbose --force
# Create GRUB custom
echo "Creating GRUB custom ..."
cat > /etc/grub.d/40_custom << EOF
#!/usr/bin/sh
exec tail -n +3 \$0
menuentry 'Qubes Overlay-Live Mode (latest kernel)' --class qubes --class gnu-linux --class gnu --class os --class xen \$menuentry_id_option 'xen-gnulinux-simple-/dev/mapper/qubes_dom0-root' {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root $BOOT_UUID
echo 'Loading Xen ...'
if [ "\$grub_platform" = "pc" -o "\$grub_platform" = "" ]; then
xen_rm_opts=
else
xen_rm_opts="no-real-mode edd=off"
fi
insmod multiboot2
multiboot2 /$XEN_PATH placeholder console=none dom0_mem=min:1024M $DOM0_MAX_RAM ucode=scan smt=off gnttab_max_frames=2048 gnttab_max_maptrack_frames=4096 \${xen_rm_opts}
echo 'Loading Linux $LATEST_KERNEL ...'
module2 /$LATEST_KERNEL placeholder root=/dev/mapper/qubes_dom0-root ro rd.luks.uuid=$LUKS_UUID rd.lvm.lv=qubes_dom0/root rd.lvm.lv=qubes_dom0/swap plymouth.ignore-serial-consoles rhgb rootovl quiet lockdown=confidentiality module.sig_enforce=1 bootscrub=on usbcore.authorized_default=0
echo 'Loading initial ramdisk ...'
insmod multiboot2
module2 --nounzip $LATEST_INITRAMFS
}
menuentry 'Qubes Zram-Live Mode (latest kernel)' --class qubes --class gnu-linux --class gnu --class os --class xen \$menuentry_id_option 'xen-gnulinux-simple-/dev/mapper/qubes_dom0-root' {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root $BOOT_UUID
echo 'Loading Xen ...'
if [ "\$grub_platform" = "pc" -o "\$grub_platform" = "" ]; then
xen_rm_opts=
else
xen_rm_opts="no-real-mode edd=off"
fi
insmod multiboot2
multiboot2 /$XEN_PATH placeholder console=none dom0_mem=min:1024M $DOM0_MAX_RAM ucode=scan smt=off gnttab_max_frames=2048 gnttab_max_maptrack_frames=4096 \${xen_rm_opts}
echo 'Loading Linux $LATEST_KERNEL ...'
module2 /$LATEST_KERNEL placeholder root=/dev/mapper/qubes_dom0-root ro rd.luks.uuid=$LUKS_UUID rd.lvm.lv=qubes_dom0/root rd.lvm.lv=qubes_dom0/swap plymouth.ignore-serial-consoles rhgb rootzram quiet lockdown=confidentiality module.sig_enforce=1 bootscrub=on usbcore.authorized_default=0
echo 'Loading initial ramdisk ...'
insmod multiboot2
module2 --nounzip $LATEST_INITRAMFS
}
EOF
chmod 755 /etc/grub.d/40_custom
# Update GRUB
grub2-mkconfig -o /boot/grub2/grub.cfg
# Creating amnesic-dvms
clone_if_needed() {
local source="$1"
local target="$2"
if qvm-ls "$source" >/dev/null 2>&1 && ! qvm-ls "$target" >/dev/null 2>&1; then
echo "â Creating $target from $source..."
if qvm-clone -P vm-pool "$source" "$target" && \
qvm-prefs "$target" label purple; then
echo "â $target created successfully (purple color)"
else
echo "â Error creating $target"
return 1
fi
else
echo "- $target: $(qvm-ls "$source" >/dev/null 2>&1 && echo "â $source found" || echo "â $source missing"), $(qvm-ls "$target" >/dev/null 2>&1 || echo "cancel creating")"
fi
}
echo "Creating amnesic DVMs..."
echo "======================================"
echo "Creating amnesic DVM..."
clone_if_needed "fedora-dvm" "amnesic-dvm"
echo
echo "Creating amnesic Whonix DVM..."
clone_if_needed "whonix-dvm" "amnesic-whonix-dvm"
# Add rw config to amnesic-dvm
qvm-volume config amnesic-dvm:root rw False
qvm-run -u root amnesic-dvm 'bash -c "cat > /rw/config/rc.local << ENDMARK
#!/bin/sh
timedatectl set-timezone Etc/UTC
mkdir -p /tmp/home-user
chown user:user /tmp/home-user
chmod 700 /tmp/home-user
cp -a /home/user/. /tmp/home-user/
mount --bind /tmp/home-user /home/user
mount -o remount,size=2G /home/user
sudo mkdir -p /tmp/usrlocal
sudo cp -a /usr/local/. /tmp/usrlocal/
sudo mount --bind /tmp/usrlocal /usr/local
ENDMARK"'
# Add rw config to amnesic-whonix-dvm
qvm-volume config amnesic-whonix-dvm:root rw False
qvm-run -u root amnesic-whonix-dvm 'bash -c "cat > /rw/config/rc.local << ENDMARK
#!/bin/sh
umount /home/user/.cache/tb 2>/dev/null || true
umount /rw/home/user/.cache/tb 2>/dev/null || true
mkdir -p /tmp/tb-cache
chown user:user /tmp/tb-cache
chmod 755 /tmp/tb-cache
mkdir -p /tmp/home-user
chown user:user /tmp/home-user
chmod 700 /tmp/home-user
cp -a /home/user/. /tmp/home-user/
cp -a /tmp/tb-cache/. /tmp/home-user/.cache/tb/ 2>/dev/null || true
mount --bind /tmp/home-user /home/user
mount -o remount,size=2G /home/user
sudo mkdir -p /tmp/usrlocal
sudo cp -a /usr/local/. /tmp/usrlocal/
sudo mount --bind /tmp/usrlocal /usr/local
ENDMARK"'
# Shutdown amnesic-dvms
qvm-shutdown amnesic-dvm
qvm-shutdown amnesic-whonix-dvm
# Add new kernel options
echo "Hardening amnesic DVMs..."
qvm-prefs amnesic-dvm kernelopts "init_on_free=1 init_on_alloc=1"
qvm-prefs amnesic-whonix-dvm kernelopts "init_on_free=1 init_on_alloc=1"
echo
echo "Done!"
echo "â ALL STEPS COMPLETED SUCCESSFULLY!"
Done!
Restart Qubes OS and Test Qubes live modes ![]()
Remember that the data will be removed only after a reboot of Qubes OS.
Now if dom0 updates kernels or you add more ram to device, just run script again and live modules and live-grub config update kernel and ram-settings
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]()
If you want to create new amnesic appVMs / DVMs, simply copy the existing amnesic DVMs or add the commands from /rw/config/rc.local in amnesicâdefaultâdvm to your new AppVM (these commands work for Debian, Fedora, and Kicksecure templates).
If your device has 32-256 GB of memory, you can launch amnesic DVMs in a paranoidâprotected mode within the varlibqubes pool (pool in dom0). This consumes gigabytes of memory - VMs will run from dom0âs live disk.
Resize dom0 storage (for example 30G) using these commands:
sudo lvresize --size 30G /dev/mapper/qubes_dom0-root
sudo resize2fs /dev/mapper/qubes_dom0-root
Then In the Qube Manager click clone qube, then in Advanced select varlibqubes in Storage pool. Or create a new appVM, and select varlibqubes Storage pool in the Advanced Options. But an AppVM in the varlibqubes pool loses the discard (TRIM) option because the varlibqubes pool uses an outdated driver, therefore, size of the appVM will only increase.
You can also add these kernel options for paranoid protection against forensics in your new amnesic-appVMs (it will increase appVM CPU load by 5-15%):
qvm-prefs <appVM> kernelopts "init_on_free=1 init_on_alloc=1"
Add templates to varlibqubes pool, if you want to install and test new packages or applications.
You can update templates in live modes, but update dom0 in default persistent mode!
You can make backups of all VMs (and dom0) in live modes.
Ephemeral encryption is disabled in the default Qubes OS boot! To enable it, use this command:
qvm-pool set vm-pool -o ephemeral_volatile=True
Comment out (#) commands in
/rw/config/rc.localand restart AppVM if you want to customize a DVM/AppVM (otherwise all changes wonât persist after VM shutdown because/home/useris mounted in RAM). Then uncomment/rw/config/rc.local. Alternatively, customize default DVMs first and then run script.
Zram-Live Mode takes longer to start (about 30-40 seconds more). Donât worry about the errors when starting Zram-Live Mode â those are just informative errors indicating that a swap couldnât be created.
If you want to add your custom kernel options for live modes, do it in
sudo nano /etc/grub.d/40_custom
and then update GRUB
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
![]()
You can add a âGeneric Monitorâ widget to the XFCE panel and configure it to run command findmnt -n -o SOURCE /. This widget will display which mode youâre currently in:
You can also use this terminal theme so can see which mode youâre currently in:
Click CTRL + H in thunar of dom0 and add this code into .bashrc instead of the default code:
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
###########################
export VIRTUAL_ENV_DISABLE_PROMPT=true
__qubes_update_prompt_data() {
local RETVAL=$?
__qubes_venv=''
[[ -n "$VIRTUAL_ENV" ]] && __qubes_venv=$(basename "$VIRTUAL_ENV")
__qubes_git=''
__qubes_git_color=$(tput setaf 10) # clean
local git_branch=$(git --no-optional-locks rev-parse --abbrev-ref HEAD 2> /dev/null)
if [[ -n "$git_branch" ]]; then
local git_status=$(git --no-optional-locks status --porcelain 2> /dev/null | tail -n 1)
[[ -n "$git_status" ]] && __qubes_git_color=$(tput setaf 11) # dirty
__qubes_git="âč${git_branch}âș"
fi
__qubes_prompt_symbol_color=$(tput sgr0)
[[ "$RETVAL" -ne 0 ]] && __qubes_prompt_symbol_color=$(tput setaf 1)
return $RETVAL # to preserve retcode
}
if [[ -n "$git_branch" ]]; then
PROMPT_COMMAND="$PROMPT_COMMAND; __qubes_update_prompt_data"
else
PROMPT_COMMAND="__qubes_update_prompt_data"
fi
PS1=''
PS1+='\[$(tput setaf 7)\]$(echo -ne $__qubes_venv)\[$(tput sgr0)\]'
PS1+='\[$(tput setaf 14)\]\u'
PS1+='\[$(tput setaf 15)\] đ '
PS1+='\[$(tput setaf 9)\]\h'
PS1+=" $(findmnt -n -o SOURCE /)"
PS1+='\[$(tput setaf 15)\]:'
PS1+='\[$(tput setaf 7)\]\w '
PS1+='\[$(echo -ne $__qubes_git_color)\]$(echo -ne $__qubes_git)\[$(tput sgr0)\] '
PS1+='\[$(tput setaf 8)\]\[$([[ -n "$QUBES_THEME_SHOW_TIME" ]] && echo -n "[\t]")\]\[$(tput sgr0)\]'
PS1+='\[$(tput sgr0)\]\n'
PS1+='\[$(echo -ne $__qubes_prompt_symbol_color)\]\$\[$(tput sgr0)\] '
Also see these guides for additional hardening of live modes:
- USB Kill Switch for Qubes OS
- Installation of Amnezia VPN and Amnezia WG: effective tools against internet blocks via DPI for China, Russia, Belarus, Turkmenistan, Iran. VPN with Vless XRay reality. Best obfuscation for WireGuard. Easy selfâhosted VPN. Bypass
- Anonymize hostname hardened template automatic installation of browser
- Apparmor profile for Qubes available!
ps: Do not use script from second comment - itâs outdated, and I can no longer edit this message.





