Installing VMs on KVM using Virt-builder

The virt-builder command-line tool simplifies and speed up the process of creating virtual machines (VMs) on kVM. It can be a suitable tool for local development, testing, or deployment of an actual server for production use. It is designed to be an efficient and flexible solution.

Key highlights of virt-builder are:

  • Quick VM creation – It leverages pre-prepared OS templates, allowing you to create VMs in just minutes or even seconds.
  • High customization – Extensive customization options for VM during creation such as password setting for user, packages installation, network configurations, files copy, e.t.c.
  • It fits into automation workflows – It is a command-line utility making it easy to integrate with automation scripts
  • It doesn’t need root privileges to use – All operations are executed at the user-level, making it a suitable solution in shared systems or restricted environments.
  • Plenty of secure templates – Virt-builder uses cleanly prepared, signed OS templates, ensuring that the VMs you create are secure and trustworthy.
🔥 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 →

Getting Started with Virt-Builder: Practical Examples

The libguestfs-tools package provides a set CLI tools such as virt-builder. Ensure it’s installed in your KVM system.

  • Debian-based systems
sudo apt install libguestfs-tools
  • RHEL-based systems
sudo dnf install -y libguestfs-tools guestfs-tools
  • SLES / openSUSE
sudo zypper -n install bridge-utils libguestfs
  • Arch-based systems
sudo pacman -S libguestfs guestfs-tools

Confirm successful installation by checking the version of virt-builder:

$ virt-builder --version
virt-builder 1.52.2

Let’s dive into some examples to showcase the versatility and ease of use of virt-builder:

To print the help page for virt-builder, you can use the --help flag.

virt-builder --help

This displays a detailed overview of the available options and their usage.

Example 1: Listing OS Templates

Virt-builder provides access to a variety of OS templates for creating virtual machines from quickly for different distributions and versions.

The basic command to list all available OS templates is:

virt-builder --list
# Or virt-builder -l

In the command output you will get a table of templates with the following details:

  • Name: The identifier of the template (e.g., debian-12ubuntu-20.04).
  • Version: The release version of the OS.
  • Arch: The architecture supported by the template (e.g., x86_64aarch64).
  • Description: Additional information about the template.

Use the grep command to find templates for a specific OS, like Debian:

$ virt-builder -l | grep debian
...
debian-10                x86_64     Debian 10 (buster)
debian-11                x86_64     Debian 11 (bullseye)
debian-12                x86_64     Debian 12 (bookworm)

Other examples:

  • Fedora: virt-builder -l | grep fedora
  • CentOS Stream: virt-builder -l | grep centosstream
  • Ubuntu: virt-builder -l | grep ubuntu

Example 2: Get OS Template installation notes

Before you can use the OS template, check installation notes by using the command:

virt-builder virt-builder <OS-VERSION>

For example, to display Debian 12 notes, run:

$ virt-builder --notes debian-12
Debian 12 (bookworm)

This is a minimal Debian install.

This image is so very minimal that it only includes an ssh server
This image does not contain SSH host keys.  To regenerate them use:

    --firstboot-command "dpkg-reconfigure openssh-server"

This template was generated by a script in the libguestfs source tree:
    builder/templates/make-template.ml
Associated files used to prepare this template can be found in the
same directory.

Example 3: Create customized VM image from OS Template

Let’s create a Debian 12 virtual machine image from the template.

virt-builder debian-12 --format qcow2 --output debian-12-server.qcow2

Output sample from the run:

[   0.4] Downloading: http://builder.libguestfs.org/debian-12.xz
###################################################################################################################################################################################################################################### 100.0%
[   3.3] Planning how to build this image
[   3.3] Uncompressing
[   6.8] Opening the new disk
[  12.3] Setting a random seed
virt-builder: warning: random seed could not be set for this type of guest
[  12.3] Setting passwords
virt-builder: Setting random password of root to wQHCkP0zG93gMZiS
[  13.1] SELinux relabelling
[  13.1] Finishing off
                   Output file: debian-12-server.qcow2
                   Output size: 6.0G
                 Output format: raw
            Total usable space: 5.8G
                    Free space: 4.6G (79%)

A random root user password is generated and printed out.

1. Changing output image format

The default output image format is raw, to use qcow2 format pass --format qcow2:

--format qcow2
2. Setting custom image size

The disk size of the output image can be set using --size <size>

--size 20G
3. Setting custom root password

To set a custom root user password, use  --root-password <SELECTOR>. In this example we are setting root user password to StrongPassw0rd

--root-password password:StrongPassw0rd
4. Setting hostname

Use --hostname <HOSTNAME>. Example:

--hostname webserver.cloudspinx.com
5. Install software package into VM image

The command options for installing software packages is --install <PKG,PKG..>. Let’s consider and example to install openssh-server, mariadb-server, apache2, and php packages.

--install openssh-server,mariadb-server,apache2,libapache2-mod-php,php-mysql
6. Run command at first guest boot

We can provide the commands that will be run on first boot using --firstboot-command <'CMD+ARGS'>

--firstboot-command 'apt update && apt upgrade -y'
7. Set the default timezone

The default timezone can be set by passing --timezone <TIMEZONE>

--timezone America/Los_Angeles
8. Upload local file to destination

It is possible to upload files from your local machine into the image with --upload <FILE:DEST>

Let’s begin by creating a Hello World PHP code.

echo '<?php echo "<h1>Hello, World!</h1>"; ?>' > helloworld.php

The example below will copy the php script created into /var/www/html/ on the VM image.

--upload ./helloworld.php:/var/www/html

Files can also be moved instead of copy by using --move <SOURCE:DEST>

9. Inject SSH public key into the guest

SSH public key can be injected into the guest VM using --ssh-inject <USER[:SELECTOR]>

Generate ssh keys if you don’t have:

ssh-keygen -t rsa -b 2048

The default path location for the SSH public key is ~/.ssh/id_rsa.pub. We can inject this file.

--ssh-inject root:file:/home/$USER/.ssh/id_rsa.pub
  • root is the name of guest OS user account
  • /home/$USER/.ssh/id_rsa.pub is the absolute path to the ssh public key. If using root user account this will be /root/.ssh/id_rsa.pub

The final virt-builder commands will be:

virt-builder debian-12 --format qcow2 \
--size 20G \
--output debian-12-server.qcow2 \
--root-password password:StrongPassw0rd \
--hostname webserver.cloudspinx.com \
--install vim,openssh-server,mariadb-server,apache2,libapache2-mod-php,php-mysql \
--firstboot-command 'apt update && apt upgrade -y' \
--timezone America/Los_Angeles \
--upload ./helloworld.php:/var/www/html \
--ssh-inject root:file:/home/user/.ssh/id_rsa.pub

Example execution output:

[   0.4] Downloading: http://builder.libguestfs.org/debian-12.xz
[   0.8] Planning how to build this image
[   0.8] Uncompressing
[   4.3] Resizing (using virt-resize) to expand the disk to 20.0G
[  17.0] Opening the new disk
[  20.8] Setting a random seed
virt-builder: warning: random seed could not be set for this type of guest
[  20.8] Setting the hostname: webserver.cloudspinx.com
[  21.5] Installing packages: mariadb-server apache2 libapache2-mod-php php-mysql
[  40.0] Installing firstboot command: apt update && apt upgrade -y
[  40.0] Setting the timezone: America/Los_Angeles
[  40.0] Uploading: ./helloworld.php to /var/www/html
[  40.1] SSH key inject: root
[  40.9] Setting passwords
[  41.7] SELinux relabelling
[  41.7] Finishing off
                   Output file: debian-12-server.qcow2
                   Output size: 20.0G
                 Output format: qcow2
            Total usable space: 19.6G
                    Free space: 18.1G (92%)
10. Disable SELinux (Valid for RHEL based systems)

The --edit <FILE:EXPR> allows you to edit file using Perl expression. Here is an example that will disable SELinux.

--edit '/etc/selinux/config: s/^SELINUX=.*/SELINUX=disabled/'

Or putting it in permissive mode:

--edit '/etc/selinux/config: s/^SELINUX=.*/SELINUX=permissive/'

Example 3: Create a Virtual Machine from the image

A virtual machine (VM) can now be created from an image built using virt-builder. In this section we provide a detailed guide on how to create and launch a VM using a virt-builder-generated image.

Before we import the VM move the image to /var/lib/libvirt/images directory:

sudo mv debian-12-server.qcow2 /var/lib/libvirt/images

Define and create the VM using the virt-install command:

sudo virt-install \
  --name webserver-01 \
  --memory 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/debian-12-server.qcow2,format=qcow2,bus=virtio \
  --os-variant debian12 \
  --network bridge=virbr0,model=virtio \
  --graphics none \
  --import

To get a complete list of avaialable OS variants run osinfo-query os:

osinfo-query os | grep debian

Explanation of used options:

  • --name: Name of the VM (webserver-01).
  • --memory: Allocates 2 GB of RAM to the VM.
  • --vcpus: Assigns 2 virtual CPUs to the VM.
  • --disk: Specifies the disk file (debian-12-server.qcow2) and its format.
  • --os-type and --os-variant: Optimizes the VM for Debian 12.
  • --network: Connects the VM to a bridge network (virbr0).
  • --graphics none: Runs the VM in a headless mode (no GUI).
  • --import: Indicates the disk image is pre-installed and does not need installation media.

The VM console will show the boot up process.

                           GNU GRUB  version 2.06-13

 +----------------------------------------------------------------------------+
 |*Debian GNU/Linux                                                           |
 | Advanced options for Debian GNU/Linux                                      |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 +----------------------------------------------------------------------------+

      Use the ^ and v keys to select which entry is highlighted.
      Press enter to boot the selected OS, `e' to edit the commands
      before booting or `c' for a command-line.

Input root user and password you did set for the image earlier to login.

webserver login: root
Password:
Linux webserver.cloudspinx.com 6.1.0-9-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.27-1 (2023-05-08) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@webserver:~# dhclient enp1s0

The escape sequence to exit the console is Ctrl+]. To reconnect use the commands:

virsh console <VM-Name>

The VM’s status can be checked by using virsh list --all:

$ sudo virsh list --all
 Id   Name           State
------------------------------
 2    webserver-01   running

Use the following command to retrieve the DHCP leases for the virtual network:

sudo virsh net-dhcp-leases default

This will output the leases table:

 Expiry Time           MAC address         Protocol   IP address          Hostname    Client ID or DUID
---------------------------------------------------------------------------------------------------------
 2024-12-24 11:11:02   52:54:00:0d:ec:ca   ipv4       192.168.122.69/24   webserver   -

In the output we can see the IP address assigned to the instance is 192.168.122.69.

To initiate SSH connection into the VM:

ssh root@ServerIP

Example 4: Automation with bash script in image / VM

We will create a bash script that can perform the following:

  • Update packages index and upgrade system
  • Install basic utilities – vim, wget,cul,git,bash-completion,openssh-server
  • Install MariaDB Server
  • Install and prepare PHP environment including necessary extensions
  • Start and enable systemd services

Create a new script file called install_and_setup_full.sh:

vim vm_setup.sh

Copy the following code into the file. It can be modified to fit your specific requirements.

#!/bin/bash
apt update

echo "Installing essential packages: vim, wget, git, curl, bash-completion, openssh-server..."
apt install -y vim wget git curl bash-completion openssh-server

echo "Installing MariaDB server..."
apt install -y mariadb-server

echo "Installing PHP environment: PHP, Apache2, libapache2-mod-php, php-mysql, and basic PHP modules..."
apt install -y apache2 php libapache2-mod-php php-mysql php-cli php-curl php-json php-xml php-mbstring php-zip php-soap php-intl

echo "Starting and enabling services..."
systemctl start ssh mariadb apache2
systemctl enable ssh mariadb apache2

# Test PHP environment
echo "Setting up a PHP test file..."
echo "<?php phpinfo(); ?>" > /var/www/html/info.php
echo "You can access the PHP info page at: http://<your-server-ip>/info.php"

Make the script executable:

chmod +x vm_setup.sh

There are two ways this script can be run:

  • Running the script in the image build process

The virt-builder --run <SCRIPT>  option allows us to run script in disk image.

virt-builder debian-12 --format qcow2 \
--size 20G \
--output debian-12-server.qcow2 \
--root-password password:StrongPassw0rd \
--hostname webserver.cloudspinx.com \
--firstboot-command 'apt update && apt upgrade -y' \
--timezone America/Los_Angeles \
--ssh-inject root:file:/root/.ssh/id_rsa.pub \
--upload ./vm_setup.sh:/root/vm_setup.sh \
--run /root/vm_setup.sh

Sample script execution output:

[   3.4] Downloading: http://builder.libguestfs.org/debian-12.xz
[   6.6] Planning how to build this image
[   6.6] Uncompressing
[  15.2] Resizing (using virt-resize) to expand the disk to 20.0G

[ 152.2] Opening the new disk
[ 174.3] Setting a random seed
virt-builder: warning: random seed could not be set for this type of guest
[ 174.5] Setting the hostname: webserver.cloudspinx.com
[ 183.7] SSH key inject: root
[ 191.8] Uploading: ./vm_setup.sh to /root/vm_setup.sh
[ 192.0] Running: /root/vm_setup.sh
[ 231.9] Setting passwords
[ 240.7] SELinux relabelling
[ 241.1] Finishing off
                   Output file: debian-12-server.qcow2
                   Output size: 20.0G
                 Output format: qcow2
            Total usable space: 19.6G
                    Free space: 18.0G (91%)
  • Running the script at first guest boot

An alternative to running the script in disk image is to execute it on first guest os boot. For this we use --firstboot <SCRIPT> . We can utilise --upload option which will allow us to copy local files or directories into image

virt-builder debian-12 --format qcow2 \
--size 20G \
--output debian-12-server.qcow2 \
--root-password password:StrongPassw0rd \
--hostname webserver.cloudspinx.com \
--firstboot-command 'apt update && apt upgrade -y' \
--timezone America/Los_Angeles \
--ssh-inject root:file:/root/.ssh/id_rsa.pub \
--upload ./vm_setup.sh:/root/vm_setup.sh \
--firstboot /root/vm_setup.sh

Expected output:

[   0.4] Downloading: http://builder.libguestfs.org/debian-12.xz
[   0.9] Planning how to build this image
[   0.9] Uncompressing
[   4.3] Resizing (using virt-resize) to expand the disk to 20.0G
[  17.6] Opening the new disk
[  21.4] Setting a random seed
virt-builder: warning: random seed could not be set for this type of guest
[  21.4] Setting the hostname: webserver.cloudspinx.com
[  22.1] Installing firstboot command: apt update && apt upgrade -y
[  22.1] Setting the timezone: America/Los_Angeles
[  22.2] SSH key inject: root
[  22.8] Uploading: ./vm_setup.sh to /root/vm_setup.sh
[  22.9] Installing firstboot script: /root/vm_setup.sh
[  22.9] Setting passwords
[  23.6] SELinux relabelling
[  23.6] Finishing off
                   Output file: debian-12-server.qcow2
                   Output size: 20.0G
                 Output format: qcow2
            Total usable space: 19.6G
                    Free space: 18.4G (94%)

After image is build refer to Example 3 for how to create a virtual machine from the created os image.

Example 5: Removing the Virtual Machine

Follow the following steps to remove a virtual machine (VM) if nolonger needed.

  • Check the list of active and inactive VMs:
sudo virsh list --all
  • Shutdown the VM
sudo virsh shutdown <vm-name>
  • To force-stop the VM (if it doesn’t shut down gracefully):
sudo virsh destroy <vm-name>
  • To remove the VM with all associated storage volumes:
sudo virsh undefine --remove-all-storage <vm-name>

🌍 Our KVM eBook covers all this in details and more. In the book you will learn:

  • Understanding Virt-install
  • Linux VM Installation from ISO image
  • Linux VM Installation using Cloud-Init
  • Windows installation (Desktop and Server) using virt-install
  • VMs Installation using Virt-builder
  • VMs Install using PXE Boot and virt-install
  • VMs Installation using virt-install and kickstart
  • GPU Passthrough to Virtual Machines

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

Installation of Windows operating systems on a KVM hypervisor is a common requirement in varying environments. While the process is […]

Installation of Windows operating systems on a KVM hypervisor is a common requirement in varying environments. While the process is […]

The virt-install command-line tool is used to create and configure new virtual machines on KVM. It offers numerous options that allowsusers to […]

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.