Skip to main content
RunBook Academy

Proxmox VEXXVI · Windows GuestsGetting Windows onto the hypervisor

VirtIO drivers, the guest agent and the balloon service

Intermediate⏱ ~35 minqmvirtio-win ISO

What you'll learn

  • Enumerate the components on the virtio-win ISO and the PVE device each one drives
  • Install the driver set, the QEMU guest agent and the balloon service by the correct mechanism for each
  • Explain why the balloon service is a separate installation step from the balloon driver
  • Diagnose a half-installed driver set from the host, without a console session
  • Decide what a missing component actually costs before scheduling a reboot to fix it

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

“Install the VirtIO drivers” is one instruction in every Windows-on-Proxmox guide, and it hides three separate installations with three separate mechanisms, three separate failure symptoms, and one of them not being a driver at all.

That is why the most common state of a Windows guest in a real estate is not “drivers installed” or “drivers missing”. It is partly done — storage on VirtIO because setup demanded it, network on VirtIO because someone noticed the NIC was slow, no guest agent, no balloon service, and a Proxmox summary page reporting memory figures that nobody trusts.

This lesson makes that state diagnosable.

What is actually on the ISO

The virtio-win ISO is organised by component, then by Windows version, then by architecture. The Proxmox wiki names the directories you will meet: Balloon, NetKVM, vioscsi, QXL and guest-agent, each containing subdirectories per Windows release — w10, 2k19, 2k22, 2k25 and older — and an amd64 directory inside those.

The components that matter operationally, and the PVE configuration that creates the device each one claims:

ComponentDirectoryDevice it drivesCreated bySymptom when missing
VirtIO SCSIvioscsiRed Hat VirtIO SCSI pass-through controllerscsihw: virtio-scsi-singleDisks do not enumerate at all; setup shows no drives
VirtIO BlockviostorRed Hat VirtIO block devicea disk on the virtio0 busSame, for the older block transport
NetworkNetKVMRedhat VirtIO Ethernet Adapternet0: virtio,...No NIC; an unknown Ethernet controller in Device Manager
BalloonBalloonVirtIO Balloon Driverpresent unless balloon: 0Unknown PCI device; no memory reclaim
SerialvioserialVirtIO Serial Driveragent: enabled=1Guest agent installs but never answers
DisplayQXLQXL videovga: qxlBasic display adapter, low resolutions
Guest agentguest-agentnot a driver — a serviceagent: enabled=1qm agent ping times out

Two rows in that table are the ones people skip, and they are the two that are not drivers you can see failing. vioserial is invisible because nothing looks broken without it; guest-agent is invisible because it is a service, not a device, so Device Manager has nothing to complain about.

The three mechanisms

One: the driver bundle

The wiki gives the straightforward path: execute virtio-win-gt-x64 from the CD-ROM and follow the prompts, then reboot. The same content is available as a downloadable virtio-win-gt-x64.msi (or virtio-win-gt-x86.msi for 32-bit) if you would rather pull it inside the guest than mount the ISO.

The manual alternative is per-driver: navigate to the directory matching your Windows version, right-click the Setup Information file, choose Install, repeat for each driver, reboot. It exists for the cases where the bundle is not appropriate — a locked-down image, an unattended build that installs specific .inf files, or a guest where you deliberately want the storage and network drivers and nothing else.

Two: the guest agent

The agent is not in the driver bundle by default and it needs two things the bundle does not necessarily give it. The wiki is explicit about the order: download the VirtIO ISO, install the virtio-serial driver via Device Manager, then run the installer — qemu-ga-x86_64.msi for 64-bit or qemu-ga-i386.msi for 32-bit — from the mounted ISO. The service that results is named QEMU-GA.

There is also virtio-win-guest-tools, a wizard the wiki describes as optionally installing the QEMU Guest Agent and the SPICE agent alongside the drivers. On a fresh build that is the one-step path.

The third requirement is on the host, not in the guest: the VM must have the agent enabled, qm set VMID --agent 1. All three are required and each fails differently, which is what makes agent problems feel mysterious.

Three: the balloon service

This is the one that is genuinely a separate component, and the Proxmox wiki states it in one sentence:

You need to install the VirtIO Balloon Driver and the management service (blnsvr.exe -i).

Read that as two objects. The driver is a kernel-mode driver for the virtio-balloon PCI device; it is what allows the host to inflate and deflate the balloon and reclaim memory. The service is a user-mode Windows service that reports the guest memory statistics back through the same device.

Since virtio-win-0.1.173-2 the wiki notes that the ISO provides an installer at the root of the CD drive — virtio-win-gt-x64.msi — which can install the ballooning service for Windows Server 2012, Windows 8.1 and newer, so on a current guest the MSI usually covers it. On older guests, and on any guest where the driver went in by hand from Device Manager, the service does not exist until somebody runs blnsvr.exe -i from an elevated prompt.

Installing, in order

Run these inside the guest, from an elevated command prompt, with the VirtIO ISO mounted. Adjust the drive letter and the Windows version directory.

Configuration changeguest-side installation, PowerShell as Administrator
# 1. Drivers, plus the ballooning service on 2012/8.1 and newer
Start-Process msiexec.exe -Wait -ArgumentList '/i D:\virtio-win-gt-x64.msi /qn /norestart'

# 2. QEMU guest agent
Start-Process msiexec.exe -Wait -ArgumentList '/i D:\guest-agent\qemu-ga-x86_64.msi /qn /norestart'

# 3. Balloon service, if the MSI did not install it
Get-Service BlnSvr -ErrorAction SilentlyContinue

Restart-Computer

Then, on the host, make sure the VM side is enabled — this is configuration on the hypervisor and has no effect inside the guest until the agent is running:

Configuration changeenable the agent on the VM
VMID=9100
qm set "$VMID" --agent enabled=1,fstrim_cloned_disks=1
qm config "$VMID" | grep '^agent:'

fstrim_cloned_disks=1 asks the agent to run a filesystem trim after a disk move or a clone, which matters on thin-provisioned and ZFS-backed storage. Part IX covers the rest of the sub-options; the defaults are documented as enabled: 0, fstrim_cloned_disks: 0, freeze-fs: 1 and type: virtio.

Diagnosing a half-installed set from the host

This is the part worth keeping. You can determine most of a Windows guest driver state from the hypervisor, without a console session and without RDP, which means you can audit an estate rather than inspecting a machine.

Read-only / Safeprobe the agent
# qm agent 9100 ping && echo "agent responding"
agent responding

Illustrative output

qm agent is documented as an alias for qm guest cmd, and the allowed command set is fixed: ping, info, get-osinfo, get-host-name, get-time, get-timezone, get-users, get-vcpus, get-fsinfo, network-get-interfaces, get-memory-blocks, get-memory-block-info, fsfreeze-freeze, fsfreeze-thaw, fsfreeze-status, fstrim, shutdown, suspend-ram, suspend-disk and suspend-hybrid. Four of them answer driver questions.

Is the network driver bound and configured?

Read-only / Safethe guest view of its own interfaces
# qm agent 9100 network-get-interfaces
[
 {
    "hardware-address" : "bc:24:11:3a:00:1f",
    "ip-addresses" : [
       {
          "ip-address" : "192.0.2.51",
          "ip-address-type" : "ipv4",
          "prefix" : 24
       }
    ],
    "name" : "Ethernet",
    "statistics" : { "rx-bytes" : 918273645, "tx-bytes" : 273645918 }
 },
 {
    "hardware-address" : "00:00:00:00:00:00",
    "ip-addresses" : [
       {
          "ip-address" : "127.0.0.1",
          "ip-address-type" : "ipv4",
          "prefix" : 8
       }
    ],
    "name" : "Loopback Pseudo-Interface 1"
 }
]

Illustrative output

An interface named Ethernet carrying the MAC from net0 means NetKVM is bound. A guest that answers ping but returns only the loopback interface has an agent and no working NIC — which is a diagnosis, and a specific one.

What is the guest, and does it match what PVE thinks it is?

Read-only / Safeguest OS as reported by the guest itself
# qm agent 9100 get-osinfo
{
 "id" : "mswindows",
 "kernel-release" : "26100",
 "kernel-version" : "10.0",
 "machine" : "x86_64",
 "name" : "Microsoft Windows",
 "pretty-name" : "Windows Server 2025 Standard",
 "version" : "Microsoft Windows Server",
 "version-id" : "2025"
}

Illustrative output

Use this to audit ostype. A fleet-wide sweep that compares what each guest says it is against what its configuration claims will find the Server 2022 guest somebody created as ostype: other in 2024.

Is the clock right? qm agent VMID get-time returns nanoseconds since the epoch as the guest sees it. Compare it to the host. Lesson 6 explains what a drifting Windows clock costs; this is how you measure it cheaply across an estate.

Read-only / Safesweep every running VM for agent state
for VMID in $(qm list | awk '$3 == "running" { print $1 }'); do
if qm agent "$VMID" ping >/dev/null 2>&1; then
  NAME=$(qm agent "$VMID" get-osinfo 2>/dev/null | grep -o '"pretty-name" : "[^"]*"' | cut -d'"' -f4)
  printf '%-6s OK       %s\n' "$VMID" "${NAME:-unknown}"
else
  printf '%-6s NO-AGENT\n' "$VMID"
fi
done

Run that once against a real estate and the result is usually uncomfortable. It is also the first honest inventory of Windows guest tooling most estates have had.

Key takeaways

  • The virtio-win ISO carries drivers, a guest agent and a balloon service, and they install by three different mechanisms.
  • The balloon driver enables memory reclaim. The balloon service (blnsvr.exe -i) enables memory reporting. Without the service, the Proxmox GUI reports something close to the allocation, and the correct end state is that the GUI figure matches Windows Task Manager.
  • The guest agent needs three things: agent: enabled=1 on the VM, the virtio-serial driver in the guest, and the QEMU-GA service running. All three fail as the same timeout.
  • qm agent VMID network-get-interfaces, get-osinfo and get-time let you audit driver state, ostype correctness and clock drift across an estate from the host.
  • On an imported guest, remove the old hypervisor tooling first, install VirtIO drivers second, and change the NIC model third — with console access and the IP configuration written down.
  • Missing components have very different costs. The agent and the balloon service are the two usually worth a maintenance window.

Knowledge check

Knowledge check · 4 questions

  1. Q1. A Windows guest with 16 GiB assigned reports 15.8 GiB used on the Proxmox summary page, while Task Manager inside the guest shows 4 GiB. The balloon driver is present in Device Manager. What is the correct conclusion?

  2. Q2. qm agent 9100 ping times out on a Windows guest. Which of these are genuine possible causes? Select all that apply.

  3. Q3. A Windows guest imported from VMware boots fine on VirtIO storage but still has an e1000 NIC and VMware Tools installed. What is the correct order of operations?

  4. Q4. Installing only the VirtIO balloon driver, without the management service, means the host cannot reclaim memory from the guest at all.

Passing score: 75%. Answers are checked in this browser.