# How to Install and Configure a Custom Linux Kernel for Containers

> Learn to install and configure a custom Linux kernel for containers using the container system kernel set CLI or Swift API. Optimize your container environments today.

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

---

**Use the `container system kernel set` CLI command or the `KernelService` Swift API to install a custom kernel binary into the managed kernels directory, then configure the runtime to use it via the TOML configuration in [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift).**

The apple/container repository provides a lightweight container runtime for macOS that runs Linux workloads inside a virtual machine. When you need to install and configure a custom Linux kernel for containers—whether for security patches, custom compile flags, or specific feature support—the runtime exposes both CLI tools and Swift APIs to manage kernel artifacts.

## Kernel Configuration Architecture

### Configuration Schema in ContainerSystemConfig.swift

The runtime discovers kernel locations through the TOML configuration defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). The `kernel` property contains two critical fields:

- `binaryPath`: The path inside the kernel archive pointing to the actual kernel binary
- `url`: The remote archive URL to download when no kernel is installed

By default, these values point to the Kata Containers static release for the host architecture.

### Kernel Storage on the Host

The `KernelService` class manages a dedicated kernels directory at `$APP_ROOT/kernels`. According to [`Sources/Services/ContainerAPIService/Server/Kernel/KernelService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Kernel/KernelService.swift) (lines 34-35), the service initializes this directory:

```swift
self.kernelDirectory = appRoot.appending(path: "kernels")
try FileManager.default.createDirectory(at: self.kernelDirectory,
                                        withIntermediateDirectories: true)

```

After installation, the service creates a symbolic link named `default.kernel-<arch>` that points to the active kernel binary, providing a stable reference for the runtime.

## Installing a Custom Kernel via CLI

The `container system kernel` subcommand provides multiple installation methods.

### Install from a Local Binary

To install a compiled kernel binary directly:

```bash
container system kernel set \
    --arch arm64 \
    --binary /path/to/custom/vmlinux \
    --force

```

This invokes `installKernel(kernelFile:platform:force:)` in [`KernelService.swift`](https://github.com/apple/container/blob/main/KernelService.swift), copying the binary into the managed directory and updating the default symlink.

### Install from a Tarball

For distributed kernel archives, specify the tarball source and the internal path to the kernel binary:

```bash
container system kernel set \
    --arch arm64 \
    --tar https://example.com/custom-kernel.tar.zst \
    --binary opt/kata/share/kata-containers/vmlinux

```

This command triggers `installKernelFrom(tar:kernelFilePath:platform:...)` which extracts the specified file and installs it using the binary method.

### Reset to Default Kernel

To revert to the pre-built Kata kernel:

```bash
container system kernel set --recommended

```

## Programmatic Kernel Management

For runtime extensions, import the `ContainerAPIService` module and interact with `KernelService` directly:

```swift
import Services.ContainerAPIService

let kernelService = KernelService(appRoot: appRoot, platform: .linuxArm)

let customKernelURL = URL(fileURLWithPath: "/path/to/custom/vmlinux")
try kernelService.installKernel(kernelFile: customKernelURL,
                                platform: .linuxArm,
                                force: true)

```

When launching VMs, the runtime requests the default kernel via `getDefaultKernel(platform:)` (referenced in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift), line 162). The returned `Kernel` struct, defined in [`Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/Services/Runtime/RuntimeClient/RuntimeConfiguration.swift), contains the binary URL and command-line arguments accessible through `kernel.commandLine.kernelArgs`.

## Kernel Requirements and Compatibility

When you install and configure a custom Linux kernel for containers, the binary must meet specific feature requirements. The VM requires support for:

- **KVM** virtualization
- **cgroup** resource management
- **virtio** drivers
- **LSM modules** including `lockdown`, `capability`, `landlock`, `yama`, and `apparmor`

Additionally, the kernel architecture must match the host platform: arm64 kernels for Apple Silicon Macs and amd64 kernels for Intel-based Macs. The `--arch` flag enforces this constraint during installation.

## Summary

- Configuration resides in [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift) with `binaryPath` and `url` fields defining kernel locations
- The `KernelService` manages kernels in `$APP_ROOT/kernels` and maintains `default.kernel-<arch>` symlinks
- Use `container system kernel set --binary <path>` for local binaries or `--tar <url>` for remote archives
- Swift developers can call `installKernel(kernelFile:...)` or `installKernelFrom(tar:...)` directly
- Custom kernels require specific virtualization features and must match the host architecture

## Frequently Asked Questions

### Where does the container runtime store installed kernels?

The runtime stores kernels in a `kernels` subdirectory under the application root (`$APP_ROOT/kernels`). The `KernelService` class creates this directory during initialization and maintains a symbolic link named `default.kernel-<arch>` that points to the currently active kernel binary.

### Can I use any Linux kernel with the apple/container runtime?

No, the kernel must include specific features enabled: KVM support, cgroup resource management, virtio drivers, and mandatory LSM modules including `lockdown`, `capability`, `landlock`, `yama`, and `apparmor`. Additionally, the kernel architecture must match your Mac's hardware (arm64 for Apple Silicon, amd64 for Intel).

### How do I switch back to the default kernel after installing a custom one?

Run `container system kernel set --recommended` to download and install the default Kata Containers kernel. This restores the official kernel release and updates the default symlink accordingly.

### Is it possible to specify a custom kernel per container rather than system-wide?

While the default kernel is set system-wide via `KernelService`, you can pass specific kernel paths when launching individual containers through the `RuntimeConfiguration` struct. Set the `kernel` property in `RuntimeConfiguration` before calling `RuntimeService.startContainer` to override the default for that specific VM instance.