KVM Virtualization (Beginner)
Introduction to KVM virtualization
Section titled “Introduction to KVM virtualization”0. Specs
Section titled “0. Specs”0.0. The What
Section titled “0.0. The What”KVM Virtualization Tutorial 1 for Debian and Ubuntu Server.
Our objective is to install and configure a host system for virtual machines.
This tutorial aims to bring you (and me) to a moderate level of virtualization administration proficiency.
0.1. How It Works
Section titled “0.1. How It Works”KVM (Kernel-based Virtual Machine) is a loadable kernel module that provides virtualization capabilities via APIs.
QEMU (Quick EMUlator) is a virtualizer that uses the KVM API. QEMU also supports other virtualization solutions.
Libvirt is a library for managing virtualization hosts. The virsh command originates from Libvirt.
Libguestfs is a collection of tools for accessing and managing virtual machine images.
virt-manager is a GUI for managing virtual machines. I use it on my workstation for simple tasks.
0.2. Infrastructure
Section titled “0.2. Infrastructure”- Server (Host): Debian (12/13) or Ubuntu (24.04/22.04) Server
- IP: 192.168.1.121
- Name: elma
- NIC: enp3s0f0
- Workstation: Debian 13 or Ubuntu 24.04 LTS Desktop
- Network: 192.168.1.0/24 supplied by my internet modem/router
0.3. (Very) Basic Terminology
Section titled “0.3. (Very) Basic Terminology”- Domain: Virtual Machine (VM)
- Image: A file containing a virtual machine or its disk
- Host: A server running virtualization software
- Guest: A virtual machine running on a host
- Snapshot: A saved state of an image that can be restored later
0.4. Resources
Section titled “0.4. Resources”- ostechnix.com
- www.qemu.org
- www.libvirt.org
- https://docs.fedoraproject.org/en-US/Fedora/18/html/Virtualization_Administration_Guide/index.html (not working now
- libguestfs.org
- fabianlee.org
- cloudinit.readthedocs.io
- ISBN: 979-10-91414-20-3 The Debian Administrator’s Handbook by Raphaël Hertzog and Roland Mas
- ISBN: 978-1-78829-467-6 KVM Virtualization Cookbook by Konstantin Ivanov
1. Installation and Configuration
Section titled “1. Installation and Configuration”1.1. Installation
Section titled “1.1. Installation”Install necessary packages:
sudo apt updatesudo apt install libvirt-clients libvirt-daemon-system qemu-kvm \ virtinst virt-manager virt-viewer bridge-utils --yesAdd your user to the libvirt group (replace exforge with your username):
sudo usermod -aG libvirt exforge1.2. Bridge Configuration
Section titled “1.2. Bridge Configuration”For guest computers to access the network, a bridge configuration on the host is required.
Bridge configuration differs slightly between Debian and Ubuntu, so we’ll handle them separately.
1.2.1. Ubuntu Bridge Configuration
Section titled “1.2.1. Ubuntu Bridge Configuration”By default, KVM creates a virtual bridge named virbr0. This bridge allows VMs to communicate with each other and the host. However, we want VMs to join our network by obtaining IP addresses from it.
First, disable netfilter (enabled on bridges by default):
sudo nano /etc/sysctl.d/bridge.confAdd the following lines (file is initially empty):
net.bridge.bridge-nf-call-ip6tables=0net.bridge.bridge-nf-call-iptables=0net.bridge.bridge-nf-call-arptables=0Create a udev rule to apply these settings:
sudo nano /etc/udev/rules.d/99-bridge.rulesAdd this line (file is initially empty):
ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"Reboot to apply changes:
sudo rebootRemove the default KVM bridge. List networks with ip link to see virbr0.
Delete and undefine KVM networks:
virsh net-destroy defaultvirsh net-undefine defaultIf errors occur, force removal:
sudo ip link delete virbr0 type bridgeRun ip link again to confirm virbr0 is removed. Note your physical interface name(s) (e.g., enp0s0).
Back up your network configuration file (if 50-cloud-init.yaml doesn’t exist, look for another .yaml file):
sudo cp /etc/netplan/50-cloud-init.yaml{,.backup}Edit your network configuration:
sudo nano /etc/netplan/50-cloud-init.yamlReplace the content with the following (adjust enp3s0f0 to your interface name, and use your local network IP and gateway):
network: ethernets: enp3s0f0: dhcp4: false dhcp6: false bridges: br0: interfaces: [enp3s0f0] addresses: - 192.168.1.121/24 routes: - to: default via: 192.168.1.1 mtu: 1500 nameservers: addresses: - 8.8.8.8 - 8.8.4.4 parameters: stp: true forward-delay: 4 dhcp4: false dhcp6: false version: 2Apply changes (SSH connection may drop; reconnect if needed):
sudo netplan applyVerify the bridge with ip link; you should see br0.
1.2.2. Debian Bridge Configuration
Section titled “1.2.2. Debian Bridge Configuration”By default, KVM creates a virtual bridge named virbr0. This bridge allows VMs to communicate with each other and the host. However, we want VMs to join our network by obtaining IP addresses from it.
First, disable netfilter (enabled on bridges by default):
sudo nano /etc/sysctl.d/bridge.confAdd the following lines (file is initially empty):
net.bridge.bridge-nf-call-ip6tables=0net.bridge.bridge-nf-call-iptables=0net.bridge.bridge-nf-call-arptables=0Create a udev rule to apply these settings:
sudo nano /etc/udev/rules.d/99-bridge.rulesAdd this line (file is initially empty):
ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"Reboot to apply changes:
sudo rebootBack up your network configuration file:
sudo cp /etc/network/interfaces{,.backup}Edit your network configuration:
sudo nano /etc/network/interfacesReplace the content with the following (adjust enp3s0f0 to your interface name, and use your local network IP and gateway):
# This file describes the network interfaces available on your system# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interfaceauto loiface lo inet loopback
# The primary network interfaceallow-hotplug enp3s0f0#make sure we don't get addresses on our raw deviceiface enp3s0f0 inet manual#set up bridge and give it a static ipauto br0iface br0 inet static address 192.168.1.121 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.1 bridge_ports enp3s0f0 bridge_stp off bridge_fd 0 bridge_maxwait 0 dns-nameservers 8.8.8.8Apply changes (SSH connection may drop; reconnect if needed):
sudo systemctl restart networking.service1.3. Add Our Bridge to KVM
Section titled “1.3. Add Our Bridge to KVM”Create an XML file for the bridge definition:
nano host-bridge.xml<network> <name>host-bridge</name> <forward mode="bridge"/> <bridge name="br0"/></network>Define, start, and enable autostart for the bridge:
virsh net-define host-bridge.xmlvirsh net-start host-bridgevirsh net-autostart host-bridge1.4. Configure Directories
Section titled “1.4. Configure Directories”Set up directories for disk images and installation ISOs:
/srv/kvmfor VM disk images/srv/isosfor installation ISO images
sudo mkdir /srv/kvm /srv/isossudo virsh pool-create-as srv-kvm dir --target /srv/kvmAt this point, you may want to copy some installation ISOs to the server’s /srv/isos directory.
2. VM Creation
Section titled “2. VM Creation”2.1. Create the First VM
Section titled “2.1. Create the First VM”Now it’s time to create our first virtual machine.
It will be Ubuntu Server 24.04 LTS with 1 GB RAM and 10 GB HDD.
I’ve already copied the Ubuntu Server ISO ubuntu-24.04.2-live-server-amd64.iso to /srv/isos.
Install a VM named testkvm:
sudo virt-install --name testkvm \ --connect qemu:///system --virt-type kvm \ --memory 1024 --vcpus 1 \ --disk /srv/kvm/testkvm.qcow2,format=qcow2,size=10 \ --cdrom /srv/isos/ubuntu-24.04.2-live-server-amd64.iso \ --network bridge=br0 \ --graphics vnc,port=5901,listen=0.0.0.0 \ --os-variant ubuntu24.04 \ --noautoconsoleParameters explained:
--name: VM name--connect: Connection URI (local system)--virt-type: Virtualization type (KVM)--memory: RAM in MB--vcpus: Virtual CPU count--disk: Storage location, format, and size (GB)--cdrom: Installation media--network: Network bridge for VM connectivity--graphics: VNC settings (listens on all interfaces)--os-variant: Guest OS optimization profile--noautoconsole: Don’t automatically connect to console
Note: Ubuntu 22.04 may not recognize ubuntu24.04 OS variant; use ubuntu22.04 instead.
2.2. OS Variant List
Section titled “2.2. OS Variant List”Many OS variants are available. Find yours with:
sudo apt install libosinfo-bin --yesosinfo-query osThis helps the hypervisor optimize for the guest OS. The parameter can be omitted if unsure.
2.3. Connecting to the VM
Section titled “2.3. Connecting to the VM”A graphical desktop is required to connect via VNC. Install virt-viewer on your workstation:
Run on your workstation:
sudo apt updatesudo apt install virt-viewer --yesvirt-viewer --connect qemu+ssh://exforge@elma/system testkvmReplace exforge with your username on the server and elma with your server’s hostname.
3. Remote Graphical Management
Section titled “3. Remote Graphical Management”Our server lacks a graphical interface (like most servers). For graphical management, install virt-manager on your workstation:
Run on your workstation:
sudo apt updatesudo apt install virt-manager --yesvirt-managerThe application appears in the Applications Menu as “Virtual Machine Manager.”
4. Installing VMs from Pre-built Images
Section titled “4. Installing VMs from Pre-built Images”Installing an OS from scratch is time-consuming. An alternative is using pre-built cloud images with cloud-init configuration.
4.0. Installing cloud-image-utils
Section titled “4.0. Installing cloud-image-utils”sudo apt updatesudo apt install cloud-image-utils --yes4.1. Acquiring Cloud Images
Section titled “4.1. Acquiring Cloud Images”Search for cloud images:
- Ubuntu: cloud-images.ubuntu.com
- Debian: cloud.debian.org
Download the latest images (e.g., Ubuntu 24.04 Noble and Debian 13 Trixie) to /srv/isos.
cd /srv/isossudo wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.imgsudo wget https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow24.2. Creating a New Image From the Original Image
Section titled “4.2. Creating a New Image From the Original Image”Create new images with increased size (20 GB) and convert to qcow2 format.
Ubuntu image:
sudo qemu-img create -b /srv/isos/noble-server-cloudimg-amd64.img \ -F qcow2 -f qcow2 /srv/kvm/ubuntusrv-cloudimg.qcow2 20GDebian image:
sudo qemu-img create -b /srv/isos/debian-13-generic-amd64.qcow2 \ -F qcow2 -f qcow2 /srv/kvm/debiansrv-cloudimg.qcow2 20G4.3. Cloud-init Configuration
Section titled “4.3. Cloud-init Configuration”The next step is to crate a cloud-init config file. This file contains instructions for the cloud image. There is a wide range of instructions like; creating a user, creating and filling files, adding apt repositories, running initial commands, installing packages, reboot and poweroff after finishing, disk and configuration. See below url for details:
Our cloud-init file will configure the following:
- Set hostname and Fully Qualified Domain Name,
- Create a user named exforge with sudo privileges,
- assign its password,
- add it to exforge group as primary,
- also add it to users group,
- create its home directory as /home/exforge,
- and set its shell to bash.
First, generate a password hash:
sudo apt install whois --yesmkpasswd --method=SHA-512 --rounds=4096Enter the desired password and copy the hash output.
We will create configuration files in /srv/init. Create the folder:
sudo mkdir /srv/initUbuntu cloud-init configuration:
sudo nano /srv/init/ubuntu-cloud-init.cfgFill as below (Remember updating password with the hash you get):
#cloud-confighostname: ubuntu24fqdn: ubuntu24.x386.orgmanage_etc_hosts: truegroups: exforgeusers: - name: exforge sudo: ALL=(ALL) ALL primary_group: exforge groups: users home: /home/exforge shell: /bin/bash lock_passwd: false passwd: $6$rounds=4096$hVAmry7V/zE8KHCT$Ha.qFtVJLDxRhmKTFY3hFhQqXmWrbF3n39dlWMXnmIAmdm5hJriRWRHVlT7FtaVUHIPeSm5u966vOcXFfXCyI/packages: qemu-guest-agentDebian cloud-init configuration:
sudo nano /srv/init/debian-cloud-init.cfgFill as below (Again remember updating password with the hash you get):
#cloud-confighostname: debian13fqdn: debian13.x386.orgmanage_etc_hosts: truegroups: exforgeusers: - name: exforge sudo: ALL=(ALL) ALL primary_group: exforge groups: users home: /home/exforge shell: /bin/bash lock_passwd: false passwd: $6$rounds=4096$hVAmry7V/zE8KHCT$Ha.qFtVJLDxRhmKTFY3hFhQqXmWrbF3n39dlWMXnmIAmdm5hJriRWRHVlT7FtaVUHIPeSm5u966vOcXFfXCyI/packages: qemu-guest-agent4.4. Cloud-init Network Configuration
Section titled “4.4. Cloud-init Network Configuration”For static IP configuration, create network config files.
Ubuntu network configuration:
sudo nano /srv/init/ubuntu-network-init.cfg#cloud-configversion: 2ethernets: enp1s0: dhcp4: false addresses: [ 192.168.1.243/24 ] gateway4: 192.168.1.1 nameservers: addresses: [ 192.168.1.1,8.8.8.8 ]Debian network configuration:
sudo nano /srv/init/debian-network-init.cfgFill as below:
#cloud-configversion: 2ethernets: enp1s0: dhcp4: false addresses: [ 192.168.1.244/24 ] gateway4: 192.168.1.1 nameservers: addresses: [ 192.168.1.1,8.8.8.8 ]Adjust IP addresses according to your network.
4.5. Creating Cloud-init Seed Images
Section titled “4.5. Creating Cloud-init Seed Images”Create seed images containing cloud-init and network configurations.
Ubuntu seed image:
sudo cloud-localds --network-config /srv/init/ubuntu-network-init.cfg \ /srv/kvm/ubuntu24-seed.qcow2 \ /srv/init/ubuntu-cloud-init.cfgDebian seed image:
sudo cloud-localds --network-config /srv/init/debian-network-init.cfg \ /srv/kvm/debian13-seed.qcow2 \ /srv/init/debian-cloud-init.cfg4.6. Start VMs from Cloud Images
Section titled “4.6. Start VMs from Cloud Images”Ubuntu Server VM:
virt-install --name ubuntu24 \ --connect qemu:///system \ --virt-type kvm --memory 2048 --vcpus 2 \ --boot hd,menu=on \ --disk path=/srv/kvm/ubuntu24-seed.qcow2,device=cdrom \ --disk path=/srv/kvm/ubuntusrv-cloudimg.qcow2,device=disk \ --graphics vnc,port=5902,listen=0.0.0.0 \ --os-variant ubuntu24.04 \ --network bridge=br0 \ --noautoconsole \ --install no_install=yesDebian Server VM:
virt-install --name debian13 \ --connect qemu:///system \ --virt-type kvm --memory 2048 --vcpus 2 \ --boot hd,menu=on \ --disk path=/srv/kvm/debian13-seed.qcow2,device=cdrom \ --disk path=/srv/kvm/debiansrv-cloudimg.qcow2,device=disk \ --graphics vnc,port=5903,listen=0.0.0.0 \ --os-variant debian13 \ --network bridge=br0 \ --noautoconsole \ --install no_install=yesNote: If --os-variant debian13 fails on Ubuntu servers, try --os-variant debian11.
Cloud-init may take several minutes to complete. Connect via virt-viewer:
** Run on your workstation **
virt-viewer --connect qemu+ssh://exforge@elma/system ubuntu24virt-viewer --connect qemu+ssh://exforge@elma/system debian134.7. Disable Cloud-init After Initial Configuration
Section titled “4.7. Disable Cloud-init After Initial Configuration”On each VM, run:
sudo touch /etc/cloud/cloud-init.disabledThis prevents cloud-init from running on subsequent boots.
4.8. Automation with Python Script
Section titled “4.8. Automation with Python Script”The entire process (except step 4.7) can be automated with a Python script:
- Download the latest cloud image (or use cached)
- Create a new base image with
qemu-img create - Generate password hash and create cloud-init files
- Create seed image with
cloud-localds - Launch VM with
virt-install
Script parameters could include:
- Image name and size
- Username and password
- Network properties (IP, gateway, DNS)
- Memory size and vCPU count
- VNC port number
5. virsh: Shell Based VM Management
Section titled “5. virsh: Shell Based VM Management”virt-manager handles basic management tasks, but advanced administration requires the command-line interface.
The virsh command offers extensive capabilities. I’ll cover the most useful commands here (in my opinion).
For complete documentation, visit: www.libvirt.org
In all examples, replace NAME with your VM’s name.
5.0. Environment Variable Set
Section titled “5.0. Environment Variable Set”On Debian, to run virsh commands without sudo, set an environment variable:
export LIBVIRT_DEFAULT_URI='qemu:///system'For permanent setup, add to your shell profile:
nano ~/.bashrcAdd this line:
export LIBVIRT_DEFAULT_URI='qemu:///system'Then reload:
source ~/.bashrc5.1. Host Information
Section titled “5.1. Host Information”Display host system details:
virsh nodeinfo5.2. List VMs and Their States
Section titled “5.2. List VMs and Their States”List running VMs:
virsh listList all VMs (running and stopped):
virsh list --all5.3. VM Lifecycle Management
Section titled “5.3. VM Lifecycle Management”Start, stop, reboot, force stop, or remove a VM:
virsh start NAME # Start VMvirsh shutdown NAME # Graceful shutdownvirsh reboot NAME # Reboot VMvirsh destroy NAME # Force shutdown (power off)virsh undefine NAME # Remove VM definitionvirsh undefine NAME --remove-all-storage # Remove VM with all storage5.4. Pause and Resume VM
Section titled “5.4. Pause and Resume VM”Suspend and resume VM execution:
virsh suspend NAME # Pause VMvirsh resume NAME # Resume VM5.5. Autostart Configuration
Section titled “5.5. Autostart Configuration”Configure VM to start automatically with host boot:
virsh autostart NAME # Enable autostartvirsh autostart --disable NAME # Disable autostart5.6. VM Information
Section titled “5.6. VM Information”Display various VM details:
virsh dominfo NAME # General VM informationvirsh domid NAME # VM IDvirsh domuuid NAME # VM UUIDvirsh domstate NAME # Current state (running, shut off, etc.)virsh domdisplay NAME # VNC/display connection details5.7. VM Memory Management
Section titled “5.7. VM Memory Management”VMs have two memory parameters:
- Current Memory: Currently allocated RAM
- Maximum Memory: Maximum allocatable RAM
View current allocation:
virsh dominfo NAMEChange maximum memory (requires shutdown and start to activate):
virsh setmaxmem NAME 2G --configNote: Size can be specified as 2G, 1536M, etc.
Change current memory allocation:
virsh setmem NAME 2G # Current session onlyvirsh setmem NAME 2G --live # Live change (immediate)virsh setmem NAME 2G --config # Persistent after shutdown/startvirsh setmem NAME 2G --live --config # Immediate + persistentWarning: Decreasing memory on a running VM is not recommended.
Beware of Shutdown and Start. Reboots do not count.
5.8. VM vCPU Management
Section titled “5.8. VM vCPU Management”VMs have two vCPU parameters:
- Current: Active vCPUs
- Maximum: Maximum allocatable vCPUs
Two states exist:
- Config: Persistent state (after shutdown and start)
- Live: Current running state
A cartesian product gives us 4 values:
- maximum config: Max number of vCPUs, valid after shutdown and start.
- maximum live: Max number of vCPUs, valid now (while running).
- current config: Active number of vCPUs, valid after shutdown and start.
- current live: Active number of vCPUs, valid now (while running).
View vCPU information:
virsh vcpucount NAMEI keep saying shutdown and start instead of restart or reboot, because kvm, qemu or whatever it is, acts differently when you reboot or shutdown and then start the VM.
So when I say shutdown and start, I mean shutdown first, wait a while (from 0.001 miliseconds to as long as you want) and then start the VM.
Change maximum vCPUs (config state only - requires shutdown and start to activate):
virsh setvcpus NAME NUMBER --maximum --configvirsh setvcpus ubuntu24 3 --maximum --configChange current vCPU count:
virsh setvcpus NAME 3 # Current sessionvirsh setvcpus NAME 3 --live # Live changevirsh setvcpus NAME 3 --config # Persistent changevirsh setvcpus NAME 3 --live --config # Both immediate and persistentvirsh setvcpus ubuntu24 3virsh setvcpus ubuntu24 3 --livevirsh setvcpus ubuntu24 3 --currentvirsh setvcpus ubuntu24 3 --live --configImportant: After increasing vCPUs on a running VM, new vCPUs may be offline. Check online status on the VM:
lscpu | headActivate offline vCPU (on the VM):
sudo sh -c 'echo 1 > /sys/devices/system/cpu/cpu2/online'Replace cpu2 with the appropriate vCPU number (starting from 0).
5.9. Snapshots
Section titled “5.9. Snapshots”Create a live snapshot:
virsh snapshot-create-as VMNAME \ --name SNAPSHOTNAME \ --description "Description text"Example:
virsh snapshot-create-as ubuntu24 \ --name ss1-ubuntu24 \ --description "First snapshot of Ubuntu24"Manage snapshots:
virsh snapshot-revert VMNAME --current # Revert to current snapshotvirsh snapshot-revert VMNAME --snapshotname SNAPSHOTNAME # Revert to specificvirsh snapshot-current VMNAME --name # Show current snapshotvirsh snapshot-delete VMNAME --current # Delete current snapshotvirsh snapshot-delete VMNAME --snapshotname SNAPSHOTNAME # Delete specificvirsh snapshot-list VMNAME # List all snapshots5.10. Attach Another Disk to a VM
Section titled “5.10. Attach Another Disk to a VM”Add a secondary disk to a VM (e.g., 20GB for Ubuntu24).
Create a new disk image:
sudo qemu-img create -f qcow2 /srv/kvm/ubuntu24-disk2.qcow2 20GIdentify disk naming on VM (run on VM):
lsblk -o name -d | grep vdTypical names: vda (primary), vdb (secondary), etc.
Attach disk to VM:
virsh attach-disk ubuntu24 \ /srv/kvm/ubuntu24-disk2.qcow2 \ vdb \ --persistentOptions:
--persistent: Survives shutdown/start--live: Current session only--config: Persistent but not immediate
Detach disk:
virsh detach-disk ubuntu24 vdb --persistentAs in virsh attach-disk, you can change —persistent option to —live or —config.
5.11. Other virsh Commands
Section titled “5.11. Other virsh Commands”Get the list of all virsh subcommands:
virsh --help6. qemu-img: Shell Based Image Management
Section titled “6. qemu-img: Shell Based Image Management”qemu-img manipulates VM disk images. Important: Always stop the VM before using qemu-img on its images.
Complete documentation: www.qemu.org
6.1. Get Basic Image Information
Section titled “6.1. Get Basic Image Information”qemu-img info FILENAMEExample for Ubuntu24 VM:
qemu-img info /srv/kvm/ubuntusrv-cloudimg.qcow26.2. Creating an Image
Section titled “6.2. Creating an Image”Create a new image:
qemu-img create -f FORMAT FILENAME SIZEExample (from section 5.10):
sudo qemu-img create -f qcow2 /srv/kvm/ubuntu24-disk2.qcow2 20GCreate an image backed by another image (differencing image):
sudo qemu-img create \ -b BACKINGFILENAME \ -F BACKINGFILEFORMAT \ -f OUTPUTFILEFORMAT \ OUTPUTFILENAME \ SIZEExample (from section 4.2):
sudo qemu-img create \ -b /srv/isos/noble-server-cloudimg-amd64.img \ -F qcow2 \ -f qcow2 \ /srv/kvm/ubuntusrv2-cloudimg.qcow2 \ 20G6.3. Converting Image Formats
Section titled “6.3. Converting Image Formats”Common formats:
- raw: Simple, unformatted binary
- qcow2: QEMU format with snapshots, compression, encryption
- qcow: Older QEMU format
- vdi: VirtualBox format
- vmdk: VMware format
- vhdx: Microsoft Hyper-V format
- dmg: Apple Disk Image
Convert between formats:
qemu-img convert \ -f SOURCEFORMAT \ -O DESTINATIONFORMAT \ SOURCEFILE \ DESTFILE6.4. Resize a Disk Image.
Section titled “6.4. Resize a Disk Image.”Increase or decrease image size:
sudo qemu-img resize FILENAME [+|-]SIZEIncrease Ubuntu24 image by 5GB:
sudo qemu-img resize /srv/kvm/ubuntusrv-cloudimg.qcow2 +5GWarning: To shrink an image:
- Use
--shrinkflag:qemu-img resize --shrink FILENAME -SIZE - Shrink partitions/filesystem inside VM first
- Verify disk usage before shrinking
6.5. Check an Image For Errors
Section titled “6.5. Check an Image For Errors”qemu-img check FILENAMEUse if you suspect image corruption.
7. Export and Import of VMs
Section titled “7. Export and Import of VMs”Migrate VMs between hosts or create backups.
7.1. Export
Section titled “7.1. Export”Important: Shut down the VM before export for data consistency.
Create backup directory:
mkdir /tmp/kvmbackupExport VM definition (XML):
virsh dumpxml ubuntu24 > /tmp/kvmbackup/ubuntu24.xmlIdentify disk images from XML:
grep "source file" /tmp/kvmbackup/ubuntu24.xmlExample output:
<source file='/srv/kvm/ubuntu24-seed.qcow2'/> <source file='/srv/kvm/ubuntusrv-cloudimg.qcow2'/>Copy disk images to backup location:
cp /srv/kvm/ubuntu24-seed.qcow2 /srv/kvm/ubuntusrv-cloudimg.qcow2 \ /tmp/kvmbackupCreate archive:
tar -cf /tmp/ubuntu24.tar -C /tmp/kvmbackup .You have to copy this file to another server, before importing there.
7.2. Import
Section titled “7.2. Import”Important: Remove or rename VM on source host to avoid IP conflicts.
Copy archive to new host, then:
Create import directory:
mkdir /tmp/importExtract archive:
tar -xf /tmp/ubuntu24.tar -C /tmp/importCopy disk images to storage location:
sudo cp \ /tmp/import/ubuntu24-seed.qcow2 \ /tmp/import/ubuntusrv-cloudimg.qcow2 \ /srv/kvm/Define VM from XML:
virsh define /tmp/import/ubuntu24.xmlStart VM:
virsh start ubuntu24Note: If using different directory structure, edit XML file paths before defining.
8. libguestfs: VM Disk Management
Section titled “8. libguestfs: VM Disk Management”Tools for accessing and modifying VM disk images without starting the VM.
Documentation: libguestfs.org
8.1. Installation
Section titled “8.1. Installation”sudo apt updatesudo apt-get --yes install libguestfs-tools8.2. Mounting VM’s Disks
Section titled “8.2. Mounting VM’s Disks”Mount VM disk read-only (safer):
sudo guestmount -d ubuntu24 -i --ro /mntMount with write access (use with caution - VM must be shut down):
sudo guestmount -d ubuntu24 -i /mntUnmount:
sudo guestunmount /mntDetails for guestmount and guestunmount commands:
guestmount --helpguestunmount --help8.3. Common libguestfs Commands
Section titled “8.3. Common libguestfs Commands”- guestfish: Interactive shell for disk manipulation
- guestmount: Mount guest filesystem on host
- guestunmount: Unmount guest filesystem
- virt-cat: Display file from VM
- virt-copy-in: Copy files into VM
- virt-copy-out: Copy files from VM
- virt-edit: Edit file in VM
- virt-ls: List files in VM
- virt-df: Show disk usage
- virt-filesystems: List filesystems and partitions
- virt-inspector: Inspect VM image contents
- virt-resize: Resize disk partitions
- virt-sparsify: Make VM disks sparse (thin-provisioned)
- virt-sysprep: Prepare VM for cloning
Example: Copy file from VM:
sudo virt-copy-out -d ubuntu24 /etc/hostname /tmp/Example: List files in VM:
sudo virt-ls -d ubuntu24 /etc/Security Note: These tools allow host administrators to access VM data without VM knowledge—consider encryption for sensitive VMs.