Skip to content

fix: bind gateway to 0.0.0.0 and document remote dashboard access (Fixes #20)#114

Open
deepujain wants to merge 1 commit intoNVIDIA:mainfrom
deepujain:fix/20-remote-dashboard-bind
Open

fix: bind gateway to 0.0.0.0 and document remote dashboard access (Fixes #20)#114
deepujain wants to merge 1 commit intoNVIDIA:mainfrom
deepujain:fix/20-remote-dashboard-bind

Conversation

@deepujain
Copy link
Contributor

@deepujain deepujain commented Mar 17, 2026

Summary

When NemoClaw runs on a remote host, the dashboard gateway bound to 127.0.0.1, so forwarded browser connections could fail with "origin not allowed" or device-auth issues even when the port was forwarded. This change makes remote dashboard access work by binding the gateway to all interfaces by default and documenting the supported pattern.

Fixes #20.

Changes

  • scripts/nemoclaw-start.sh
    • Set gateway.bind to lan (OpenClaw listens on 0.0.0.0) so port-forwarding from the host reaches the gateway. Optional env GATEWAY_BIND (default lan; use loopback to restrict to 127.0.0.1).
    • Document CHAT_UI_URL and GATEWAY_BIND in the script header.
    • Delegate config write to scripts/write-openclaw-gateway-config.py for reuse and testing.
  • scripts/write-openclaw-gateway-config.py (new)
    • Standalone script that writes/updates OpenClaw gateway config (bind, controlUi, trustedProxies, default model). Uses OPENCLAW_JSON_PATH when set (for tests).
  • docs/deployment/deploy-to-remote-gpu.md
    • Added "Remote dashboard access" section: set CHAT_UI_URL to the browser origin, use SSH port-forward, and open the dashboard URL with token; note that gateway binds to 0.0.0.0 by default and device auth is disabled for the sandbox UI.
  • test/gateway-config.test.js (new)
    • Unit tests for the gateway config script: default gateway.bind === 'lan', GATEWAY_BIND=loopback honored, allowedOrigins includes local and CHAT_UI_URL origin, dangerouslyDisableDeviceAuth true.

Testing

  • npm test passes (including the new gateway-config tests).
  • No TypeScript under nemoclaw/ was changed; build step not run.

Summary by CodeRabbit

  • New Features

    • Remote dashboard access via SSH port‑forwarding with automatic origin handling
    • GATEWAY_BIND option to restrict gateway binding to loopback
    • Automatic generation/updating of gateway configuration at startup
  • Documentation

    • Step‑by‑step guide for connecting to the Control UI from a laptop, including token auth and port‑forwarding
    • Clarified CHAT_UI_URL and PUBLIC_PORT usage
  • Tests

    • Added tests validating generated gateway configuration, bind behavior, allowed origins, and device‑auth setting

@wscurran wscurran added enhancement New feature or request NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). labels Mar 19, 2026
@wscurran
Copy link
Contributor

Thanks for enhancing the gateway and making it more accessible, this will definitely improve the user experience for remote users.

@wscurran wscurran added the priority: medium Issue that should be addressed in upcoming releases label Mar 19, 2026
@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from c4a3c25 to f32c2b3 Compare March 20, 2026 00:49
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Python CLI to generate/update OpenClaw gateway config, updates the start script to export UI-related env vars and invoke the generator, documents SSH port‑forwarded remote dashboard access and GATEWAY_BIND, and adds tests validating the written gateway JSON.

Changes

Cohort / File(s) Summary
Documentation
docs/deployment/deploy-to-remote-gpu.md
Adds "Remote dashboard access" section with SSH port‑forwarding steps, requirement to set CHAT_UI_URL to the laptop origin, notes on #token=... auth fragment, and optional GATEWAY_BIND=loopback configuration.
Start script
scripts/nemoclaw-start.sh
Exports CHAT_UI_URL and PUBLIC_PORT, documents GATEWAY_BIND values, adds fix_openclaw_config() to compute script dir and run the new Python config writer, and calls it during startup before launching gateway.
Gateway config generator
scripts/write-openclaw-gateway-config.py
New executable that loads/creates openclaw.json (path from OPENCLAW_JSON_PATH or defaults), ensures parent dirs, sets agents.defaults.model.primary from NEMOCLAW_MODEL, computes controlUi.allowedOrigins from PUBLIC_PORT and CHAT_UI_URL, enforces gateway.mode="local", sets gateway.bind from GATEWAY_BIND (default lan), sets controlUi flags including dangerouslyDisableDeviceAuth: true, writes JSON with indentation and 0600 perms.
Tests
test/gateway-config.test.js
Adds tests that run the Python writer in a temp dir and assert gateway.bind default/override, controlUi.allowedOrigins includes local http://127.0.0.1:${PUBLIC_PORT} and CHAT_UI_URL origin, and dangerouslyDisableDeviceAuth is true.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant Laptop as "Laptop (ssh -L)"
  participant Remote as "Remote Gateway"
  participant Backend as "App Backend"

  Browser->>Laptop: Open http://127.0.0.1:18789/ (forwarded)
  Laptop->>Remote: SSH tunnel forwards localhost:18789 -> remote:18789
  Remote->>Remote: Validate Origin against allowedOrigins (PUBLIC_PORT, CHAT_UI_URL)
  Remote-->>Browser: Serve dashboard HTML (may include `#token` fragment)
  Browser->>Remote: Open websocket (origin matches, device auth disabled)
  Remote->>Backend: Proxy websocket/requests
  Backend-->>Browser: Responses via gateway
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I’m a rabbit on the network stream,
I stitch the tunnel, chase the scheme,
I write the gateway, set the port,
Token tucked in the URL fort —
Hop online, the dashboard gleams! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: binding gateway to 0.0.0.0 and documenting remote dashboard access, with reference to the fixed issue.
Linked Issues check ✅ Passed The pull request comprehensively addresses all acceptance criteria from #20: enables 0.0.0.0 binding via GATEWAY_BIND, honors dangerouslyDisableDeviceAuth, documents remote access, and includes automated tests.
Out of Scope Changes check ✅ Passed All changes directly support the objectives in issue #20: gateway configuration changes, documentation, and test coverage for remote dashboard access; no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@deepujain
Copy link
Contributor Author

Rebased onto latest main to resolve conflicts. Key change during rebase: updated write-openclaw-gateway-config.py to honor the new NEMOCLAW_MODEL env var conditionally (matching the Ollama integration merged upstream in #295) instead of hardcoding the default model. All gateway-config tests pass.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
docs/deployment/deploy-to-remote-gpu.md (2)

64-64: Multiple sentences on one line.

This line contains two independent clauses joined, making diffs harder to read. Split into separate lines.

Suggested fix
-When you access the dashboard from your laptop via SSH port-forward, set `CHAT_UI_URL` to the URL your browser will use so the gateway allows that origin and websocket connections succeed.
+When you access the dashboard from your laptop via SSH port-forward, set `CHAT_UI_URL` to the URL your browser uses.
+This ensures the gateway allows that origin and websocket connections succeed.

As per coding guidelines: "One sentence per line in source (makes diffs readable)."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` at line 64, The sentence mentioning
SSH port-forward and CHAT_UI_URL contains two independent clauses on one line;
edit the sentence so each independent clause is on its own line (i.e., split
into two lines), keeping the same wording and preserving the `CHAT_UI_URL`
reference and meaning so diffs are readable and follow "one sentence per line"
guidelines.

66-66: Passive voice detected.

"Device auth is disabled" uses passive voice. Per the style guide, active voice is required.

Suggested fix
-The gateway inside the sandbox binds to all interfaces (`0.0.0.0`) by default so that port-forwarding works. Device auth is disabled for the sandbox Control UI; use the token in the dashboard URL to authenticate.
+The gateway inside the sandbox binds to all interfaces (`0.0.0.0`) by default so that port-forwarding works.
+The sandbox Control UI disables device auth; use the token in the dashboard URL to authenticate.

As per coding guidelines: "Active voice required. Flag passive constructions."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` at line 66, The sentence "Device
auth is disabled for the sandbox Control UI; use the token in the dashboard URL
to authenticate." uses passive voice—reword it in active voice (e.g., "The
sandbox Control UI disables device auth; use the token in the dashboard URL to
authenticate.") so the documentation adheres to the active-voice style
guideline; update the sentence referencing "sandbox Control UI" and the token
usage accordingly.
test/gateway-config.test.js (2)

4-8: Inconsistent import style.

Lines 4-5 use the node: protocol prefix while lines 6-8 use bare module names. Consider using node: consistently for built-in modules.

Suggested fix
 const { describe, it } = require("node:test");
 const assert = require("node:assert/strict");
-const fs = require("fs");
-const path = require("path");
-const { execSync } = require("child_process");
+const fs = require("node:fs");
+const path = require("node:path");
+const { execSync } = require("node:child_process");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gateway-config.test.js` around lines 4 - 8, The imports use mixed
styles: `require("node:test")` and `require("node:assert/strict")` but the rest
use bare names (`fs`, `path`, `child_process`); update the requires for the
built-ins (`fs`, `path`, and `child_process`) to use the `node:` protocol so all
built-in modules are imported consistently (i.e., change the `require("fs")`,
`require("path")`, and `require("child_process")` usages that provide `fs`,
`path`, and `execSync` to `require("node:fs")`, `require("node:path")`, and
`require("node:child_process")` respectively).

13-20: Consider cleaning up temp directories after tests.

The runGatewayConfigScript helper creates temp directories that are never removed. While the OS cleans /tmp periodically, explicitly cleaning up prevents accumulation during repeated test runs.

Suggested approach
+const os = require("node:os");
+
 function runGatewayConfigScript(env = {}) {
-  const configDir = fs.mkdtempSync(path.join(require("os").tmpdir(), "nemoclaw-gateway-config-"));
+  const configDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-gateway-config-"));
   const configPath = path.join(configDir, "openclaw.json");
   const fullEnv = { ...process.env, OPENCLAW_JSON_PATH: configPath, ...env };
   execSync(`python3 "${PYTHON_SCRIPT}"`, { env: fullEnv, encoding: "utf-8" });
   const content = fs.readFileSync(configPath, "utf-8");
-  return { config: JSON.parse(content), configPath };
+  return { config: JSON.parse(content), configPath, cleanup: () => fs.rmSync(configDir, { recursive: true, force: true }) };
 }

Then call cleanup() after each test or use after() hooks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gateway-config.test.js` around lines 13 - 20, The helper
runGatewayConfigScript currently leaves temp directories behind; update it to
remove the temp directory after use (or return a cleanup function so callers can
remove it). Specifically, adjust runGatewayConfigScript to either (A) read the
file then delete configDir with fs.rmSync(configDir, { recursive: true, force:
true }) before returning, or (B) return { config, configPath, cleanup: () =>
fs.rmSync(configDir, { recursive: true, force: true }) } and update tests to
call cleanup() in an after/afterEach hook; reference the function name
runGatewayConfigScript and the local variable configDir/configPath to locate
where to add the removal logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/deployment/deploy-to-remote-gpu.md`:
- Around line 69-75: Update the two CLI code blocks that currently use the bash
fence to use the console fence and add a leading "$ " prompt to each command;
specifically change the block containing export
CHAT_UI_URL="http://YOUR_HOST_IP_OR_NAME:18789" and the block containing ssh -L
18789:localhost:18789 <instance-name> so their fences are ```console and each
command line begins with "$ ".

In `@scripts/write-openclaw-gateway-config.py`:
- Around line 19-22: The code currently calls json.load(f) into cfg when the
file at config_path exists but doesn't catch malformed JSON; wrap the
json.load(...) call in a try/except that catches json.JSONDecodeError (and
optionally ValueError), log a clear error mentioning config_path and the
exception (or print to stderr), and then either exit with a non‑zero status or
fall back to an empty cfg; update the block around config_path, cfg and the
json.load call to implement this handling so the script no longer crashes on
invalid JSON.
- Around line 39-43: The code currently assigns gateway['controlUi'] = { ... }
which overwrites any existing controlUi config; update the assignment to merge
with existing values (e.g., use gateway.setdefault('controlUi', {}) and
gateway['controlUi'].setdefault('allowInsecureAuth', True) /
.setdefault('dangerouslyDisableDeviceAuth', True) /
.setdefault('allowedOrigins', origins)) so existing keys are preserved, or if
intentional, add a concise comment next to the gateway['controlUi'] block
stating that sandbox defaults intentionally replace any preexisting controlUi
settings for clarity and consistency with the earlier use of setdefault().

---

Nitpick comments:
In `@docs/deployment/deploy-to-remote-gpu.md`:
- Line 64: The sentence mentioning SSH port-forward and CHAT_UI_URL contains two
independent clauses on one line; edit the sentence so each independent clause is
on its own line (i.e., split into two lines), keeping the same wording and
preserving the `CHAT_UI_URL` reference and meaning so diffs are readable and
follow "one sentence per line" guidelines.
- Line 66: The sentence "Device auth is disabled for the sandbox Control UI; use
the token in the dashboard URL to authenticate." uses passive voice—reword it in
active voice (e.g., "The sandbox Control UI disables device auth; use the token
in the dashboard URL to authenticate.") so the documentation adheres to the
active-voice style guideline; update the sentence referencing "sandbox Control
UI" and the token usage accordingly.

In `@test/gateway-config.test.js`:
- Around line 4-8: The imports use mixed styles: `require("node:test")` and
`require("node:assert/strict")` but the rest use bare names (`fs`, `path`,
`child_process`); update the requires for the built-ins (`fs`, `path`, and
`child_process`) to use the `node:` protocol so all built-in modules are
imported consistently (i.e., change the `require("fs")`, `require("path")`, and
`require("child_process")` usages that provide `fs`, `path`, and `execSync` to
`require("node:fs")`, `require("node:path")`, and
`require("node:child_process")` respectively).
- Around line 13-20: The helper runGatewayConfigScript currently leaves temp
directories behind; update it to remove the temp directory after use (or return
a cleanup function so callers can remove it). Specifically, adjust
runGatewayConfigScript to either (A) read the file then delete configDir with
fs.rmSync(configDir, { recursive: true, force: true }) before returning, or (B)
return { config, configPath, cleanup: () => fs.rmSync(configDir, { recursive:
true, force: true }) } and update tests to call cleanup() in an after/afterEach
hook; reference the function name runGatewayConfigScript and the local variable
configDir/configPath to locate where to add the removal logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6e4ebaca-58e8-437a-a420-df6815f443a7

📥 Commits

Reviewing files that changed from the base of the PR and between dbfd78c and f32c2b3.

📒 Files selected for processing (4)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/nemoclaw-start.sh
  • scripts/write-openclaw-gateway-config.py
  • test/gateway-config.test.js

@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from f32c2b3 to 67a6002 Compare March 20, 2026 01:14
@deepujain
Copy link
Contributor Author

Addressed all CodeRabbit review comments

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/deployment/deploy-to-remote-gpu.md (1)

70-70: Use present tense in the setup instruction.

Line 70 uses future tense (“you will use”). Rewrite it in present tense (for example, “the origin you use in the browser”) to match the docs voice standard.

As per coding guidelines, “Present tense. Flag future tense (‘will’) in descriptions of current behavior.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` at line 70, Change the sentence "On
the remote host, ensure the sandbox is started with the origin you will use in
the browser, for example:" to present tense by replacing "you will use" with
"you use" (i.e., "On the remote host, ensure the sandbox is started with the
origin you use in the browser, for example:") so the setup instruction in the
deploy-to-remote-gpu documentation follows the present-tense docs voice.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/deployment/deploy-to-remote-gpu.md`:
- Line 70: Change the sentence "On the remote host, ensure the sandbox is
started with the origin you will use in the browser, for example:" to present
tense by replacing "you will use" with "you use" (i.e., "On the remote host,
ensure the sandbox is started with the origin you use in the browser, for
example:") so the setup instruction in the deploy-to-remote-gpu documentation
follows the present-tense docs voice.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2fe373f0-ef90-4e90-b8c3-ca6b70b6c663

📥 Commits

Reviewing files that changed from the base of the PR and between f32c2b3 and 67a6002.

📒 Files selected for processing (4)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/nemoclaw-start.sh
  • scripts/write-openclaw-gateway-config.py
  • test/gateway-config.test.js
✅ Files skipped from review due to trivial changes (1)
  • scripts/write-openclaw-gateway-config.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/gateway-config.test.js
  • scripts/nemoclaw-start.sh

@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from 67a6002 to 21cc648 Compare March 21, 2026 23:09
@deepujain
Copy link
Contributor Author

Addressed the CodeRabbit nitpick. Rebased on main, resolved conflicts .

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/gateway-config.test.js`:
- Around line 14-21: The temp directory created in runGatewayConfigScript can
leak if execSync or JSON.parse throws; wrap the body that creates/uses configDir
in a try/finally so fs.rmSync(configDir, { recursive: true, force: true })
always runs, and rethrow (or let) the original error after cleanup; keep use of
configPath, config, and fullEnv unchanged and ensure the function still returns
the parsed config when no error occurs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 66e5fe22-b5c8-41d7-80d7-9a7a0761df74

📥 Commits

Reviewing files that changed from the base of the PR and between 67a6002 and 21cc648.

📒 Files selected for processing (4)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/nemoclaw-start.sh
  • scripts/write-openclaw-gateway-config.py
  • test/gateway-config.test.js
✅ Files skipped from review due to trivial changes (1)
  • scripts/write-openclaw-gateway-config.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/nemoclaw-start.sh

@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from 21cc648 to d175e5c Compare March 22, 2026 00:16
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/deployment/deploy-to-remote-gpu.md (1)

70-70: Use periods instead of colons before the code blocks in these steps.

Line 70 and Line 74 use colons as general punctuation before examples; this page style reserves colons for introducing lists.

As per coding guidelines, "Colons should only introduce a list. Flag colons used as general punctuation between clauses."

Also applies to: 74-74

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` at line 70, Replace the use of
colons as general punctuation before the inline/example code blocks in the
sentences "On the remote host, ensure the sandbox is started with the origin you
use in the browser, for example:" and the similar sentence at the other
occurrence (line containing "for example:") — change the trailing colon to a
period and ensure the following code block remains directly beneath the sentence
so the colon is only used for lists per style guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/deployment/deploy-to-remote-gpu.md`:
- Line 70: Replace the use of colons as general punctuation before the
inline/example code blocks in the sentences "On the remote host, ensure the
sandbox is started with the origin you use in the browser, for example:" and the
similar sentence at the other occurrence (line containing "for example:") —
change the trailing colon to a period and ensure the following code block
remains directly beneath the sentence so the colon is only used for lists per
style guidelines.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ddca0bb2-911e-4dbc-8e78-1f662b1a6a1c

📥 Commits

Reviewing files that changed from the base of the PR and between 21cc648 and d175e5c.

📒 Files selected for processing (4)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/nemoclaw-start.sh
  • scripts/write-openclaw-gateway-config.py
  • test/gateway-config.test.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/gateway-config.test.js
  • scripts/write-openclaw-gateway-config.py

@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from d175e5c to d0a0afa Compare March 24, 2026 00:59
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/nemoclaw-start.sh (1)

19-22: Consider declaring SCRIPTS_DIR as local.

SCRIPTS_DIR is only used within this function but isn't declared local, so it leaks into the global shell namespace.

♻️ Suggested improvement
 fix_openclaw_config() {
-  SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)"
+  local SCRIPTS_DIR
+  SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)"
   python3 "${SCRIPTS_DIR}/write-openclaw-gateway-config.py"
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/nemoclaw-start.sh` around lines 19 - 22, The function
fix_openclaw_config declares SCRIPTS_DIR without scoping, leaking it into the
global shell namespace; make SCRIPTS_DIR a local variable by declaring it local
inside fix_openclaw_config (referencing SCRIPTS_DIR and the fix_openclaw_config
function that computes the script path used to call
write-openclaw-gateway-config.py) so the variable is confined to the function's
scope.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/nemoclaw-start.sh`:
- Around line 19-22: The function fix_openclaw_config declares SCRIPTS_DIR
without scoping, leaking it into the global shell namespace; make SCRIPTS_DIR a
local variable by declaring it local inside fix_openclaw_config (referencing
SCRIPTS_DIR and the fix_openclaw_config function that computes the script path
used to call write-openclaw-gateway-config.py) so the variable is confined to
the function's scope.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 76bcca86-75af-4cd4-ab05-090251c961ac

📥 Commits

Reviewing files that changed from the base of the PR and between d175e5c and d0a0afa.

📒 Files selected for processing (4)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/nemoclaw-start.sh
  • scripts/write-openclaw-gateway-config.py
  • test/gateway-config.test.js
✅ Files skipped from review due to trivial changes (2)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/write-openclaw-gateway-config.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/gateway-config.test.js

Copy link
Contributor

@cv cv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not ready to merge — needs reconciliation with several in-flight PRs and current main.

Stale against main

nemoclaw-start.sh has diverged. Main now locks openclaw.json to root-owned mode 444 and verifies its SHA-256 hash at startup. The write-openclaw-gateway-config.py script writes to openclaw.json at runtime, which will either fail against the locked file or require undoing the security hardening.

Conflicts with #721 (gateway isolation)

#721 restructures the entire entrypoint with gosu privilege separation, PATH hardening, and config integrity checks. If #721 merges first, this PR will conflict heavily. The runtime config write approach is incompatible with #721's security model — gateway config changes would need to happen at build time or through a different mechanism (e.g., environment variables that the gateway reads directly, rather than rewriting the JSON).

Overlaps with #740

PR #740 solves the same remote dashboard access problem by wildcarding allowedOrigins in the Dockerfile. These two PRs should be reconciled — either the dynamic approach here or the static approach in #740, not both.

dangerouslyDisableDeviceAuth: true is unconditional

There's no way to opt out. This weakens the auth model for all deployments, including ones that don't need remote access. Should be conditional on GATEWAY_BIND=lan or a separate opt-in env var.

Tests are good

The Python script is clean, testable, and the vitest tests use proper temp directory isolation.

 NVIDIA#20)

- Set gateway.bind to lan in sandbox so port-forward works; optional GATEWAY_BIND env.
- Extract gateway config to write-openclaw-gateway-config.py for tests.
- Add Remote dashboard access section to deploy-to-remote-gpu.md.
- Add test/gateway-config.test.js for bind and allowedOrigins.
- Address CodeRabbit review: console fences, active voice, JSON error handling, temp cleanup.

Fixes NVIDIA#20

Signed-off-by: Deepak Jain <deepujain@gmail.com>
@deepujain deepujain force-pushed the fix/20-remote-dashboard-bind branch from d0a0afa to 25ec520 Compare March 24, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). priority: medium Issue that should be addressed in upcoming releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make remote-host dashboard access work over SSH by binding to a reachable address and honoring disabled device auth

3 participants