From 48a6bc9a45ba6a59c91c969939e628f35c61bfbf Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Wed, 12 Nov 2025 11:22:30 +0100 Subject: [PATCH 1/8] feat(registry): Forward ssl env variables to containerization --- Package.resolved | 28 +++++++++---------- Package.swift | 4 ++- .../System/SystemStart.swift | 5 +++- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Package.resolved b/Package.resolved index 0cf5d163..3317f83e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "cdb00eae6b7604ecbcae4d6486a6e5e0f5f89e93c1e645b50a7c4758b8ef38ca", + "originHash" : "71f94c8c9becc3984bd6967fd4460e43c13c3915905d22b4a6d847a9537f9f58", "pins" : [ { "identity" : "async-http-client", @@ -13,10 +13,10 @@ { "identity" : "containerization", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/containerization.git", + "location" : "https://github.com/sebimarkgraf/containerization.git", "state" : { - "revision" : "2f55d75fec39474212170439b73274006200e2e2", - "version" : "0.19.0" + "branch" : "sm/add-ssl-custom-ca", + "revision" : "016528df7c1fb04b7af1985961cd75500f3a5e05" } }, { @@ -78,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-async-algorithms.git", "state" : { - "revision" : "6c050d5ef8e1aa6342528460db614e9770d7f804", - "version" : "1.1.1" + "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b", + "version" : "1.0.4" } }, { @@ -96,8 +96,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-certificates.git", "state" : { - "revision" : "133a347911b6ad0fc8fe3bf46ca90c66cff97130", - "version" : "1.17.0" + "revision" : "c059d9c9d08d6654b9a92dda93d9049a278964c6", + "version" : "1.12.0" } }, { @@ -141,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-structured-headers.git", "state" : { - "revision" : "76d7627bd88b47bf5a0f8497dd244885960dde0b", - "version" : "1.6.0" + "revision" : "1625f271afb04375bf48737a5572613248d0e7a0", + "version" : "1.4.0" } }, { @@ -150,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-types.git", "state" : { - "revision" : "45eb0224913ea070ec4fba17291b9e7ecf4749ca", - "version" : "1.5.1" + "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", + "version" : "1.4.0" } }, { @@ -213,8 +213,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-numerics.git", "state" : { - "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", - "version" : "1.1.1" + "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", + "version" : "1.0.3" } }, { diff --git a/Package.swift b/Package.swift index a20b03f3..2e31abe8 100644 --- a/Package.swift +++ b/Package.swift @@ -55,7 +55,9 @@ let package = Package( .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.20.1"), .package(url: "https://github.com/orlandos-nl/DNSClient.git", from: "2.4.1"), .package(url: "https://github.com/Bouke/DNS.git", from: "1.2.0"), - .package(url: "https://github.com/apple/containerization.git", exact: Version(stringLiteral: scVersion)), + // FIXME: Rever the package URL to the main branch + .package(url: "https://github.com/sebimarkgraf/containerization.git", branch: "sm/add-ssl-custom-ca"), + .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.36.0"), ], targets: [ .executableTarget( diff --git a/Sources/ContainerCommands/System/SystemStart.swift b/Sources/ContainerCommands/System/SystemStart.swift index eae26800..ce6ea8ae 100644 --- a/Sources/ContainerCommands/System/SystemStart.swift +++ b/Sources/ContainerCommands/System/SystemStart.swift @@ -70,7 +70,10 @@ extension Application { let apiServerDataUrl = appRoot.appending(path: "apiserver") try! FileManager.default.createDirectory(at: apiServerDataUrl, withIntermediateDirectories: true) - var env = PluginLoader.filterEnvironment() + var env = PluginLoader.filterEnvironment( + env: ProcessInfo.processInfo.environment, + additionalAllowKeys: ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE"], + ) env[ApplicationRoot.environmentName] = appRoot.path(percentEncoded: false) env[InstallRoot.environmentName] = installRoot.path(percentEncoded: false) From 42d2cbb4b3826c183c4bb3e4590c8bb89a420434 Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Mon, 5 Jan 2026 08:57:01 +0100 Subject: [PATCH 2/8] Add environment aware tls --- .../Client/FileDownloader.swift | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift index 83aabfc5..7f63bc19 100644 --- a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift +++ b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift @@ -19,6 +19,7 @@ import ContainerizationError import ContainerizationExtras import Foundation import TerminalProgress +import NIOSSL public struct FileDownloader { public static func downloadFile(url: URL, to destination: URL, progressUpdate: ProgressUpdateHandler? = nil) async throws { @@ -49,7 +50,7 @@ public struct FileDownloader { } }) - let client = FileDownloader.createClient(url: url) + let client = try FileDownloader.createClient(url: url) do { _ = try await client.execute(request: request, delegate: delegate).get() } catch { @@ -59,7 +60,7 @@ public struct FileDownloader { try await client.shutdown() } - private static func createClient(url: URL) -> HTTPClient { + private static func createClient(url: URL) throws -> HTTPClient { var httpConfiguration = HTTPClient.Configuration() // for large file downloads we keep a generous connect timeout, and // no read timeout since download durations can vary @@ -67,6 +68,8 @@ public struct FileDownloader { connect: .seconds(30), read: .none ) + + httpConfiguration.tlsConfiguration = try makeEnvironmentAwareTLSConfiguration() if let host = url.host { let proxyURL = ProxyUtils.proxyFromEnvironment(scheme: url.scheme, host: host) if let proxyURL, let proxyHost = proxyURL.host { @@ -76,4 +79,20 @@ public struct FileDownloader { return HTTPClient(eventLoopGroupProvider: .singleton, configuration: httpConfiguration) } + + private static func makeEnvironmentAwareTLSConfiguration() throws -> TLSConfiguration { + var tlsConfig = TLSConfiguration.makeClientConfiguration() + + // Check standard SSL environment variables in priority order + let customCAPath = ProcessInfo.processInfo.environment["SSL_CERT_FILE"] + ?? ProcessInfo.processInfo.environment["CURL_CA_BUNDLE"] + ?? ProcessInfo.processInfo.environment["REQUESTS_CA_BUNDLE"] + + if let caPath = customCAPath { + tlsConfig.trustRoots = .file(caPath) + } + // else: use .default + + return tlsConfig +} } From b1f63597e9013754b0ae91fb8d69285e5e580e40 Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Mon, 5 Jan 2026 08:59:10 +0100 Subject: [PATCH 3/8] Use main containerization --- Package.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 2e31abe8..a20b03f3 100644 --- a/Package.swift +++ b/Package.swift @@ -55,9 +55,7 @@ let package = Package( .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.20.1"), .package(url: "https://github.com/orlandos-nl/DNSClient.git", from: "2.4.1"), .package(url: "https://github.com/Bouke/DNS.git", from: "1.2.0"), - // FIXME: Rever the package URL to the main branch - .package(url: "https://github.com/sebimarkgraf/containerization.git", branch: "sm/add-ssl-custom-ca"), - .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.36.0"), + .package(url: "https://github.com/apple/containerization.git", exact: Version(stringLiteral: scVersion)), ], targets: [ .executableTarget( From b46203dc0b9273de0f476293a8a1775d281fac05 Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Mon, 5 Jan 2026 09:19:42 +0100 Subject: [PATCH 4/8] Use TLSutils environment aware config --- Package.resolved | 28 +++++++++---------- .../Client/FileDownloader.swift | 17 +---------- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/Package.resolved b/Package.resolved index 3317f83e..0cf5d163 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "71f94c8c9becc3984bd6967fd4460e43c13c3915905d22b4a6d847a9537f9f58", + "originHash" : "cdb00eae6b7604ecbcae4d6486a6e5e0f5f89e93c1e645b50a7c4758b8ef38ca", "pins" : [ { "identity" : "async-http-client", @@ -13,10 +13,10 @@ { "identity" : "containerization", "kind" : "remoteSourceControl", - "location" : "https://github.com/sebimarkgraf/containerization.git", + "location" : "https://github.com/apple/containerization.git", "state" : { - "branch" : "sm/add-ssl-custom-ca", - "revision" : "016528df7c1fb04b7af1985961cd75500f3a5e05" + "revision" : "2f55d75fec39474212170439b73274006200e2e2", + "version" : "0.19.0" } }, { @@ -78,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-async-algorithms.git", "state" : { - "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b", - "version" : "1.0.4" + "revision" : "6c050d5ef8e1aa6342528460db614e9770d7f804", + "version" : "1.1.1" } }, { @@ -96,8 +96,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-certificates.git", "state" : { - "revision" : "c059d9c9d08d6654b9a92dda93d9049a278964c6", - "version" : "1.12.0" + "revision" : "133a347911b6ad0fc8fe3bf46ca90c66cff97130", + "version" : "1.17.0" } }, { @@ -141,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-structured-headers.git", "state" : { - "revision" : "1625f271afb04375bf48737a5572613248d0e7a0", - "version" : "1.4.0" + "revision" : "76d7627bd88b47bf5a0f8497dd244885960dde0b", + "version" : "1.6.0" } }, { @@ -150,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-types.git", "state" : { - "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", - "version" : "1.4.0" + "revision" : "45eb0224913ea070ec4fba17291b9e7ecf4749ca", + "version" : "1.5.1" } }, { @@ -213,8 +213,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-numerics.git", "state" : { - "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", - "version" : "1.0.3" + "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", + "version" : "1.1.1" } }, { diff --git a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift index 7f63bc19..53433c1b 100644 --- a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift +++ b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift @@ -69,7 +69,7 @@ public struct FileDownloader { read: .none ) - httpConfiguration.tlsConfiguration = try makeEnvironmentAwareTLSConfiguration() + httpConfiguration.tlsConfiguration = TLSUtils.makeEnvironmentAwareTLSConfiguration() if let host = url.host { let proxyURL = ProxyUtils.proxyFromEnvironment(scheme: url.scheme, host: host) if let proxyURL, let proxyHost = proxyURL.host { @@ -80,19 +80,4 @@ public struct FileDownloader { return HTTPClient(eventLoopGroupProvider: .singleton, configuration: httpConfiguration) } - private static func makeEnvironmentAwareTLSConfiguration() throws -> TLSConfiguration { - var tlsConfig = TLSConfiguration.makeClientConfiguration() - - // Check standard SSL environment variables in priority order - let customCAPath = ProcessInfo.processInfo.environment["SSL_CERT_FILE"] - ?? ProcessInfo.processInfo.environment["CURL_CA_BUNDLE"] - ?? ProcessInfo.processInfo.environment["REQUESTS_CA_BUNDLE"] - - if let caPath = customCAPath { - tlsConfig.trustRoots = .file(caPath) - } - // else: use .default - - return tlsConfig -} } From 35390f576f868057a369ea63ffdc4ce92c4490fe Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Mon, 5 Jan 2026 09:21:01 +0100 Subject: [PATCH 5/8] Add tls config to file downloader --- .../Services/ContainerAPIService/Client/FileDownloader.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift index 53433c1b..321bfd81 100644 --- a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift +++ b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift @@ -50,7 +50,7 @@ public struct FileDownloader { } }) - let client = try FileDownloader.createClient(url: url) + let client = FileDownloader.createClient(url: url) do { _ = try await client.execute(request: request, delegate: delegate).get() } catch { @@ -60,7 +60,7 @@ public struct FileDownloader { try await client.shutdown() } - private static func createClient(url: URL) throws -> HTTPClient { + private static func createClient(url: URL) -> HTTPClient { var httpConfiguration = HTTPClient.Configuration() // for large file downloads we keep a generous connect timeout, and // no read timeout since download durations can vary From be0b344fab3ab055edea26a469a975cfa7a7648c Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Mon, 5 Jan 2026 09:27:42 +0100 Subject: [PATCH 6/8] Format --- Sources/ContainerCommands/System/SystemStart.swift | 2 +- .../Services/ContainerAPIService/Client/FileDownloader.swift | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/ContainerCommands/System/SystemStart.swift b/Sources/ContainerCommands/System/SystemStart.swift index ce6ea8ae..4bc56f78 100644 --- a/Sources/ContainerCommands/System/SystemStart.swift +++ b/Sources/ContainerCommands/System/SystemStart.swift @@ -72,7 +72,7 @@ extension Application { var env = PluginLoader.filterEnvironment( env: ProcessInfo.processInfo.environment, - additionalAllowKeys: ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE"], + additionalAllowKeys: ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE"], ) env[ApplicationRoot.environmentName] = appRoot.path(percentEncoded: false) env[InstallRoot.environmentName] = installRoot.path(percentEncoded: false) diff --git a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift index 321bfd81..44e5cec5 100644 --- a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift +++ b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift @@ -18,8 +18,8 @@ import AsyncHTTPClient import ContainerizationError import ContainerizationExtras import Foundation -import TerminalProgress import NIOSSL +import TerminalProgress public struct FileDownloader { public static func downloadFile(url: URL, to destination: URL, progressUpdate: ProgressUpdateHandler? = nil) async throws { @@ -79,5 +79,4 @@ public struct FileDownloader { return HTTPClient(eventLoopGroupProvider: .singleton, configuration: httpConfiguration) } - } From 0003d6ec3c02242327ac35e8e66a21fc46b08261 Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Wed, 7 Jan 2026 12:03:45 +0100 Subject: [PATCH 7/8] Remove unneeded import --- Sources/Services/ContainerAPIService/Client/FileDownloader.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift index 44e5cec5..ab540ef8 100644 --- a/Sources/Services/ContainerAPIService/Client/FileDownloader.swift +++ b/Sources/Services/ContainerAPIService/Client/FileDownloader.swift @@ -18,7 +18,6 @@ import AsyncHTTPClient import ContainerizationError import ContainerizationExtras import Foundation -import NIOSSL import TerminalProgress public struct FileDownloader { From 6925cf88e30cbf4641ed8573f298755b55de779a Mon Sep 17 00:00:00 2001 From: Sebastian Mossburger Date: Fri, 9 Jan 2026 09:11:07 +0100 Subject: [PATCH 8/8] Reduce env variables to "SSL_CERT_FILE" --- Sources/ContainerCommands/System/SystemStart.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ContainerCommands/System/SystemStart.swift b/Sources/ContainerCommands/System/SystemStart.swift index 4bc56f78..6cf62766 100644 --- a/Sources/ContainerCommands/System/SystemStart.swift +++ b/Sources/ContainerCommands/System/SystemStart.swift @@ -72,7 +72,7 @@ extension Application { var env = PluginLoader.filterEnvironment( env: ProcessInfo.processInfo.environment, - additionalAllowKeys: ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE"], + additionalAllowKeys: ["SSL_CERT_FILE"], ) env[ApplicationRoot.environmentName] = appRoot.path(percentEncoded: false) env[InstallRoot.environmentName] = installRoot.path(percentEncoded: false)