Skip to content

Run the agent as its own OS user on managed machines - #162

Merged
molefrog merged 6 commits into
mainfrom
managed-container
Oct 15, 2026
Merged

molefrog merged 6 commits into
mainfrom
managed-container

Conversation

@molefrog

@molefrog molefrog commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

On a managed machine (one per organization, in the cloud) moi and the agent now run as different OS users. The agent can't change moi's config, stop or replace it, or read what moi keeps for itself, yet it keeps the whole moi CLI except the system commands. Nothing changes for a local install: everything is off until config.json sets it.

The machine's start script writes this config.json at every start:

{
  "workspacesDir": "/data/workspaces",
  "agentLauncher": "/opt/moi/bin/agent-run",
  "unixSocket": "/run/moi/web.sock"
}
  • agentLauncher: every agent process starts through it. That covers Claude Code (via the SDK's spawn hook), Codex, ACP agents, function workers, applet builds and installs.
  • unixSocket: the web side listens on a socket file only the gateway can open, instead of port 13337. moi status and the /status page show the socket then.
  • The agent's moi CLI: moi env goes over the control port, because the agent's user can't open moi's data folder. init, start, service and update refuse to run. The control port takes workspace:register only from moi's own user.

Details are in docs/managed-machine.md.

Worth a close look

  • server/peer-user.ts finds who is calling the control port by reading /proc/net/tcp. It runs only when agentLauncher is set, and refuses when the owner can't be found.
  • A new place that starts agent code must use agentCommand() or claudeCodeSpawn(). Otherwise it runs as moi's user.

Tested: bun test (2135 pass), typecheck, lint. New tests cover the config fields, the /proc/net/tcp parser, and the CLI when moi's data folder is closed. On a live machine, chats with real Claude and Codex sign-ins worked; the socket in moi status was checked against a local server.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ

Managed machines (one per organization) run moi and the agent as
different OS users, so the agent can't change moi's config, stop it, or
read what moi keeps for itself. This adds what moi needs for that, all
off unless config.json says otherwise:

- config.json gains workspacesDir, agentLauncher and unixSocket, read
  from the file only, with no env override.
- Every agent process starts through agentLauncher: harness CLIs,
  Claude Code via the SDK's spawn hook, ACP agents, function workers,
  applet builds and dependency installs (server/agent-launcher.ts).
- The web side can listen on a Unix socket file instead of port 13337,
  so only the machine's gateway reaches the API meant for people.
- Chat titles run in a temp folder the agent owns.
- The agent's moi CLI can't open moi's data folder: `moi env` and
  finding the current workspace go over the control port, and system
  commands refuse to run. The control port accepts workspace:register
  only from moi's own user, read from the socket owner in /proc/net/tcp.

PUT /env and the control port share one env patch validator.
See docs/managed-machine.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T13:04:40.763873Z 9506531 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95065315ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/workspace-init.ts
Comment thread server/agent-launcher.ts
molefrog and others added 5 commits October 14, 2026 17:16
`moi status`, the `/status` page and the "already running" messages printed
port 13337 even when the web side listens on the `unixSocket` file. The server
now reports its socket in `server:info`, and the CLI prints it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
The CLI no longer reads moi's data folder for `moi env`, `set`, `unset`,
`exec` or finding the current workspace: it always asks the server over
the control port. One path instead of two, writes take effect at once
and go through the server's per-workspace queue, and the agent on a
managed machine uses the same path as everyone else. These commands now
need moi running; without it they say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
No more `mktemp` through the agent launcher: moi makes the folder with
mkdtemp and opens it to everyone, so the agent can work in it and Codex
can write its answer there. moi stays the owner, so it can also remove
the folder from /tmp, which the agent-owned folder didn't allow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
Drop peer-user.ts and its /proc/net/tcp lookup. Before sending
workspace:register, the CLI checks that it can open the folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
One page for every config.json option and when it's needed: the demo,
Cloudflare Access, and the three managed-machine paths. It also says the
agent launcher sets the agent's HOME.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mz31v7KHhLQFK29pFBvMpQ
@molefrog
molefrog merged commit 707aeac into main Oct 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant