feat(server-s3): a member's tmux follows tmux upgrades — tmux-member + Users → Members' tmux
A member's tmux server keeps the version it started with until their last pane closes, but the dashboard asked it with TMUX_BIN, the newest tmux: a 3.8 client on a 3.6 server spun it at 100% CPU (three members needed a manual kill on 2026-10-15). - /opt/agenthub/libexec/tmux-member (install-system, in sudoers): runs a member's tmux call with the binary of THEIR running server (/proc/<pid>/exe, found from the socket in /proc/net/unix), else TMUX_BIN. It runs as the member and execs only a process they own. sudoArgv uses it once installed (linux-accounts readConf), TMUX_BIN until then. - Users → Members' tmux (GET /api/users/tmux): each member server's version beside the installed one, sessions, agents working. An admin restarts one (POST /api/users/:id/tmux-restart) or every idle outdated one (POST /api/users/tmux-restart-idle), with their password again, audited per member; a server that will not stop answers 409 ETMUXSTUCK naming its pid for root. - server-s3-system.test.js: `delete` is a provision action since Delete user, so the "unknown action" case now uses `purge`. Operators: run `sudo agenthub server install-system` once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -240,9 +240,20 @@ describe("run-as: a path under the users root belongs to that user", () => {
|
||||
process.env.AGENTHUB_SERVER_CONF,
|
||||
`HOST_USER=h\nHOST_UID=1\nUSERS_ROOT=${TMP}/users\nGIT_BIN=/usr/bin/git\nTMUX_BIN=/opt/x/tmux\n`
|
||||
);
|
||||
linux.__resetConfCache();
|
||||
linux.__setTmuxMember(path.join(TMP, "no-tmux-member"));
|
||||
assert.equal(runAs.sudoArgv(ACCT, "git", ["status"])[1][3], "/usr/bin/git");
|
||||
assert.equal(runAs.sudoArgv(ACCT, "tmux", [])[1][3], "/opt/x/tmux");
|
||||
// Once install-system put tmux-member there, a member's tmux goes through
|
||||
// it (their running server's own binary); the installed one is still known.
|
||||
const wrapper = path.join(TMP, "tmux-member");
|
||||
fs.writeFileSync(wrapper, "#!/bin/sh\n", { mode: 0o755 });
|
||||
linux.__setTmuxMember(wrapper);
|
||||
try {
|
||||
assert.equal(runAs.sudoArgv(ACCT, "tmux", [])[1][3], wrapper);
|
||||
assert.equal(linux.serverConf().tmuxInstalled, "/opt/x/tmux");
|
||||
} finally {
|
||||
linux.__setTmuxMember(path.join(TMP, "no-tmux-member"));
|
||||
}
|
||||
assert.equal(
|
||||
runAs.sudoArgv(ACCT, "/opt/agenthub/libexec/write-as", [])[1][3],
|
||||
"/opt/agenthub/libexec/write-as"
|
||||
|
||||
Reference in New Issue
Block a user