Skip to main content
Version: v4 (current)

Windows

Windows VMs on QEMU + KVM work very well provided that you have tailored your VM to match your needs. There are multiple possible combinations of images, hardware types, and installation methods that each have their own benefits and drawbacks.

Choosing an Image

Since Windows is proprietary software, downloading an ISO is not as straight-forward as with Linux.

  • Server and Enterprise

    Microsoft makes evaluation copies of it's server and enterprise images available through their Evaluation Center. You will need to enter your contact details to obtain the image. These evaluation images are multi-edition and therefore do not easily work for automated installation.

  • Home and Pro

    You can also obtain an image for Windows 10 from Microsoft. This is another multi-edition image that cannot be easily automated due to the need to manually select the version to install during the setup process.

  • Alternative Sources for single-edition images

    For those who need a single-edition ISO which can be fully automated, it is easier to use 3rd party services such as https://uupdump.net/ to obtain the ISO image. There is a decent guide HERE on how to use the site.

  • Licenses

    Be aware that all of the images above are unlicensed and it is up to you to obtain a valid activation key for your installation. See this post on Reddit's /r/cheapwindowskeys for more information about how to acquire a license.

  • Rename your ISO file

Once you have download your ISO image, rename it to windows.iso for compatibility with the rest of the commands in this guide.

Choosing a disk type

There are two ways to create virtual disks covered in this guide: Virtio and SATA.

  • Virtio is more performant, but cannot be easily automated since the drivers must be manually installed before Windows setup can start.


  • SATA drivers are supported natively by Windows and can easily be used for fully automated installations. They are however, slower than Virtio drives.


    Testing performed using Qcow2 disk format, Windows 10 Pro Guest OS, and a Samsung 990 Pro SSD. For additional performance-tuning advice, see the article Improving the performance of a Windows Guest on KVM/QEMU.

Creating an Answer file

You can skip interactive steps of the Windows install process by using an answer-file. These are .xml config files which store system configuration data, similar to Cloud-Init or pre-seed on Linux. Answer files can only provide full-automation of the install process when using single-edition images. Multi-edition images will still require manual interaction to select a Windows version during setup.

  • You can use the website Windows Answer File Generator to easily create your own answer file.

    Example of a pre-made answer file for Windows 10 with an auto-login admin account:

    wget -O ./config/autounattend.xml https://raw.githubusercontent.com/small-hack/smol-metal/main/autounattend.xml
  • Answer files must be mounted in the root partition of the installation medium. That's usually a USB drive but since we are using a virtual machine we will use an ISO file instead.

    mkdir ./config
    mv $YOUR_ANSWER_FILE ./config/
    mkisofs -o config.iso -J -r config

VM Setup

  • Configure the Virtual Machine options

    # The name of the Virtual Machine
    export VM_NAME="gameci"

    # Number of physical CPU cores to allocate to the VM
    export PHYSICAL_CORES="2"

    # Number of threads per core.
    # Set this to `1` for CPUs that do not support hyper-threading
    export THREADS="1"
    export SMP=$(( $PHYSICAL_CORES * $THREADS ))

    # Amount of Disk Space to allocate to the VM.
    # Cannot exceed available on host.
    export DISK_SIZE="32G"

    # Amount of RAM to allocate to the VM.
    # Cannot exceed available RAM on host.
    export MEMORY="8G"

    # IP address where host may be reached. Do not use `localhost`.
    export HOST_ADDRESS="SOME IP HERE"

    # Port number to expose on the host for VNC
    export VNC_PORT="0"
  • Download virtual-disk drivers

    wget -O "virtio-drivers.iso" "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.240-1/virtio-win-0.1.240.iso"
  • Create the virtual disk

    qemu-img create -f qcow2 disk.qcow2 $DISK_SIZE

Creating the VM

Automated install With SATA Drive

  • Create new guest:

    sudo qemu-system-x86_64 \
    -machine accel=kvm,type=q35 \
    -cpu host,kvm="off",hv_vendor_id="null" \
    -smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
    -m "$MEMORY" \
    -drive id=disk0,if=none,cache=none,format=qcow2,file=disk.qcow2 \
    -device ahci,id=ahci -device ide-hd,drive=disk0,bus=ahci.0 \
    -drive file=windows.iso,index=0,media=cdrom \
    -drive file=virtio-drivers.iso,index=2,media=cdrom \
    -drive file=config.iso,index=1,media=cdrom \
    -bios /usr/share/ovmf/OVMF.fd \
    -usbdevice tablet \
    -serial stdio -vga virtio -parallel none \
    -device virtio-net-pci,netdev=network \
    -netdev user,id=network,hostfwd=tcp::3389-:3389 \
    -vnc "$HOST_ADDRESS":"$VNC_PORT"
  • Boot existing guest:

    sudo qemu-system-x86_64 \
    -machine accel=kvm,type=q35 \
    -cpu host,kvm="off",hv_vendor_id="null" \
    -smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
    -m "$MEMORY" \
    -drive id=disk0,if=none,cache=none,format=qcow2,file=disk.qcow2 \
    -device ahci,id=ahci -device ide-hd,drive=disk0,bus=ahci.0 \
    -bios /usr/share/ovmf/OVMF.fd \
    -usbdevice tablet \
    -serial stdio -vga virtio -parallel none \
    -device virtio-net-pci,netdev=network \
    -netdev user,id=network,hostfwd=tcp::3389-:3389 \
    -vnc "$HOST_ADDRESS":"$VNC_PORT"

Manual Install With Virtio Drive

  • Create new guest:

    sudo qemu-system-x86_64 \
    -machine accel=kvm,type=q35 \
    -cpu host,kvm="off",hv_vendor_id="null" \
    -smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
    -m "$MEMORY" \
    -object iothread,id=io \
    -device virtio-blk-pci,drive=disk,iothread=io \
    -drive if=none,id=disk,cache=none,format=qcow2,aio=threads,file=disk.qcow2 \
    -drive file=windows.iso,index=1,media=cdrom \
    -drive file=virtio-drivers.iso,index=2,media=cdrom \
    -boot menu=on \
    -bios /usr/share/ovmf/OVMF.fd \
    -usbdevice tablet \
    -serial stdio -vga virtio -parallel none \
    -device virtio-net-pci,netdev=network \
    -netdev user,id=network,hostfwd=tcp::3389-:3389 \
    -vnc "$HOST_ADDRESS":"$VNC_PORT"
  • Boot existing guest:

    sudo qemu-system-x86_64 \
    -machine accel=kvm,type=q35 \
    -cpu host,kvm="off",hv_vendor_id="null" \
    -smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
    -m "$MEMORY" \
    -object iothread,id=io \
    -device virtio-blk-pci,drive=disk,iothread=io \
    -drive if=none,id=disk,cache=none,format=qcow2,aio=threads,file=disk.qcow2 \
    -drive file=virtio-drivers.iso,index=2,media=cdrom \
    -boot menu=on \
    -serial none \
    -parallel none \
    -bios /usr/share/ovmf/OVMF.fd \
    -usbdevice tablet \
    -serial stdio -vga virtio -parallel none \
    -device virtio-net-pci,netdev=network \
    -netdev user,id=network,hostfwd=tcp::3389-:3389 \
    -vnc "$HOST_ADDRESS":"$VNC_PORT"

Boot from CD

  • Multi-edition images will prompt the user to 'Press any key to boot CD or DVD' as shown below. When you see this prompt, press enter.



  • Other ISO images may not present the 'Press Enter' prompt to the serial console, instead you will need to press enter after you see the following:



  • Connect to the VM using VNC

    In your VNC software use the address format $HOST_ADDRESS:$VNC_PORT to connect to the VM.



Install Windows Manually

  • Select 'Install now'



  • Set language and region



  • Product Key

    Enter your key or select "I don't have a product key" to skip.



  • Select Version

    Choose a windows version to install, using a 'Pro' version is advised.



  • Accept the EULA



  • Select 'Custom Install'



Install Drivers (Optional)

  • You should now see the disk selection screen without any available disk. This is because Windows cannot use the virtio disks without adding drivers during the installation process.



  • To install the required drivers, select the 'Load Driver' button, then select 'Browse' to open a file-explorer from which to choose the install media.



  • The drivers are located in disk drive 'E' which should be named 'virtio-win-[version]'



Viostor (Required)

  • Find and select the 'Viostor' directory, then choose the directory that corresponds to your operating system version. Choose the 'amd64' directory inside and click 'OK'.



    Click 'Next' on the following screen to install the driver.



NetKvm (Required)

  • Repeat the same process from above to find and install the NetKVM driver



Viogpudo (Optional)

  • This driver will add more screen resolution options to the VNC display. The installation process is the same as the previous drivers.



Format and Partition Disk

  • With the drivers installed, we are now able to format and partition our virtual disk. Select 'Drive 0' then click 'new'.



  • Select largest of the newly-created partitions, then click 'Next'.



  • The install process should now begin. From this point you may simply follow the directions on-screen. When the system reboots, allow the 'Press any key to boot from CD' prompt to time-out. This avoids restarting the setup process.



RDP