# Apple Container Configuration File Structure: A Complete Guide to config.toml

> Explore the config.toml structure in Apple Container. Learn how layered settings merge from user, app, and install roots, falling back to hard-coded defaults.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: architecture
- Published: 2026-06-23

---

**Apple Container uses a layered TOML configuration file named [`config.toml`](https://github.com/apple/container/blob/main/config.toml) that is searched in three locations—user home, app root, and install root—with settings merged in order of precedence and falling back to hard-coded defaults defined in [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift).**

The open-source `apple/container` repository defines its runtime behavior through a hierarchical configuration system. The **Apple Container configuration file** follows the TOML format and supports layered overrides across user, application, and system directories, allowing developers to customize everything from builder VM resources to DNS domains and network subnets.

## Configuration File Locations and Layered Precedence

Apple Container implements a *first-match-wins* precedence system that searches for [`config.toml`](https://github.com/apple/container/blob/main/config.toml) in three distinct locations. The loader logic in [`Sources/ContainerPersistence/ConfigurationLoader.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ConfigurationLoader.swift) builds a layered snapshot from these paths, with earlier layers overriding later ones.

- **User-home** (`~/.config/container`): The editable user configuration at [`config.toml`](https://github.com/apple/container/blob/main/config.toml) takes highest priority.
- **App-root** (`…/config`): A read-only copy at [`config/config.toml`](https://github.com/apple/container/blob/main/config/config.toml) used by the application at runtime.
- **Install-root** (`/usr/local/etc/container`): System-wide defaults shipped with the installation at [`etc/container/config.toml`](https://github.com/apple/container/blob/main/etc/container/config.toml).

If a key is missing from every layer, the code defaults defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift) are applied. If all files are absent, `ConfigurationLoader.load()` returns `ContainerSystemConfig()` containing the hard-coded defaults.

## Top-Level Configuration Sections

The TOML schema is documented in [`docs/container-system-config.md`](https://github.com/apple/container/blob/main/docs/container-system-config.md). All top-level tables are optional; omitted sections fall back to the defaults defined in [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift).

### [build] – Builder VM Resources

Controls the builder virtual machine settings for container builds.

- **`rosetta`**: `Bool` (default: `true`) – Use Rosetta translation for non-native builds.
- **`cpus`**: `Int` (default: `2`) – CPU count for the builder VM.
- **`memory`**: `MemorySize` (default: `"2048mb"`) – RAM allocated to the builder VM.
- **`image`**: `String` (default: `ghcr.io/apple/container-builder-shim/builder:<tag>`) – Builder image reference.

### [container] – Per-Container Defaults

Defines default resource allocations for individual containers.

- **`cpus`**: `Int` (default: `4`) – Default CPU count for a container.
- **`memory`**: `MemorySize` (default: `"1g"`) – Default RAM for a container.

### [dns] – DNS Domain Configuration

- **`domain`**: `String?` (default: *unset*) – When set (e.g., `"test"`), hostnames acquire this suffix (e.g., `my-web-server.test`).

### [kernel] – Guest Kernel Settings

- **`binaryPath`**: `String` (default: `"opt/kata/share/kata-containers/vmlinux-6.18.15-186"`) – Path inside the downloaded archive.
- **`url`**: `URL` (default: `https://github.com/kata-containers/kata-containers/releases/download/3.28.0/kata-static-3.28.0-arm64.tar.zst`) – Archive URL used if the kernel is not present locally.

### [network] – Subnet Defaults

- **`subnet`**: `CIDRv4?` (default: *unset*) – IPv4 CIDR (e.g., `"192.168.100.0/24"`).
- **`subnetv6`**: `CIDRv6?` (default: *unset*) – IPv6 CIDR (e.g., `"fd00:abcd::/64"`).

### [registry] – Default Registry

- **`domain`**: `String` (default: `"docker.io"`) – Registry used when an image reference omits a host.

### [vminit] – vminitd Image Configuration

- **`image`**: `String` (default: `ghcr.io/apple/containerization/vminit:<tag>`) – Image for the `vminitd` daemon; the tag is derived from the bundled containerization version.

### [plugin.<id>] – Plugin-Scoped Configuration

Plugins may add their own tables under `plugin.<id>`. The plugin defines the schema; values are isolated per-plugin and scoped to the specific plugin ID.

## Type Formats and Validation

The configuration system uses strongly-typed values beyond standard primitives.

### MemorySize

Quoted strings with a numeric prefix and binary unit suffix (`b`, `kb`, `mb`, `gb`, `tb`, `pb`). Parsing is case-insensitive, and values are stored as binary amounts (powers of 1024). Example: `"2048mb"` or `"4g"`. See [`Sources/ContainerPersistence/MemorySize.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MemorySize.swift) for the implementation details.

### CIDRv4 and CIDRv6

Quoted strings containing standard CIDR notation. Examples: `"192.168.100.0/24"` for IPv4 or `"fd00:abcd::/64"` for IPv6.

## How Configuration Loading Works

The loading process in [`ConfigurationLoader.swift`](https://github.com/apple/container/blob/main/ConfigurationLoader.swift) follows a specific sequence to resolve the final configuration:

1. **`ConfigurationLoader.configurationFile(_:)`** builds the concrete `FilePath` for the requested base (home, appRoot, or installRoot).
2. **`load()`** creates a `FileProvider<TOMLSnapshot>` for each layer, allowing missing files to proceed without error.
3. The snapshots are merged with earlier layers overriding later ones.
4. `ConfigSnapshotDecoder` decodes the merged snapshot into `ContainerSystemConfig`, which supplies the defaults defined in its `init()` methods.

This layered approach ensures that user-specific settings in `~/.config/container/config.toml` override application defaults while maintaining system-wide fallbacks.

## Configuration File Examples

### Minimal User Configuration

Create `~/.config/container/config.toml` to override specific defaults:

```toml

# User-only overrides – everything else uses library defaults.

[build]
cpus = 4
memory = "4g"

[container]
memory = "2g"

[dns]
domain = "test"

[registry]
domain = "myregistry.example.com"

```

### Plugin-Specific Configuration

Plugins can receive their own configuration tables:

```toml
[plugin.mylogger]
logLevel = "debug"
output = "/var/log/container.log"

```

The plugin `mylogger` defines its own schema; the core loader scopes the TOML snapshot to `plugin.mylogger`.

### Programmatic Access in Swift

Access the loaded configuration at runtime:

```swift
import ContainerPersistence

// Load the layered configuration (user config overrides system defaults)
let systemConfig = try await ConfigurationLoader.load()

print("Builder CPUs:", systemConfig.build.cpus)          // → 4 (from example above)
print("Default DNS domain:", systemConfig.dns.domain ?? "none")

```

## Summary

- **Apple Container configuration file** uses TOML format named [`config.toml`](https://github.com/apple/container/blob/main/config.toml) with layered loading from three locations.
- **Precedence order**: User-home (`~/.config/container`) overrides App-root, which overrides Install-root (`/usr/local/etc/container`).
- **Top-level sections** include `[build]`, `[container]`, `[dns]`, `[kernel]`, `[network]`, `[registry]`, `[vminit]`, and `[plugin.<id>]`.
- **Special types** `MemorySize`, `CIDRv4`, and `CIDRv6` provide validated parsing for resources and networking.
- **Implementation** resides in [`ConfigurationLoader.swift`](https://github.com/apple/container/blob/main/ConfigurationLoader.swift) for loading logic and [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift) for defaults and data models.
- **Fallback behavior**: If all configuration files are absent, hard-coded defaults from `ContainerSystemConfig()` are applied.

## Frequently Asked Questions

### Where does Apple Container look for the configuration file?

Apple Container searches three locations with first-match-wins precedence: the user home directory at `~/.config/container/config.toml`, the application root at [`config/config.toml`](https://github.com/apple/container/blob/main/config/config.toml), and the installation root at [`/usr/local/etc/container/etc/container/config.toml`](https://github.com/apple/container/blob/main//usr/local/etc/container/etc/container/config.toml). The search logic is implemented in [`Sources/ContainerPersistence/ConfigurationLoader.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ConfigurationLoader.swift).

### What format does the Apple Container configuration file use?

The configuration file uses **TOML** format. All top-level tables are optional, and the schema supports typed values including custom `MemorySize` strings (e.g., `"2048mb"`) and CIDR notation for network subnets.

### How are missing configuration keys handled?

If a key is missing from every configuration layer, the system falls back to hard-coded defaults defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). If no configuration files exist at any layer, `ConfigurationLoader.load()` returns `ContainerSystemConfig()` initialized with these code defaults.

### Can plugins define their own configuration sections?

Yes. Plugins can add custom tables under `[plugin.<id>]` where `<id>` is the plugin identifier. The plugin defines its own schema for values within that table, and the core configuration loader isolates these values per-plugin without enforcing a specific structure.