fix(docker): install ca-certificates so git can clone over HTTPS

Operator hit "Git clone failed: ... server certificate verification failed.
CAfile: none CRLfile: none" the moment they tried to add a project in the
container.

The runner stage installed git but not ca-certificates, and the slim base ships
zero CA certificates (/etc/ssl/certs was empty). git verifies TLS against the
SYSTEM trust store, so every HTTPS remote failed and project setup — the first
thing anyone does after logging in — was impossible in Docker.

It hid because Node carries its OWN bundled CA store: the dashboard, model API
calls, and the OAuth token exchanges against platform.claude.com and OpenAI all
worked fine, so the image looked healthy right up until the first clone. Nothing
else in the image exercises the system trust store, so a guard is added rather
than trusting someone to notice next time.

Verified in the running container: installing ca-certificates took it from 0 to
301 certs and `git clone https://github.com/Runfusion/Fusion.git` then succeeded
as the node user.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-08-17 22:21:13 -07:00
parent 9eae6b9bc5
commit 3105b06102
3 changed files with 39 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Fix HTTPS git clones failing in Docker with "server certificate verification failed".
category: fix
dev: The runner stage installed `git` but not `ca-certificates`, and the slim base ships zero CA certificates. git verifies TLS against the SYSTEM trust store, so every HTTPS clone failed and project setup was impossible in a container. It stayed hidden because Node carries its own bundled CA store — the dashboard, model APIs, and OAuth token exchanges all worked. Guarded by a new assertion in scripts/__tests__/dockerfile-workspace-manifests.test.mjs.

View File

@@ -68,8 +68,14 @@ LABEL org.opencontainers.image.description="AI-orchestrated task board"
ENV NODE_ENV=production
ENV PORT=4040
# FNXC:DockerRun 2026-08-18-05:35: ca-certificates is REQUIRED, not optional hardening. The slim
# base ships zero CA certificates, and git verifies TLS against the SYSTEM store — so every HTTPS
# clone failed with "server certificate verification failed. CAfile: none CRLfile: none", which
# breaks project setup outright (operator report). It hid behind Node, which carries its own bundled
# CA store: the dashboard, model APIs, and OAuth token exchanges all worked, so the image looked
# healthy right up until the first clone.
RUN apt-get update \
&& apt-get install -y --no-install-recommends git \
&& apt-get install -y --no-install-recommends git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN corepack enable && corepack prepare pnpm@10.33.0 --activate

View File

@@ -102,3 +102,28 @@ test("coverage ignores post-install and runner copies while tolerating removed p
"removed or nonexistent COPY paths must not affect selected workspace coverage",
);
});
/*
FNXC:DockerRun 2026-08-18-05:35:
The runner stage MUST install ca-certificates. The slim base ships none, and git verifies TLS
against the system store, so without it every HTTPS clone dies with "server certificate
verification failed. CAfile: none CRLfile: none" and project setup is impossible in Docker.
This regressed unnoticed because Node carries its OWN bundled CA store: the dashboard, model APIs
and OAuth token exchanges all worked, so nothing looked wrong until the first clone. Nothing else
in the image exercises the system trust store, which is exactly why it needs a guard rather than
relying on someone noticing.
*/
test("runner stage installs ca-certificates alongside git", () => {
const dockerfile = readFileSync(path.join(repoRoot, "Dockerfile"), "utf8");
const runnerStage = dockerfile.slice(dockerfile.indexOf("FROM node:22-slim AS runner"));
assert.ok(runnerStage.length > 0, "runner stage must exist");
const aptInstall = runnerStage.match(/apt-get install[^\n]*(?:\\\n[^\n]*)*/)?.[0] ?? "";
assert.match(aptInstall, /\bgit\b/, "runner stage must install git");
assert.match(
aptInstall,
/\bca-certificates\b/,
"runner stage must install ca-certificates — git cannot verify HTTPS remotes without a system CA bundle",
);
});