From 9ef2794577ad64f2520bebb90d8c73271a7cee80 Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 20 Apr 2026 12:50:56 -0700 Subject: [PATCH 1/2] fix: add auth proxy port to local-inference policy and fail on proxy startup error (#709) The local-inference policy preset only allowed port 11434 (direct Ollama) but on non-WSL systems containers route through the auth proxy on port 11435. This port mismatch caused HTTP 403/401 errors from inside sandboxes even with the local-inference policy enabled. Also upgrades the proxy startup failure from a warning to a hard error so onboarding does not continue with a broken provider configuration. --- nemoclaw-blueprint/policies/presets/local-inference.yaml | 7 +++++++ src/lib/onboard.ts | 5 ++++- test/policies.test.ts | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/nemoclaw-blueprint/policies/presets/local-inference.yaml b/nemoclaw-blueprint/policies/presets/local-inference.yaml index c692cdce252..f24cc44642b 100644 --- a/nemoclaw-blueprint/policies/presets/local-inference.yaml +++ b/nemoclaw-blueprint/policies/presets/local-inference.yaml @@ -16,6 +16,13 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + - host: host.openshell.internal + port: 11435 + protocol: rest + enforcement: enforce + rules: + - allow: { method: GET, path: "/**" } + - allow: { method: POST, path: "/**" } - host: host.openshell.internal port: 8000 protocol: rest diff --git a/src/lib/onboard.ts b/src/lib/onboard.ts index 133d6aab096..c2b3d5a388b 100644 --- a/src/lib/onboard.ts +++ b/src/lib/onboard.ts @@ -1912,7 +1912,10 @@ function startOllamaAuthProxy(): void { const pid = spawnOllamaAuthProxy(ollamaProxyToken); sleep(1); if (!isOllamaProxyProcess(pid)) { - console.error(` Warning: Ollama auth proxy did not start on :${OLLAMA_PROXY_PORT}`); + console.error(` Error: Ollama auth proxy failed to start on :${OLLAMA_PROXY_PORT}`); + console.error(` Containers will not be able to reach Ollama without the proxy.`); + console.error(` Check if port ${OLLAMA_PROXY_PORT} is already in use: lsof -ti :${OLLAMA_PROXY_PORT}`); + process.exit(1); } } diff --git a/test/policies.test.ts b/test/policies.test.ts index fac2571f5af..543dfef4b4d 100644 --- a/test/policies.test.ts +++ b/test/policies.test.ts @@ -155,10 +155,11 @@ describe("policies", () => { } }); - it("local-inference preset targets host.openshell.internal on Ollama and vLLM ports", () => { + it("local-inference preset targets host.openshell.internal on Ollama, proxy, and vLLM ports", () => { const content = policies.loadPreset("local-inference"); expect(content).toContain("host.openshell.internal"); expect(content).toContain("port: 11434"); + expect(content).toContain("port: 11435"); expect(content).toContain("port: 8000"); }); From c168878428ad92ac800315975e19f9e5ca71fd3f Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 20 Apr 2026 13:05:21 -0700 Subject: [PATCH 2/2] fix: return boolean from startOllamaAuthProxy, exit at call sites The previous process.exit(1) inside startOllamaAuthProxy broke 4 onboard-selection tests that mock runCapture but not child_process.spawn. Return a boolean instead and let the onboard flow call sites handle the failure. Update the 4 Ollama test mocks to handle the ps command used by isOllamaProxyProcess. --- src/lib/onboard.ts | 13 +++++++++---- test/onboard-selection.test.ts | 4 ++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/lib/onboard.ts b/src/lib/onboard.ts index c2b3d5a388b..9820c1476b8 100644 --- a/src/lib/onboard.ts +++ b/src/lib/onboard.ts @@ -1901,7 +1901,7 @@ function killStaleProxy(): void { } } -function startOllamaAuthProxy(): void { +function startOllamaAuthProxy(): boolean { const crypto = require("crypto"); killStaleProxy(); @@ -1915,8 +1915,9 @@ function startOllamaAuthProxy(): void { console.error(` Error: Ollama auth proxy failed to start on :${OLLAMA_PROXY_PORT}`); console.error(` Containers will not be able to reach Ollama without the proxy.`); console.error(` Check if port ${OLLAMA_PROXY_PORT} is already in use: lsof -ti :${OLLAMA_PROXY_PORT}`); - process.exit(1); + return false; } + return true; } /** @@ -4147,7 +4148,9 @@ async function setupNim(gpu) { // WSL2 doesn't need the proxy — Docker can reach the host directly. console.log(` ✓ Using Ollama on localhost:${OLLAMA_PORT}`); } else { - startOllamaAuthProxy(); + if (!startOllamaAuthProxy()) { + process.exit(1); + } console.log(` ✓ Using Ollama on localhost:${OLLAMA_PORT} (proxy on :${OLLAMA_PROXY_PORT})`); } provider = "ollama-local"; @@ -4207,7 +4210,9 @@ async function setupNim(gpu) { // Shell required: backgrounding (&), env var prefix, output redirection. run(`OLLAMA_HOST=0.0.0.0:${OLLAMA_PORT} ollama serve > /dev/null 2>&1 &`, { ignoreError: true }); sleep(2); - startOllamaAuthProxy(); + if (!startOllamaAuthProxy()) { + process.exit(1); + } console.log(` ✓ Using Ollama on localhost:${OLLAMA_PORT} (proxy on :${OLLAMA_PROXY_PORT})`); provider = "ollama-local"; credentialEnv = "OPENAI_API_KEY"; diff --git a/test/onboard-selection.test.ts b/test/onboard-selection.test.ts index bd078f9c2ff..22cf0605c05 100644 --- a/test/onboard-selection.test.ts +++ b/test/onboard-selection.test.ts @@ -611,6 +611,7 @@ runner.runCapture = (command) => { if (cmd.includes("ollama list")) return "nemotron-3-nano:30b abc 24 GB now"; if (cmd.includes("127.0.0.1:8000/v1/models")) return ""; if (cmd.includes("api/generate")) return '{"response":"hello"}'; + if (cmd.includes("-o args=")) return "node ollama-auth-proxy.js"; return ""; }; @@ -708,6 +709,7 @@ runner.runCapture = (command) => { if (cmd.includes("ollama list")) return "nemotron-3-nano:30b abc 24 GB now"; if (cmd.includes("127.0.0.1:8000/v1/models")) return ""; if (cmd.includes("api/generate")) return '{"response":"hello"}'; + if (cmd.includes("-o args=")) return "node ollama-auth-proxy.js"; return ""; }; @@ -811,6 +813,7 @@ runner.runCapture = (command) => { if (cmd.includes("ollama list")) return ""; if (cmd.includes("127.0.0.1:8000/v1/models")) return ""; if (cmd.includes("api/generate")) return '{"response":"hello"}'; + if (cmd.includes("-o args=")) return "node ollama-auth-proxy.js"; return ""; }; @@ -921,6 +924,7 @@ runner.runCapture = (command) => { if (cmd.includes("ollama list")) return ""; if (cmd.includes("127.0.0.1:8000/v1/models")) return ""; if (cmd.includes("api/generate")) return '{"response":"hello"}'; + if (cmd.includes("-o args=")) return "node ollama-auth-proxy.js"; return ""; };