How to Install and Configure a Custom Linux Kernel for Containers
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.
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. The kernel property contains two critical fields:
binaryPath: The path inside the kernel archive pointing to the actual kernel binaryurl: 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 (lines 34-35), the service initializes this directory:
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:
container system kernel set \
--arch arm64 \
--binary /path/to/custom/vmlinux \
--force
This invokes installKernel(kernelFile:platform:force:) in 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:
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:
container system kernel set --recommended
Programmatic Kernel Management
For runtime extensions, import the ContainerAPIService module and interact with KernelService directly:
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, line 162). The returned Kernel struct, defined in 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, andapparmor
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.swiftwithbinaryPathandurlfields defining kernel locations - The
KernelServicemanages kernels in$APP_ROOT/kernelsand maintainsdefault.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:...)orinstallKernelFrom(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.
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 →