diff --git a/packaging/config.example.yaml b/packaging/config.example.yaml new file mode 100644 index 0000000..a06d732 --- /dev/null +++ b/packaging/config.example.yaml @@ -0,0 +1,30 @@ +# llmsproxy — 统一 OpenAI 兼容网关配置(示例模板) +# +# 这个是打包进发行包、供首次安装使用的模板。它故意不含任何可用的凭据: +# 首次启动时程序会生成一个随机 admin key 并写入实际配置(WebUI「密钥」页可见)。 +# +# ⚠ 不要在本文件里填一个写死的具体 key。示例文件是公开的,写进去的任何值 +# 都会成为一个全网皆知的 admin key(旧版示例里的 sk-gw-local-0001 就踩过 +# 这个坑:它被直接抄进生产配置并真实可用)。 + +# 网关监听地址(默认 :8080,建议绑内网/回环) +listen: 127.0.0.1:8080 + +# 客户端访问本网关所需的 API Key(Bearer)。留空数组 = 不鉴权(仅内网)。 +gateway_keys: [] + +# 默认模型选择:具体模型 id 或 AUTO(按各源模型的 priority 自动选最高可用源) +default_model: AUTO + +# Lua 适配器目录(默认 adapters/,首次启动自动写入内置适配器) +adapter_dir: adapters + +# 运行时持久化文件(WebUI 新增/编辑的源会写入此文件,重启后仍生效) +runtime_file: runtime.json + +# 全局并发上限(0 = 不限) +max_concurrent: 0 + +# ---- 上游 LLM 源列表 ---- +# 留空:安装后到 WebUI 添加源,或从内置模板一键创建。 +sources: [] diff --git a/packaging/core-dist.sh b/packaging/core-dist.sh index 514a2e5..5445fc4 100755 --- a/packaging/core-dist.sh +++ b/packaging/core-dist.sh @@ -68,7 +68,12 @@ log "packaging tar.gz..." TAR_DIR="$DIST/llmsproxy-$VERSION-linux-amd64" rm -rf "$TAR_DIR"; mkdir -p "$TAR_DIR" cp "$BUILD_BIN" "$TAR_DIR/llmsproxy" -cp "$ROOT/config.yaml" "$TAR_DIR/config.example.yaml" +# Use the tracked sanitised template, NOT the local config.yaml: that file is +# gitignored and carries the operator's real gateway_keys / upstream keys. It +# was previously copied verbatim as config.example.yaml, which shipped a real, +# working admin key (sk-gw-local-0001) to every install — and postinst.sh copies +# the example to /etc when none exists, so it ended up live in production. +cp "$ROOT/packaging/config.example.yaml" "$TAR_DIR/config.example.yaml" cp "$ROOT/packaging/llmsproxy.service" "$TAR_DIR/llmsproxy.service" mkdir -p "$TAR_DIR/adapters" cp "$ROOT"/internal/lua/adapters/*.lua "$TAR_DIR/adapters/" diff --git a/packaging/nfpm.yaml b/packaging/nfpm.yaml index 618ab6e..efcbcb3 100644 --- a/packaging/nfpm.yaml +++ b/packaging/nfpm.yaml @@ -28,8 +28,11 @@ contents: dst: /etc/systemd/system/llmsproxy.service file_info: mode: 0644 - # example config (seeded to /etc/llmsproxy on first install by postinst) - - src: ./config.yaml + # example config (seeded to /etc/llmsproxy on first install by postinst). + # Must be the tracked sanitised template: ./config.yaml is the operator's own + # gitignored config and shipping it would leak real credentials — it shipped a + # working admin key (sk-gw-local-0001) to every install for a while. + - src: ./packaging/config.example.yaml dst: /usr/share/llmsproxy/config.example.yaml file_info: mode: 0644 diff --git a/packaging/postinst.sh b/packaging/postinst.sh index a41100d..63768d3 100755 --- a/packaging/postinst.sh +++ b/packaging/postinst.sh @@ -9,9 +9,19 @@ mkdir -p /etc/llmsproxy/adapters if [ -f /etc/llmsproxy/config.yaml ]; then echo "llmsproxy: keeping existing /etc/llmsproxy/config.yaml" else - # seed a starter config from the packaged example - cp -f /usr/share/llmsproxy/config.example.yaml /etc/llmsproxy/config.yaml 2>/dev/null || true - chmod 0644 /etc/llmsproxy/config.yaml + # Do NOT seed a starter config here. Packaging/installing one used to hand + # everyone the same file, and while it was copied from the maintainer's + # live config it shipped a real, working admin key (sk-gw-local-0001) to + # every install. + # + # Instead, leave the file absent: on first start the binary's EnsureDefault + # path creates config.yaml with a FRESH RANDOM admin key and logs it, which + # is both unique per install and actually usable. The packaged + # config.example.yaml stays in /usr/share as a reference template only. + # + # (Seeding it with gateway_keys: [] would be worse: the gateway would start + # but reject every request, with no way in except editing the file.) + echo "llmsproxy: no /etc/llmsproxy/config.yaml — a random admin key will be generated on first start" fi # systemd