How to Set System-Wide Defaults in Container's config.toml
Create or edit /usr/local/etc/container/config.toml (or the equivalent install-root path) with your default values, using sudo for permissions; Container's ConfigurationLoader automatically merges this system-wide file with user-specific configs, applying your defaults as the baseline for all users unless overridden.
Apple's container tool uses a layered configuration system defined in ConfigurationLoader.swift that merges multiple TOML files to determine runtime behavior. While individual users can customize settings in their personal config directories, administrators can establish system-wide defaults that apply to every user on the machine by editing a specific file in the installation root. This approach ensures consistent baseline configurations across teams while preserving the flexibility for per-user overrides.
Understanding Container's Configuration Layering
The configuration system in apple/container reads from three distinct layers, processed in order by ConfigurationLoader.defaultConfigFiles() in Sources/ContainerPersistence/ConfigurationLoader.swift. The loader implements a first-match-wins strategy where earlier files override later ones:
- User configuration:
<appRoot>/config/config.toml(typically~/Library/Application Support/com.apple.container/config/config.toml) - System defaults:
<installRoot>/etc/container/config.toml(typically/usr/local/etc/container/config.toml) - Fallback (home):
<home>/config.toml(typically~/.config/container/config.toml)
When a key exists in the user configuration, it takes precedence over the system defaults. If absent from both, the system falls back to hard-coded defaults defined in ContainerSystemConfig.swift.
Locating the System-Wide Configuration Path
The system-wide defaults file resides within the installation root directory, determined by PathUtils.BaseConfigPath.installRoot.basePath(). In standard installations (such as those via Homebrew or Apple's official package), this resolves to /usr/local, making the full path /usr/local/etc/container/config.toml.
Because this location typically requires administrative privileges, you must use sudo when creating or modifying the file.
Creating the System Defaults File
Follow these steps to establish system-wide defaults:
- Create the directory hierarchy if it does not exist:
sudo mkdir -p /usr/local/etc/container
- Write your
config.tomlwith the desired default sections. Common configuration groups include[build],[container], and[registry]:
# /usr/local/etc/container/config.toml
[build]
rosetta = false # Disable Rosetta by default
cpus = 4 # Default to 4 vCPUs for builds
memory = "4096MB" # Default build memory
[container]
cpus = 2 # Default container CPUs
memory = "2g" # Default container memory
[registry]
domain = "my-registry.example.com"
- Set appropriate permissions to ensure the file is readable by all users but modifiable only by root:
sudo chmod 444 /usr/local/etc/container/config.toml
Verifying the Configuration
To confirm that container recognizes your system-wide settings, run the configuration viewer:
container config view
This command displays the merged configuration, showing values from the system file unless superseded by user-level settings.
You can also verify programmatically using the ConfigurationLoader API:
import ContainerPersistence
// Load the full system configuration (user config overrides system defaults)
let systemConfig = try await ConfigurationLoader.load()
print("Build image: \(systemConfig.build.image)") // Uses default if not overridden
For plugin-specific configurations, the system defaults are still respected:
// Load a plugin-scoped configuration – still respects system defaults
struct MyPluginConfig: LoadablePluginConfiguration {
static var pluginId = "myplugin"
var enabled: Bool = true
}
let pluginConfig = try await ConfigurationLoader.loadForPlugin(MyPluginConfig.self)
How Configuration Precedence Works
The ConfigurationLoader creates a FileProvider<TOMLSnapshot> for each configuration path (lines 76-81 in ConfigurationLoader.swift), allowing missing files via allowMissing: true. It builds the final configuration by layering these providers, meaning:
- Values from
/usr/local/etc/container/config.tomlapply to all users by default - Individual users can override specific keys in
~/Library/Application Support/com.apple.container/config/config.toml - If a key is absent from all TOML files,
ContainerSystemConfig.swiftprovides the hard-coded default
This design ensures that Package.swift (lines 266-376) correctly excludes bundled config files, forcing the loader to read from the install root or user directories at runtime.
Summary
- System-wide defaults for
containerbelong in/usr/local/etc/container/config.toml(or the equivalent install-root path determined byPathUtils.BaseConfigPath.installRoot) - The
ConfigurationLoader.swiftimplementation merges configurations in order: user config overrides system defaults, which override hard-coded values fromContainerSystemConfig.swift - Use
sudoto create and protect the system configuration file with read-only permissions (e.g.,chmod 444) - Verify your changes with
container config viewor by inspecting theConfigurationLoader.load()output in Swift - Plugins automatically inherit system defaults through the same
ConfigurationLoadermechanism usingloadForPlugin()
Frequently Asked Questions
Where does Container look for system-wide configuration files?
Container checks for system-wide defaults in <installRoot>/etc/container/config.toml, which typically resolves to /usr/local/etc/container/config.toml on standard installations. This path is determined by PathUtils.BaseConfigPath.installRoot.basePath() and processed after user-specific configurations but before hard-coded defaults according to the implementation in ConfigurationLoader.swift.
Do I need root permissions to set system-wide defaults?
Yes. Because the system-wide configuration resides in the installation root (typically /usr/local/etc), you must use sudo to create the directory structure and write the file. After creating the file, set it to read-only (mode 444) to prevent accidental modifications while allowing all users to read the configuration.
Can users override system-wide defaults?
Yes. The configuration loader implements a first-match-wins strategy. Values defined in the user configuration file (~/Library/Application Support/com.apple.container/config/config.toml) take precedence over system-wide defaults. If a user does not specify a particular key, the system-wide value applies; if no system-wide value exists, the hard-coded default from ContainerSystemConfig.swift is used.
What happens if the config.toml file is missing?
The ConfigurationLoader initializes file providers with allowMissing: true, meaning missing configuration files do not cause errors. If no config files exist at any layer, Container uses the hard-coded defaults defined in ContainerSystemConfig.swift. This ensures the tool functions immediately after installation without requiring initial configuration.
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 →