virt-install Command in Linux: Create KVM VMs from the CLI

Tested on Rocky Linux 10.2 (Red Quartz)
Package virt-install 5.1.0
libvirt 11.10.0
qemu-kvm 10.1.0
Applies to RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Ubuntu, Debian
Privilege sudo or root
Man page virt-install(1)
Scope Provision KVM guests from ISO, HTTP install trees, PXE, or imported disks — CPU, memory, storage, networking, console, and autostart options.
Related guides Install KVM on RHEL/CentOS 8
Create KVM VM with Cockpit
KVM PXE netboot
Create KVM VM with Virtual Manager
Linux commands

virt-install — quick reference

Guest sizing and identity

When to use Command
Set guest name (must be unique on the host) virt-install --name VMNAME ...
Allocate RAM in MiB virt-install --memory 4096 ...
Set vCPU count virt-install --vcpus 4 ...
Pick OS profile for defaults virt-install --osinfo rocky10 ...
Connect to system libvirt (KVM default) virt-install --connect qemu:///system ...

Install media

When to use Command
Install from local ISO virt-install --cdrom /path/to.iso ...
Install from distro tree or mirror URL virt-install --location http://mirror/... ...
Boot from PXE (network must reach DHCP/TFTP/iPXE) virt-install --pxe --network bridge=br0 ...
Skip install — boot an existing disk image virt-install --import --disk path=/path/to.img ...
Install using the URL and defaults from a libosinfo profile virt-install --install rocky10 ...

Storage

When to use Command
Create a qcow2 disk in the default pool virt-install --disk size=20 ...
Create a volume in a custom libvirt pool virt-install --disk pool=vm-disks,size=40,format=qcow2 ...
Custom path, size, and format virt-install --disk path=/disks/vm.qcow2,size=20,format=qcow2 ...
Attach multiple disks virt-install --disk size=20 --disk path=/disks/data.qcow2,size=50 ...

Network

When to use Command
Attach the libvirt default NAT network virt-install --network network=default ...
Bridge to a host bridge virt-install --network bridge=br0 ...
Add a second NIC virt-install --network network=default --network bridge=br0 ...

Console and graphics

When to use Command
Enable a graphical VNC console virt-install --graphics vnc ...
Headless serial console only virt-install --graphics none --console pty,target_type=serial ...
Detach from the console and return quickly virt-install --noautoconsole ...
Keep a detached install alive through reboot virt-install --noautoconsole --wait -1 ...
Pass kernel args (with --location) virt-install --extra-args "console=ttyS0" ...

Post-install behavior

When to use Command
Mark the guest to start on host boot virt-install --autostart ...
Preview domain XML without defining the VM virt-install --dry-run --print-xml ...
Unattended OS install (distro-dependent) virt-install --unattended ...

virt-install — command syntax

virt-install creates guests through libvirt. On a KVM host you normally target the system hypervisor with --connect qemu:///system. Synopsis from virt-install --help on Rocky Linux 10.2 (virt-install 5.1.0):

text
virt-install OPTIONS

Create a new virtual machine from specified install media.

General Options:
  -n NAME, --name NAME  Name of the guest instance
  --memory MEMORY       Configure guest memory allocation (MiB)
  --vcpus VCPUS         Number of vCPUs to configure
  --cpu CPU             CPU model and features

Installation Method Options:
  --cdrom CDROM         CD-ROM installation media
  -l LOCATION, --location LOCATION
                        Distro install URL or local tree
  --pxe                 Boot from the network using PXE
  --import              Build guest around an existing disk image
  --install INSTALL     Specify fine grained install options

Minimum inputs for a manual install are typically --memory, guest storage (--disk or --filesystem), an install method (--cdrom, --location, --pxe, --import, or --install), and --osinfo when detection cannot run. The graphics default is adaptive — virt-install may choose SPICE, VNC, or no graphics depending on environment; pass --graphics vnc explicitly when you need VNC. Install and enable KVM on the host before running these examples.


virt-install — command examples

Essential Check version and list OS profiles

Confirm virt-install is installed and see which --osinfo values libosinfo knows on your host.

Run the command:

bash
virt-install --version

Sample output:

output
5.1.0

List short OS IDs you can pass to --osinfo:

bash
virt-install --osinfo list | head -8

Sample output:

output
almalinux10
almalinux9
almalinux8
almalinux-kitten10
alpinelinux3.23
alpinelinux3.22
alpinelinux3.21
alpinelinux3.20

Use osinfo-query os for the full table with distro names and versions.

Essential List libvirt networks before attaching one

virt-install references network names defined in libvirt — usually default on a fresh KVM host.

Run the command:

bash
virsh net-list --all

Sample output:

output
Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes

Pass network=default to attach the NAT network, or bridge=br0 when the guest should share a host bridge.

If default is missing or inactive on RHEL-family hosts:

bash
sudo virsh net-autostart default
sudo virsh net-start default

When the network does not exist, verify or reinstall libvirt-daemon-config-network.

Essential Preview domain XML with --dry-run

--dry-run --print-xml validates options and prints libvirt XML without defining the guest. Include the same install method (--cdrom, --location, --pxe, --import, or --install) you plan to use — --dry-run skips changes but still runs normal validation. With --location, virt-install may fetch installation metadata or boot files for OS detection.

Run the command:

bash
virt-install --connect qemu:///system \
  --dry-run --print-xml \
  --name demo-test \
  --memory 2048 --vcpus 2 \
  --osinfo rocky10 \
  --location https://download.rockylinux.org/pub/rocky/10/BaseOS/x86_64/os/ \
  --disk size=5,format=qcow2 \
  --network network=default \
  --graphics vnc \
  --noautoconsole

Sample output:

output
<domain type="kvm">
  <name>demo-test</name>
  <memory>2097152</memory>
  <vcpu>2</vcpu>
  <os>
    <type arch="x86_64" machine="q35">hvm</type>
  </os>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2" discard="unmap"/>
      <source file="/var/lib/libvirt/images/demo-test.qcow2"/>
      <target dev="vda" bus="virtio"/>
    </disk>

On a KVM-capable host the root element is normally <domain type="kvm">. If you see type="qemu", the host is falling back to software emulation — enable hardware virtualization in firmware and confirm the kvm module is loaded.

If the default storage pool is too small, shrink --disk size= or free space under /var/lib/libvirt/images/.

Common Install from a local ISO with VNC graphics

Match --osinfo to the OS on the ISO — Rocky media needs rocky10, not an RHEL profile. Linux paths are case-sensitive; use the exact filename on your host.

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name rocky10-guest \
  --memory 4096 --vcpus 2 \
  --osinfo rocky10 \
  --cdrom /var/isos/Rocky-10.2-x86_64-dvd.iso \
  --disk size=20,format=qcow2 \
  --network network=default \
  --graphics vnc \
  --console pty,target_type=serial

VNC commonly listens on 127.0.0.1 only. Find the display with virsh vncdisplay rocky10-guest, then connect through local virt-viewer, an SSH tunnel, or a libvirt connection over SSH — you do not need to expose VNC publicly. --cdrom boots the ISO; use --location when virt-install should fetch kernel/initrd and start the installer automatically.

Common Install from an HTTP mirror with --location

--location points at a distro install tree. virt-install pulls vmlinuz and initrd, then hands off to the network installer.

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name rocky10-netinst \
  --memory 2048 --vcpus 2 \
  --osinfo rocky10 \
  --location https://download.rockylinux.org/pub/rocky/10/BaseOS/x86_64/os/ \
  --disk size=10 \
  --network network=default \
  --graphics vnc --noautoconsole

Use a mirror URL that matches your architecture. For kickstart, point inst.ks= at an HTTP, HTTPS, NFS, or other installer-accessible URL:

bash
--extra-args "inst.ks=https://server.example.com/kickstart/rocky10.cfg"

Or inject a host-local file into the installer initrd:

bash
--initrd-inject /path/to/rocky10.cfg \
--extra-args "inst.ks=file:/rocky10.cfg"

Confirm the profile exists locally with virt-install --osinfo list before using --install rocky10 — an older osinfo database can lack newer distributions even when virt-install supports --install.

Common Place disks in a libvirt storage pool

RHEL-family hosts recommend file-backed disks as volumes in a directory storage pool. /var/lib/libvirt/images is labeled for libvirt by default; custom paths need equivalent SELinux/sVirt handling — changing ownership to qemu alone may not fix access.

Define a pool, then reference it from virt-install:

bash
sudo mkdir -p /disks
sudo virsh pool-define-as vm-disks dir --target /disks
sudo virsh pool-start vm-disks
sudo virsh pool-autostart vm-disks

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name app-vm \
  --memory 8192 --vcpus 4 \
  --osinfo rocky10 \
  --cdrom /var/isos/Rocky-10.2-x86_64-dvd.iso \
  --disk pool=vm-disks,size=40,format=qcow2 \
  --network bridge=br0 \
  --graphics vnc --autostart

--autostart marks the persistent domain to start automatically during host boot. When you must use a raw path=, verify parent-directory traversal, libvirt/QEMU permissions, and SELinux contexts — not just Unix ownership.

Common Attach multiple network interfaces

Repeat --network for each NIC. Mix NAT and bridged attachments when the guest needs management and data-plane separation.

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name dual-nic-vm \
  --memory 4096 --vcpus 2 \
  --osinfo rocky10 \
  --location https://download.rockylinux.org/pub/rocky/10/BaseOS/x86_64/os/ \
  --disk size=20 \
  --network network=default \
  --network bridge=br0 \
  --graphics vnc --console pty,target_type=serial

List host bridges with ip link show type bridge before choosing bridge=.

Advanced Detach after kickoff with --noautoconsole

When you launch from SSH, --noautoconsole returns control immediately. Finish the install through VNC or virsh console.

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name headless-install \
  --memory 2048 --vcpus 2 \
  --osinfo rocky10 \
  --location https://download.rockylinux.org/pub/rocky/10/BaseOS/x86_64/os/ \
  --disk size=10 \
  --network network=default \
  --graphics none \
  --console pty,target_type=serial \
  --extra-args "console=ttyS0" \
  --noautoconsole

Sample output:

output
Domain installation still in progress. You can reconnect to
the console to complete the installation process.

Reconnect with virsh console headless-install. Press Ctrl+] to leave the serial session.

--noautoconsole detaches virt-install from the console and normally lets the command exit quickly. For a multi-stage --location or --cdrom install, the guest may be left shut off when installation completes. Start it with virsh start headless-install, or add --wait -1 when you want virt-install to remain running through the post-install reboot.

Advanced Import an existing disk image with --import

Skip the installer when you already have a configured bootable disk image or clone — not a generic cloud image that still needs cloud-init credentials.

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name imported-vm \
  --memory 2048 --vcpus 2 \
  --import \
  --disk path=/var/lib/libvirt/images/existing.qcow2,format=qcow2 \
  --osinfo rocky10 \
  --network network=default \
  --graphics vnc --noautoconsole

The disk file must exist before you run the command. The new domain name must be unique — no virsh undefine is required when importing under a different name. When reusing an existing domain name, shut down and undefine that domain deliberately, and confirm whether its storage or UEFI NVRAM must be retained.

For cloud images that ship without a local login, add --cloud-init (optionally with root-ssh-key=, clouduser-ssh-key=, or user-data=). Plain --cloud-init creates temporary NoCloud metadata, generates a root password, prints it, and disables cloud-init after the first boot.

Advanced Network install with --pxe

--pxe configures network boot for the first boot only. The selected network must reach DHCP, TFTP/iPXE, and boot configuration — use a host bridge when your PXE server lives on the physical LAN. inst.ks= belongs in the PXE boot entry the server serves, not in --extra-args (that flag is for --location installs).

Run the command:

bash
sudo virt-install --connect qemu:///system \
  --name pxe-guest \
  --memory 4096 --vcpus 2 \
  --osinfo rocky10 \
  --pxe \
  --disk size=20 \
  --network bridge=br0 \
  --graphics vnc \
  --console pty,target_type=serial

Use network=default only when that libvirt network is configured to provide or forward PXE services. See KVM PXE netboot for the full server setup.


virt-install — when to use / when not

Use virt-install when Use something else when
You need a scriptable, repeatable VM create from SSH You prefer a GUI — Cockpit or virt-manager
You automate installs with kickstart, cloud-init, or --unattended You only need to start/stop existing guests — virsh
You want explicit control over every disk, NIC, and console flag in one command You manage VMs at scale with oVirt, OpenStack, or a cloud API
You provision from ISO, HTTP tree, or PXE in one step The host does not have KVM/libvirt installed yet — install the stack first

virt-install vs Cockpit / virt-manager

virt-install Cockpit / virt-manager
Interface CLI flags and scripts Web UI or desktop GUI
Automation Easy in shell, Ansible, CI Manual clicks; limited scripting
Preview --dry-run --print-xml Visual wizard
Learning curve Must know libvirt options Discover options in forms
Typical use Servers, kickstart farms, docs-as-code Ad-hoc lab VMs

Many teams use virt-install (or virt-install --install DISTRO) in scripts and fall back to Cockpit for one-off troubleshooting.


virt-install — interview corner

What does virt-install do?

virt-install is the libvirt CLI tool that creates new virtual machines — it defines CPU, memory, disks, networks, and install media, then either launches an interactive installer or imports an existing disk.

A strong answer is:

"virt-install talks to libvirt to define a KVM guest and attach install media — ISO, URL, PXE, or an imported disk — with the console and storage layout I specify."

What is the difference between --cdrom and --location?
Flag Behavior
--cdrom /path/to.iso Attaches ISO as virtual CD — guest boots installer media
--location URL or path Fetches kernel/initrd from an install tree and often starts the installer automatically

Use --location for HTTP/FTP mirrors; use --cdrom for a single ISO file on disk.

A strong answer is:

"--cdrom mounts an ISO; --location points at a distro tree and virt-install pulls boot files — better for network-based installs."

Why use --osinfo?

--osinfo (formerly --os-variant) selects a libosinfo profile so virt-install picks sensible defaults: chipset, disk bus, clock, and supported install methods for that OS.

Run virt-install --osinfo list or osinfo-query os on the host to see valid IDs.

A strong answer is:

"--osinfo tells virt-install which OS I'm installing so it applies the right virtio defaults and avoids misconfigured guests."

When would you use --noautoconsole?

Use --noautoconsole when you start a long install over SSH and do not want virt-install to hold the terminal until the installer finishes. You reconnect with VNC (virsh vncdisplay VMNAME) or virsh console.

For multi-stage --cdrom or --location installs, the guest may shut off when installation completes unless you add --wait -1 to keep virt-install running through the post-install reboot.

Pair with --graphics vnc for graphical installs, or --graphics none --extra-args "console=ttyS0" for serial-only.

A strong answer is:

"--noautoconsole returns the shell quickly; I finish through VNC or virsh console, and I use --wait -1 when I need virt-install to survive the install-to-reboot transition."

How do you validate a virt-install command before creating a VM?

Run the same flags with --dry-run and --print-xml, including the install method (--cdrom, --location, --pxe, --import, or --install). virt-install may still fetch metadata for --location installs even in dry-run mode.

A strong answer is:

"I dry-run with --print-xml and the same install source to verify disks, networks, and OS profile before defining the guest."


Troubleshooting

Symptom Likely cause Fix
failed to connect to the hypervisor Modular libvirt sockets not running, insufficient privileges, or wrong URI (EL10) Start virt*d sockets: for drv in qemu network nodedev nwfilter secret storage interface; do sudo systemctl start virt${drv}d{,-ro,-admin}.socket; done; verify virsh -c qemu:///system list --all; confirm root or libvirt group access
Same error on older distributions Monolithic libvirt service stopped sudo systemctl start libvirtd on releases that still use libvirtd.service; use --connect qemu:///system
cannot find network: default Default libvirt network missing or inactive sudo virsh net-autostart default; sudo virsh net-start default; verify libvirt-daemon-config-network
KVM acceleration not available CPU virtualization off or nested virt missing Enable VT-x/AMD-V in firmware; load kvm module
exceed the available pool space Default pool too small for --disk size= Free space under /var/lib/libvirt/images/ or use a larger storage pool
Validating install media ... failed Wrong ISO/tree path Fix path; for trees use --location, for ISO use --cdrom
Stuck at Escape character is ^] --graphics none without serial console setup Add --console pty,target_type=serial and --extra-args "console=ttyS0", or use --graphics vnc
Active console session exists Another virsh console still attached Exit with Ctrl+] or close the other session
OS detection failed Missing or unknown install media Set --osinfo NAME explicitly from virt-install --osinfo list
Guest not autostarting on host reboot --autostart not set virsh autostart VMNAME or recreate with --autostart
<domain type="qemu"> in XML preview Software emulation fallback Enable KVM in firmware; confirm /dev/kvm and kvm module on the host

References

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)