Skip to content

Managed VPS: root-owned install state (/opt/kimaki-config, .opencode, .claude/hooks) makes non-root upgrade permanently partial #598

Description

@chubes4

Summary

#596/#597 fixed the first symptom (unreadable installation-profile), but the same root cause makes a non-root ./upgrade.sh on a managed VPS permanently partial. Setup defaults to --root (setup.sh: --root Run agent as root (default)), lays install state down as root, and the service identity (opencode) that runs every later upgrade cannot maintain it.

Evidence (v1.22.1, run as opencode on the live install)

Phase 1 now passes, but the run still exits 1 with:

OpenCode subagent projection failed: [Errno 13] Permission denied: '<site>/.opencode/.wp-coding-agents-subagents.json'
chmod: changing permissions of '<site>/.claude/hooks/dm-agent-sync.sh': Operation not permitted
cp: cannot create regular file '/opt/kimaki-config/plugins/dm-agent-sync.ts': Permission denied
chmod: changing permissions of '/opt/kimaki-config/restart-continuation.py': Operation not permitted
Skipping chat bridge unit refresh because upgrade is running non-root
{"status":"root_repair_required","profile":"managed-vps","repair_command":"sudo ./upgrade.sh --systems-capabilities managed-vps --wp-path <site>"}
Keeping current root-owned persistent Kimaki skill source

63 root-owned entries under /opt/kimaki-config, <site>/.opencode, <site>/.claude, <site>/.wp-coding-agents:

root:root     755  /opt/kimaki-config            (+ plugins/, skills/, .git/, post-upgrade.sh …)
root:www-data 2775 <site>/.opencode
root:www-data 600  <site>/.opencode/.wp-coding-agents-subagents.json

So the managed plugin sync (data-machine, wp-codebox) works, but the Kimaki plugin sources, the upgrade skill, the OpenCode subagent projection and the Claude hooks silently stay at whatever version root last wrote. The script itself reports root_repair_required and prints a sudo command — which is exactly the thing an agent-run upgrade must never need. (Asking the operator for root to run the agent's own upgrade is not an acceptable answer; that is why this is filed rather than worked around.)

What should change

  1. Ownership follows the service identity, not the invoking uid. Everything setup/upgrade writes for the agent to maintain — /opt/kimaki-config, <site>/.opencode, <site>/.claude, <site>/.wp-coding-agents, skills — should be chowned to SERVICE_USER (site group preserved) at write time, the same way fix_ownership already treats plugin dirs. A root-run setup for a non-root service should leave zero root-owned agent state behind.
  2. One-shot migration in upgrade. When running as root and SERVICE_USER != root, reconcile ownership of those roots once (chown -R), so existing installs converge without a manual repair. When running non-root and root-owned state is found, emit a single consolidated root_repair_required report listing the paths, not per-file cp:/chmod: noise, and exit non-zero only if a required component could not be updated.
  3. Default should not be root for managed VPS. --non-root is already the owned-mode default per No model for agent server capability: every install runs an unrestricted root shell, including managed #327; setup.sh's help still advertises --root as default. Make the default the service user unless --root is explicit, and refuse to run setup as root without a resolved non-root SERVICE_USER on a managed-vps profile.
  4. Anything that genuinely needs root (systemd unit refresh) stays behind the existing root_repair_required handoff — but that should be the only thing left in it.

Related: #596, #327, #204, #93.

Authored by Extra Chill Bot (AI agent).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions