Skip to content

Plugin config (plugins.entries.<id>.config) has no env-var or writable-overlay path — every change requires image rebuild in policy-locked sandboxes #72950

@mayank6136

Description

@mayank6136

Summary

In plain English: plugin config (plugins.entries.<id>.config) is sourced from openclaw.json at startup — and that file is in a directory that NemoClaw makes read-only by Landlock policy at runtime. So a plugin like <observability-plugin> that needs per-deployment config (OTLP endpoint, service name, etc.) cannot be reconfigured after the sandbox is built; every config change requires a full image rebuild. There's no env-var override path and no writable-overlay path documented.

Companion issue planned against NVIDIA/NemoClaw to make plugin config writable from the policy side; this is the OpenClaw-core angle on the same problem.

Problem

The OpenClaw config schema currently sources plugin config from a single location: plugins.entries.<id>.config in openclaw.json. That file is in /sandbox/.openclaw/openclaw.json in NemoClaw, which is Landlock-RO at runtime per sandbox security policy. So:

  • Editing the file at runtime → EACCES, no useful diagnostic.
  • Plugin code can't read overrides from anywhere else.
  • Change config = full image rebuild (~5–10min).

For plugins that follow OTel ecosystem conventions, this is particularly awkward: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME, etc. are well-established standard env-vars, and the OpenTelemetry SDK reads them automatically. But the plugin can't pass them through if OpenClaw's config layer doesn't surface them — and OpenClaw's plugin-config schema currently has no env-var overlay support.

Suggested fix (in priority order)

1. Env-var overrides for plugin config

Allow plugins to declare which env vars override which config keys. Either:

  • Schema-level: plugins.entries.<id>.configEnv: { endpoint: "OTEL_EXPORTER_OTLP_ENDPOINT" } — OpenClaw resolves env-vars at startup, applies to config.
  • Or: pass process.env through to plugin's register(api) so the plugin can read its own env-vars.

2. Writable-overlay path for plugin config

Allow plugin config to source from a writable path AS WELL AS openclaw.json. e.g., /sandbox/.openclaw-data/plugin-config.json (which IS writable in NemoClaw) overlaid on top of openclaw.json. Plugin sees the merged result.

3. (Minimum) document the build-time-only constraint

If neither of the above is acceptable, at least document that plugin config is build-time-only in policy-locked environments and explain how plugins should be developed accordingly (e.g., consume only env vars, or expose a runtime config endpoint).

Repro

# 1. Build a NemoClaw sandbox with deep-observability plugin baked in (per
#    project setup; openclaw.json baked at build time with plugin config block).

# 2. Try to edit openclaw.json at runtime:
openshell sandbox exec -n nemoclaw-deepobs -- /bin/bash -c '
  sed -i "s|http://172.17.0.1:14318|https://example.com|" /sandbox/.openclaw/openclaw.json
'
# Output: sed: cannot rename /sandbox/.openclaw/sed3iy3v: Operation not permitted

# 3. The OPS path is to rebuild the image. Multi-minute round-trip per config tweak.

Why it matters

This compounds with the deploy/docker-compose architectural mismatch — when users debug span-not-landing issues under NemoClaw, they want to try different OTel endpoint configurations. Each attempt is a full image rebuild. The iteration cost discourages diagnosis. Eight cycles of "tweak endpoint → rebuild → test → no change" is what we did during this run; it didn't have to be that painful.

Alternatives considered

  • Hot-reload of openclaw.json: doesn't help if the file is RO at runtime.
  • Plugins read their own config independently from openclaw.json: breaks the unified-config contract that's already established.

Test plan

After fix #1 (env-var overrides):

  • Plugin config has endpoint: "http://default-endpoint" baked in.
  • Set OTEL_EXPORTER_OTLP_ENDPOINT=http://override.example.com in the sandbox env (via openshell sandbox-create env injection).
  • Plugin's actual exporter URL should be http://override.example.com/v1/traces.
  • Restart sandbox → endpoint persists per env, no image rebuild.

Risk / blast radius

  • Env-var overrides: medium risk for plugins that read config without expecting env-overlay (could surprise on existing deployments). Mitigated by making it opt-in at the plugin level (plugin declares which keys are env-overridable).
  • Writable-overlay: small risk; opt-in via config schema change.
  • Docs-only: zero risk.

Open questions for maintainers

  1. Is there architectural intent to keep plugin config strictly file-based? If so, what's the path forward for policy-locked environments?
  2. Companion: a NVIDIA/NemoClaw issue is planned suggesting NemoClaw expose a writable overlay path for plugin config. Which fix-side is preferred?
  3. The OTel ecosystem env-var conventions (OTEL_EXPORTER_OTLP_ENDPOINT, etc.) are well-established. Acceptable to lean on those rather than invent OpenClaw-specific ones?

Tested-against

  • OpenClaw v2026.4.9
  • NemoClaw v0.0.26 / OpenShell 0.0.36 (sandbox provider with Landlock RO)

Severity

Medium. Doesn't block functionality, but it's a development-velocity tax that compounds with other plugin issues. Anyone iterating on plugin config under NemoClaw will hit it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions