Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions docs/LINUX_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pgrep -a Xvfb
| `CODEX_DESKTOP_EXECUTABLE_PATH` | Electron 可执行文件路径 | `/tmp/codex-desktop-linux/codex-app/electron` |
| `CODEX_CLI_PATH` | Codex CLI 二进制路径 | `/opt/codex-cli/codex` |
| `CODEX_HOME` | Codex 配置目录 | `~/.codex` |
| `OPENCODEX_HEADLESS_ELECTRON` | 设为 `1` 时追加无头服务器所需 Electron 参数 | `1` |

`DISPLAY` 指向 Xvfb。其余变量让 OpenCodex 知道 Electron 和 Codex CLI 的位置,以及配置文件存放路径。

Expand All @@ -100,22 +101,19 @@ pgrep -a Xvfb
const officialRuntimeArgs = [`--user-data-dir=${officialUserDataDir}`];
```

在无头 Linux 上需改为:

```js
const officialRuntimeArgs = [
`--user-data-dir=${officialUserDataDir}`,
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
];
```
无头 Linux 上不需要改动源码:设置环境变量 `OPENCODEX_HEADLESS_ELECTRON=1`,
launcher 与 dev runner 会在官方隐藏运行时之外追加以下参数。

| 参数 | 说明 |
|------|------|
| `--no-sandbox` | 服务器环境下 Chrome 沙箱通常不可用(root 运行或容器环境),不加会导致 Electron 启动失败 |
| `--disable-setuid-sandbox` | 配合 `--no-sandbox` 禁用 setuid 辅助进程 |
| `--disable-dev-shm-usage` | 避免 `/dev/shm` 过小(容器默认 64MB)导致崩溃,改用普通内存 |
| `--headless` | 让窗口不依赖真实显示服务,配合 Xvfb 使用 |
| `--disable-gpu` | 无 GPU 的服务器上 GPU 进程会 FATAL 并让 gateway 收到 SIGTRAP 退出 |

若 `/dev/shm` 过小(容器默认 64MB),可再额外设置 `--disable-dev-shm-usage`。

判据:设置该变量后 `systemctl show -p Environment` 或进程 cmdline 中应能看到上述三个参数;
不设置时行为与桌面端完全一致(参数列表为空)。

## 启动 OpenCodex

Expand Down
3 changes: 3 additions & 0 deletions gateway/dev/run-gateway.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
} = require("../../shared/gateway-lifecycle.cjs");
const {
hiddenRuntimeGcmCommandLineArgs,
headlessRuntimeCommandLineArgs,
isolateHiddenRuntimeGcmStoresForUserData,
} = require("../runtime/electron/hidden-runtime-command-line.cjs");

Expand Down Expand Up @@ -119,6 +120,8 @@ async function main() {
const officialRuntimeArgs = [
`--user-data-dir=${officialUserDataDir}`,
...hiddenRuntimeGcmCommandLineArgs(process.env),
// 无头服务器适配走环境变量开关,保持仓库默认行为与桌面端一致(见 docs/LINUX_GUIDE.md)。
...headlessRuntimeCommandLineArgs(process.env),
];
spawnGateway(officialRuntime, officialRuntimeArgs);

Expand Down
16 changes: 16 additions & 0 deletions gateway/runtime/electron/hidden-runtime-command-line.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const UNUSED_HIDDEN_RUNTIME_FEATURES = ["PushMessaging"];
const UNUSED_HIDDEN_RUNTIME_BLINK_FEATURES = ["PushMessaging"];
const HIDDEN_RUNTIME_GCM_HOLD_PATH = "/__opencodex-internal/gcm-checkin-hold";
const HIDDEN_RUNTIME_GCM_STORE_BACKUP = "GCM Store.opencodex-disabled";
const HEADLESS_RUNTIME_ARGS_ENV = "OPENCODEX_HEADLESS_ELECTRON";

function appendMergedSwitch(commandLine, name, additions) {
const existing =
Expand Down Expand Up @@ -98,6 +99,19 @@ function hiddenRuntimeGcmHoldUrl(env = process.env) {
return `http://127.0.0.1:${safePort}${HIDDEN_RUNTIME_GCM_HOLD_PATH}`;
}

/**
* 无头服务器(无 GPU / 无 X 11 显示)所需的额外 Electron 参数。
* 由 OPENCODEX_HEADLESS_ELECTRON 环境变量开关,默认不改变桌面端行为:
* 不加 --no-sandbox 时 Chromium 在 root 或无用户命名空间的环境里会启动失败,
* 不加 --disable-gpu 时 GPU 进程会 FATAL 并让 gateway 收到 SIGTRAP 退出,
* --headless 让窗口不依赖真实显示服务。详见 docs/LINUX_GUIDE.md。
*/
function headlessRuntimeCommandLineArgs(env = process.env) {
const enabled = String(env?.[HEADLESS_RUNTIME_ARGS_ENV] ?? "").trim().toLowerCase();
if (!["1", "true", "yes", "on"].includes(enabled)) return [];
return ["--no-sandbox", "--headless", "--disable-gpu"];
}

function hiddenRuntimeGcmCommandLineArgs(env = process.env) {
const holdUrl = hiddenRuntimeGcmHoldUrl(env);
/**
Expand Down Expand Up @@ -151,6 +165,8 @@ module.exports = {
hiddenRuntimeGcmStorePaths,
hiddenRuntimeGcmCommandLineArgs,
hiddenRuntimeGcmHoldUrl,
HEADLESS_RUNTIME_ARGS_ENV,
headlessRuntimeCommandLineArgs,
isolateHiddenRuntimeGcmStore,
isolateHiddenRuntimeGcmStoresForUserData,
};
3 changes: 3 additions & 0 deletions launcher/main.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
} = require("../shared/gateway-lifecycle.cjs");
const {
hiddenRuntimeGcmCommandLineArgs,
headlessRuntimeCommandLineArgs,
isolateHiddenRuntimeGcmStoresForUserData,
} = require("../gateway/runtime/electron/hidden-runtime-command-line.cjs");
const packageMetadata = require("../package.json");
Expand Down Expand Up @@ -882,6 +883,8 @@ async function startGatewayOnce() {
const officialRuntimeArgs = [
`--user-data-dir=${officialUserDataDir}`,
...hiddenRuntimeGcmCommandLineArgs({ PORT: String(gatewayState.port) }),
// 无头服务器(无 GPU/无 X)通过环境变量开关追加 Electron 参数,桌面端默认不受影响。
...headlessRuntimeCommandLineArgs(process.env),
];
const childEnv = {
...process.env,
Expand Down