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