feat(packaging): core distribution packages (deb + rpm + tar.gz) via nfpm

Previously only the Electron GUI had installers; server admins had to build the
core by hand (`make build` -> bare binary). This adds a first-class server
distribution:

- `make core-dist` -> packaging/core-dist.sh -> cmd/build/dist/
    llmsproxy_<ver>_amd64.deb        (systemd unit + adapters + example config)
    llmsproxy-<ver>.x86_64.rpm
    llmsproxy-<ver>-linux-amd64.tar.gz
- nfpm config (packaging/nfpm.yaml): binary to /usr/bin, systemd unit with the
  measured memory tuning (GOGC=50, MALLOC_ARENA_MAX=2) baked in, Lua adapters to
  /usr/share/llmsproxy/adapters, repo's config.yaml as the example.
- postinst seeds /etc/llmsproxy/config.yaml on first install and keeps existing
  runtime state across reinstalls; prerm stops the service on removal.

Gotchas handled: nfpm v2 here does not render `{{ .Env.VERSION }}`, so the script
stamps the version into a throwaway config copy; and under `set -o pipefail` the
idiom `strings | grep -q` is broken (grep -q closes the pipe and strings dies on
SIGPIPE -> spurious 141), so the symbol sanity-gate stages strings in a temp file.

README (zh/en) updated: memory figures replaced with production-measured
32-35 MB settled (was 37-42), and the packaging docs now describe core-dist and
the dockerized Windows build.
This commit is contained in:
JianFeeeee
2026-08-30 10:49:25 +08:00
parent c309448414
commit ed05cccb72
9 changed files with 320 additions and 34 deletions

View File

@ -16,7 +16,7 @@
### 极致轻量
- **单二进制**:编译后 8~12MB`-s -w` strip 后约 8MB零运行时依赖仅依赖系统 libc部署即用
- **低内存占用**:与源数量相关,非与运行时长相关——单源 ~10MB、16 源生产实例 ~40MB[实测分解与调优](#内存占用实测与调优)
- **低内存占用**:与源数量相关,非与运行时长相关——单源 ~10MB、16 源生产实例 ~3235MB[实测分解与调优](#内存占用实测与调优)
- **日志按需加载**:统计数字来自**全量**审计日志启动时流式扫一遍即释放29MB/22 万行约 260ms但原始记录不常驻内存——默认只加载首屏下滚自动分页CSV 导出流式写出O(1) 内存),离页即释放
- **零运行时依赖**:纯 Go + LuaJIT 静态链接,无需安装 Python/Node/Java 等运行时
- **启动极快**:冷启动 < 200ms热重载配置 < 10ms
@ -293,7 +293,7 @@ WebUI 上的"新增/编辑源"、"上传 Lua 适配器"、"改 AUTO 优先级链
|---|---|---|
| 1 源 / 1 适配器(最小配置) | ~4 MB | ~10 MB |
| 1 源 + 29 MB 历史审计日志 | ~19 MB | ~20 MB |
| **16 源 / 13 适配器 / 59 模型(本机生产)** | ~28 MB | **~3742 MB** |
| **16 源 / 13 适配器 / 59 模型(本机生产)** | ~28 MB | **~3235 MB** |
> 历史参考:本项优化前同一生产配置为 **~105 MB**。降幅来自三处:审计日志的**原始记录**
> 不再常驻内存(约 25 MB统计聚合仍扫全量但扫完即释放、Lua 状态池不再单调增长、
@ -408,15 +408,16 @@ return {
发布到 Release 的安装包分为两类,面向不同用户:
- **Headless服务器版**:纯核心二进制(无 Electron配置驱动适合服务器、
容器、systemd 等无人值守场景。Linux 为 `.tar.gz`(二进制 + `config.example.yaml`
+ `adapters/` + READMEWindows 为 `.zip`
容器、systemd 等无人值守场景。发布包含 `deb` + `rpm`(含 systemd unit、内存调优
与示例配置)与 `tar.gz`(二进制 + `config.example.yaml` + `adapters/` + README
Windows 为 `.zip`
- **Desktop桌面版**Electron GUI 安装包,内嵌核心,适合个人桌面日常使用。
### 选择 GUI 还是纯后端
| 场景 | 推荐 | 理由 |
| ------ | ------ | ------ |
| 服务器 / 内网网关 / 无人值守常驻 | **Headless**(单二进制) | 极轻量(二进制 ~8MBRSS 随源数量,单源 ~10MB、16 源 ~40MB见[内存占用](#内存占用实测与调优)),零依赖单进程,直接跑在 systemd/任意容器里,远程管理 |
| 服务器 / 内网网关 / 无人值守常驻 | **Headless**(单二进制) | 极轻量(二进制 ~8MBRSS 随源数量,单源 ~10MB、16 源 ~3235MB见[内存占用](#内存占用实测与调优)),零依赖单进程,直接跑在 systemd/任意容器里,远程管理 |
| 个人桌面日常使用 / 多设备内网共享 | **Desktop**GUI | 免登录内嵌 WebUI、系统托盘一键启停、开机自启、静默后台适合不懂命令行的使用者 |
| Windows 桌面 | **Desktop** | 纯后端在 Windows 上需自行注册服务GUI 提供原生托盘/自启体验 |
| CI 一键出三平台安装包 | **Desktop 打包脚本** | `make gui-*` 系列出 deb/AppImage/NSIS可进发行流水线 |
@ -432,28 +433,35 @@ npm install
make gui # 或 npm run dev —— 开发运行(需先 make build 生成 bin/llmsproxy
make gui-deb # 本机构建 deb分享给其它 Linux 用户)
make gui-dist # 构建 deb + rpm + AppImagelinuxrpm 需系统 rpmbuild
make core-dist # 构建核心 deb + rpm + tar.gz服务器版需 nfpm
make gui-win # 构建 Windows nsis 安装包(本机 mingw + wine
make gui-win-docker # 构建 Windows nsis 安装包(全 docker 自足,无需本机 mingw
make gui-win-docker # 构建 Windows nsis 安装包(全 docker 自足,含 wine
make gui-dist-dir # 仅解包产物(调试用,不产安装包)
```
产物在 `cmd/build/gui-dist/``ModelRouter-<ver>.AppImage`
`modelrouter-gui_<ver>_amd64.deb``ModelRouter Setup <ver>.exe`win。rpm 需系统 `rpmbuild`
`modelrouter-gui_<ver>_amd64.deb``ModelRouter Setup <ver>.exe`win
核心包在 `cmd/build/dist/``llmsproxy_<ver>_amd64.deb``llmsproxy-<ver>.x86_64.rpm`
rpm 需系统 `rpmbuild`。每次打包后都会跑 `packaging/verify-dist.sh` 产物体检
大小下限门禁——1.3.0 曾因宿主 wine 损坏产出 264KB 的残缺 exe 却没有被拦住)。
发布时会把产物重命名为 `ModelRouter-Desktop-*`GUI`ModelRouter-Headless-*`(纯后端)
两类上传到 GitCode Release。
#### Windows 打包docker 固化方案,推荐)
`make gui-win-docker` 一步完成:交叉编译核心 + NSIS 打包,宿主机**无需安装 mingw**。
`make gui-win-docker` 一步完成:交叉编译核心 + NSIS 打包**全在 docker 内**,宿主机
**无需 mingw、无需 wine、无需 node**。镜像内置 wine含 i386 运行时),修复了
此前宿主 wine 损坏(缺 syswow64 → `c0000135`)导致产出 264KB 残缺 exe 的问题。
- 构建镜像:`cmd/gui/docker/win-builder/Dockerfile``golang:1.25` + mingw-w64 +
预编译 LuaJIT windows 版 `lua51.dll` 与 import libLuaJIT 源码取自 gitcode
镜像国内可达github 兜底Go 依赖走 `https://goproxy.cn`
- 核心编译`cmd/gui/scripts/win-core-docker.sh` —— 在容器内产出
`cmd/gui/bin/{llmsproxy.exe,lua51.dll}`
- 一键发布:`cmd/gui/scripts/dist-win-docker.sh` —— 核心编译后调用
electron-builder宿主需有 `wine` 用于 NSIS
- 首次运行自动构建 `modelrouter/win-builder` 镜像;已存在则直接复用。
node + wine32/wine64 + 预编译 LuaJIT windows 版 `lua51.dll` 与 import lib
LuaJIT 源码取自 gitcode 镜像国内可达github 兜底Go 依赖走 `https://goproxy.cn`
- 一键发布`cmd/gui/scripts/dist-win-docker.sh` —— 核心编译 + electron-builder
NSIS 全部在容器内执行(`USE_SYSTEM_WINE=true` 走镜像内的 wineelectron-builder
的 ~400MB 工具链缓存挂到 docker volume二次构建增量复用。
- 首次运行自动构建 `modelrouter/win-builder` 镜像(约 510 分钟);已存在则直接复用
- 打包完成后自动跑 `packaging/verify-dist.sh` 门禁exe 低于 5MB / deb·rpm·7z 低于
10MB 即失败——残缺安装包不可能再溜进 Release。
```bash
# 全 Windows 发布(核心重编 + NSIS