Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ docker-compose.yml text eol=lf
.dockerignore text eol=lf
bin/kin-kernel binary
bin/kin-egress binary
bin/kin-slot-gate binary
bin/kin-worker binary
bin/kin-codex-kernel binary
bin/kin-oauth-auth binary
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
mkdir -p dist
(cd worker && CGO_ENABLED=0 go build -trimpath -o ../dist/kin-worker ./cmd/kin-worker)
(cd worker && CGO_ENABLED=0 go build -trimpath -o ../dist/kin-egress ./cmd/kin-egress)
(cd worker && CGO_ENABLED=0 go build -trimpath -o ../dist/kin-slot-gate ./cmd/kin-slot-gate)
node scripts/fetch-payload.mjs
node scripts/fetch-payload.mjs --stage dist
- uses: actions/upload-artifact@v7
Expand All @@ -73,6 +74,7 @@ jobs:
dist/kin-codex-kernel
dist/kin-worker
dist/kin-egress
dist/kin-slot-gate
dist/kin-oauth-auth
dist/kin-computer
dist/cli-node
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- 槽位种子页:`settings.json` 的 env 行与 `theme` 可直接编辑并随播种写入;`autoUpdates`、`grove_enabled` 只读且播种时固定为 `false`;TZ/LANG/LC_ALL、遥测 kill-switch、Bedrock/Vertex、gateway hint 等同理只读(播种由契约重写)。缺 `CLAUDE_CODE_ATTRIBUTION_HEADER` 时默认 `0`。调试上传默认关,独立 query 拉最近 40 条上传,切换开关不重置未保存编辑;Go sidecar 写 `vms/<id>/run/telemetry-upload.log`,面板 `GET seed-settings?debug=1` 返回 `telemetry_log`。
- 槽位种子页按当前槽 `settings.json` 列出真实配置;`claude.setting` 可编辑播种;缺失文件返回 `null`、空文件返回空串,不用策略默认冒充槽内文件;遥测开关与 sidecar 进程状态分开展示,保存不因遥测进程刷新失败而 502。
- fleet 遥测刷新在 kin-egress 二进制被替换(含 `(deleted)` 旧进程与脏 pidfile)时,会按 egress 配置扫停全部 helper、等待 `/proc/<pid>` 消失后再绑定新二进制;同一 SOCKS 出口的 stop/start 与 `ensureProxyEgress` 共用 per-proxy 锁,避免并发 telemetry 互相 SIGTERM。(#604)
- 扩展节点直连通道:`PUT /api/panel/cluster/nodes/:id/direct-link` 在节点上建 `kin-slot-gate`(TLS 1.3,首次启动自签证书,控制面经 SSH 读取并固定指纹;每节点随机令牌),远程槽 kernel / worker 请求改为每次一条直连 TLS 连接,不再全部挤在一条 SSH 长连接里(长连接在零碎流量下拥塞窗口会卡在约 17KB/s,突发请求正文排队数秒)。请求正文随握手后的第一包发出、不等应答。gate 只连槽的两个 socket 且不跟随符号链接;连不上、证书不符或令牌被拒时该节点退回 SSH 30 秒。面板节点详情可启用 / 关闭,节点行显示「直连」/「直连→SSH」。新增 Go 命令 `kin-slot-gate`(`npm run build:gate`,Release 附件同名)。
- 面板:侧栏「GitHub / 文档」两枚链接不再折行,字体偏宽时「文档」不会逐字竖排,空间不够先缩箭头再省略文字;VM 列表搜索框关闭浏览器自动填充,不再被回填成登录邮箱。
- 集群页「扩展节点」新增 CPU / 内存 / 容器三列:健康检查(每 30 秒)经同一条 SSH 连接读节点 `/proc` 和 cgroup,口径同本机宿主列;容器 = 节点上全部 Docker 容器内存合计(扣除 inactive_file,同 `docker stats`)。修复本机宿主列 CPU 最高只显示 10%(`Math.min(100, …×1000)/10` 写错上限)。链路列不再折行。
- 集群槽无需重建 VM 即可更新 Go 槽位服务(kin-worker / kin-egress):持久化 `slot-bin` 挂载推送二进制,fleet `action=telemetry` 热更新遥测与 egress。(#600)
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN cd api-kernel && go mod download
COPY api-kernel/ ./api-kernel/
RUN cd worker && go build -buildvcs=false -trimpath -o /out/kin-worker ./cmd/kin-worker \
&& go build -buildvcs=false -trimpath -o /out/kin-egress ./cmd/kin-egress \
&& CGO_ENABLED=0 go build -buildvcs=false -trimpath -o /out/kin-slot-gate ./cmd/kin-slot-gate \
&& cd ../api-kernel && go build -buildvcs=false -trimpath -o /out/kin-api-kernel ./cmd/kin-api-kernel

FROM --platform=$BUILDPLATFORM node:22-bookworm-slim AS payload
Expand Down
2 changes: 2 additions & 0 deletions deploy/Dockerfile.arm64-control
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RUN cd worker && go build -buildvcs=false -trimpath -ldflags="-s -w" -o /out/kin
&& go build -buildvcs=false -trimpath -ldflags="-s -w" -o /out/kin-worker ./cmd/kin-worker \
&& GOARCH=amd64 go build -buildvcs=false -trimpath -o /out/amd64/kin-egress ./cmd/kin-egress \
&& GOARCH=amd64 go build -buildvcs=false -trimpath -o /out/amd64/kin-worker ./cmd/kin-worker \
&& CGO_ENABLED=0 GOARCH=amd64 go build -buildvcs=false -trimpath -o /out/amd64/kin-slot-gate ./cmd/kin-slot-gate \
&& cd ../api-kernel && go build -buildvcs=false -trimpath -ldflags="-s -w" -o /out/kin-api-kernel ./cmd/kin-api-kernel

FROM --platform=linux/arm64 ${NODE_IMAGE} AS web
Expand Down Expand Up @@ -79,6 +80,7 @@ ENV NODE_ENV=production \
KIN_API_KERNEL_BIN=/opt/vm2api/bin/kin-api-kernel \
KIN_CLUSTER_WORKER_BIN=/opt/vm2api/cluster-bin-amd64/kin-worker \
KIN_CLUSTER_EGRESS_BIN=/opt/vm2api/cluster-bin-amd64/kin-egress \
KIN_CLUSTER_GATE_BIN=/opt/vm2api/cluster-bin-amd64/kin-slot-gate \
DOCKER_DEFAULT_PLATFORM=linux/amd64
EXPOSE 8787
ENTRYPOINT ["/usr/local/bin/vm2api-entrypoint"]
1 change: 1 addition & 0 deletions docker-compose.arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ services:
DOCKER_DEFAULT_PLATFORM: linux/amd64
KIN_CLUSTER_WORKER_BIN: /opt/vm2api/cluster-bin-amd64/kin-worker
KIN_CLUSTER_EGRESS_BIN: /opt/vm2api/cluster-bin-amd64/kin-egress
KIN_CLUSTER_GATE_BIN: /opt/vm2api/cluster-bin-amd64/kin-slot-gate
volumes:
# Keep native runtime helpers out of the repository's amd64 bin/ assets.
- ./.local/arm64/vms:/opt/vm2api/vms
Expand Down
3 changes: 3 additions & 0 deletions docs/BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ git push origin v1.2.22
|---|---|
| `kin-kernel` | Claude Code 槽内核(payload,推理必带) |
| `kin-egress` | 远程 SOCKS5 透明网关 |
| `kin-slot-gate` | 扩展节点直连通道入口(控制面每请求一条 TLS 连接直达节点槽位) |
| `kin-worker` | **只** `telemetry`,不是 hop |
| `kin-codex-kernel` | Codex 槽(payload) |
| `kin-oauth-auth` | OAuth / Setup Token 换票服务二进制;源码不随部署上传 |
Expand Down Expand Up @@ -78,6 +79,7 @@ pnpm -C web install --frozen-lockfile

npm run fetch:payload # bin/kin-{kernel,codex-kernel,oauth-auth}、share/wrap-cli、share/crag
npm run build:egress # bin/kin-egress
npm run build:gate # bin/kin-slot-gate(扩展节点直连通道)
npm run build:web # web/dist
npm run build:worker # bin/kin-worker(telemetry)
```
Expand All @@ -93,6 +95,7 @@ npm run format:check

```bash
CGO_ENABLED=0 go build -trimpath -o bin/kin-egress ./worker/cmd/kin-egress
CGO_ENABLED=0 go build -trimpath -o bin/kin-slot-gate ./worker/cmd/kin-slot-gate
CGO_ENABLED=0 go build -trimpath -o bin/kin-worker ./worker/cmd/kin-worker
pnpm -C web build
```
Expand Down
2 changes: 2 additions & 0 deletions docs/PANEL_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ sessionKey / 授权码导入必须走该槽 SOCKS5。
| PATCH | `/cluster/nodes/:id` | 编辑名称或 SSH 配置,必须带 `expected_updated_at`(取列表中的 `updated_at`);返回更新后的公开节点信息 |
| POST | `/cluster/nodes/:id/probe` | 与 PATCH 同体;使用已保存的未更换凭证及原主机指纹测试候选配置,不保存、不切断原连接;返回 `{ host_key, docker, vm_count, dependent_count }` |
| POST | `/cluster/nodes/:id/reconnect` | 清掉 `error` 与退避,立刻重连 |
| PUT / DELETE | `/cluster/nodes/:id/direct-link` | 直连通道:PUT `{ address, port? }`(节点 IP 字面量,端口默认 7790)启用或修改,DELETE 关闭并删除节点上的 `kin-slot-gate`;返回节点(含 `direct_link`) |
| POST | `/cluster/nodes/:id/shell-ticket` | 30 秒一次性终端票据 |
| WS | `/cluster/nodes/:id/shell?ticket=&cols=&rows=` | 客户端发 `{"t":"d","d":"…"}` 输入、`{"t":"r","c":列,"r":行}` 改尺寸;服务端二进制帧为终端输出,文本帧 `{"t":"exit"\|"error"}` |
| GET | `/cluster/nodes/:id/docker/info` | 版本 / 系统 / 容器数 |
Expand All @@ -523,6 +524,7 @@ sessionKey / 授权码导入必须走该槽 SOCKS5。
- 仅改名无需 SSH 连接,也不重连。SSH 配置保存时服务端会重新验证,不能以先前 probe 成功代替:先使用原指纹建立候选连接,验证成功再保存并接管原链路;失败保留原配置和连接。已有终端和转发连接可能在切换时断开,远端 VM 容器不会被重建。这里只修改控制面保存的连接配置,不修改远端 sshd、密码或 authorized_keys。
- 省略凭证字段表示保留。切换认证方式必须提供新密码或新私钥,并清理旧方式的凭证;新私钥不继承旧私钥的口令,`passphrase: ""` 表示清空。空密码/空私钥不是“保持不变”,会校验失败;响应不返回凭证。
- 已有 VM 的节点不能修改登录用户(`node_username_in_use`)。候选连接必须仍能访问现有 VM 容器、挂载目录及匹配的 UID/GID(否则 `node_runtime_mismatch`);不用于将已有节点迁移到另一台 VPS。被其他节点用作跳板、正在安装 Docker、构建镜像、处理调度请求或有 `withVmLock` 操作(如 VM 重置)尚未完成时拒绝修改连接配置,仍可改名。主机密钥轮换、跳板拓扑修改和 VM 迁移不在此接口范围。
- 直连通道:远程槽的 kernel / worker 请求默认在节点那一条 SSH 长连接里各开一个通道,长时间零碎流量会让这条连接的拥塞窗口卡在很低的值(实测约 17KB/s),突发的请求正文全部排队。`PUT /direct-link` 后控制面经 SSH 在节点上建 `kin-slot-gate`(宿主网络、只读挂载 `<root>/vms`、监听 `0.0.0.0:<port>`),之后每个槽连接是一条独立的 TLS 1.3 连接。gate 首次启动自签证书(`<root>/gate/tls/`),控制面经已固定主机密钥的 SSH 读取并固定其 SHA-256,指纹不符即不发令牌;每节点随机令牌加密存库,令牌与指纹任何响应都不回传。请求正文紧跟前言发出,不等 gate 应答。gate 只连 `<root>/vms/<vm>/run/{kernel,worker}.sock`,以 `O_PATH|O_NOFOLLOW` 打开,不跟随槽内植入的符号链接。连不上、证书不符或令牌被拒时该节点退回 SSH 30 秒,健康检查 ping 成功即恢复;Docker、终端、健康检查始终走 SSH。**节点防火墙应只对控制面出口 IP 放行该端口**(令牌之外的第二道门)。`direct_link.state`:`ok` 直连、`down` 已退回 SSH(`error` 为原因)、`pending` 尚未检查或尚未固定证书;`gate_error` 为节点端创建失败原因(如节点上还没有槽位镜像)。
- 本机 Docker 桥:每个节点在 `<data>/cluster/<id>/docker.sock`(0600)监听,`docker -H unix://…/docker.sock ps` 直接操作远端 daemon。数据目录所在文件系统不支持 unix socket(如 WSL `/mnt/*`)时设 `VM2API_CLUSTER_SOCKET_DIR`。

## 管理口(master)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test:all": "npm run test:unit && npm run test:go",
"build:worker": "mkdir -p bin && cd worker && CGO_ENABLED=0 go build -trimpath -o ../bin/kin-worker ./cmd/kin-worker",
"build:egress": "mkdir -p bin && cd worker && CGO_ENABLED=0 go build -trimpath -o ../bin/kin-egress ./cmd/kin-egress",
"build:gate": "mkdir -p bin && cd worker && CGO_ENABLED=0 go build -trimpath -o ../bin/kin-slot-gate ./cmd/kin-slot-gate",
"build:web": "pnpm -C web build",
"fetch:payload": "node scripts/fetch-payload.mjs",
"test:web": "pnpm -C web test",
Expand Down
1 change: 1 addition & 0 deletions scripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ ensure_bin() {
}
ensure_bin kin-kernel
ensure_bin kin-egress
ensure_bin kin-slot-gate
ensure_bin kin-worker
ensure_bin kin-api-kernel
ensure_bin kin-codex-kernel
Expand Down
Loading
Loading