Information Security 11 min read

How to Encrypt KVM Virtual Machine Disks with LUKS and Ceph RBD

Learn step‑by‑step how to secure KVM virtual machine disks using LUKS encryption, convert qcow2 images, define libvirt secrets, and apply encryption to both local and Ceph RBD storage, including necessary XML configurations, command‑line tools, and best‑practice considerations.

Ops Development Stories
Ops Development Stories
Ops Development Stories
How to Encrypt KVM Virtual Machine Disks with LUKS and Ceph RBD

KVM qcow2 Disk Encryption

About LUKS Encryption

LUKS implements a platform‑independent standard disk format for various tools. It encrypts block devices, allowing any filesystem—including swap partitions—to be encrypted. An unencrypted header stores up to 8 (LUKS1) or 32 (LUKS2) key slots, password types, and key sizes. The header distinguishes LUKS from plain dm‑crypt because it enables multiple passphrases and easy key changes. If the header is lost or damaged, the device becomes undecryptable. LUKS provides a standard disk‑encryption format that works across Linux distributions, supports multi‑user/passphrase, and allows password changes without re‑encrypting the whole disk.

Implementing LUKS Encryption for KVM Virtual Machine Disks

Before libvirt 4.5, qcow encryption was also supported. However, qcow encryption has been deprecated since QEMU 2.3.

<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>

The default encryption format and qcow are no longer used for creating encrypted volumes. Below is the main method using LUKS to encrypt an existing VM disk. If you create a new VM with an encrypted disk, the conversion step is unnecessary.

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 target 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's 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

&lt;disk&gt;

element to reference the secret.

<code>&lt;disk type='file' device='disk'&gt;
  &lt;driver name='qemu' type='raw'/&gt;
  &lt;source file='/home/kvm/images/fw.luks'/&gt;
  &lt;target dev='vda' bus='virtio'/&gt;
  &lt;encryption format='luks'&gt;
    &lt;secret type='passphrase' uuid='dc057b2b-6a7d-4dba-b76e-37a458448765'/&gt;
  &lt;/encryption&gt;
  &lt;address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/&gt;
&lt;/disk&gt;</code>

For volume creation, you can specify the cipher and IV generator for the LUKS volume. The default algorithm used by

qemu-img

is

aes-256-cbc

with

essiv

IV generation and

sha256

hashing.

<code>&lt;volume&gt;
  &lt;name&gt;twofish.luks&lt;/name&gt;
  &lt;capacity unit='G'&gt;5&lt;/capacity&gt;
  &lt;target&gt;
    &lt;path&gt;/var/lib/libvirt/images/demo.luks&lt;/path&gt;
    &lt;format type='raw'/&gt;
    &lt;encryption format='luks'&gt;
      &lt;secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/&gt;
      &lt;cipher name='twofish' size='256' mode='cbc' hash='sha256'/&gt;
      &lt;ivgen name='plain64' hash='sha256'/&gt;
    &lt;/encryption&gt;
  &lt;/target&gt;
&lt;/volume&gt;</code>

Start the VM after the configuration:

<code>virsh start vm</code>

If you copy the encrypted disk to another host, repeat the secret‑definition steps on the new host.

Note: The password set for the secret must match the one defined on the host.

KVM Using Ceph RBD Disk Encryption

Define Secret

Generate a secret on each Ceph node.

<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 Ceph client key and save it.

<code>ceph auth get-key client.libvirt | tee client.libvirt.key</code>

Set the secret's password using the base64‑encoded key.

<code>virsh secret-set-value --secret 01a0ba00-f277-48bb-b937-9001ec91f53e --base64 $(cat client.libvirt.key)
Secret value set</code>

Edit the VM XML to use the Ceph RBD disk with the secret.

<code>&lt;devices&gt;
  &lt;disk type='network' device='disk'&gt;
    &lt;driver name='qemu' type='raw'/&gt;
    &lt;auth username='libvirt'&gt;
      &lt;secret type='ceph' uuid='01a0ba00-f277-48bb-b937-9001ec91f53e'/&gt;
    &lt;/auth&gt;
    &lt;source protocol='rbd' name='libvirt-pool/fw-system'&gt;
      &lt;host name='node1' port='6789'/&gt;
      &lt;host name='node2' port='6789'/&gt;
      &lt;host name='node3' port='6789'/&gt;
    &lt;/source&gt;
    &lt;target dev='vdb' bus='virtio'/&gt;
    &lt;address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/&gt;
  &lt;/disk&gt;
&lt;/devices&gt;</code>

Define and start the VM.

<code>virsh define vm.xml
virsh start vm</code>

After encryption, the disk cannot be mounted directly; it must be mapped via

cryptsetup luksOpen

before use.

<code>cryptsetup luksOpen /dev/vdb fw</code>
CephKVMdisk encryptionlibvirtRBDLUKS
Ops Development Stories
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.