Enabling Nested Virtualization for Container Machines: Requirements and Setup Guide
Container machines can expose a virtual /dev/kvm device to guests running on M3+ Apple Silicon with macOS 15+, but only when using a custom Linux kernel compiled with CONFIG_KVM=y.
The apple/container project supports nested virtualization, allowing workloads like QEMU or Docker-in-Docker to run their own VMs inside container machines. This capability requires specific hardware, host OS versions, and a custom kernel configuration that differs from the project's default minimal kernel.
Prerequisites for Nested Virtualization
Before enabling nested virtualization, you must satisfy three hard requirements enforced by the runtime checks in Sources/ContainerCommands/Machine/MachineCapabilities.swift.
Hardware and Operating System Requirements
Nested virtualization requires M3 or newer Apple Silicon and macOS 15 or later. According to the source code in Sources/ContainerCommands/Machine/MachineCapabilities.swift, the requireNestedVirtualizationSupported() function validates that the host hardware exposes the necessary virtualization extensions (VMX equivalents) and that the operating system provides the required hypervisor framework APIs. These APIs were opened to third-party developers starting with macOS 15 on M3 silicon.
If you attempt to enable virtualization on unsupported hardware or older macOS versions, the CLI aborts with the error:
Error: unsupported: "nested virtualization is not supported on the platform"
Kernel Configuration Requirements
The container machine must run a custom Linux kernel built with CONFIG_KVM=y. The default kernel shipped with the project intentionally omits KVM support to minimize image size. Without this compile-time option, the Linux kernel cannot create /dev/kvm, and the device will not appear inside the container machine regardless of host capabilities.
As documented in docs/container-machine.md, you must supply your own kernel binary (for example, a distribution kernel or a custom-built vmlinux) that includes the KVM subsystem.
How to Create a Container Machine with Nested Virtualization
Use the --virtualization flag combined with the --kernel option when creating a new machine. The flag implementation in Sources/ContainerCommands/Machine/MachineCreate.swift invokes the platform checks before provisioning the virtual device.
Create a machine with a KVM-enabled kernel:
# Obtain or build a Linux kernel with CONFIG_KVM=y (e.g., vmlinux-kvm)
container machine create \
--virtualization \
--kernel /path/to/vmlinux-kvm \
--name kvm-dev \
alpine:latest
Verify that /dev/kvm exists inside the machine:
container machine run -n kvm-dev -- ls -l /dev/kvm
You should see output similar to:
crw-rw---- 1 root kvm 10, 232 Jan 1 00:00 /dev/kvm
Enabling Virtualization on an Existing Machine
To enable nested virtualization on a machine that was created without it, update the configuration and restart:
container machine set -n kvm-dev virtualization=true kernel=/path/to/vmlinux-kvm
container machine stop kvm-dev
container machine start kvm-dev
container machine run -n kvm-dev -- ls -l /dev/kvm
How to Disable Nested Virtualization
To revert to the default kernel and remove KVM access, unset the custom kernel path:
container machine set -n kvm-dev kernel=
container machine stop kvm-dev
container machine start kvm-dev
After the machine restarts, the /dev/kvm device will no longer exist inside the container, and workloads will not be able to spawn nested VMs.
Summary
- Nested virtualization in
apple/containerexposes/dev/kvmto container machine guests, enabling workloads like QEMU or Docker-in-Docker. - Hard requirements include M3+ Apple Silicon, macOS 15+, and a custom kernel compiled with
CONFIG_KVM=y. - Default kernel limitation: The project's minimal kernel excludes KVM support; you must provide a custom
vmlinuxbinary via the--kernelflag. - CLI control: Use
container machine create --virtualization --kernelfor new machines orcontainer machine setto modify existing machines, with changes applying after the next boot. - Validation: The runtime enforces platform checks in
MachineCapabilities.swift, returning an explicit error if requirements are not met.
Frequently Asked Questions
Why doesn't the default kernel support KVM?
The default kernel shipped with apple/container is built as a minimal image to reduce size and attack surface. According to the project documentation in docs/container-machine.md, this kernel explicitly omits CONFIG_KVM and many device drivers. Users requiring nested virtualization must compile their own kernel or obtain one from a Linux distribution that includes KVM support.
Can I enable nested virtualization on M1 or M2 Macs?
No. The hardware-assisted virtualization extensions required to expose /dev/kvm to guests are only available on M3 or newer Apple Silicon. The runtime check in Sources/ContainerCommands/Machine/MachineCapabilities.swift specifically validates the CPU generation and will reject the request on M1 or M2 systems with the "nested virtualization is not supported on the platform" error.
What happens if I try to enable virtualization without meeting the requirements?
The CLI performs validation before creating or modifying the machine. If your hardware is older than M3, your macOS version is below 15, or you omit the --kernel flag, the command aborts immediately. The error originates from MachineCapabilities.requireNestedVirtualizationSupported() in Sources/ContainerCommands/Machine/MachineCapabilities.swift.
How do I verify my custom kernel has KVM support?
Check that your kernel configuration includes CONFIG_KVM=y. You can verify this by running zcat /proc/config.gz | grep CONFIG_KVM inside a system running the kernel, or by inspecting the kernel build configuration. When the container machine boots with this kernel, verify functionality by running ls -l /dev/kvm inside the machine—successful configuration shows the device node with root:kvm ownership.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →