Configuring Cloud-Init for Rocky Linux QCOW2 Images
Introduction
CIQ provides QCOW2 cloud images for Rocky Linux, including RLC Pro, LTS, and other variants. These images use cloud-init for first-boot provisioning, which means you need to supply configuration data (user credentials, SSH keys, network settings) before the instance is usable.
This article covers how to build a cloud-init data source and boot a Rocky Linux QCOW2 image using libvirt/KVM, and includes pointers for other virtualization platforms.
Problem
After importing a Rocky Linux QCOW2 cloud image and booting a virtual machine from it, you can't log in. The image has no default password set and relies entirely on cloud-init to configure user accounts, SSH keys, and networking on first boot. Without a properly configured cloud-init data source, the instance boots but is inaccessible.
Resolution
Cloud-init reads configuration from a data source attached to the VM. The most common method for on-premises virtualization is a NoCloud ISO containing your user-data and meta-data files, attached as a virtual CD-ROM. You can also include a network-config file in the ISO for static IP assignment or other network settings (see the NoCloud data source documentation for the full format). The VM reads this ISO on first boot, applies the configuration, and marks itself as initialized. Some hypervisors (such as Proxmox and Xen Orchestra) handle this automatically through their own cloud-init integration, so you don't always need to build the ISO yourself.
Rocky Linux 9 ships cloud-init 24.4 and Rocky Linux 8 ships cloud-init 23.4. See the cloud-init documentation for the full list of supported modules and data sources.
The sections below walk through building a NoCloud data source manually with libvirt/KVM, followed by pointers for other platforms.
Create the cloud-init configuration
Create a user-data file with your desired first-boot settings. At minimum, you need a user account with either a password or SSH key:
#cloud-config
hostname: rocky
users:
- name: rocky
lock_passwd: false
plain_text_passwd: changeme
ssh_authorized_keys:
- ssh-rsa AAAA...your-key-here
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_pwauth: true
Setting ssh_pwauth: true allows password-based SSH login, which is useful as a fallback if SSH key delivery fails. You can also include additional directives such as package installation, timezone configuration, or custom commands:
#cloud-config
hostname: rocky
users:
- name: rocky
lock_passwd: false
ssh_authorized_keys:
- ssh-rsa AAAA...your-key-here
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_pwauth: true
timezone: America/New_York
packages:
- vim
- tmux
runcmd:
- systemctl enable --now cockpit.socket
Create a minimal meta-data file. This identifies the instance to cloud-init:
instance-id: rocky-vm-01
local-hostname: rocky
Build the NoCloud ISO
Use mkisofs (provided by the xorriso package in AppStream) to generate the NoCloud ISO. The volume label must be set to cidata so cloud-init recognizes it as a NoCloud data source:
dnf install xorriso
mkisofs -output seed.iso -volid cidata -joliet -rock user-data meta-data
This produces a seed.iso file that contains your cloud-init configuration in the NoCloud format.
Boot the image with virt-install
Create a working copy of the QCOW2 image and optionally resize it, then launch the VM with the cloud image and seed ISO attached:
cp Rocky-9-GenericCloud.latest.x86_64.qcow2 rocky-vm.qcow2
qemu-img resize rocky-vm.qcow2 20G
virt-install \
--name rocky-cloud \
--memory 2048 \
--vcpus 2 \
--import \
--disk rocky-vm.qcow2 \
--disk seed.iso,device=cdrom \
--os-variant rocky9 \
--network bridge=br0
Cloud-init runs during the first boot, applies your user-data configuration, and writes a marker to /var/lib/cloud/instance/boot-finished. On subsequent boots, cloud-init recognizes the marker and skips re-initialization.
Alternative: virt-install --cloud-init
On Rocky Linux 9 and later, virt-install has a --cloud-init flag that generates a temporary NoCloud ISO automatically and removes it after the first boot:
virt-install \
--name rocky-cloud \
--memory 2048 \
--vcpus 2 \
--import \
--disk rocky-vm.qcow2 \
--cloud-init root-password-generate=on,ssh-key=/home/user/.ssh/id_rsa.pub \
--os-variant rocky9 \
--network bridge=br0
The generated root password is printed to the console during creation. This flag is not available on Rocky Linux 8, where the manual mkisofs method is required.
Other virtualization platforms
The same cloud-init principles apply on other hypervisors and cloud platforms. Each has its own mechanism for delivering cloud-init data to the guest. Note that vSphere does not natively support QCOW2, so you need to convert the image to VMDK format with qemu-img convert before importing.
- Proxmox VE cloud-init support
- XCP-ng / Xen Orchestra cloud features
- OpenStack instance user data
- VMware vSphere cloud-init data source
Notes
If you need to re-apply cloud-init configuration after the initial boot, clear the cloud-init state and reboot:
cloud-init clean
reboot
CIQ support covers the Rocky Linux operating system and the cloud-init package as shipped in the distribution. Hypervisor-specific configuration is outside the scope of CIQ support, but CIQ can assist with cloud-init behavior on the guest side.