How To Customize VM Images using virt-customize

virt-customize is a powerful command-line tool used to customize virtual machine (disk image) by editing configuration files, installing packages, configuring services, upload files, add users, and so on. All these customizations can be done without booting the virtual machine. Virt-customize works with both raw and qcow2 image formats.

To avoid potential disk corruption, it is not recommedned to use virt-customize on live virtual machines, or concurrently with other disk editing tools. Make sure the virtual machine is offline before you use this command, and disk images must not be edited concurrently.

Note that virt-customize modifies the guest or disk image in place without making a copy of it. If you want to preserve the existing contents of the guest virtual machine, you must snapshot, copy or clone the disk first. For more information on copying and cloning disks, see libguestfs.org.

🔥 TRENDING - Our #1 Selling eBook

Mastering KVM Virtualization - The Ultimate eBook

From home labs to production clouds - master KVM Host management, automating KVM administration using Terraform, Vagrant, and cloud automation. This eBook will enable you to build scalable virtual infrastructure that works whether you're learning at home or deploying enterprise solutions. Get your full copy today

Only $10 $20
Get Instant Access →

Installing virt-customize on Linux systems

The virt-customize utility is provided by libguestfs  suite available for installation on major Linux distributions. To install the package which provide the tool, run the following commands.

  • Debian-based systems
sudo apt update && sudo apt install libguestfs-tools
  • RHEL-based systems
sudo dnf -y install libguestfs-tools guestfs-tools
  • Arch Linux based systems
sudo pacman -Syy
sudo pacman -S --noconfirm --needed libguestfs guestfs-tools
  • SUSE / openSUSE
sudo zypper refresh
sudo zypper -n install guestfs-tools virt-top libguestfs

Confirm installation was successful by querying the version:

virt-customize --version

Usage page can be viewed by running:

virt-customize --help

To modify images directly, set

export LIBGUESTFS_BACKEND=direct

Usage examples of virt-customize

In this section, we will explore practical examples of using virt-customize to create custom VM images tailored to your specific needs. This versatile utility enables you to modify images efficiently, making them ready for diverse scenarios. We’ll cover a range of use cases to ensure that users with different requirements can benefit from these tutorials.

Before we proceed let’s download sample Linux cloud images.

For our examples, let’s download Ubuntu 24.04 image and Rocky Linux 9 KVM Qcow2 guest images.

  • Ubuntu 24.04
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
mv noble-server-cloudimg-amd64.img ubuntu-24.04-amd64.img
  • Rocky Linux 9
wget https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2
mv Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 Rocky-9.x86_64.qcow2

We can save the image to be used in IMAGE variable for ease of reference later.

IMAGE=ubuntu-24.04-amd64.img

For Rocky Linux one we can use:

IMAGE=Rocky-9.x86_64.qcow2
Example 1: Grow / filesystem in guest image

Get default filesystem disk size using qemu-img:

qemu-img info $IMAGE

In the output we can confirm the default is 3.5GiB

file format: qcow2
virtual size: 3.5 GiB (3758096384 bytes)
disk size: 581 MiB
cluster_size: 65536
...

Suppose we want to increase image disk size by 20GB, the command to run is:

qemu-img resize $IMAGE +20G
  • +20G: Increases the size of the image by 20GB

Confirmation after the change:

$ qemu-img info $IMAGE
image: ubuntu-24.04-amd64.img
file format: qcow2
virtual size: 23.5 GiB (25232932864 bytes)
...

Use virt-customize and fdisk to delete and recreate the partition using all available space.

virt-customize -a $IMAGE --run-command 'echo -e "d\nn\n\n\n\n\nw\n" | fdisk /dev/sda'

Check partition after resizing and recreating partition.

virt-filesystems --long -h --all -a $IMAGE

Check total size of the /dev/sda disk in the image.

Name       Type       VFS     Label           MBR Size Parent
/dev/sda1  filesystem ext4    cloudimg-rootfs -   2.4G -
/dev/sda2  filesystem unknown -               -   20G  -
/dev/sda14 filesystem unknown -               -   4.0M -
/dev/sda15 filesystem vfat    UEFI            -   104M -
/dev/sda16 filesystem ext4    BOOT            -   880M -
/dev/sda1  partition  -       -               -   2.5G /dev/sda
/dev/sda2  partition  -       -               -   20G  /dev/sda
/dev/sda14 partition  -       -               -   4.0M /dev/sda
/dev/sda15 partition  -       -               -   106M /dev/sda
/dev/sda16 partition  -       -               -   913M /dev/sda
/dev/sda   device     -       -               -   24G  -
Example 2: Run a Shell Command

You can run command in disk image using --run-command

  • Update packages list index in Debian-based system
virt-customize -a $IMAGE --run-command 'apt update'
  • Update RHEL based system
virt-customize -a $IMAGE --run-command 'yum -y update'
Example 3: Update and install software packages

To update all packages use --update. This is the equivalent of yum update, apt-get upgrade:

virt-customize -a $IMAGE --update

Use --installto add package(s) to install separated by command:

virt-customize -a $IMAGE --install vim,bash-completion,wget

On Debian / Ubuntu run apt update before installations:

virt-customize -a $IMAGE --run-command 'apt update'
virt-customize -a $IMAGE --install vim,bash-completion,wget
Example 4: Set root user password

This command will set the root user password StrongRootPass

virt-customize -a $IMAGE --root-password password:StrongRootPass
Example 5: Upload local file to the image

To upload a local file to destination use command option --upload. In this example, the file hello.txt will be uploaded from a local machine to the image path /root/hello.txt

echo "Hello World">hello.txt
virt-customize -a $IMAGE --upload hello.txt:/root

Another example to copy custom yum.conf file.

virt-customize -a $IMAGE --upload yum.conf:/etc/yum.conf
Example 6: Set default system timezone

To set default timezone for the guest OS use --timezone <TIMEZONE>

virt-customize -a $IMAGE --timezone America/New_York
Example 7: Enable ssh password authentication (not recommended)

You can use --run-command to modify SSH configuration file and allow password authentication for SSH connections.

virt-customize -a $IMAGE --run-command 'sed -i "s/.*PasswordAuthentication.*/PasswordAuthentication yes/g" /etc/ssh/sshd_config'

Here is another example to allow root login only with ssh key.

virt-customize -a $IMAGE --run-command 'sed -i "s/.*PermitRootLogin.*/PermitRootLogin without-password/g" /etc/ssh/sshd_config'
Example 8: Inject ssh public key

The --ssh-inject command option is used inject a public key into the guest. The following example will upload the key to root user.

virt-customize -a $IMAGE --ssh-inject root:file:./id_rsa.pub

If you don’t ssh key you can generate with the command ssh-keygen -t rsa -b 4096

ssh-keygen -t rsa -b 4096
cp ~/.ssh/id_rsa.pub id_rsa.pub
virt-customize -a $IMAGE --ssh-inject root:file:./id_rsa.pub

The root username be substituted with any other user account name.

After uploading SSH key you can decide to only accept ssh keys for authentication and disallow password authentication

virt-customize -a $IMAGE --append-line /etc/ssh/sshd_config:"AuthenticationMethods publickey"
Example 9: Add standard user account

We will add a user with the following details:

  • Username: cloudspinx
  • Member of wheel / sudo group
  • Using encrypted / hashed password – StrongUserPassw0rd

Start by generating encrypted password:

python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'

Create a user account with the password generate with the python commands above.

  • Debian based systems – sudo group
virt-customize -a $IMAGE --run-command 'useradd -p $6$Ui.kb./S6sYllMxs$RY7HknSon4chvGexIj1zkXYs6FR4f.CmmTYLWhFxqdjUMoAPH2T..dPvKDjyexjvcu6CyNZ7VN2gHTHP9WwA1. cloudspinx && usermod -aG sudo cloudspinx'
  • RHEL-based systems (wheel group)
virt-customize -a $IMAGE --run-command 'useradd -p $6$Ui.kb./S6sYllMxs$RY7HknSon4chvGexIj1zkXYs6FR4f.CmmTYLWhFxqdjUMoAPH2T..dPvKDjyexjvcu6CyNZ7VN2gHTHP9WwA1. cloudspinx && usermod -aG wheel cloudspinx'
Example 10: Using customize cloud.conf file

It is possible to replaced the contents of default cloud-init configuration file with a custom one.

Create a file called cloud.cfg and modify contents to work for your particular use needs.

disable_root: true
preserve_hostname: false
users:
- name: <username>
  shell: /bin/bash
  groups: [adm, systemd-journal]
  sudo: ["ALL=(ALL) NOPASSWD:ALL"]
  lock_passwd: true
  ssh_authorized_keys:
    - '<your-ssh-pub-key>'

Upload the file into /etc/cloud/cloud.cfg

virt-customize -a $IMAGE --upload cloud.cfg:/etc/cloud/cloud.cfg
Example 11: Set SELinux mode (Only RHEL based systems)

Put SELinux in enforcing mode.

virt-customize -a $IMAGE --edit /etc/selinux/config:'s/^SELINUX=.*/SELINUX=enforcing/g'

Permissive mode:

virt-customize -a $IMAGE --edit /etc/selinux/config:'s/^SELINUX=.*/SELINUX=permissive/g'

Disabled mode:

virt-customize -a $IMAGE --edit /etc/selinux/config:'s/^SELINUX=.*/SELINUX=disabled/g'
Example 12: Set strong password policy for user accounts

Install libpam-pwqualityon Debian / Ubuntu:

virt-customize -a $IMAGE --install libpam-pwquality

Therafter, use virt-customize to enforce strong password policy

RHEL based systems:

virt-customize -a $IMAGE \
  --append-line /etc/security/pwquality.conf:"enforce_for_root" \
  --append-line /etc/security/pwquality.conf:"minlen = 9" \
  --append-line /etc/security/pwquality.conf:"dcredit = -1" \
  --append-line /etc/security/pwquality.conf:"ucredit = -1" \
  --append-line /etc/security/pwquality.conf:"lcredit = 1" \
  --append-line /etc/security/pwquality.conf:"ocredit = -1" \
  --append-line /etc/security/pwquality.conf:"maxrepeat = 2" \
  --append-line /etc/security/pwquality.conf:"maxclassrepeat = 1" \
  --append-line /etc/security/pwquality.conf:"difok = 5"

Debian based systems:

virt-customize -a $IMAGE \
  --append-line /etc/security/pwquality.conf:"enforce_for_root" \
  --append-line /etc/security/pwquality.conf:"minlen = 9" \
  --append-line /etc/security/pwquality.conf:"dcredit = -1" \
  --append-line /etc/security/pwquality.conf:"ucredit = -1" \
  --append-line /etc/security/pwquality.conf:"lcredit = 1" \
  --append-line /etc/security/pwquality.conf:"ocredit = -1" \
  --append-line /etc/security/pwquality.conf:"maxrepeat = 2" \
  --append-line /etc/security/pwquality.conf:"maxclassrepeat = 1" \
  --append-line /etc/security/pwquality.conf:"difok = 5" \
  --append-line /etc/security/pwquality.conf:"dictcheck = 0"

Added Configurations

SettingDescription
enforce_for_rootEnforces the password quality rules for the root user.
minlen = 9Sets the minimum password length to 9 characters.
dcredit = -1Requires at least one digit (negative values specify the minimum number of characters).

Here is a breakdown of WebVirtCloud key functionalities and features:

  • Manage Multiple hypervisors: You can manage multiple QEMU/KVM Hypervisor
  • VM Management: Create, manage, and access virtual machines directly from a web browser interface.
  • Remote Server Support: Install WebVirtCloud on your own server or even your laptop/PC, transforming it into a virtual machine management platform.
  • Pre-configured VM Templates: Deploy VMs quickly with pre-configured templates featuring popular operating systems like Ubuntu, Debian, Fedora, CentOS, AlmaLinux, and Rocky Linux.
  • User Management: Create and manage user accounts, allowing delegation of VM access and control.
  • Console Access: Access the virtual machine console directly through your web browser for real-time interaction.
  • User-based Authorization and Authentication: Implement user roles and permissions for secure access control.
  • Cloud-Init Integration: Utilize cloud-init for easier VM configuration during creation.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Unlock the Right Solutions with Confidence

At CloudSpinx, we don’t just offer services - we deliver clarity, direction, and results. Whether you're navigating cloud adoption, scaling infrastructure, or solving DevOps challenges, our seasoned experts help you make smart, strategic decisions with total confidence. Let us turn complexity into opportunity and bring your vision to life.

Leave a Comment

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

Related Post

Virt-Lightning is a lightweight virtual machine management tool created to help developers and system administrators to quickly and consistently deploy […]

Durham, UK, October 14, 2025 – Although over 95% of all Bitcoins are already in circulation, there are still over […]

When you work with virtual machines, you frequently need to conduct rapid changes to the disk image without booting the […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.