How to deploy a new Cloud Image virtual machine VM image to a KVM server using libvirt

New KVM Setup Guide

This is a guide on how to set up a new KVM image on a Ubuntu KVM installation.

The other way which might be much simpler would be to mount an ISO, but if you want to do it programmatically follow this article.

The steps required are:

  1. Generate cidata.iso file composed of `user-data` and `meta-data`
  2. Download the appropriate Cloud Image
  3. Convert the Cloud Image to a raw file
  4. Generate an new .img file that will be become your actual VM
  5. Install the VM

In the examples below, we assume you want to set up a new host called

It’s best to perform this work in a good working directory, e.g.:

cd /var/lib/libvirt/images

Just be super careful because this is where all your VM disks are stored and you don’t want anything to go wrong.

Generate cidata.iso file

We’ve listed this first because it’s the most complicated and getting anything wrong means you’ll have a non-working VM, e.g., difficulty logging in a root.

Ubuntu compatible user-data:


hostname: host1
manage_etc_hosts: true
  - name: ubuntu
    groups: users, admin
    home: /home/ubuntu
    shell: /bin/bash
    lock_passwd: false
      - <sshPUBKEY>
# only cert auth via ssh (console access can still login)
ssh_pwauth: false
disable_root: false
  list: |
  expire: False
package_update: true
  - qemu-guest-agent
- path: /etc/cloud/cloud.cfg.d/99-custom-networking.cfg
  permissions: '0644'
  content: |
      network: {config: disabled}
- path: /etc/netplan/my-new-config.yaml
  permissions: '0644'
  content: |
      version: 2
            - A.B.C.D/24
            search: []
            addresses: [,]
            - to: default
              via: E.F.G.H
  - rm /etc/netplan/50-cloud-init.yaml
  - netplan generate
  - netplan apply
# written to /var/log/cloud-init-output.log
final_message: "The system is finally up, after $UPTIME seconds"

Note: As of 05 June 2023 we haven’t been able to get a AlmaLinux 9 user-data file working (root password issue and keys don’t work). The format is a lot different than Ubuntu since Ubuntu doesn’t typically use the root user. Watch this space.



Generate funny cidata.iso file:

genisoimage -output cidata.iso -V cidata -r -J user-data meta-data

Download the Cloud Image

Make sure you’re in a good working directory as mentioned above. You’ll need to clean up after yourself afterwards.

Ubuntu Focal


AlmaLinux 9

Notice Ubuntu supplies .img files and AlmalLinux supplies .qcow2 files. This will be important later.

Convert the Cloud Image to a .raw file

qemu-img convert -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw

Generate an new .img file

This will be become your actual VM.

qemu-img create -b focal-server-cloudimg-amd64.img -f qcow2 -F qcow2 hal9000.img 10G

Install the VM

virt-install --name=hal9000 --ram=2048 --vcpus=1 --import --disk path=hal9000.img,format=qcow2 --disk path=cidata.iso,device=cdrom --os-variant=generic --network bridge=virbr0,model=virtio --graphics vnc,listen= --noautoconsole

Missing packages?

  • yum install genisoimage
  • yum install virt-install


Caveats with regards to download Cloud Images from different vendors (e.g. Debian track versus Redhat track)

  • A caveat is that Cloud Images are sometimes in QCOW2 format, and other times at IMG format.
    • AlmaLinux Supplies QCOW2 format
    • Ubuntu supplies IMG format
  • This is important because later in this process you’ll need to create a conversion, and if you haven’t selected the correct format the steps will break down. This error is easy to see because it will warn you.
  • Alternative downloads locations for download of Cloud Images:
    • It’s very easy to search for Cloud Image for any vendor.

Share this article

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top