How to Configure Container Networking with Custom CIDR Blocks in Apple's Container Runtime

You configure custom CIDR blocks by setting the subnet (IPv4) and subnetv6 (IPv6) values in the NetworkConfig structure, either through CLI flags (--subnet, --subnet-v6) when creating a network or persistently in the config.toml file under the [network] table.

The apple/container repository provides a lightweight container runtime for macOS that uses Apple's native virtualization frameworks. Understanding how to define custom network address ranges is essential for avoiding IP conflicts and integrating with existing network infrastructure.

Understanding the NetworkConfig Structure

The networking model centers on the NetworkConfig structure defined in Sources/ContainerPersistence/ContainerSystemConfig.swift. This structure holds optional CIDRv4? and CIDRv6? fields named subnet and subnetv6 respectively.

When the system initializes, it parses the configuration file into this structure. If these fields remain unset, the runtime automatically allocates a non-overlapping CIDR from the internal system pool. The NetworkVmnet plugin then translates these values into the underlying vmnet configuration during network instantiation.

Methods to Configure Custom CIDR Blocks

You can specify custom address spaces through two primary mechanisms, both resulting in the same NetworkConfig object being passed to the vmnet helper.

Via the CLI (Per-Network)

Pass the CIDR strings directly when creating a network using the container network create command. The CLI validates these strings at decode time using the CIDRv4 and CIDRv6 types, rejecting malformed input immediately.


# IPv4 only

container network create --subnet 192.168.100.0/24 mynet

# IPv4 + IPv6 dual-stack

container network create \
  --subnet 192.168.100.0/24 \
  --subnet-v6 fd00:abcd::/64 \
  mynet

The NetworkVmnetHelper+Start.swift file handles the parsing of these CLI options into strongly-typed CIDRv4 and CIDRv6 objects before passing them to the allocation layer.

Via Configuration File (Persistent)

Edit your config.toml file (default location: ~/.config/container/config.toml) to set default CIDR blocks for all new networks. Under the [network] table, specify the subnet and subnetv6 keys:

[network]

# Custom IPv4 subnet for all new networks

subnet   = "10.0.0.0/16"

# Custom IPv6 prefix for all new networks

subnetv6 = "fd01:abcd::/48"

This approach modifies the ContainerSystemConfig initialization behavior, ensuring that every network created without explicit CLI flags inherits these ranges.

CIDR Validation and Defaults

The runtime enforces strict validation to prevent runtime failures. The CIDRv4 and CIDRv6 types perform validation at decode time, ensuring only well-formed address blocks are accepted.

If you do not specify custom values, the AllocationOnlyVmnetNetwork class in Sources/Services/NetworkVmnet/Server/AllocationOnlyVmnetNetwork.swift provides a built-in default of 192.168.64.1/24. When custom CIDRs are present in the configuration, this class overrides the default with your specified ranges during the virtual bridge provisioning phase.

Practical Examples

To verify that your custom CIDR blocks have been applied correctly, inspect the network after creation:

container network inspect mynet

The output includes IPv4Subnet and IPv6Subnet fields confirming the exact CIDR blocks in use.

For a complete system configuration, combine persistent settings with per-network overrides:

  1. Set your organization-wide defaults in ~/.config/container/config.toml
  2. Override specific networks using CLI flags when launching development environments
  3. Verify allocation using the inspect command to ensure no overlap with existing infrastructure

Summary

  • The NetworkConfig structure in ContainerSystemConfig.swift defines networking through optional subnet and subnetv6 fields.
  • CLI method: Use --subnet and --subnet-v6 flags with container network create for immediate, per-network configuration.
  • Config file method: Set [network] table values in config.toml for persistent defaults.
  • CIDRv4 and CIDRv6 types validate input at parse time, preventing malformed CIDR strings from causing runtime errors.
  • The AllocationOnlyVmnetNetwork class applies custom CIDRs or falls back to the default 192.168.64.1/24 when provisioning the virtual bridge.

Frequently Asked Questions

How do I check if my custom CIDR was applied correctly?

Run container network inspect <network-name> and look for the IPv4Subnet and IPv6Subnet fields in the JSON output. These fields display the exact CIDR blocks currently allocated to the network interface.

What happens if I specify an invalid CIDR format?

The runtime rejects the input immediately during the parsing phase. Both the CIDRv4 and CIDRv6 types perform strict validation when decoding configuration files or CLI arguments, returning an error before any network resources are allocated.

Can I use IPv6-only networking without IPv4?

Yes. You can configure IPv6-only networks by specifying only the --subnet-v6 flag or setting only subnetv6 in the config.toml file. The subnet field is optional, and the system will not allocate an IPv4 address if you provide only IPv6 configuration.

Where is the default 192.168.64.1/24 subnet defined?

The default subnet is hardcoded in Sources/Services/NetworkVmnet/Server/AllocationOnlyVmnetNetwork.swift at lines 26-27. This value serves as the fallback when no custom CIDR is specified in either the configuration file or CLI arguments.

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 →