> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trylaunchkit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 桥接模式

> 在内网沙箱平台旁运行 launchkit-worker 守护进程

桥接模式下，你的沙箱平台留在内网，外部不可达。你在沙箱平台旁的主机上运行 **`launchkit-worker`** 守护进程（产品界面中称「工作节点」）：它**只发起出站 HTTPS 调用**，长轮询 LaunchKit 获取沙箱作业，在你的**本地**沙箱平台上执行每个操作，并把结果回传。

```
你的网络                                     LaunchKit 云
──────────────────────────────               ────────────────────
launchkit-worker 守护进程       ── HTTPS ──► 作业队列(轮询)
  │  在本地执行操作             ◄─ 作业 ───  各任务的操作
  ▼                            ── 结果 ───► 任务继续
E2B 兼容沙箱平台
(CubeSandbox / E2B)
```

无需开放任何入站端口，且 **LaunchKit 永不持有你沙箱平台的凭证**：worker 仅从本地环境变量读取。

## 前置条件

* Python **3.11+**。
* 到 LaunchKit 云 API 的出站 HTTPS。
* 到本地沙箱平台的网络访问。
* 用于 worker 结果日志的持久化磁盘（见下文「结果日志与恢复」）。

## 安装

`launchkit-worker` 已发布到 PyPI；你的 **runtime id** 和 **runtime worker 密钥** 由 LaunchKit 对接人另行提供。作为系统服务运行时，请将锁定版本安装到由 root 管理的虚拟环境：

```bash theme={null}
sudo python3 -m venv /opt/launchkit-worker
sudo /opt/launchkit-worker/bin/pip install launchkit-worker==0.5.0
```

请锁定版本，让升级成为运维人员的明确动作；worker 不会自动更新。`pipx` 或 `uv tool` 适合交互式用户使用，但二进制通常位于该用户的主目录中，而下文加固后的 systemd 单元会刻意禁止访问用户主目录。

发行版本由 LaunchKit CI 通过 [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/) 发布，并附带 Sigstore [PEP 740 证明（attestations）](https://docs.pypi.org/attestations/)以便校验来源。本软件以源码可见（source-available）方式发布，采用受限使用许可（见 `LICENSE`）：你可以运行它以连接 LaunchKit，但不得再分发或修改。

## 配置

worker 读取的 LaunchKit 设置：

| 变量                                | 必填 | 默认值                                                  | 含义                                                                                    |
| --------------------------------- | -- | ---------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `LAUNCHKIT_API_URL`               | 是  |                                                      | LaunchKit 云 API 基础 URL，`https://api.trylaunchkit.ai`（必须 https；纯 http 仅限 localhost 开发） |
| `LAUNCHKIT_RUNTIME_ID`            | 是  |                                                      | 本 worker 服务的 runtime                                                                  |
| `LAUNCHKIT_RUNTIME_KEY`           | 是  |                                                      | runtime worker 密钥（`lkw01_...`）                                                        |
| `LAUNCHKIT_WORKER_CONCURRENCY`    | 否  | `4`                                                  | 并发工作槽位数                                                                               |
| `LAUNCHKIT_WORKER_IDLE_TIMEOUT_S` | 否  | `330`                                                | 空闲多少秒后释放已认领的作业                                                                        |
| `LAUNCHKIT_WORKER_STATE_DB`       | 否  | `~/.local/state/launchkit-worker/op-results.sqlite3` | 持久化结果日志路径；容器内请挂载其所在目录                                                                 |
| `LAUNCHKIT_WORKER_LOG_LEVEL`      | 否  | `INFO`                                               | Python 日志级别                                                                           |

沙箱平台设置由 `e2b` SDK 自行读取（worker 有意不触碰这些变量，这正是它能同时兼容 E2B 官方云与 CubeSandbox 的原因）：

| 变量                     | 含义                                                           |
| ---------------------- | ------------------------------------------------------------ |
| `E2B_API_KEY`          | 本地沙箱平台的 API 密钥                                               |
| `E2B_DOMAIN`           | 沙箱平台主机，例如 CubeSandbox 的内网域名                                  |
| `E2B_API_URL`          | 显式控制面 URL（优先于 `E2B_DOMAIN`）                                  |
| `E2B_VALIDATE_API_KEY` | 沙箱平台密钥非 E2B 格式时设为 `false`；见[兼容性](/zh/runtimes/compatibility) |
| `SSL_CERT_FILE`        | 私有 CA 内网平台的自定义 CA 证书包                                        |

## 关于 runtime worker 密钥

runtime worker 密钥（`lkw01_...`）由 LaunchKit 针对单个 runtime 签发，仅展示一次，由你的 LaunchKit 对接人交付。它只能访问本 runtime 的作业队列（一个 runtime 的密钥永远无法轮询另一个 runtime 的队列）。请保存在 root 拥有、权限 `600` 的文件中。轮换即重新签发：收到新密钥后，换入环境变量文件即可。

## 用 systemd 运行

将以下单元保存为 `/etc/systemd/system/launchkit-worker.service`：

```ini theme={null}
[Unit]
Description=LaunchKit bridge worker (sandbox daemon)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
DynamicUser=yes
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictNamespaces=yes
RestrictSUIDSGID=yes
LockPersonality=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
CapabilityBoundingSet=
SystemCallArchitectures=native
EnvironmentFile=/etc/launchkit-worker.env
StateDirectory=launchkit-worker
StateDirectoryMode=0700
Environment=LAUNCHKIT_WORKER_STATE_DB=/var/lib/launchkit-worker/op-results.sqlite3
ExecStart=/opt/launchkit-worker/bin/launchkit-worker run
Restart=always
RestartPreventExitStatus=2
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=60

[Install]
WantedBy=multi-user.target
```

然后创建环境变量文件并启动守护进程：

```bash theme={null}
sudo touch /etc/launchkit-worker.env && sudo chmod 600 /etc/launchkit-worker.env
sudo "$EDITOR" /etc/launchkit-worker.env        # 填入上文变量
sudo systemctl daemon-reload
sudo systemctl enable --now launchkit-worker
sudo journalctl -u launchkit-worker -f
```

该单元为结果日志使用持久化状态目录，并自动重启守护进程，唯独在版本被拒后不重启（见下文）。收到 `SIGTERM` 时，worker 会优雅退出：停止认领新作业，完成进行中的操作，上报当前仍被认领的作业后退出。

## 启用前检查：doctor

请在启用守护进程前运行，并在沙箱平台升级后再次运行：

```bash theme={null}
launchkit-worker doctor
```

每项检查输出 `OK`、`WARN` 或 `FAIL`，只要出现 `FAIL` 命令就以非零状态码退出：

1. 云端可达性、密钥有效性、密钥与 runtime 的绑定关系。
2. 与服务器的时钟偏差（超 30 秒警告，超 300 秒失败）。
3. 本地沙箱平台可达性。
4. 暂停能力（未加 `--probe` 时仅提示）。
5. 快照能力（CubeSandbox >= v0.5.1；未加 `--probe` 时仅提示）。
6. 磁盘剩余空间。

```bash theme={null}
launchkit-worker doctor --probe
```

`--probe` 额外执行**真实沙箱检查**：在你的沙箱平台上创建真实沙箱，验证暂停后磁盘数据得以保留并能正常恢复，再执行快照往返测试（为沙箱创建快照、**从**快照启动派生沙箱、验证磁盘数据完整传递）——所有测试产物随后销毁。这是暂停与快照支持的功能性验收，其中快照检查与 LaunchKit 云端探测经由该 worker 执行的往返测试**完全一致**，因此 doctor 与云端的结论永远不会互相矛盾。请在接入时执行一次，并在每次沙箱平台升级后再次执行。关于 CubeSandbox 为何必须执行此检查，参见[兼容性](/zh/runtimes/compatibility)。

## 版本锁定与 HTTP 426

云端强制部署级最低 worker 版本。低于下限的 worker 会被 **HTTP 426** 拒绝，并以特定非零状态码退出，systemd 刻意**不**重启它（避免对永久性错误进入崩溃重启循环）。请升级锁定的软件包（`sudo /opt/launchkit-worker/bin/pip install --upgrade launchkit-worker==0.5.0`）并重启守护进程（`sudo systemctl restart launchkit-worker`）。worker **0.5.0** 新增了快照相关操作（创建快照、删除快照、快照探测、模板删除），因此部署级最低版本为 0.5.0。

## 结果日志与恢复

每个操作的结果都会在上报**之前**先提交到本地 SQLite 结果日志，使结果具备崩溃安全性：

* 守护进程或主机重启后，重新投递的操作会**回放结果日志中的记录**，不会重复执行。
* 若操作被重新投递到**另一台主机**（例如故障转移到第二台 worker 机器），且该主机没有对应的结果日志记录，worker 会将本次执行上报为**不确定（indeterminate）**，不会重复执行命令，也不会重复创建沙箱。

<Warning>
  请把结果日志放在持久化存储上（`LAUNCHKIT_WORKER_STATE_DB` 路径）。若在容器中运行
  worker，请把结果日志目录挂载为卷；一旦结果日志随容器丢失，原本可干净完成的同机恢复也会变成不确定结果。
</Warning>

## 调优

* `LAUNCHKIT_WORKER_CONCURRENCY`：沙箱平台有余量且任务出现排队时可调高；每个槽位同一时间只处理一个沙箱的操作。
* `LAUNCHKIT_WORKER_IDLE_TIMEOUT_S`：一个空闲的认领保留多久后释放。默认值（330 秒）设计为高于云端的单次操作超时预算；仅在槽位不足时才调低。
