fix(core): inject NO_PROXY into waitForHttp loopback probes (#4181)#4215
Conversation
) waitForHttp() spawns curl via spawnSync({ stdio: "ignore" }) with no env override, so the child curl inherits HTTP_PROXY / http_proxy from the user shell. When the user runs nemoclaw onboard behind Privoxy or a corporate proxy that does not bypass loopback (a common macOS setup), curl tunnels http://127.0.0.1:<port>/ through the proxy, which returns 503, and waitForHttp reports the service as unhealthy. Symptom on macOS: "Install Ollama (macOS)" prompt instead of "Local Ollama -- running", even though brew installed ollama and ollama serve is healthy on :11434. Build the curl child env through the existing withLocalNoProxy() helper (src/lib/subprocess-env.ts) so localhost, 127.0.0.1, host.docker.internal, ::1 and 0.0.0.0 are added to NO_PROXY / no_proxy whenever any HTTP_PROXY is set. waitForPort() uses nc and does not need the fix. Tests: 3 new cases on buildLoopbackProbeEnv covering the no-proxy, HTTP_PROXY-set, and pre-existing-NO_PROXY-entries scenarios. 6 wait + 14 subprocess-env + 3 credential-exposure tests pass in the container. Closes NVIDIA#4181. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR fixes HTTP readiness checks failing when ChangesLoopback Proxy Environment Handling
Sequence DiagramsequenceDiagram
participant waitForHttp
participant buildLoopbackProbeEnv
participant curl
participant localhost_service
waitForHttp->>buildLoopbackProbeEnv: request adjusted env (with NO_PROXY)
buildLoopbackProbeEnv-->>waitForHttp: return env {NO_PROXY: "localhost,127.0.0.1,..."}
waitForHttp->>curl: spawnSync("curl", ..., env=adjustedEnv)
curl->>localhost_service: direct HTTP request (proxy bypassed)
localhost_service-->>curl: 200 OK
curl-->>waitForHttp: exit status 0
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
✨ Thanks for submitting this detailed PR about fixing the Ollama readiness check issue on macOS. This proposes a way to inject NO_PROXY into waitForHttp loopback probes, ensuring that curl bypasses the user's HTTP_PROXY for localhost probes, which should resolve the issue where the wizard reports Ollama as not ready and falls back to the provider menu. Related open issues: |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Summary
waitForHttp()insrc/lib/core/wait.tsnow spawns itscurlprobe with a loopback-safe environment so health checks forlocalhost/127.0.0.1services (Ollama, gateway, dashboard) bypass any user-configuredHTTP_PROXY/http_proxyinstead of tunneling loopback requests through the proxy and failing.Problem
During
nemoclaw onboard, selecting "Install Ollama (macOS)" installs Ollama via Homebrew andollama servebecomes healthy on:11434, yet the wizard reports "Ollama did not become ready on :11434" and falls back to the provider menu. The provider menu then keeps offering "Install Ollama (macOS)" instead of "Local Ollama - running" on subsequent runs.Root cause:
waitForHttp()spawnedcurlwith{ stdio: "ignore" }and noenvoverride, so the childcurlinherited the ambientHTTP_PROXY/http_proxy. When that proxy does not bypass loopback (a common Privoxy setup on macOS),curltunnelshttp://127.0.0.1:11434/through the proxy, which returns 503, so the readiness probe fails for the entire deadline.The codebase already documents this pattern in
src/lib/onboard/http-proxy-preflight.ts("NemoClaw injects NO_PROXY for its own subprocess spawns") and thewithLocalNoProxy()helper insrc/lib/subprocess-env.tsalready implements it;waitForHttp()was the one subprocess spawn that was not going through that path.A standalone repro confirms the mechanism: with
http_proxy=http://203.0.113.1:9 curl -v --connect-timeout 1 --max-time 1 http://127.0.0.1:14999/,curlroutes to203.0.113.1:9; onceNO_PROXY=localhost,127.0.0.1is set,curlconnects directly to the loopback target.Related Issue
Closes #4181
Changes
waitForHttp()insrc/lib/core/wait.tsnow passes acurl-friendly env to itsspawnSyncso loopback probes (Ollama, gateway, dashboard) bypass any userHTTP_PROXY/http_proxy.buildLoopbackProbeEnv()helper that reuses the existingwithLocalNoProxy()helper insrc/lib/subprocess-env.ts, so the set of bypassed hosts (localhost,127.0.0.1,host.docker.internal,::1,0.0.0.0) stays consistent with every other NemoClaw subprocess.waitForPort()usesncand does not readHTTP_PROXY, so it is left unchanged.Type of Change
Verification
npx prek run --all-filespassesnpm testpassesnpm run docsbuilds without warnings (doc changes only)Ran:
npx vitest run test/wait.test.ts(6/6 pass, including 3 new cases forbuildLoopbackProbeEnv()covering the no-proxy,HTTP_PROXY-set, and pre-existing-NO_PROXY-entries paths);npx vitest run test/wait.test.ts src/lib/subprocess-env.test.ts test/credential-exposure.test.ts(23/23 pass, verifying no regression for thewithLocalNoProxyconsumers and the env-leak boundary);npx tsc --noEmit -p tsconfig.src.jsonclean.Signed-off-by: latenighthackathon latenighthackathon@users.noreply.github.com
Summary by CodeRabbit
Bug Fixes
Tests