# How Container Manages Kernel Installation and Updates on macOS

> Discover how apple/container manages Linux kernel installation and updates on macOS. Learn about its VM approach, lifecycle management, and integration details.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-07-08

---

**Container** runs Linux containers on macOS by launching a lightweight virtual machine (VM), managing the complete lifecycle of Linux kernel binaries through configuration files, CLI commands, and runtime service integration.

The `apple/container` repository provisions Linux kernels to boot these VMs, supporting both automated downloads from remote archives and custom kernel binaries. The system provides system-wide defaults while allowing per-machine overrides, ensuring flexible kernel management for diverse container workloads.

## Kernel Configuration and Defaults

The kernel installation behavior is governed by **ContainerSystemConfig**, defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). This struct decodes the top-level [`config.toml`](https://github.com/apple/container/blob/main/config.toml) file and establishes default values for kernel provisioning.

The configuration specifies two critical fields:

- **`kernel.url`** – The remote URL of the kernel archive (defaults to a Kata Containers static tarball).
- **`kernel.binaryPath`** – The path inside the downloaded archive pointing to the kernel binary.

Both fields reference internal defaults (`defaultURL` and `defaultBinaryPath`) when not explicitly configured, ensuring the system can bootstrap without manual configuration.

## Installing and Updating Kernels via CLI

Container provides explicit commands for kernel lifecycle management, allowing administrators to install recommended binaries or custom builds.

### System-Wide Kernel Installation

The `container system kernel set` command installs or replaces the host-side kernel used by the container runtime. Users can install the **recommended** kernel or supply a custom tarball.

Key flags include:

- **`--recommended`** – Downloads and installs the default Kata Containers kernel.
- **`--tar <url>`** – Specifies a custom remote tarball containing the kernel.
- **`--binary <path>`** – Defines the path to the kernel file inside the tarball or a direct kernel file path.
- **`--arch <arch>`** – Selects architecture (`arm64` or `amd64`, defaulting to `arm64`).
- **`--force`** – Overwrites existing kernel installations without prompting.

```bash

# Install the recommended kernel (override any existing one)

container system kernel set --recommended --force

# Install a custom kernel from a remote tarball

container system kernel set \
    --tar https://example.com/mykernel.tar \
    --binary vmlinux \
    --arch arm64 \
    --force

```

### Automatic Installation on Service Start

When executing `container system start`, the service can automatically install the default kernel if none is present on the system.

Use **`--enable-kernel-install`** to prompt for automatic installation based on the configured `kernel.url` and `binaryPath` values. Conversely, **`--disable-kernel-install`** suppresses this behavior if you prefer manual kernel management.

```bash

# Start services and install default kernel if missing

container system start --enable-kernel-install

```

This automation ensures VMs can boot immediately after the first service start without requiring explicit kernel setup commands.

## Per-Machine Kernel Overrides

Individual container machines can override the system-wide kernel configuration, enabling specialized workloads such as nested virtualization scenarios.

When creating a machine, specify a custom kernel using the **`--kernel`** flag:

```bash

# Create a machine with a custom kernel for nested virtualization

container machine create \
    --virtualization \
    --kernel ./vmlinux-kvm \
    alpine:3.22

```

For existing machines, update the kernel path using the `set` command:

```bash

# Apply custom kernel to existing machine

container machine set -n my-machine kernel=/opt/kernels/vmlinux-kvm

# Revert to system-wide default kernel

container machine set -n my-machine kernel=

```

Setting `kernel=` (empty value) clears the override and falls back to the system-wide kernel configured in `ContainerSystemConfig`.

## Runtime Kernel Loading

At runtime, the container service loads kernel configuration from `ContainerSystemConfig` and passes it to the VM launcher. In [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 162–166), the kernel path is read from the configuration and supplied to the VM initialization routine.

This ensures the hypervisor always boots with the correct kernel, whether using the system default or a machine-specific override.

## Summary

- **Configuration-driven defaults** – `ContainerSystemConfig` in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift) defines default kernel URLs and binary paths via [`config.toml`](https://github.com/apple/container/blob/main/config.toml).
- **Explicit installation commands** – `container system kernel set` supports `--recommended` and `--tar` sources with architecture selection.
- **Automatic provisioning** – `container system start --enable-kernel-install` downloads and installs kernels on first run if missing.
- **Flexible overrides** – Per-machine kernel settings via `container machine create --kernel` and `container machine set kernel=<path>`.
- **Runtime integration** – [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) loads the configured kernel and passes it to the VM launcher at boot time.

## Frequently Asked Questions

### Where does Container download the default kernel from?

By default, Container downloads kernels from Kata Containers static release tarballs. The URL is defined in the `kernel.url` field of `ContainerSystemConfig` (in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift)), which provides a default URL pointing to official Kata Containers releases. You can override this by modifying [`config.toml`](https://github.com/apple/container/blob/main/config.toml) or using the `--tar` flag with `container system kernel set`.

### Can I use a custom kernel instead of the recommended one?

Yes. Use `container system kernel set --tar <url> --binary <path>` to install a custom kernel from any remote archive. You can also specify `--arch` to target specific architectures like `arm64` or `amd64`. For individual machines, use `container machine create --kernel <path>` or `container machine set kernel=<path>` to override the system-wide default without changing global configuration.

### How do I revert a machine to the system-wide kernel?

Execute `container machine set -n <machine-name> kernel=` with an empty value. This clears the machine-specific override in the persistence layer, causing the runtime to fall back to the kernel configured in `ContainerSystemConfig` when the machine boots.

### What architectures are supported for kernels?

Container supports both `arm64` (Apple Silicon) and `amd64` (Intel) architectures. The `--arch` flag on `container system kernel set` allows explicit selection, defaulting to `arm64`. Ensure the kernel binary matches your host architecture, as the VM requires native execution capabilities.