# How the `--ssh` Flag Forwards SSH Authentication Sockets to Containers in Apple's Container Framework

> Learn how Apple's container framework --ssh flag securely forwards SSH authentication sockets enabling password-less container operations. Understand dynamic mounting and environment variable injection for seamless SSH.

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

---

**The `--ssh` flag dynamically mounts the host's SSH agent socket into the container at `/run/host-services/ssh-auth.sock` and injects the `SSH_AUTH_SOCK` environment variable, enabling password-less SSH operations inside the container without static volume mounts.**

The apple/container framework provides a seamless mechanism to forward your host's SSH authentication agent into running containers. Understanding how the `--ssh` option forward SSH authentication sockets to containers reveals a sophisticated implementation that re-evaluates the socket path on every container start, ensuring compatibility across different SSH agent configurations and session changes.

## How the `--ssh` Flag Works Under the Hood

The implementation spans three coordinated components across the Container API service and the Linux runtime service.

### Flag Parsing and Configuration

In [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) (lines 31-33), the CLI registers `--ssh` as a Boolean flag within the `Management` options struct. When the user includes `--ssh` in their command, the flag is stored as `ssh = true` in the container configuration.

```swift
public struct Management: ParsableArguments {
    @Flag(name: .long, help: "Forward SSH agent socket to container")
    public var ssh = false
}

```

This configuration is then passed to the runtime service when the container start request is initiated.

### Socket Path Propagation

When the runtime receives a request with `config.ssh` enabled, it reads the host's `SSH_AUTH_SOCK` environment variable from the dynamic environment supplied via the XPC message (`dynamicEnv`). In [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 80-95), the runtime creates a `UnixSocketConfiguration` that mounts the host socket at `/var/host-services/ssh-auth.sock` inside the VM.

```swift
if let socketUrl = Self.sshAuthSocketHostUrl(config: config,
                                            dynamicEnv: dynamicEnv,
                                            log: log) {
    let socketConfig = UnixSocketConfiguration(
        source: socketUrl,
        destination: URL(fileURLWithPath: Self.sshAuthSocketGuestPath),
        permissions: permissions,
        direction: .into)
    czConfig.sockets.append(socketConfig)
}

```

### Environment Variable Injection

After mounting the socket, the runtime injects the `SSH_AUTH_SOCK` environment variable pointing to `/run/host-services/ssh-auth.sock` for the container's initial process. As implemented in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) (lines 78-80), this occurs only if the variable is not already present in the container configuration:

```swift
if config.ssh {
    if !czConfig.process.environmentVariables
          .contains(where: { $0.starts(with: "\(Self.sshAuthSocketEnvVar)=") }) {
        czConfig.process.environmentVariables.append(
            "\(Self.sshAuthSocketEnvVar)=\(Self.sshAuthSocketGuestPath)")
    }
}

```

Inside the container, `/run/host-services/ssh-auth.sock` is a symlink that points to the guest-side mount at `/var/host-services/ssh-auth.sock`.

### Dynamic Updates on Container Restart

Unlike static volume mounts, the `--ssh` flag re-evaluates the host's current `SSH_AUTH_SOCK` value every time the container starts. This design, documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md), means that logging out, changing the socket location, or switching SSH agents is handled transparently without requiring container rebuilds or manual flag updates.

## Practical Usage Example

To forward your SSH authentication socket when running a container:

```bash

# On the host (macOS)

$ export SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.XYZ/Listeners
$ container run -it --rm --ssh alpine:latest sh
/ # env | grep SSH_AUTH_SOCK

SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock
/ # ssh-add -l          # shows the keys from the host agent

/ # git clone git@github.com:myorg/private-repo.git

```

This grants the container immediate access to your host's SSH keys without copying them into the image or exposing private key material.

## Summary

- The `--ssh` flag is defined in [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) as a Boolean option that triggers socket forwarding when set to `true`.
- The runtime service reads `SSH_AUTH_SOCK` from the host's `dynamicEnv` and creates a `UnixSocketConfiguration` to mount it at `/var/host-services/ssh-auth.sock` inside the VM.
- The environment variable `SSH_AUTH_SOCK` is automatically set to `/run/host-services/ssh-auth.sock` for the container process if not already specified.
- The socket path is re-evaluated on every container start, supporting dynamic SSH agent changes and transparent session updates.

## Frequently Asked Questions

### What is the exact path where the SSH socket is mounted inside the container?

The host socket is mounted at `/var/host-services/ssh-auth.sock` inside the VM, while the container process sees it at `/run/host-services/ssh-auth.sock` via a symlink. The `SSH_AUTH_SOCK` environment variable is automatically set to point to this location for the container's initial process.

### Does the `--ssh` flag work if I change my SSH agent after starting the container?

The `--ssh` flag re-evaluates the host's `SSH_AUTH_SOCK` path every time the container starts, not just during the initial creation. This means you can change your SSH agent or socket location between restarts, and the container will automatically use the current configuration without requiring manual updates or container rebuilds.

### How is the `--ssh` flag defined in the Container API service?

In [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) (lines 31-33), the flag is declared as a Swift `@Flag` within the `Management` struct: `@Flag(name: .long, help: "Forward SSH agent socket to container") public var ssh = false`. This makes it available as `--ssh` in the CLI and stores the boolean value in the container configuration passed to the runtime.

### Can I manually set `SSH_AUTH_SOCK` instead of using the `--ssh` flag?

While you can manually set environment variables, the `--ssh` flag provides additional functionality by creating the underlying Unix socket mount configuration through `UnixSocketConfiguration`. Manual settings would not create the necessary socket forwarding between the host and guest VM without equivalent runtime configuration in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift).