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

English isn’t my native language, so I used llm to translate and improve the comment. I’ll also note that whonix/kicksecure also uses a function similar to tails to clear RAM when shutting down the OS.
Related: ram-wipe - Wipe RAM on shutdown and reboot

///

However, while reviewing the code, I noticed a fundamental flaw in how the 40ram-wipe dracut module is implemented. Currently, it does not actually wipe the RAM.

In wipe-ram.sh, the script executes:

echo 3 > /proc/sys/vm/drop_caches

While the comment references the Tails OS pre-shutdown hook, drop_caches alone does not overwrite or wipe memory . It merely instructs the Linux kernel to release pagecache, dentries, and inodes.
In Tails OS, dropping caches is only a preparatory step. It forces file caches into “free” memory so that their actual memory-wiping mechanism can overwrite them.

Because the script stops at dropping caches, all active process memory (anonymous memory), encryption keys, and active buffers remain untouched in the RAM until the power naturally fades out, leaving the system vulnerable to Cold Boot Attacks.

How to fix this and achieve a true RAM wipe:

1. Add a real memory wiper (e.g., sdmem):
After dropping the caches, you need a tool that actually allocates and overwrites the freed memory. You can use sdmem (from the secure-delete package). The logic in wipe-ram.sh should be updated to run something like:

sync
echo 3 > /proc/sys/vm/drop_caches
sync
sdmem -f -ll  # Overwrites all available free RAM with zeros

(Note: Users would need to install the secure-delete package in dom0 for this).

2. Add Kernel memory poisoning for Dom0:
Your script beautifully adds init_on_free=1 init_on_alloc=1 and xen_scrub_pages=1 to the DVMs via qvm-prefs, which is great! However, these parameters are missing in the custom GRUB entries for Dom0 (40_custom).
If you add init_on_free=1 init_on_alloc=1 to the Dom0 GRUB kernel parameters, the Linux kernel will automatically zero out memory pages as soon as they are freed by drop_caches or when processes are killed during shutdown.

Combining init_on_free=1 in Dom0 GRUB with drop_caches and sdmem during shutdown will give this script a true, Tails-grade anti-forensic RAM wipe.

Thanks again for your hard work on this project! I hope this feedback helps make it even more secure.

P.S. A couple of ideas for “Paranoid” / Ultimate Hardening:

Since we are on the topic of maximum anti-forensics and security, I have two more architectural suggestions that could take the Live modes (especially the Zram mode) to an absolute “paranoid” level against advanced persistent threats (APTs):

1. On-the-fly Physical Drive Disconnection (For Zram mode)
Since the Zram mode copies the entire system to RAM, the physical SSD/HDD is technically no longer needed for the OS to function during that session.
If we logically disconnect the block device via sysfs after the live boot, the physical disk completely disappears from the OS.

Proposed Implementation:
Since users might have multiple NVMe or SATA drives, the script shouldn’t hardcode nvme0 or sda. Instead, it can dynamically detect the underlying physical parent disk of the Qubes LUKS container.

To make this secure-by-default, the installer script can automatically append a custom kernel parameter (e.g., qubes.detach_disk=1) to the GRUB custom menu entries (/etc/grub.d/40_custom).

Then, a startup script (like swapoff.sh) checks /proc/cmdline. If the flag is present, it dynamically detects and detaches the drive:

if grep -q "qubes.detach_disk=1" /proc/cmdline; then
    # Get the partition device (e.g., /dev/nvme0n1p2)
    LUKS_PART=$(blkid -t TYPE="crypto_LUKS" -o device | head -n1)
    # Find the parent physical disk (e.g., nvme0n1)
    PARENT_DISK=$(lsblk -no pkname "$LUKS_PART" 2>/dev/null)

    # Trigger removal based on device type
    if [ -n "$PARENT_DISK" ]; then
        if [[ "$PARENT_DISK" == nvme* ]]; then
            echo 1 > /sys/block/"$PARENT_DISK"/device/device/remove
        else
            echo 1 > /sys/block/"$PARENT_DISK"/device/delete
        fi
    fi
fi

Why this approach is great: It implements a solid “secure by default” model. The disk is automatically isolated on every live boot. If a user needs to keep the disk attached for some reason (e.g., to mount a secondary partition) or if the hardware behaves unexpectedly, they can easily opt-out by pressing e in the GRUB menu during boot and deleting the qubes.detach_disk=1 flag.

2. Linux Kernel Lockdown (lockdown=confidentiality)
Adding the lockdown=confidentiality parameter to the GRUB menuentry for the Live modes would be a massive security boost. Even if the Live Dom0 is compromised, this native Linux feature prevents the root user from modifying the running kernel, reading raw memory (/dev/mem), or accessing low-level hardware ports (like SPI flash). This mitigates the risk of malware trying to flash a malicious UEFI/BIOS firmware to establish hardware-level persistence from the live environment.

1 Like

@QubesParanoia Hello. I added default Kicksecure ram wipe module since it has passed an independent audit. Extracting the disk in zram live mode requires a very large amount of device memory: 64-128 GB, and also involves copying all qubes to the varlibqubes pool, so it’s too specific a use case. I don’t see any issues with disk access, since the disk is required for system boot and is mounted read-only anyway. Regarding dom0 kernel hardening, I removed some hardening options because it caused stability issues on dom0 for some devices used by users in this chat and my friends. I believe it’s sufficient that the disk is read-only and all operations are performed in an entirely separate directory (upper overlay or zram block device). However, in theory, a script could be created specifically for zram mode that copies all AppVMs (or just Whonix-Qubes) to the varlibqubes pool and then extracts the SSD from the device. You could test this and develop a working version based on your experience. Then, we could update the zram mode in my script accordingly. For kernel hardening, I’ve kept only the sysctl options. I also chose not to modify dom0 in default mode, in order to keep the live mode isolated from the default boot.

Hi @linuxuser1
I just want to double check. When Live Mode is installed, are the options to fully ephemerally encrypt my old AppVMs already applied or should I follow this guide and do it manually?

@ledOnion live mode in grub menu = live mode for dom0.
appVM in varlibqubes pool = live mode for appVM.
appVM with ephemeral encryption script in /rw/config/rc.local and in dom0 rw.service = ephemeral encryption appVM.
appVM without script and in vm-pool = persistent mode (disk)

If the AppVM is in rw.service and it has a script in /rw/config/rc.local, it means ephemeral encryption is working. Always check rw.service - this service won’t work if you renamed qube in the qube manager or if you deleted qube in the qube manager but it’s still in rw.service - then rw.service will fail because it couldn’t find that qube.rw.service should only contain valid qube names.

1 Like

Sorry for the delay but I realized, recently, that there’s a difference between ephemeral encryption and qubes placed in varlibqubes. Just to clarify, it has to be one or the other? I can’t do both for the same AppVM, right?

Sorry for the delay but I realized, recently, that there’s a difference between ephemeral encryption and qubes placed in varlibqubes. Just to clarify, it has to be one or the other? I can’t do both for the same AppVM, right?

Edit: Oh yeah. We talked about it before.

Sorry. It’s been a while so I’m trying to refresh my memory.

Script will be edit shortly. I was able to create an overlay without using RAM - upper layer uses an ephemeral encrypted container in dom0. It means you will be able to have a live mode of 100-500 GB size even with just 8 GB of memory on the device

1 Like

That’s interesting, @linuxuser1. I’m interested to know how you pulled that off and how the script used to be in comparison.

All qubes, including sys-net, sys-usb, sys-whonix, and all templates, are successfully working with the new ephemeral overlay encryption. I will start updating the guide and script tomorrow. Now everything will work more smoothly for beginners.

1 Like

@linuxuser1 I’ve looked at your profile but can’t find an overview of all those howto’s you’ve written in total - is there a link or a collection to this? I’d really love to look at all of them in detail and see if I can’t steal a bit of sth for my kuhbs project (with a reference to the original author of course!)

Big update to the guide and script!

  • Now overlay mode works with an encrypted container using ephemeral encryption - it completely eliminates the additional RAM overhead and makes it possible to launch an amnesic session with just 50-500 GB of free disk space.
  • We no longer have two in-memory modes, but rather a mode for ephemeral disk encryption and a mode for running in memory.
  • Guide and script have been significantly shortened and made simpler for beginners.

If for some reason you want to run overlay mode in memory, as before - then replace the cryptovl kernel option to rootovl in /etc/grub.d/40_custom

@kuhbs This guide + Duress guide + this 2 guides:

1 Like

got a link to this one too?

1 Like

after install(no errors) when I choose new boot options I have errors:

error: no such device: root

Loading Xen …

error: not a regular file.

Loading Linux …

error: you need to load kernel first.

Loading initial ramdisk …

error: filename expected

@murqa hello haha sorry, I accidentally deleted the variables for creating the custom GRUB config :joy: I will add it to script now.

upd; Script updated

1 Like

Update: Now you can use swap in overlay mode. This is very useful for devices with 12-16 GB of RAM. Dom0 has two swaps by default: /dev/zram0 (volatile) and /dev/dm-5 (an unencrypted partition). My script disables /dev/dm-5. You can create an additional ephemeral encrypted dm-swap (max privacy):
open ternimal in default persistent dom0:

sudo swapoff -a
sudo wipefs -a /dev/dm-5

edit crypttab
sudoedit /etc/crypttab
add this:
swap /dev/dm-5 /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=512
edit fstab
sudoedit /etc/fstab
add this:
/dev/mapper/swap none swap defaults,x-systemd.device-timeout=0 0 0
update dracut
sudo dracut --force

You will see this in overlay mode:

user 👑 dom0 overlay:~  
$ sudo swapon --show
NAME       TYPE      SIZE USED PRIO
/dev/zram0 partition   8G   0B  100
/dev/dm-6  partition 3,9G   0B   -1
user 👑 dom0 overlay:~  
$ sudo cryptsetup status /dev/dm-6
/dev/dm-6 is active and is in use.
  type:    PLAIN
  cipher:  aes-xts-plain64
  keysize: 512 [bits]
  key location: dm-crypt
  device:  /dev/mapper/qubes_dom0-swap
  sector size:  512 [bytes]
  offset:  2048 [512-byte units] (1048576 [bytes])
  size:    8222720 [512-byte units] (4210032640 [bytes])
  mode:    read/write

We now have not only a full amnesia mode with anti-forensic protection, but also significantly reduced memory consumption. Overlay mode will now be as comfortable as possible even on devices with 12-16 GB of RAM.

Delete this file if you’ve already run my script; otherwise, it will block swap from starting.
sudo rm -rf /home/user/.config/swapoff.sh
Then run my script again

How does one modify the software in a Qube after its been added to varlibspool under instructions of this updated guide? Do we still need bother with rw.service/this link: 🛡 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 - #75 by linuxuser1

Is it possible to have some qubes run in encrypted swap while others run in ram like it used to? This way reduce wear on ssd by only using it for instances where not even 32gb of ram was enough such as a windows Qube while most else runs in ram.

Can I also run the new script over the old script with the ephemeral-dvm qubes and all without it causing problems?

@Path5 Hello. This service is no longer mandatory, but it doesn’t interfere with the operation of live modes. You no longer need to mess with /rw/config/rc.local and insert scripts there. Therefore, you can delete all old ephemeral dvm. Now it’s sufficient to add qubes to the varlibqubes pool.

Do you mean an encrypted dm-container in overlay and want to use overlay with a dm-container + memory?

Running the new script shouldn’t break anything - it only resizes dom0 and adds a new dracut module. I would delete this file sudo rm -rf /home/user/.config/swapoff.sh after running new script (it will allow using zram swap in overlay).

Thank you.
In my opinion, your script should be versioned so we know which release it is and so we can notice if there’s an update.

3 Likes