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.
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
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.
- Ubuntu Cloud Images
- Debian Cloud Images
- Rocky Linux Cloud Images
- AlmaLinux Cloud Images
- Fedora Cloud Images
- Kali Linux Cloud Images
- RHEL Cloud Images: RHEL 9 KVM Guest Image , RHEL 8 mage
- Alpine Linux cloud Image
- BSD: DragonFlyBSD, FreeBSD, NetBSD, OpenBSD 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 --install
to 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-pwquality
on 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
Setting | Description |
---|---|
enforce_for_root | Enforces the password quality rules for the root user. |
minlen = 9 | Sets the minimum password length to 9 characters. |
dcredit = -1 | Requires 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.