RudderVirt

#Windows from an ISO

Windows builds are the hardest case. There are four moving pieces:

  1. Autounattend.xml on a virtual floppy — Windows Setup looks for Autounattend.xml on attached floppies during install and runs an unattended setup if found.
  2. Virtio drivers on the same floppy — Windows Setup needs vioscsi (SCSI) and netkvm (network) to see the disk and the network. They're loaded via the unattend's <DriverPaths> section.
  3. An OpenSSH bootstrap script — runs on first logon to install OpenSSH so the build can SSH in afterward.
  4. A boot command — types a few Enters to dismiss "Press any key to boot from CD".
sequenceDiagram participant Aileron participant VM as Windows VM Aileron->>VM: power on (boot from ISO) Aileron->>VM: bootCommand <enter> VM->>VM: Setup reads Autounattend.xml from floppy VM->>VM: loads vioscsi and netkvm drivers from floppy VM->>VM: partitions disk and installs OS VM->>VM: reboots VM->>VM: first logon as autologon user VM->>VM: runs configure-openssh.ps1 VM->>Aileron: SSH ready Aileron->>VM: runs provisioners

#The Autounattend.xml essentials

The Autounattend XML is large but standardized. Key sections you'll customize:

  • <settings pass="windowsPE">
    • <DriverPaths> — tells Setup where to find virtio drivers (point at the floppy: %configsetroot%\).
    • <DiskConfiguration> and <ImageInstall> — partition layout and which Windows edition to install.
    • <UserData> — accept EULA, optional product key.
  • <settings pass="oobeSystem">
    • <AutoLogon> — automatic first-boot login as a known user.
    • <UserAccounts> — local admin accounts.
    • <FirstLogonCommands> — runs the OpenSSH installer.
  • <settings pass="specialize"> — computer name, timezone.

A complete working sample lives in this repo at Autounattend.xml. Copy it, then search for YOUR and replace every occurrence before using the file. The placeholders are:

  • YOURCOMPUTERNAME — the VM's hostname.
  • YOURUSERNAME — the registered owner string shown in winver and similar metadata.
  • YOURUSER — the local administrator account name created during setup.
  • YOURPASSWORD — the local administrator account password (also used for autologon).

Tailor the rest to match your Windows version (10, 11, Server 2022, etc.).

#Files you need

files:
    # Unattend that drives Setup. Paste the full sample from
    # /docs/building/recipes/Autounattend and replace each YOUR* placeholder.
    - name: Autounattend.xml
      inline: |
          <?xml version="1.0" encoding="utf-8"?>
          <unattend ...>
            ...
          </unattend>

    # Bootstrap script: runs on first logon, installs OpenSSH
    - name: configure-openssh.ps1
      inline: |
          iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
          choco install openssh --pre -y
          . "C:\Program Files\OpenSSH-Win64\install-sshd.ps1"
          New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
          Set-Service SSHD -StartupType Automatic
          Start-Service SSHD

    # Virtio network driver (netkvm)
    - name: netkvm.inf
      url: https://example.com/virtio/netkvm.inf
    - name: netkvm.sys
      url: https://example.com/virtio/netkvm.sys
    - name: netkvm.cat
      url: https://example.com/virtio/netkvm.cat

    # Virtio SCSI driver (vioscsi)
    - name: vioscsi.inf
      url: https://example.com/virtio/vioscsi.inf
    - name: vioscsi.sys
      url: https://example.com/virtio/vioscsi.sys
    - name: vioscsi.cat
      url: https://example.com/virtio/vioscsi.cat

You need the .inf, .sys, and .cat for each driver you want loaded during install. The Fedora project publishes signed virtio-win drivers; you can download a virtio-win ISO and host the files yourself.

#The VM block

vms:
    - name: builder
      source:
          blank: true
      resources:
          cpu: 4
          memory: '8Gi' # Windows Setup is RAM-hungry
      disks:
          - name: rootdisk
            size: '25Gi'
            bus: scsi # matches vioscsi driver
      efiFirmware:
          secureBoot: false # Windows 11 needs UEFI
      isos:
          - url: 'https://example.com/Windows11.iso'
            checksum: 'f260e50bf9...'
      floppy:
          files:
              - name: Autounattend.xml
              - name: configure-openssh.ps1
              - name: netkvm.inf
              - name: netkvm.sys
              - name: netkvm.cat
              - name: vioscsi.inf
              - name: vioscsi.sys
              - name: vioscsi.cat
      communicator:
          shell: powershell
          sshUsername: skills # match the local admin in Autounattend.xml
          sshPassword: skills
          sshTimeout: '8h' # Windows Setup is slow
      bootCommand:
          - '<enter>' # dismiss "Press any key to boot from CD"

#Suggested provisioner order

flowchart TB A[install-updates<br/>type: windows-update] --> B[install-guest-tools<br/>type: shell - choco installs etc] B --> C[reboot] C --> D[upload certs and binaries<br/>type: file] D --> E[configure-system<br/>type: shell - registry, services] E --> F[reboot] F --> G[final-cleanup<br/>type: shell - sdelete, optimize-volume] G --> H[reboot-final]
provisioners:
    - name: install-updates
      type: windows-update
      windowsUpdate:
          searchCriteria: 'BrowseOnly=0 and IsInstalled=0'
          filters:
              - "exclude:$_.Title -like '*Preview*'"
              - 'include:$true'

    - name: install-guest-tools
      type: shell
      shell:
          inline: |
              choco install sdelete -y --ignore-checksums
              choco install autohotkey.portable -y

    - type: reboot

    - name: configure-system
      type: shell
      shell:
          inline: |
              Rename-Computer "MYHOST"
              Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
              powercfg -h off

    - type: reboot

    - name: compact
      type: shell
      shell:
          inline: |
              Optimize-Volume -DriveLetter C -ReTrim -Verbose

#Windows-specific gotchas

  • Always start with NIC model: e1000 (the default). Windows Setup doesn't have virtio at first boot. Once netkvm is installed and a reboot has happened, you can switch the model.
  • Use bus: scsi for the disk, paired with the vioscsi driver. virtio is faster but the install-time driver loading is fiddlier.
  • efiFirmware.secureBoot: false is required for most automated installs. Windows 11 strictly requires UEFI but Secure Boot can be enabled later.
  • File destinations use C:\\... (double backslash in YAML strings).
  • sshTimeout should be measured in hours for fresh ISO installs. Windows Setup + first updates can take 1–2 hours before SSH is reachable.
  • ssh_authorized_keys: [] doesn't apply — Windows uses a different key injection path. The build handles this for you as long as configure-openssh.ps1 is wired into Autounattend's <FirstLogonCommands>.