mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(docker): restore config parent ownership
This commit is contained in:
@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Gateway/perf: tighten restart and startup benchmark failure handling so long profiling runs, failed probes, and fresh Linux runners no longer produce false passing or `n/a` results.
|
||||
- Checks: keep intentional Knip unused-file findings optional so full CI and sparse proof workspaces stay aligned.
|
||||
- Docker: restore writable `~/.config` in runtime images. Fixes #85968. Thanks @hkoessler and @Bartok9.
|
||||
- Tests: normalize bundled plugin lifecycle probe paths and state-root lookup so native Windows release sweeps accept valid packaged plugin installs.
|
||||
- Config: keep benign legacy metadata write anomalies out of default doctor and config command output while preserving explicit anomaly logging for diagnostics.
|
||||
- Codex: log when implicit app-server `never` approvals are promoted for OpenClaw tool policy, including whether the trigger was a `before_tool_call` hook or trusted tool policy.
|
||||
|
||||
@@ -287,12 +287,17 @@ RUN ln -sf /app/openclaw.mjs /usr/local/bin/openclaw \
|
||||
|
||||
# Pre-create default named-volume mount points so first-run Docker volumes copy
|
||||
# node ownership from the image instead of starting as root-owned directories.
|
||||
RUN install -d -m 0700 -o node -g node \
|
||||
# NOTE: /home/node/.config must be created with node ownership first so that
|
||||
# the leaf /home/node/.config/openclaw inherits the correct parent permissions.
|
||||
# Without this, install -d leaves /home/node/.config as root:root (issue #85968).
|
||||
RUN install -d -m 0755 -o node -g node /home/node/.config && \
|
||||
install -d -m 0700 -o node -g node \
|
||||
/home/node/.openclaw \
|
||||
/home/node/.openclaw/workspace \
|
||||
/home/node/.config/openclaw && \
|
||||
stat -c '%U:%G %a' /home/node/.openclaw | grep -qx 'node:node 700' && \
|
||||
stat -c '%U:%G %a' /home/node/.openclaw/workspace | grep -qx 'node:node 700' && \
|
||||
stat -c '%U:%G %a' /home/node/.config | grep -qx 'node:node 755' && \
|
||||
stat -c '%U:%G %a' /home/node/.config/openclaw | grep -qx 'node:node 700'
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
@@ -554,6 +554,7 @@ echo "==> Fixing data-directory permissions"
|
||||
# (.openclaw/) inside the workspace gets chowned, not the user's project files.
|
||||
run_prestart_gateway --user root --entrypoint sh openclaw-gateway -c \
|
||||
'find /home/node/.openclaw -xdev -exec chown node:node {} +; \
|
||||
chown node:node /home/node/.config; \
|
||||
find /home/node/.config/openclaw -xdev -exec chown node:node {} +; \
|
||||
[ -d /home/node/.openclaw/workspace/.openclaw ] && chown -R node:node /home/node/.openclaw/workspace/.openclaw || true'
|
||||
|
||||
|
||||
@@ -482,6 +482,7 @@ describe("scripts/docker/setup.sh", () => {
|
||||
expect(chownIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(onboardIdx).toBeGreaterThan(chownIdx);
|
||||
expect(log).toContain("run --rm --no-deps --user root --entrypoint sh openclaw-gateway -c");
|
||||
expect(log).toContain("chown node:node /home/node/.config");
|
||||
});
|
||||
|
||||
it("precreates auth profile secret key dir outside the mounted state dir", async () => {
|
||||
|
||||
@@ -327,15 +327,24 @@ describe("Dockerfile", () => {
|
||||
it("pre-creates named-volume mount points before switching to the node user", async () => {
|
||||
const dockerfile = await readFile(dockerfilePath, "utf8");
|
||||
const runtimeStageIndex = dockerfile.lastIndexOf("FROM base-runtime");
|
||||
const stateDirIndex = dockerfile.indexOf(
|
||||
"RUN install -d -m 0700 -o node -g node \\",
|
||||
const parentConfigDirIndex = dockerfile.indexOf(
|
||||
"RUN install -d -m 0755 -o node -g node /home/node/.config",
|
||||
runtimeStageIndex,
|
||||
);
|
||||
const stateDirIndex = dockerfile.indexOf(
|
||||
"install -d -m 0700 -o node -g node \\",
|
||||
parentConfigDirIndex,
|
||||
);
|
||||
const userIndex = dockerfile.indexOf("USER node", runtimeStageIndex);
|
||||
|
||||
expect(runtimeStageIndex).toBeGreaterThan(-1);
|
||||
// Regression: /home/node/.config parent must be created with node ownership
|
||||
// before the leaf .config/openclaw dir (issue #85968).
|
||||
expect(parentConfigDirIndex).toBeGreaterThan(-1);
|
||||
expect(stateDirIndex).toBeGreaterThan(-1);
|
||||
expect(userIndex).toBeGreaterThan(-1);
|
||||
expect(parentConfigDirIndex).toBeGreaterThan(runtimeStageIndex);
|
||||
expect(parentConfigDirIndex).toBeLessThan(stateDirIndex);
|
||||
expect(stateDirIndex).toBeGreaterThan(runtimeStageIndex);
|
||||
expect(stateDirIndex).toBeLessThan(userIndex);
|
||||
expect(dockerfile).not.toContain("mkdir -p /home/node/.openclaw");
|
||||
@@ -347,6 +356,10 @@ describe("Dockerfile", () => {
|
||||
expect(dockerfile).toContain(
|
||||
"stat -c '%U:%G %a' /home/node/.openclaw/workspace | grep -qx 'node:node 700'",
|
||||
);
|
||||
// Regression: assert parent /home/node/.config is also node-owned (issue #85968).
|
||||
expect(dockerfile).toContain(
|
||||
"stat -c '%U:%G %a' /home/node/.config | grep -qx 'node:node 755'",
|
||||
);
|
||||
expect(dockerfile).toContain(
|
||||
"stat -c '%U:%G %a' /home/node/.config/openclaw | grep -qx 'node:node 700'",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user