mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(docker): keep setup chown from following symlinks (#107847)
* Fix Docker setup chown symlink handling * fix(docker): harden setup ownership repair Co-authored-by: luyifan <al3060388206@gmail.com> * fix(docker): pin ownership repair path * test(docker): assert ownership setup ordering --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me>
This commit is contained in:
+10
-4
@@ -792,13 +792,19 @@ echo "==> Fixing data-directory permissions"
|
||||
# Use -xdev to restrict chown to the config-dir mount only — without it,
|
||||
# the recursive chown would cross into the workspace bind mount and rewrite
|
||||
# ownership of all user project files on Linux hosts.
|
||||
# Run a no-dereference chown from each entry's directory. This keeps ownership
|
||||
# repair for sockets/FIFOs while preventing a swapped symlink leaf from
|
||||
# redirecting the root operation outside the mounted tree.
|
||||
# After fixing the config dir, only the OpenClaw metadata subdirectory
|
||||
# (.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'
|
||||
'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH; \
|
||||
/usr/bin/find -P /home/node/.openclaw -xdev -execdir /usr/bin/chown -h node:node {} +; \
|
||||
/usr/bin/chown -h node:node /home/node/.config; \
|
||||
/usr/bin/find -P /home/node/.config/openclaw -xdev -execdir /usr/bin/chown -h node:node {} +; \
|
||||
if [ -d /home/node/.openclaw/workspace/.openclaw ] && [ ! -L /home/node/.openclaw/workspace/.openclaw ]; then \
|
||||
/usr/bin/find -P /home/node/.openclaw/workspace/.openclaw -xdev -execdir /usr/bin/chown -h node:node {} +; \
|
||||
fi || true'
|
||||
|
||||
echo ""
|
||||
if [[ -n "$SKIP_ONBOARDING" ]]; then
|
||||
|
||||
@@ -179,6 +179,10 @@ const prestartContainerEnvFlags = [
|
||||
"-e OPENCLAW_WORKSPACE_DIR=/home/node/.openclaw/workspace",
|
||||
].join(" ");
|
||||
|
||||
const noFollowOwnershipRepair = (root: string) =>
|
||||
`/usr/bin/find -P ${root} -xdev -execdir /usr/bin/chown -h node:node {} +`;
|
||||
const prestartSafePath = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
||||
|
||||
function createEnv(
|
||||
sandbox: DockerSetupSandbox,
|
||||
overrides: Record<string, string | undefined> = {},
|
||||
@@ -847,11 +851,24 @@ describe("scripts/docker/setup.sh", () => {
|
||||
// Verify that a root-user chown step runs before setup.
|
||||
const log = await readDockerLog(activeSandbox);
|
||||
const chownIdx = log.indexOf("--user root");
|
||||
const safePathIdx = log.indexOf(`${prestartSafePath}; export PATH`);
|
||||
const stateRepairIdx = log.indexOf(noFollowOwnershipRepair("/home/node/.openclaw"));
|
||||
const onboardIdx = log.indexOf("onboard");
|
||||
expect(chownIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(safePathIdx).toBeGreaterThan(chownIdx);
|
||||
expect(stateRepairIdx).toBeGreaterThan(safePathIdx);
|
||||
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");
|
||||
expect(log).toContain("/usr/bin/chown -h node:node /home/node/.config");
|
||||
expect(log).toContain(noFollowOwnershipRepair("/home/node/.openclaw"));
|
||||
expect(log).toContain(noFollowOwnershipRepair("/home/node/.config/openclaw"));
|
||||
expect(log).toContain("[ ! -L /home/node/.openclaw/workspace/.openclaw ]");
|
||||
expect(log).toContain(noFollowOwnershipRepair("/home/node/.openclaw/workspace/.openclaw"));
|
||||
expect(log).toContain("fi || true");
|
||||
expect(log).not.toContain("-type d -o -type f");
|
||||
expect(log).not.toContain("-exec chown");
|
||||
expect(log).not.toContain(" chown node:node");
|
||||
expect(log).not.toContain("chown -R node:node /home/node/.openclaw/workspace/.openclaw");
|
||||
});
|
||||
|
||||
it("precreates auth profile secret key dir outside the mounted state dir", async () => {
|
||||
@@ -872,7 +889,7 @@ describe("scripts/docker/setup.sh", () => {
|
||||
expect(secretDir.startsWith(`${configDir}/`)).toBe(false);
|
||||
|
||||
const log = await readDockerLog(activeSandbox);
|
||||
expect(log).toContain("find /home/node/.config/openclaw -xdev");
|
||||
expect(log).toContain(noFollowOwnershipRepair("/home/node/.config/openclaw"));
|
||||
});
|
||||
|
||||
it("reuses existing config token when OPENCLAW_GATEWAY_TOKEN is unset", async () => {
|
||||
|
||||
Reference in New Issue
Block a user