# How Container Uses XPC Services for Inter-Process Communication

> Discover how Apple's Container framework leverages XPC services for secure inter process communication between apiserver, helper daemons, and client tools. Learn about mach services and anonymous endpoints.

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

---

**Apple's Container framework relies on XPC (Cross-Process Communication) to securely coordinate between the apiserver, specialized helper daemons, and client CLI tools, using mach services and anonymous endpoints for isolated, privilege-separated container operations.**

Container orchestrates Linux containers on macOS by decomposing functionality into separate processes that communicate exclusively through XPC. According to the technical documentation in [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md), the `container-apiserver` launches distinct XPC helper services—each running in isolated sandboxes—to handle image management, virtual networking, and per-container runtime operations. This architecture ensures that a compromise in one component cannot easily propagate to others, while the XPC transport layer provides type-safe messaging and automatic cleanup on process termination.

## XPC Helper Service Architecture

The system spawns three primary XPC helper services managed by `launchd` and the `container-apiserver`:

- **container-core-images**: Manages the local image store and exposes XPC methods for importing, listing, and deleting images.
- **container-network-vmnet**: Owns the vmnet virtual network device and allocates IP addresses via XPC requests from the apiserver and runtime helpers.
- **container-runtime-linux**: Implements the container runtime for individual VM-backed containers, exposing a comprehensive XPC API for bootstrap, process creation, I/O handling, and lifecycle management.

Each helper runs in its own sandbox with minimal privileges, communicating with the apiserver over well-defined XPC interfaces. This design is documented in the technical overview at lines 36-48 of [`docs/technical-overview.md`](https://github.com/apple/container/blob/main/docs/technical-overview.md).

## Endpoint Creation and Anonymous Connections

When a client requires direct communication with a specific container runtime, the helper creates an anonymous XPC endpoint. In [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 21-28), the `createEndpoint` method generates this endpoint from the existing connection:

```swift
// RuntimeService.swift – createEndpoint
let endpoint = xpc_endpoint_create(self.connection)
let reply = message.reply()
reply.set(key: RuntimeKeys.runtimeServiceEndpoint.rawValue, value: endpoint)
return reply

```

The endpoint object is transferred back to the client via an `XPCMessage`, allowing the client to establish a direct, dedicated connection to that specific runtime instance without routing through the apiserver.

## Client-Side XPC Implementation

The `RuntimeClient` class in [`Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift) encapsulates the client-side XPC logic. Lines 48-74 demonstrate how it first connects to the helper's mach service label, requests the endpoint, and then constructs a new `XPCClient` using that endpoint:

```swift
// RuntimeClient.swift – create()
let label = Self.machServiceLabel(runtime: runtime, id: id)
let client = XPCClient(service: label)
let request = XPCMessage(route: RuntimeRoutes.createEndpoint.rawValue)
let response = try await client.send(request)
let endpoint = response.endpoint(key: RuntimeKeys.runtimeServiceEndpoint.rawValue)!

let endpointConnection = xpc_connection_create_from_endpoint(endpoint)
let xpcClient = XPCClient(connection: endpointConnection, label: label)

```

Once established, this client invokes runtime methods such as `bootstrap`, `createProcess`, `startProcess`, `stop`, and `kill` by packing arguments into `XPCMessage` objects and awaiting responses.

## XPC Message Structure and Routing

All inter-process communication uses a common message structure defined in the `ContainerXPC` module. Messages are constructed using enumerated route keys (e.g., `RuntimeRoutes.bootstrap`) and typed value keys (e.g., `RuntimeKeys.dynamicEnv`).

For example, bootstrapping a container involves sending environment variables and network configuration, as shown in lines 78-87 of [`RuntimeClient.swift`](https://github.com/apple/container/blob/main/RuntimeClient.swift):

```swift
let request = XPCMessage(route: RuntimeRoutes.bootstrap.rawValue)
request.set(key: RuntimeKeys.dynamicEnv.rawValue, value: encodedEnv)
request.set(key: RuntimeKeys.networkBootstrapInfos.rawValue, value: encodedInfos)
try await client.send(request)

```

The runtime service handles these requests in methods like `startProcess`, which decodes the message and executes the corresponding operation. Lines 31-38 of [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) show the implementation:

```swift
// RuntimeService.swift – handling startProcess
public func startProcess(_ message: XPCMessage) async throws -> XPCMessage {
    self.log.debug("enter", metadata: ["func": "\(#function)"])
    defer { self.log.debug("exit", metadata: ["func": "\(#function)"])

    let pid = try message.decode(String.self, forKey: RuntimeKeys.id.rawValue)
    // … process start logic …
    return XPCMessage()
}

```

Lines 120-132 of [`RuntimeClient.swift`](https://github.com/apple/container/blob/main/RuntimeClient.swift) also demonstrate how the `XPCMessage` extension handles higher-level types like `SandboxSnapshot`.

## Security Benefits and Process Isolation

XPC provides several security advantages for the Container architecture. Each helper runs as a distinct `launchd` daemon with dedicated sandbox profiles, enforcing least-privilege access to system resources. The XPC layer validates helper binary signatures during connection establishment and automatically tears down connections when a process crashes, preventing resource leaks.

The anonymous endpoint pattern further isolates operations: once a client receives an endpoint for a specific `container-runtime-linux` instance, all subsequent container control traffic bypasses the apiserver, reducing the attack surface and limiting the blast radius of potential vulnerabilities in the runtime.

## Summary

- **XPC Helper Services**: Container uses three specialized XPC services (`container-core-images`, `container-network-vmnet`, `container-runtime-linux`) to handle distinct concerns in isolated processes.
- **Anonymous Endpoints**: Runtime helpers create unique XPC endpoints via `xpc_endpoint_create` in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift), enabling direct client-to-runtime communication.
- **Client Abstraction**: The `RuntimeClient` class manages mach service lookup, endpoint negotiation, and method invocation in [`Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift).
- **Structured Messaging**: All XPC calls use typed `XPCMessage` objects with enumerated keys for routes and parameters, ensuring type safety across process boundaries.
- **Security Model**: Sandboxed helpers, signature validation, and automatic connection cleanup provide defense-in-depth for container operations.

## Frequently Asked Questions

### How does Container establish the initial XPC connection between the CLI and runtime?

The Container CLI first communicates with the `container-apiserver` via the ContainerAPI client library. When a specific container operation is required, the apiserver spawns the appropriate `container-runtime-linux` helper, which creates an anonymous XPC endpoint. The CLI then receives this endpoint through the apiserver and establishes a direct XPC connection to the runtime helper using `xpc_connection_create_from_endpoint`, bypassing the apiserver for subsequent operations.

### What XPC methods does the runtime helper expose for container management?

The `container-runtime-linux` helper exposes a comprehensive API including `createEndpoint` for connection setup, `bootstrap` for VM initialization, `createProcess` and `startProcess` for workload execution, and lifecycle controls like `stop` and `kill`. These methods are defined in [`RuntimeRoutes.swift`](https://github.com/apple/container/blob/main/RuntimeRoutes.swift) and implemented in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift), accepting structured `XPCMessage` payloads containing configuration data and environment variables.

### Why does Container use anonymous XPC endpoints instead of direct mach service connections?

Anonymous endpoints provide per-instance isolation. While the initial connection uses a well-known mach service label registered with `launchd`, the helper immediately creates a unique endpoint for each container. This pattern allows multiple concurrent containers to run separate runtime processes without port collisions, and ensures that a client connection problem affects only one container instance rather than the shared service.

### Where are the XPC message keys and routes defined in the source code?

The XPC protocol constants are defined in the `ContainerXPC` module and referenced in [`Sources/Services/Runtime/RuntimeClient/RuntimeRoutes.swift`](https://github.com/apple/container/blob/main/Sources/Services/Runtime/RuntimeClient/RuntimeRoutes.swift) for route identifiers (like `bootstrap` and `createEndpoint`) and `RuntimeKeys` for value keys (like `runtimeServiceEndpoint` and `dynamicEnv`). These enums ensure consistent naming across the Swift implementations in both the client ([`RuntimeClient.swift`](https://github.com/apple/container/blob/main/RuntimeClient.swift)) and server ([`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift)) components.