Nested virtualization
When to use Linux KVM or Windows Hyper-V inside RunsOn runners, and the EC2 constraints that matter.
Nested virtualization lets a CI runner start another virtual machine inside the EC2 instance. The common cases are Linux KVM workloads, Android emulator acceleration, VM-based integration tests, and Windows Hyper-V workloads.
Usage
Flex
On Linux, nested-virt exposes KVM to the job so VM-based tests and accelerated emulators can run:
jobs: kvm: runs-on: runs-on=${{ github.run_id }}/family=c8i.large/image=ubuntu24-full-x64/nested-virt steps: - name: Verify KVM run: | test -c /dev/kvm sudo apt-get update -qq sudo apt-get install -y cpu-checker sudo kvm-okOn Windows, the same idea enables Hyper-V features and Hyper-V-isolated containers:
jobs: hyperv: runs-on: runs-on=${{ github.run_id }}/family=m8i.large/image=windows25-full-x64/nested-virt steps: - shell: pwsh run: | Import-Module Hyper-V Get-WindowsFeature Hyper-V,Hyper-V-PowerShell,Containers $Image = "mcr.microsoft.com/windows/nanoserver:ltsc2025" docker run --isolation=hyperv $Image cmd /c verSee nested-virt and Windows runners for full Flex syntax.
Fleet
For Fleet, nested virtualization is configured in Terraform. On a current stack the nested-enabled launch templates already exist, so you only mark the runner definitions that should launch with nested virtualization:
... runners = { deploy-nested-virt = { family = ["m8i.large"] image = "windows25-full-x64" nested-virt = true } }See Runner fleets for the full runner-catalog configuration.
Constraints
Nested virtualization is a host capability, not a package you can install after boot. The runner must launch on an EC2 family that supports it, and the stack must include the right launch templates.
Practical constraints:
- x64 only — arm64 EC2 families do not support nested virtualization;
- Linux uses KVM; Windows uses Hyper-V;
- supported EC2 families only ↗ — current x64 Nitro families that expose nested virtualization;
- requires a current RunsOn stack — existing stacks must be upgraded to include the nested-enabled launch templates before
nested-virtjobs can run, otherwise the launch fails.
Flex vs Fleet
Same hardware requirement; the difference is who decides which jobs get the capability.
| Aspect | Flex | Fleet |
|---|---|---|
| How a job enables it | nested-virt job label | Target a runner fleet that the platform team has pre-approved for nested-virt |
| Per-workflow override | ✓ | — |
| Where the policy lives | Workflow author chooses at runtime | Terraform-owned runner fleet (family, image, IAM, network) |
| Supported families | Same x64 Nitro families | Same x64 Nitro families |
When not to use it
Do not enable nested virtualization for ordinary builds, tests, or Docker workloads. It narrows instance selection and can increase launch pressure if you also require a specific family, image, region, or Spot capacity pool.