How to Enable Nested Virtualization in Containers on Apple Silicon

To enable nested virtualization in containers on Apple Silicon, you must use an M3 or newer Mac running macOS 15 or later, and provide a custom Linux kernel compiled with CONFIG_KVM=y.

The apple/container project allows you to run Linux workloads on macOS through container machines. When you need to enable nested virtualization in containers to run additional hypervisors like QEMU or Docker-in-Docker, the system exposes a virtual /dev/kvm device to the guest, but this capability requires specific hardware, OS, and kernel configurations documented in docs/container-machine.md.

Prerequisites for Nested Virtualization

Nested virtualization in apple/container is gated by three strict requirements. If any condition is missing, the CLI aborts with an error: Error: unsupported: "nested virtualization is not supported on the platform".

Apple Silicon M3 or Newer

The host must be an M3 or newer Apple Silicon Mac. Earlier silicon generations (M1/M2) lack the necessary CPU extensions for hardware-assisted virtualization. According to the source code in Sources/ContainerCommands/Machine/MachineCapabilities.swift, the runtime check requireNestedVirtualizationSupported() validates the hardware capabilities before allowing the operation.

macOS 15 or Later

The host must run macOS 15 or later. Apple's hypervisor framework, which backs the virtual /dev/kvm device, only exposes the necessary APIs to third-party developers starting with this release. The implementation in Sources/ContainerCommands/Machine/MachineCreate.swift performs this version check when processing the --virtualization flag.

Custom Kernel with KVM Support

The container machine must use a Linux kernel built with CONFIG_KVM=y. The default kernel shipped with the project omits this flag to maintain a minimal footprint. You must compile or obtain a custom kernel binary that includes KVM support, as noted in the CLI reference documentation (docs/command-reference.md).

Creating a Container Machine with Nested Virtualization

To create a new machine with nested virtualization enabled, use the --virtualization flag and specify your custom kernel path with --kernel.


# Build or obtain 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 is present inside the machine:

container machine run -n kvm-dev -- ls -l /dev/kvm

Enabling Nested Virtualization on Existing Machines

You can enable nested virtualization on an existing machine using the set command. As implemented in Sources/ContainerCommands/Machine/MachineCreate.swift, changes to the virtualization settings require a machine stop and restart to take effect.

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

To disable nested virtualization and revert to the default kernel:

container machine set -n kvm-dev kernel=
container machine stop kvm-dev
container machine start kvm-dev
container machine run -n kvm-dev -- ls -l /dev/kvm  # /dev/kvm should not exist

How the Platform Validation Works

The apple/container source code enforces nested virtualization requirements through specific checks in Sources/ContainerCommands/Machine/MachineCapabilities.swift. The requireNestedVirtualizationSupported() function validates both the hardware generation (M3+) and the macOS version (15+) before the CLI accepts the --virtualization flag.

The --kernel parameter in Sources/ContainerCommands/Machine/MachineCreate.swift allows you to override the default kernel, but the system only attempts to expose /dev/kvm when the --virtualization flag is present and the platform checks pass.

Summary

  • Enable nested virtualization in containers requires an M3+ Mac running macOS 15+ and a custom kernel with CONFIG_KVM=y.
  • Use the --virtualization and --kernel flags with container machine create to provision new machines.
  • Use container machine set to modify existing machines, but you must stop and restart the machine for changes to apply.
  • The default kernel does not support KVM; you must provide a custom binary.
  • Validation occurs in MachineCapabilities.swift, which checks hardware and OS requirements before allowing the operation.

Frequently Asked Questions

Why does nested virtualization require M3 or newer Apple Silicon?

M3 and newer chips contain hardware-assisted virtualization extensions that are equivalent to VMX on Intel or AMD-V on AMD processors. Earlier Apple Silicon generations (M1/M2) lack these specific CPU extensions, making it impossible for the hypervisor framework to expose the necessary interfaces for nested virtualization.

Can I use the default kernel for nested virtualization?

No. The default kernel shipped with apple/container is built without CONFIG_KVM to minimize image size. You must compile your own kernel or obtain one from a distribution with CONFIG_KVM=y enabled, then specify it using the --kernel flag.

How do I verify that nested virtualization is working?

After starting the machine, run container machine run -n <machine-name> -- ls -l /dev/kvm. If the device exists and the command succeeds, nested virtualization is active. If the file does not exist, the kernel lacks KVM support or the virtualization flag was not properly enabled.

Can I disable nested virtualization after enabling it?

Yes. Use container machine set -n <machine-name> kernel= to remove the custom kernel and revert to the default. You must stop and restart the machine for the change to take effect. After restarting, /dev/kvm will no longer be present in the guest.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →