Fully Ephemeral DispVM's

Currently Qubes DispVM’s are not fully ephemeral; by default data written to xvda and xvdb is written to the disk in plaintext. When the user sets ephemeral=True data written to xvdc is encrypted with an ephemeral encryption key placed in RAM. If in addition the user sets rw:root rw 0 then writes to xvda are routed to xvdc and thus encrypted. However xvdb is at present always written to the disk in plaintext.

I recently wrote a patch for initramfs that resolves this issue; after application of the patch all data written by a PVH DispVM (including to swap) is encrypted by an ephemeral key. The code and a guide is available at

Hopefully this will find its way to R4.2. The patch has been tested only on the most recent stable R4.1.


this is EPIC!!!

WOW. I saw the title and definitely not expecting this. Up until now Qubes “disposable” has been like browser “private mode”. Adding ephemeral encryption takes this to the next level. This has to be one of the most consequential improvements in the security posture of QubesOS in a long time.

I am going to do a full backup and test this out over the weekend and report back.


@ewokky: if you just want to convince yourself that it works you don’t need a full backup. Instead create a copy of a kernel in /var/lib/qubes/vm-kernels, e.g

cp -rf /var/lib/qubes/vm-kernels/5.10.90-1.fc32 /var/lib/qubes/vm-kernels/testkernel

Then patch testkernel with

sudo sh patch_initramfs.sh testkernel

Now you create an AppVM, say testvm,

qvm-create testvm --template sometemplate --class AppVM --label red

Make the testkernel the kernel for testvm with

qvm-prefs testvm kernel testkernel

Now make xvda, xvdb read-only on the AppVM and set ephemeral mode on for xvdc, i.e

qvm-volume config testapp:root rw 0
qvm-volume config testapp:private rw 0
qvm-volume config testapp:volatile ephemeral 1

Now AppVM is made fully ephemeral. In addition all the DispVM’s that will be subsequently created based on this AppVM will also inherit the ephemeral property. To test this issue

qvm-run --dispvm testapp xterm

and check that this DispVM is fully ephemeral (well it has to because xvda, xvdb are readonly, you can only write to xvdc and xvdc is being encrypted by ephemeral=True). If you don’t want the AppVM to be fully ephemeral simply make xvdb writeable again with qvm-volume config testapp:private rw 1.

The same mechanism works for DispVM’s: if you make a named DispVM use the kernel testkernel and you make its xvda, xvdb read-only and make xvdc ephemeral using qvm-prefs then this DispVM will be made fully ephemeral. This will not work on sys-usb and sys-net since they are HVM and not PVH. If you are concerned about sys-net and sys-usb I suggest running them fully in RAM. I have a solution in mind that I’m working on.

Note however that what I outlined above is a tricky way of using this patch, it’s easy to get things wrong. For example the changes made this way might not be persistent across reboots. Furthermore DispVM that were created before the AppVM was made ephemeral are not made ephemeral – one would have to clone them, delete them and then reclone them back. Patching dispvm.py removes all of this unnecessary confusion, every single PVH DispVM is then made fully ephemeral.

If you are really interested I have a python script that allows one to make only select AppVM’s fully ephemeral in a way that is persistent across reboots (it edits qubes.xml which is arguably even more dangerous than editing dispvm.py :)). If there is interest in that I can upload it too. I just find it a harder way of using the patch … less consistent, and more easy to get wrong, and also less in the spirit of what we actually want: all DispVM’s fully ephemeral. By the way even though all my DispVM’s are now fully encrypted I haven’t noticed an impact on performance.


Wow, great work. Looks very promising and hopefully will be the new default.

Have you ran into any issue after implementing the patch?


As a noob QubesOS user, can you explain a bit more this stuff about “getting written to xvda, xvdb, xvdc”? Also can you shortly explain what is a “PVH” ?


it also makes sense to put logs to some securely disposable place as well?

@BEBF738VD : The only issue that I observed so far is about HVM’s (that are also DispVM’s). After implementing the patch newly created HVM’s might start but will refuse to run any applications from qvm-run. However this is easily fixable just by issuing

qvm-volume config hvmvm:private rw 1

The point is that HVM’s cannot be at present fully ephemerized and this command disables the patch from running in initramfs. I mentioned this in the last note on the github page.

It would be good if somebody could check whether this command needs to be issued on sys-net and sys-usb after patching. They might be not affected because they might be still reading their configuration from qubes.xml. In the next iteration of the patch I’ll try to fix the issue with the HVM’s.

1 Like

My understanding is that @marmarek is intending to utilize a very similar methodology for ephemeral disposable VMs (hence the scaffolding OPs approach uses) but there are some edge cases and UI management items he still has to mull over (as well as the time factor) before moving forward.


Just to have links here to related issues, for completeness: