fix(rootless): auto-fix data-directory ownership for Docker rootless mode #1708
fix(rootless): auto-fix data-directory ownership for Docker rootless mode #1708IronicRayquaza wants to merge 3 commits into
Conversation
…mode Fixes Osmantic#1702 In Docker rootless mode, container UIDs are shifted by the host user's subuid offset (typically 100000). Containers that run as a non-root UID N map to host UID (100000 + N - 1). The installer creates data directories owned by the host user (UID 1000), making them unwritable to those remapped container UIDs. Changes ------- lib/rootless-fix.sh (new) - ods_is_rootless_docker — detects rootless mode via 'docker info --format {{.SecurityOptions}} | grep rootless' - _ods_rootless_chown_dir — chowns one dir using a short-lived Alpine container run as UID 0 (= host user in rootless mode), so no sudo is required - ods_fix_rootless_ownership — idempotent driver; only runs when rootless is detected; iterates the ODS_ROOTLESS_UID_MAP covering all 9 affected services (n8n, hermes, whisper, tts, token-spy, privacy-shield, ape, langfuse, openclaw) and the openclaw workspace config dir; non-fatal on individual dir failures - ods_warn_rootless_docker — prints a human-readable advisory block installers/phases/06-directories.sh - Sources rootless-fix.sh early in the live install path - Calls ods_fix_rootless_ownership after all data dirs are created and the existing token-spy chown is applied ods-preflight.sh - After Docker daemon check, detects rootless mode and calls warn() with the affected services and the 'ods repair rootless-ownership' recovery command scripts/ods-doctor.sh - Detects rootless mode (DOCKER_ROOTLESS bash variable) - Passes it to the Python report section as a new argument - Adds runtime.docker_rootless to the JSON report - Increments runtime_warnings counter when rootless is detected - Emits 'ods repair rootless-ownership' as an autofix_hint ods-cli - Adds 'ods repair rootless-ownership' (alias: 'rootless') sub-command that sources lib/rootless-fix.sh and calls ods_fix_rootless_ownership - Updates help text and example block tests/test-rootless-docker-ownership.sh (new) - 30 tests: static checks across all 4 modified files, UID map correctness, and filesystem simulations verifying that only existing directories are processed and the fix is a no-op in non-rootless mode
In Docker rootless mode, host.docker.internal is not automatically registered in containers' /etc/hosts. As a result, dashboard-api cannot reach the ODS host agent. This commit updates our rootless-fix library to detect rootless mode, automatically bind the ODS host agent to 0.0.0.0 (so it listens on the bridge network gateway), and auto-detect the host's LAN IP to populate ODS_AGENT_HOST in the .env file. - Added ods_fix_rootless_agent_network to lib/rootless-fix.sh - Sourced and called in installers/phases/06-directories.sh - Integrated into 'ods repair rootless-ownership' - Added doctor check hints explaining the issue and recovery - Added comprehensive unit tests validating host/bind setting and idempotence
|
Thanks for putting a fuller rootless Docker repair path together, especially the separate helper and the preflight/doctor visibility. Advisory status: not ready yet Quickest path to merge:
What I checked:
The ownership repair shape is close; the remaining issue is making sure the generated install config actually retains the rootless host-agent networking fix. |
…nd portability - Moved the ods_fix_rootless_agent_network call to run after phase 06 writes and chmods the .env file. - Added ODS_AGENT_BIND and ODS_AGENT_HOST to the phase 06 generated .env template. This ensures that their values are preserved correctly across reinstalls/upgrades. - Replaced the declare -A associative array with a Bash 3.2-compatible flat array and function helper, resolving potential parse errors on macOS. - Added two integration regression tests simulating phase 06 ordering on fresh installs and reinstalls to verify that agent bindings are set correctly and preserved.
|
Thanks for the great feedback! I've implemented the suggested changes, verified that the full test suite passes, and pushed the updates to the branch. Phase 06
|
|
Thanks for tightening the rootless Docker repair flow after the earlier pass; the phase-06 ordering and Bash portability fixes are clear improvements. Advisory status: not ready yet Quickest path to merge:
What I checked:
Thanks again for keeping at this rootless path. |
Fixes #1702
Summary
Fixes permission issues when running ODS with Docker in rootless mode.
In rootless Docker, container UIDs are remapped through the host user's subordinate UID range (typically starting at
100000). As a result, data directories created by the installer are owned by the host user (for example, UID1000) and become unwritable by containers running as non-root users.This PR adds automatic detection and repair of rootless Docker ownership during installation, provides a standalone repair command, surfaces warnings in preflight and doctor diagnostics, and adds comprehensive test coverage.
Changes
lib/rootless-fix.sh(new)ods_is_rootless_dockerto detect Docker rootless mode usingdocker info._ods_rootless_chown_dirto repair ownership through a short-lived Alpine container without requiringsudo.ods_fix_rootless_ownership, an idempotent repair routine that:ODS_ROOTLESS_UID_MAP.ods_warn_rootless_dockerto display a user-facing advisory.installers/phases/06-directories.shrootless-fix.shduring installation.ods_fix_rootless_ownershipafter all data directories are created and the existing Token Spy ownership adjustment completes.ods-preflight.shscripts/ods-doctor.shDOCKER_ROOTLESS).runtime.docker_rootlessruntime_warningswhen rootless mode is detected.ods-clitests/test-rootless-docker-ownership.sh(new)Adds 30 tests covering:
Release Lane
release/2.5.xmainStable hotfix reason:
Changed Surface
Risk And Validation
Validation run:
git diff --checkrelease/2.5.xCommands/results:
Operational Change Check
Notes For Reviewers