# How to Use Custom Kernels and Enable Nested Virtualization in Container Machine

> Learn to enable nested virtualization in Container Machine. Use custom kernels with KVM support and configure via CLI or TOML for advanced VM setups.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-21

---

**To run nested virtual machines inside Container Machine, enable the virtualization flag and provide a custom Linux kernel built with KVM support, then apply these settings via the CLI or TOML configuration.**

Container Machine, part of the [apple/container](https://github.com/apple/container) repository, runs Linux containers inside a lightweight VM on macOS. By default, it uses a generic kernel without nested virtualization support. This guide explains how to use custom kernels and enable nested virtualization using the `KernelConfig` and `MachineConfig` structures defined in the source code.

## Understanding Kernel Configuration

The runtime determines which kernel to load by reading two primary configuration structures.

### Default Kernel Settings (ContainerSystemConfig.swift)

The `KernelConfig` struct in [[`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift)](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift#L67-L86) defines the default kernel download URL and binary path. These fields are used when the runtime installs a fresh kernel archive.

### Per-Machine Overrides (MachineConfig.swift)

Individual machine settings, including the `virtualization` boolean and optional `kernelPath`, are stored in [[`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift)](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift#L55-L88). The decoder sets `virtualization` to `false` when the flag is omitted.

## Enabling Nested Virtualization

Nested virtualization requires Apple Silicon M3 or later and macOS 15 or newer. When you pass the `--virtualization` flag, the runtime sets `virtualization=true` in the machine configuration, which exposes `/dev/kvm` inside the VM.

## Configuring a Custom Kernel

To override the default kernel, provide a path to a KVM-enabled kernel binary compiled with `CONFIG_KVM=y`. You can specify this via the `--kernel` CLI flag or the `kernel` field in the configuration file. Setting `kernel=` (empty) reverts to the default.

## Step-by-Step Implementation

Create a new machine with a custom kernel and virtualization enabled:

```bash
container machine create \
    --virtualization \
    --kernel /path/to/vmlinux-kvm \
    --name kvm-dev \
    alpine:latest

```

Verify that KVM is exposed inside the VM:

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

```

Enable nested virtualization on an existing machine:

```bash
container machine set -n dev virtualization=true kernel=/path/to/vmlinux-kvm
container machine stop dev
container machine run -n dev -- ls -l /dev/kvm

```

Reset to the default kernel:

```bash
container machine set -n dev kernel=

```

## Configuration File Options

Persist these settings in [`config.toml`](https://github.com/apple/container/blob/main/config.toml) under the `[machine]` table:

```toml
[machine]
virtualization = true
kernel = "/opt/kernels/vmlinux-kvm"

```

Documentation for these flags appears in [docs/container-machine.md](https://github.com/apple/container/blob/main/docs/container-machine.md) and the command reference in [docs/command-reference.md](https://github.com/apple/container/blob/main/docs/command-reference.md).

## Summary

- **Container Machine** uses `KernelConfig` in [[`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift)](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift#L67-L86) to define default kernel binaries.
- **Per-machine overrides** for `virtualization` and `kernelPath` are managed in [[`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift)](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift#L55-L88).
- Enable nested virtualization with the `--virtualization` flag or `virtualization = true` in TOML.
- Supply a custom kernel built with `CONFIG_KVM=y` using the `--kernel` flag or `kernel` configuration key.
- Clear the custom kernel by setting the value to empty to revert to defaults.

## Frequently Asked Questions

### What hardware is required for nested virtualization?

Nested virtualization requires Apple Silicon M3 or later and macOS 15 or newer. The runtime checks these requirements when you enable the virtualization flag.

### How do I revert to the default kernel after using a custom one?

Set the kernel path to an empty value using `container machine set -n <name> kernel=` or remove the `kernel` line from your [`config.toml`](https://github.com/apple/container/blob/main/config.toml). This causes the runtime to fall back to the default `KernelConfig` binary.

### Where are the default kernel URLs defined?

The default kernel download URL and binary path are defined in the `KernelConfig` struct within [[`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift)](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift#L67-L86).

### Can I use nested virtualization without a custom kernel?

No. The default Kata Containers kernel shipped with Container Machine does not include `CONFIG_KVM=y`. You must provide a custom kernel binary that includes KVM support to expose `/dev/kvm` inside the virtual machine.