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.
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
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-12
,ubuntu-20.04
). - Version: The release version of the OS.
- Arch: The architecture supported by the template (e.g.,
x86_64
,aarch64
). - 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