How Container Integrates with the vmnet Framework for Container Networking

Container integrates with the vmnet framework through an XPC helper service that translates high-level network configurations into macOS vmnet API calls, creating NAT or host-only networks and serializing the network references for container runtime attachment.

The apple/container project implements container networking on macOS by leveraging the native vmnet framework, providing NAT and host-only connectivity for Linux containers. This integration bridges the gap between high-level network management commands and low-level macOS virtualization APIs through a carefully architected XPC service. Understanding this container vmnet framework integration reveals how the project achieves performant, native networking without requiring third-party kernel extensions.

Architecture Overview

The container vmnet framework integration follows a three-layer architecture that separates user commands from privileged virtualization operations:

  • CLI Layer: Parses container network commands and constructs NetworkConfiguration objects in Sources/ContainerCommands/Network/NetworkCreate.swift
  • XPC Helper Layer: The container-network-vmnet service receives configurations via the ContainerNetworkServer API and manages vmnet network lifecycle
  • Runtime Layer: The container-runtime-linux helper deserializes network references and creates container interfaces

This design ensures that privileged vmnet operations remain isolated within the XPC service while the runtime handles container-specific network attachment.

Network Creation and Configuration Flow

CLI Network Definition

When a user executes container network create, the CLI builds a NetworkConfiguration structure that specifies the operating mode (NAT or host-only), IPv4/IPv6 subnets, labels, and the plugin name (defaulting to container-network-vmnet). In Sources/ContainerCommands/Network/NetworkCreate.swift, this configuration is validated and passed to the XPC helper via the ContainerNetworkServer module.

XPC Helper Translation

The container-network-vmnet helper implements the Network protocol defined in the ContainerNetworkServer target. In Sources/Plugins/NetworkVmnet/NetworkVmnetHelper.swift, the helper receives the configuration and instantiates ReservedVmnetNetwork to handle the low-level vmnet operations.

vmnet Network Initialization

The ReservedVmnetNetwork class in Sources/Services/NetworkVmnet/Server/ReservedVmnetNetwork.swift manages the direct interaction with the vmnet framework.

Operating Mode Selection

The helper selects the appropriate vmnet operating mode based on the configuration:

  • .VMNET_SHARED_MODE: Used for NAT networking (default), allowing containers to access external networks through the host
  • .VMNET_HOST_MODE: Used for host-only networking when the --internal flag is specified

Subnet Configuration and DHCP Disablement

The implementation disables DHCP since the helper manages its own address allocation:

// ReservedVmnetNetwork.swift - Disabling DHCP
// Lines 16-18
config.ipv4_disable_dhcp = true
config.ipv6_disable_dhcp = true

When subnets are provided, the helper populates the vmnet configuration using native API calls:

// Lines 30-34
if let subnet = ipv4Subnet {
    guard vmnet_network_configuration_set_ipv4_subnet(&config, subnet) == VMNET_SUCCESS else {
        throw error
    }
}

// Lines 40-44
if let prefix = ipv6Prefix {
    guard vmnet_network_configuration_set_ipv6_prefix(&config, prefix) == VMNET_SUCCESS else {
        throw error
    }
}

Network Creation and Reference Storage

After configuration, the network is created and stored:

// Lines 54-58
var status = vmnet_network_status_t()
let networkRef = vmnet_network_create(&config, &status)
guard status == VMNET_SUCCESS else {
    throw error
}
self.vmnetNetworkRef = networkRef

Runtime Attachment and Interface Binding

Serialization via vmnet_network_copy_serialization

When containers need to attach to the network, the helper serializes the vmnet_network_ref into an XPC message that can be transferred to the runtime:

// ReservedVmnetNetwork.swift - Lines 92-99
var serialization = vmnet_network_serialization_t()
var serializationLength = 0
guard vmnet_network_copy_serialization(vmnetNetworkRef, &serialization, &serializationLength) == VMNET_SUCCESS else {
    throw error
}
// Attach to XPC message for runtime transfer

Deserialization and NATNetworkInterface Creation

In Sources/Services/RuntimeLinux/Server/NonisolatedInterfaceStrategy.swift, the runtime helper receives the XPC data and reconstructs the network reference:

// Lines 35-53
let networkRef = vmnet_network_create_with_serialization(additionalData.underlying, &status)
guard status == VMNET_SUCCESS else {
    throw error
}

let interface = NATNetworkInterface(
    ipv4Address: attachment.ipv4Address,
    ipv4Gateway: attachment.ipv4Gateway,
    reference: networkRef,
    macAddress: attachment.macAddress,
    mtu: attachment.mtu ?? 1280
)

This NATNetworkInterface encapsulates the container's IPv4 address, gateway, MAC address, and the underlying vmnet reference.

Address Allocation and Network Lifecycle

The helper allocates IP addresses from the configured subnet automatically. In NAT mode, the first container receives the gateway address while subsequent containers receive sequential IPs. For host-only mode, the same allocation mechanism applies without NAT translation.

The network lifecycle supports inspect and stop operations via the ContainerNetworkServer API, reporting active subnets and gateway information back to the CLI.

Practical Examples

Create a NAT network using the default vmnet plugin:

container network create \
    --label env=dev \
    --option mtu=1500 \
    my-net

Create a host-only network with specific subnet:

container network create \
    --internal \
    --subnet 10.0.0.0/24 \
    host-only-net

Inspect network configuration:

container network inspect my-net

Platform Requirements and Limitations

The vmnet framework integration requires macOS 26+ for full functionality, marked with @available(macOS 26, *) in the source. On macOS 15, the framework supports only isolated host-only networks, reflecting the API limitations documented in the technical overview.

Summary

  • Container vmnet framework integration relies on an XPC helper service (container-network-vmnet) to proxy vmnet operations from the CLI to the macOS kernel
  • The ReservedVmnetNetwork class configures vmnet using VMNET_SHARED_MODE for NAT or VMNET_HOST_MODE for host-only networking, always disabling DHCP
  • Network references are serialized using vmnet_network_copy_serialization and deserialized in the runtime via vmnet_network_create_with_serialization to create NATNetworkInterface instances
  • IP address allocation and gateway assignment are managed by the helper, not the vmnet DHCP server
  • Full functionality requires macOS 26 or later, with limited host-only support on macOS 15

Frequently Asked Questions

What is the vmnet framework and why does Container use it?

The vmnet framework is Apple's native macOS API for creating virtual networks without kernel extensions. Container uses it to provide high-performance, NAT, and host-only networking for Linux containers while maintaining compatibility with macOS virtualization standards and security models.

What is the difference between NAT and host-only networking modes in Container?

NAT mode (VMNET_SHARED_MODE) allows containers to access external networks through the host's internet connection, while host-only mode (VMNET_HOST_MODE) creates an isolated network where containers can only communicate with the host and other containers on the same network. The mode is selected via the --internal flag during network creation.

How does the XPC helper service improve security in Container's vmnet integration?

The XPC helper isolates privileged vmnet operations (vmnet_network_create, interface configuration) into a separate service (container-network-vmnet) that runs with elevated privileges, while the main CLI and runtime operate with reduced permissions. This follows the principle of least privilege, ensuring that only the minimal necessary code interacts with low-level networking APIs.

Why does Container require macOS 26+ for full vmnet functionality?

The complete vmnet API, including support for NAT networking and network serialization, requires macOS 26 or later. Earlier versions (macOS 15) only support isolated host-only networks without the serialization capabilities needed for the full container runtime integration, as implemented in ReservedVmnetNetwork.swift and NonisolatedInterfaceStrategy.swift.

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 →