How to Encrypt KVM qcow2 Disks with LUKS and Ceph RBD – Step‑by‑Step Guide
This guide explains how to use LUKS to encrypt KVM qcow2 virtual machine disks, create and define libvirt secrets, configure encrypted volumes, and apply the same technique to Ceph RBD storage, providing full command‑line examples and XML snippets for a secure virtualization setup.
kvm qcow2 disk encryption
About LUKS encryption
LUKS implements a platform‑independent standard disk format for encrypting block devices, supporting multiple key slots (up to 8 in LUKS1 or 32 in LUKS2) and allowing easy password changes without re‑encrypting the whole disk.
LUKS encryption for KVM virtual machine disks
Before libvirt 4.5, qcow encryption was also supported, but it has been deprecated. The following steps show how to use LUKS to encrypt an existing VM disk.
<code>qemu-img convert -O qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 -f qcow2 test.qcow2 fw-encry.qcow2</code>Encryption format "default" and "qcow" are no longer used for creating encrypted volumes. The example below demonstrates converting a qcow2 disk to a LUKS‑encrypted disk.
Create a 20G empty LUKS disk.
<code>qemu-img create -f luks --object secret,data=123,id=sec0 -o key-secret=sec0 fw.luks 20G</code>Convert the existing qcow2 disk to a LUKS disk (the target must exist).
<code>qemu-img convert --target-image-opts \
--object secret,data=123,id=sec0 -f qcow2 fw.qcow2 -n \
driver=luks,file.filename=fw.luks,key-secret=sec0</code>Create a secret XML file (UUID will be generated automatically if omitted).
<code>vim volume-secret.xml
<secret ephemeral='no' private='yes'>
<uuid>92f35b9e-c845-47e1-b5a6-f2036a706866</uuid>
<description>Super secret name of my first puppy</description>
<usage type='volume'>
<volume>/home/kvm/images/fw.luks</volume>
</usage>
</secret>
</code>Define the secret.
<code>virsh secret-define volume-secret.xml</code>Set the secret password value.
<code># MYSECRET=`printf %s "123" | base64`
# virsh secret-set-value dc057b2b-6a7d-4dba-b76e-37a458448765 $MYSECRET
Secret value set
</code>Edit the VM's
<disk>section to add the secret field.
<code><disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/kvm/images/fw.luks'/>
<target dev='vda' bus='virtio'/>
<encryption format='luks'>
<secret type='passphrase' uuid='dc057b2b-6a7d-4dba-b76e-37a458448765'/>
</encryption>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</disk>
</code>When creating a LUKS volume, you can specify the cipher and IV generation algorithm. By default, QEMU uses
aes-256-cbcwith
essivIV generation and
sha256hashing.
<code><volume>
<name>twofish.luks</name>
<capacity unit='G'>5</capacity>
<target>
<path>/var/lib/libvirt/images/demo.luks</path>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/>
<cipher name='twofish' size='256' mode='cbc' hash='sha256'/>
<ivgen name='plain64' hash='sha256'/>
</encryption>
</target>
</volume>
</code>Start the virtual machine:
<code>virsh start vm</code>To copy the encrypted disk to another host, repeat the secret creation steps on the new host.
Note: The password must match the one defined on the host.
If the
<encryption>field is removed from the boot disk, the VM will fail to find the boot device.
<code><encryption format='luks'>
<secret type='passphrase' uuid='dc057b2b-6a7d-4dba-b76e-37a458448765'/>
</encryption>
</code>Encrypted data disks cannot be mounted directly; they must be mapped via
cryptsetup:
<code>cryptsetup luksOpen /dev/vdb fw</code>kvm using ceph rbd disk encryption
Define secret
Generate secret (run on all Ceph nodes).
Create
secret.xml:
<code>cd /etc/libvirt/qemu
cat > secret.xml <<EOF
<secret ephemeral='no' private='no'>
<usage type='ceph'>
<name>client.libvirt secret</name>
</usage>
</secret>
EOF
</code>Define the secret and note its UUID.
<code>virsh secret-define --file secret.xml
# Example output: Secret 01a0ba00-f277-48bb-b937-9001ec91f53e created
</code>Obtain the
client.libvirtkey and save it.
<code>ceph auth get-key client.libvirt | tee client.libvirt.key</code>Set the secret password.
<code>virsh secret-set-value --secret 01a0ba00-f277-48bb-b937-9001ec91f53e --base64 $(cat client.libvirt.key)
</code>Edit the VM configuration to use the secret for the RBD disk.
<code><devices>
<emulator>/usr/bin/kvm-spice</emulator>
<disk type='network' device='disk'>
<driver name='qemu' type='raw'/>
<auth username='libvirt'>
<secret type='ceph' uuid='01a0ba00-f277-48bb-b937-9001ec91f53e'/>
</auth>
<source protocol='rbd' name='libvirt-pool/fw-system'>
<host name='node1' port='6789'/>
<host name='node2' port='6789'/>
<host name='node3' port='6789'/>
</source>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</disk>
</devices>
</code>Start VM
Define and start the virtual machine:
<code>virsh define vm.xml
virsh start vm</code>Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.