fix: pass NIXPACKS_NODE_VERSION as a CLI flag, not a process env var
All checks were successful
CI / test (push) Successful in 33s

nixpacks doesn't read NIXPACKS_* config from the process environment
at all, only from -e/--env on its own CLI — the "fix" from the
previous commit was silently a no-op (nixpacks plan still showed
nodejs_18 for a repo pinned to 20 that way). Caught because the first
real container built with it still crashed the same way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 04:51:31 +02:00
parent 9f88769922
commit 021fa2220e
2 changed files with 14 additions and 4 deletions

View File

@@ -61,7 +61,14 @@ express.json())`), since the proxy route needs the raw stream untouched.
Nixpacks does not fail when a repo's `engines`/version requirement isn't met — it silently falls back to its own default (e.g. picked Node 18 for a repo requiring Node >=20 in `Social-MCP`). The build goes green, then the container crashes at runtime (`crypto is not defined`, missing globals, etc.).
**Avoid it:** don't trust a green build as proof the runtime is correct. The manager now detects a Node version hint from the repo itself (`.nvmrc`, else `package.json` `engines.node`) and passes it to Nixpacks as `NIXPACKS_NODE_VERSION` (`apps/server/src/build/nixpacks.ts`, `detectNodeVersion`), so the build uses the version the repo actually declares instead of Nixpacks' own default. A Node repo (has `package.json`) with no hint of its own gets `DEFAULT_NODE_VERSION` (currently `20`) instead of falling through to Nixpacks' own default — confirmed necessary against a real repo (`ZenvairoSocial-MCP`, no `.nvmrc`/`engines.node` at all): build green, container crashed with "crypto is not defined" because Nixpacks picked Node 18, which predates stable `globalThis.crypto`.
**Avoid it:** don't trust a green build as proof the runtime is correct. The manager now detects a Node version hint from the repo itself (`.nvmrc`, else `package.json` `engines.node`) and passes it to Nixpacks (`apps/server/src/build/nixpacks.ts`, `detectNodeVersion`), so the build uses the version the repo actually declares instead of Nixpacks' own default. A Node repo (has `package.json`) with no hint of its own gets `DEFAULT_NODE_VERSION` (currently `20`) instead of falling through to Nixpacks' own default — confirmed necessary against a real repo (`ZenvairoSocial-MCP`, no `.nvmrc`/`engines.node` at all): build green, container crashed with "crypto is not defined" because Nixpacks picked Node 18, which predates stable `globalThis.crypto`.
**Gotcha inside the gotcha:** `nixpacks` does **not** read `NIXPACKS_*` config from the
process environment at all — only from its own `-e`/`--env` CLI flag. Setting
`NIXPACKS_NODE_VERSION` as a plain env var on the spawned process is silently ignored
(`nixpacks plan` still showed `nodejs_18`); the fix above only actually took effect once
passed as `nixpacks build ... -e NIXPACKS_NODE_VERSION=20`. Caught because the very first
container built after adding the "fix" still crashed the same way.
## Nixpacks needs a dependency manifest, and fails cleanly without one

View File

@@ -61,14 +61,17 @@ export function runNixpacksBuild(slug: string, repoDir: string, imageTag: string
fs.mkdirSync(path.dirname(logPath), { recursive: true });
const logStream = fs.createWriteStream(logPath, { flags: "a" });
const env = { ...process.env };
const args = ["build", repoDir, "--name", imageTag];
const nodeVersion = detectNodeVersion(repoDir);
if (nodeVersion) {
env.NIXPACKS_NODE_VERSION = nodeVersion;
// nixpacks does NOT read NIXPACKS_* config from the process environment — only from
// its own `-e`/`--env` CLI flag (confirmed: setting it as a plain env var is silently
// ignored, `nixpacks plan` still showed nodejs_18 for a repo pinned to 20 that way).
args.push("-e", `NIXPACKS_NODE_VERSION=${nodeVersion}`);
logStream.write(`[remote-mcp-manager] pinning NIXPACKS_NODE_VERSION=${nodeVersion}\n`);
}
const child = spawn("nixpacks", ["build", repoDir, "--name", imageTag], { env });
const child = spawn("nixpacks", args);
child.stdout.pipe(logStream, { end: false });
child.stderr.pipe(logStream, { end: false });