Create qemu disk image encrypted with LUKS

Hello.

I've been trying to create a virtual disk image that I can encrypt with LUKS and then, be able to install any Linux distro in it!.
I've been reading through qemu-img man pages and they say that encryption with qemu is discouraged because there are several flaws with the encryption system.

Then, in Welcome to QEMU’s documentation! — QEMU 7.2.50 documentation site, I see something quite different. They actually have quite a few encryption options and say nothing about flawed encryption system.
Disk Images — QEMU 7.2.50 documentation
Providing secret data to QEMU — QEMU 7.2.50 documentation

So, I want to try to use LUKS and qemu to create a LUKS encrypted virtual disk where I can later use qemu to start this virt disk and install any Linux distro in it.

So, where do I start? Create a virtuala disk/container with LUKS, already encrypted and then, try to use qemu to put an OS in it? Or the other way around where I create the disk image with qemu tan then, somehow, I encrypt it wit LUKS?

Well, just to say, i never encrypted anything but using luks LVM.
Firstly, if you wish to use qcow2 encryption with luks, check your qemu version.

But basically you have 3 choices

  1. Using qcow2 image and encryption mechanism it offers in newer versions - create using qemu-img and encryption options (check version first and experiment - i have no advice here unless i try :wink: ).
  2. Create a LUKS encrypted logical volume or any block device, which will serve qcow2 images after mount and passphrase input.
  3. Encrypt the VM during install entirely using builtin installer option LUKS + VG (ubuntu, rhel derivatives).

Options 3 and 2 seem most sane, but choice is yours.

Hope that helps
Regards
Peasant.

Well, I also use option 3 as my regular VM to test things around. Whenever I want to test a Debian distro or to install some application, learn it and configure it, play with it, etc, I also use LVM and LUKS.

But in this case, I want a VM, somehow encrypted with LUKS.
So, option 3 is not what I want. I want to have a disk image (qcow2, for example), encrypt it with LUKS and then, install some Debian distro in it!

So, I think only option 1 and 2 will fit here.
The thing I have no idea how it works is for instance:
Case 1 - if I create a LUKS encrypted volume, I get a file. This file is supposed to be mapped and mounted. Commands like luksFormat, luksOpen, mount, luksClose and umount are used. So, I'm not sure how qemu enters the game here. Because if I use qemu with the file created by LUKS, does qemu knows this is an encryted disk, so that it know it is supposed to ask for a password to decrypt the disk?

Case 2 - If I create a qcow2 disk image, how do I encrypt it with LUKS? Do I also have to use the same commands I mentioned above to be able to encrypt it? Do I need to map and mount it? If I do so, qemu no longer makes sense because after I mount the disk image, I no longer need qemu. I guess. So, I'm a bit lost here!

You create a encrypted device using cryptsetup against logical volume or disk partition.
Open it via same command and create filesystem of your choice.
You can now use it as regular logical volume or filesystem via mount and create qcow2 files in it.

Each time you want to access the data you must mount it via passphrase (boot or CLI after), or automate using crypttab, automount and fstab.

For second option, well, by reading docs, this is the way

Create a RAW image

qemu-img create --object secret,id=sec0,data=secret-passphrase -o key-secret=sec0 -f luks /srv/dump/vmz/sonion/test.vol 5G

Generate an UUID with uuidgen

Define virsh secret with secret.xml with content

<secret ephemeral='no' private='no'>
      <uuid>a19f2b7b-070a-4f8f-b9cc-80a2345d44c1</uuid>
      <usage type='volume'>
              <volume>/srv/dump/vmz/sonion/test.vol</volume>
      </usage>
      <description>kvmsecretluks</description>
</secret>

Create it from XML

virsh secret-define secret.xml

Input the previously defined passphrase into secret

virsh secret-set-value a19f2b7b-070a-4f8f-b9cc-80a2345d44c1 "$(printf "%s" secret-passphrase | base64)"

Edit the VM XML and add the encyption block for existing volume

...
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/srv/dump/vmz/sonion/test.vol'/>
      <target dev='vda' bus='virtio'/>
      <encryption format='luks'>
        <secret type='passphrase' uuid='a19f2b7b-070a-4f8f-b9cc-80a2345d44c1'/>
      </encryption>
...

Start and install the OS on encrypted qemu RAW image.
If you remove encryption format block and/or you do not have secret defined, qemu/libvirt/KVM will see this as non bootable disk.

Hope that clears things out
Regards
Peasant.

Could you please share the docs you read?

Edited;
I tested your set of commands but I got at least 2 problems.
The command virsh secret-set-value 1234ab56-7zzz-2ac2-z9e0-42e286y6xg37 "$(printf "%s" secret-passphrase | base64)"

returned this:

$:~/
error: Passing secret value as command-line argument is insecure!
Secret value set

$:~/

So, I presume, something went wrong!

The command is notifying you that using set-secret-value in such fashion is insecure, which it is.

Since it will remain in shell history or possibly other places e.g if logs/audits are shipped on 3rd party system and/or likes.

See here for interactive usage to avoid it.

This is where i got most of the info.

Hope that helps
Regards
Peasant.