Run Hyper-V workloads on Windows runners with nested virtualization
Run Hyper-V workloads on Windows runners with nested virtualization
RunsOn can launch Windows x64 runners with nested virtualization enabled, which is useful when a workflow needs Hyper-V itself: Hyper-V isolated Windows containers, VM smoke tests, image tooling, or other virtualization-heavy checks.
The important part is the /nested-virt label on a nested-capable x64 instance family:
jobs:
windows-nested-virt:
runs-on: runs-on=${{ github.run_id }}/family=m8i.large/volume=100gb:gp3:750mbs:4000iops/image=windows25-full-x64/nested-virt
steps:
- name: Verify Hyper-V on Windows
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$computer = Get-CimInstance -ClassName Win32_ComputerSystem
if ($computer.HypervisorPresent -ne $true) {
throw "Expected HypervisorPresent=True"
}
foreach ($featureName in @("Hyper-V", "Hyper-V-PowerShell", "Containers")) {
$feature = Get-WindowsFeature -Name $featureName
if ($feature.InstallState -ne "Installed") {
throw "Expected $featureName to be installed, got $($feature.InstallState)"
}
}
Import-Module Hyper-V -ErrorAction Stop
docker run --rm --isolation=hyperv `
mcr.microsoft.com/windows/servercore:ltsc2025 `
cmd /c ver
$vmName = "runs-on-nested-virt-smoke-$([guid]::NewGuid().ToString('N').Substring(0,8))"
try {
New-VM -Name $vmName -Generation 2 -MemoryStartupBytes 512MB -NoVHD | Out-Null
Start-VM -Name $vmName -ErrorAction Stop | Out-Null
Start-Sleep -Seconds 5
$state = (Get-VM -Name $vmName).State
if ($state -ne "Running") {
throw "Expected nested VM to reach Running state, got $state"
}
}
finally {
if (Get-VM -Name $vmName -ErrorAction SilentlyContinue) {
Stop-VM -Name $vmName -TurnOff -Force -ErrorAction SilentlyContinue | Out-Null
Remove-VM -Name $vmName -Force -ErrorAction SilentlyContinue
}
}
A few notes:
- Use a Windows x64 image.
- Pick an instance family that supports nested virtualization.
m8i.largeis a good default for simple checks. - Nested virtualization is opt-in. Without
/nested-virt, the normal Windows launch template is used.
Last updated: April 28, 2026