# How OCI Image Scheme Auto-Detection Chooses HTTP vs HTTPS in Apple Container

> Learn how OCI image scheme auto-detection in Apple Container automatically chooses HTTP or HTTPS for your registries based on host type. Understand the logic behind registry connection selection.

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

---

**When configured with `auto`, the Apple Container CLI automatically selects HTTP for internal registries (localhost, private IPs, or internal DNS domains) and HTTPS for external hosts by evaluating the target host in [`RequestScheme.swift`](https://github.com/apple/container/blob/main/RequestScheme.swift).**

The **apple/container** repository provides a Swift-based container runtime that simplifies registry interactions by automatically selecting the appropriate transport protocol. When users specify `--scheme auto` or rely on the default configuration, the tooling inspects the target registry host to determine whether to use plain HTTP or encrypted HTTPS. This **OCI image scheme auto-detection** mechanism balances security for public registries with convenience for private, intra-cluster deployments.

## How the Auto-Detection Algorithm Classifies Registry Hosts

The decision logic resides in [`Sources/Services/ContainerAPIService/Client/RequestScheme.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/RequestScheme.swift) and evaluates three specific criteria to identify internal hosts.

### Internal Hosts Trigger HTTP Mode

When `isInternalHost(host:internalDnsDomain:)` returns `true`, the system selects plain HTTP. A host qualifies as internal if it meets any of the following conditions:

- **Localhost**: The hostname is `localhost`.
- **Internal DNS Suffix**: The hostname ends with a configured internal DNS domain (e.g., `mycorp.local`).
- **Private IPv4 Ranges**: The address parses as an IPv4 address within these CIDR blocks:
  - `10.0.0.0/8`
  - `127.0.0.0/8` (loopback)
  - `172.16.0.0/12`
  - `192.168.0.0/16`

### External Hosts Require HTTPS

If the host fails all internal checks, the `schemeFor(host:internalDnsDomain:)` method returns `.https`, ensuring encrypted connections to public registries like Docker Hub or Amazon ECR.

## Implementation Details in RequestScheme.swift

The `RequestScheme` type in [`RequestScheme.swift`](https://github.com/apple/container/blob/main/RequestScheme.swift) encapsulates the scheme selection logic. Initialization accepts `http`, `https`, or `auto` strings, storing them as enumerated values.

The `schemeFor(host:internalDnsDomain:)` method acts as the primary entry point. When the stored scheme is `.auto`, it delegates to `isInternalHost(host:internalDnsDomain:)` to perform the classification. For explicit `http` or `https` values, the method returns the corresponding scheme without host inspection.

This implementation aligns with the OCI Distribution Specification's recommendation to use HTTP for private registries where TLS termination may be unnecessary, while mandating HTTPS for external endpoints to guarantee confidentiality and integrity.

## Configuring the Scheme via CLI Flags

Users control this behavior through the `--scheme` flag defined in [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift). Valid options include:

1. `http`: Force plain text (insecure)
2. `https`: Force TLS encryption
3. `auto`: Enable automatic detection based on host analysis

## Practical Code Examples

The following Swift examples demonstrate how `RequestScheme` resolves different host scenarios:

```swift
import ContainerAPIClient

// Explicit HTTP scheme
let scheme1 = try RequestScheme("http")
let result1 = try scheme1.schemeFor(host: "registry.local", internalDnsDomain: nil)
// result1 == .http

// Explicit HTTPS scheme
let scheme2 = try RequestScheme("https")
let result2 = try scheme2.schemeFor(host: "docker.io", internalDnsDomain: nil)
// result2 == .https

// Auto-detect: Private IP address (10.x.x.x)
let scheme3 = try RequestScheme("auto")
let result3 = try scheme3.schemeFor(host: "10.42.0.5", internalDnsDomain: nil)
// result3 == .http

// Auto-detect: Public registry
let scheme4 = try RequestScheme("auto")
let result4 = try scheme4.schemeFor(host: "registry-1.docker.io", internalDnsDomain: nil)
// result4 == .https

// Auto-detect: Internal DNS suffix match
let scheme5 = try RequestScheme("auto")
let result5 = try scheme5.schemeFor(host: "myregistry.mycorp.local", internalDnsDomain: "mycorp.local")
// result5 == .http

```

## Summary

- **OCI image scheme auto-detection** in [`RequestScheme.swift`](https://github.com/apple/container/blob/main/RequestScheme.swift) automatically chooses HTTP for internal registries and HTTPS for external ones.
- **Internal hosts** include `localhost`, addresses in private IPv4 ranges (`10.0.0.0/8`, `127.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), or hostnames matching a configured internal DNS suffix.
- **External hosts** automatically default to HTTPS to ensure secure communication with public registries.
- The logic is exposed through `schemeFor(host:internalDnsDomain:)` and `isInternalHost(host:internalDnsDomain:)` methods.
- Configuration is controlled via the `--scheme` flag in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift).

## Frequently Asked Questions

### How does the auto-detection distinguish between internal and external registries?

The `isInternalHost` function in [`RequestScheme.swift`](https://github.com/apple/container/blob/main/RequestScheme.swift) checks three criteria: whether the hostname is `localhost`, whether it matches a configured internal DNS domain suffix, or whether it parses as a private IPv4 address within the RFC 1918 ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`) or loopback (`127.0.0.0/8`). If any check passes, the registry is considered internal.

### Can I force HTTPS for a private IP address or localhost?

Yes. While `auto` mode would select HTTP for private IPs, you can override this by explicitly setting the scheme to `https` via the `--scheme https` CLI flag defined in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift), or by initializing `RequestScheme` with the string `"https"` in code.

### What happens if I specify an invalid scheme value?

The `RequestScheme` initializer throws an error if provided with a value other than `http`, `https`, or `auto`. This validation ensures that the scheme selection remains strictly controlled and prevents accidental misconfiguration.

### Where is the auto-detection logic tested?

Comprehensive unit tests covering the `auto` behavior for both HTTP and HTTPS scenarios are located in [`Tests/ContainerAPIClientTests/RequestSchemeTests.swift`](https://github.com/apple/container/blob/main/Tests/ContainerAPIClientTests/RequestSchemeTests.swift). These tests verify the correct classification of localhost, private IP ranges, internal DNS domains, and public hostnames.