[Bug] Dashboard self-update loses worker under custom systemd system service

オープン
#7,967 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
28/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
linux, node.js, typescript
領域
backend, devops

調査の方向性

Start by locating the Dashboard npm update worker, its service ownership detection and restart logic, and the job status handling; the issue does not name source files or tests. Read the v2.93.0 baseline and the staging candidate's synthetic tests, then trace how the actual systemd owner and worker scope are verified. Done means the updater safely refuses unsupported custom system units before package mutation, preserves or reports failure for the job, and has coverage for the stated lifecycle cases; destructive end-to-end certification is still outstanding.

索引モデルが issue の本文から書いたものです。

説明

bug gui proxy service
Client or integration

OpenCodex dashboard

Area

Service lifecycle

Summary

A Dashboard-triggered npm self-update can leave OpenCodex unavailable (HTTP 502 from the reverse proxy) on Linux when the running proxy belongs to a system-wide systemd service under an unprivileged UID, rather than the canonical systemd user service. An update worker may die when the original service's cgroup is stopped; moreover the updater may target a different, installed-but-inactive user unit. The Dashboard job file can remain running with a dead worker PID.

Expected: never stop an active proxy unless a worker can outlive the stop and can restart the actual owner. Unsupported custom system units should receive an actionable, fail-closed error before package mutation.

Reproduction
  1. Configure a custom root-owned systemd service with User=<unprivileged-user>, KillMode=control-group, OCX_SERVICE_MANAGED=1, and ExecStart=ocx start --port 10101. Keep an OpenCodex-managed systemctl --user service installed but inactive.
  2. With OpenCodex v2.89.0 running under the system unit, start a v2.93.0 npm update with restart:true from the Dashboard.
  3. During stop/restart, the original proxy disappears and the browser reports 502; the update job can remain running even though its recorded PID is dead.
  4. Non-destructive supporting reproduction under the same UID: systemd-run --user --scope --quiet --collect -- /usr/bin/true fails with Failed to connect to bus: No medium found when the system service has INVOCATION_ID but no XDG_RUNTIME_DIR. Supplying the verified private /run/user/<uid> makes the scope probe exit 0. A test process launched in that scope is shown under /user.slice/.../app.slice/run-*.scope, outside the system unit cgroup.
  5. Distinct installed supervisor state was reproduced: ocx service status --json reports the user unit installed/enabled but running:false, viable:false, while the independent system unit serves HTTP 200.

The full destructive update scenario has not been re-enacted after remediation; do not treat the non-destructive probes alone as a completed E2E certification.

Version

OpenCodex 2.89.0 → 2.93.0; source baseline v2.93.0 commit 88aaa754566d119b6b8fc898f8fb47602387d82e.

Operating system

Linux, systemd system service + lingered systemd user manager, Bun 1.4.4.

Provider and model

Not provider-specific.

Logs or error output
Failed to connect to bus: No medium found
OWNERSHIP_MUTATION_LEASE_BUSY: another process owns the runtime mutation lease
(recorded PID no longer alive; lease age below stale-reclaim grace period)
systemd: Main process exited, status=1/FAILURE
systemd: Failed to start OpenCodex proxy service
Screenshots and supporting files

The operator captured HTTP 502 Bad gateway during the Dashboard upgrade and a separate startup-safety warning. No screenshots containing private hostnames or identifiers are uploaded here.

Redacted configuration
{
  "systemService": {
    "type": "systemd system",
    "user": "<unprivileged uid>",
    "killMode": "control-group",
    "managed": true
  },
  "dashboardUpdate": {
    "installer": "npm",
    "restart": true
  },
  "userService": {
    "installed": true,
    "enabled": true,
    "running": false
  }
}
Checks
  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.
Suggested safety contract
  • Identify and attest the actual running supervisor before beginning update.
  • Spawn the updater in an independently managed scope with a verified UID-private user-bus socket. Refuse safely if that is impossible.
  • Do not target an unrelated user unit when a root-owned custom system unit owns the listener; such a migration needs operator-supervised authorization.
  • Record a terminal, actionable failed state when the updater PID died; avoid indefinite running status.
  • Test service stop, update, restart identity, health stability, rollback and cgroup survival.

A staging-only candidate adds these guards with synthetic tests; it is not deployed or certified.

主要言語
TypeScript
スター
16.9k
フォーク
1.3k
平均マージ
16時間 42分
マージ済み PR(30日)
695

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

lidge-jun/opencodex のほかの issue

lidge-jun/opencodex の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。