QubesOS 4.2.4
What:
Using a second hard drive as an encrypted secondary storage to host qubes which can only be accessed when the storage is unlocked.
In my example I create two different encrypted LMV storage areas with each an own password.
Why:
- Making use of a second hard drive to add new storage space.
- Having the ability to lock whole qubes.
- Adding an additional layer of encryption.
For example you use QubesOS as your main OS but you live with family (parents, partner, kids etc.) and want to lock some stuff away just to be safe… Or another example you travel a lot and work in trains, cafes, hotels etc. and even when you are careful maybe someone gets a look at your password or snatches your unlocked laptop. You should anyways protect your data with additional measures but why not keep part of the hard drive with whole qubes encrypted when you don’t need then at this moment?
Note: A compromised dom0 can expose passwords. Therefore keep dom0 secure.
This is a step-by-step guide based on secondary-storage with added encryption.
How to:
Do all these steps in dom0.
Step 1: Double check if you pick the right hard drive with:
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
I use /dev/sdb in this example.
Step 2 (optional): Delete all data on that hard drive:
sudo dd if=/dev/zero of=/dev/sdb bs=1M status=progress
This step takes time. It is not essential and step 3 also overwrites the hard drive but does not erase the old data. However if you want to be diligent you can start with a clean disk.
Step 3: Partition the disk.
In my example I want to have one partition with 60% disk space and one with the other 40%.
Probably not necessary but I make sure the boot flag is off.
sudo parted /dev/sdb -- \
mklabel gpt \
mkpart primary 1MiB 60% \
mkpart primary 60% 100% \
set 1 boot off set 2 boot off \
print
We should now have “/dev/sdb1” and “/dev/sdb2”.
Step 4: Encrypt each partition with LUKS
I call the partitions “storage1” and “storage2”.
For each partition, pick a passphrase when prompted and then unlock each partition:
# Partition 1 → “storage1”
sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup open /dev/sdb1 storage1
# Partition 2 → “storage2”
sudo cryptsetup luksFormat /dev/sdb2
sudo cryptsetup open /dev/sdb2 storage2
Step 5: Create LVM on top of the unlocked devices
Make Pvs:
sudo pvcreate /dev/mapper/storage1
sudo pvcreate /dev/mapper/storage2
Create two separate volume groups (here named “sec1” and “sec2”):
sudo vgcreate vg_sec1 /dev/mapper/storage1
sudo vgcreate vg_sec2 /dev/mapper/storage2
Step 6: Within each VG, carve out a thin-pool (here named “thinpool1” and “thinpool2”)
sudo lvcreate -n thinpool1 --type thin-pool -l 100%FREE vg_sec1
sudo lvcreate -n thinpool2 --type thin-pool -l 100%FREE vg_sec2
note:
I got the warning here: “Pool zeroing and 512.00 KiB large chunk size slows down thin provisioning. Consider disabling zeroing (-Zn) or using small chunk size (<512.00KiB)”
I continued with the default setting anyways. In my understanding zeroing is essential for security when you reuse disk space with different VMs. The old data is wiped (zeroing) by LVM before handing over the disk space to a VM. Otherwise a compromised VM might be able to recover old data from the hard drive. Maybe I am overly paranoid and maybe QubesOS takes additional steps to prevent data leakage from happening but I take the slow down for additional security anytime.
About the chunk size if you wanna run a lot of small VMs that might be worth considering but I left it like that.
Step 7. Tell QubesOS about your new pools
I call the pools “secondary1” and “secondary2”
sudo qvm-pool --add secondary1 lvm_thin \
-o volume_group=vg_sec1,thin_pool=thinpool1,revisions_to_keep=2
sudo qvm-pool --add secondary2 lvm_thin \
-o volume_group=vg_sec2,thin_pool=thinpool2,revisions_to_keep=2
You can list pools with qvm-pool –list
The pools are now available when you create a new qube or want to move a qube to a new storage area.
Unlocking storage:
In this example storage 1
sudo cryptsetup open /dev/sdb1 storage1
Locking storage 1:
Close all running qubes on this storage. Either manual or with:
qvm-shutdown --all --pool secondary1
It seems like even without running qube the mapping still prevents the storage from locking.
Deactivate the LVM layer backing the mapping:
sudo lvchange -an vg_sec1
You can also close the VG itself but it seems not necessary.
sudo vgchange -an vg_sec1
Then you can finally lock your storage with:
sudo cryptsetup close storage1
You can use a script if you want:
qvm-shutdown --all --pool secondary1
sudo lvchange -an vg_sec1
sudo vgchange -an vg_sec1
sudo cryptsetup close storage1
I’m not an expert with QubesOS but I still want to share this because maybe someone finds it helpful. And if someone find some weaknesses or improvements I am happy for some feedback!