mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-10-03 23:54:06 +00:00
feat(packaging): systemd unit 加固(逐条实测,非照抄模板)
原单元只有内存调优两行环境变量,加固项一个都没有,且以 root 运行。补上
一组经验证的加固指令。
关键决定:**仍然以 root 运行**。本服务要读 master.key(0600 root)。实测加
User=llmsproxy 直接起不来,且失败方式隐蔽——
[config] secrets disabled: open /etc/llmsproxy/master.key: permission denied
只是一行日志,服务会带着「敏感值以明文落盘」继续跑。也就是说在当前文件
权限下降权不是加固而是把密钥降级。要降权得先把 key 交给服务用户、统一
/etc/llmsproxy 属主,那是独立的、需要回滚预案的变更,不混进来。
每条指令都在一个独立探针单元(临时端口 + 独立 runtime_file/adapter_dir,
拷了真实适配器)上验证过:
- 鉴权 401/200 正常;
- 一次真实 /v1/chat/completions 走通(证明 SystemCallFilter=@system-service
没打断 LuaJIT 适配器的 JIT 代码路径——这是最容易被 seccomp 搞坏的地方);
- 审计文件可写可轮转(ReadWritePaths=/etc/llmsproxy 够用);
- 连续重启 3 次都 active + http 200,kill -9 行为符合预期。
systemd 对非法指令值不报错只「忽略」,所以逐条实测是唯一可靠做法。
读路径全在 /etc/llmsproxy;运行时写入经核对只有 config.yaml / runtime.json /
*.audit.jsonl / adapters/*.lua / master.key,全在该目录下,故 ProtectSystem=strict
+ ReadWritePaths=/etc/llmsproxy 即可。CapabilityBoundingSet 置空(本服务不需要
任何 capability,留空比写允许清单更难出错)。
已部署到线上 /etc/systemd/system/llmsproxy.service(原单元已备份为 .bak-*),
restart 后服务 active、监听 8081、WebUI 可达、审计继续写入;本仓库的
packaging/llmsproxy.service 与线上一致(去掉了部署机特有的 RSS 实测数字)。
This commit is contained in:
@ -4,21 +4,60 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
# Memory tuning (measured, see README "内存占用"):
|
||||
# Memory tuning (measured on this deployment, see README "内存占用"):
|
||||
# MALLOC_ARENA_MAX=2 caps glibc per-thread malloc arenas. LuaJIT allocates
|
||||
# through cgo -> glibc malloc, and glibc defaults to 8*nproc arenas, so every
|
||||
# OS thread that touches malloc reserved its own ~1 MB arena that is never
|
||||
# returned. Measured: 8-12 arenas -> 0.
|
||||
# GOGC=50 halves the Go heap growth target. On its own it does NOT help (the
|
||||
# saved heap is immediately eaten by more glibc arenas); combined with
|
||||
# MALLOC_ARENA_MAX it cut settled RSS by ~19%. This gateway is I/O bound, so
|
||||
# the extra GC cycles are free.
|
||||
# saved heap is immediately eaten by extra glibc arenas); combined with
|
||||
# MALLOC_ARENA_MAX it cut settled RSS by ~19% (24.7 MB -> 19.9 MB on a test
|
||||
# instance). This gateway is I/O bound (1min10s CPU per 9h), so the extra GC
|
||||
# cycles are free.
|
||||
Environment=GOGC=50
|
||||
Environment=MALLOC_ARENA_MAX=2
|
||||
ExecStart=/usr/bin/llmsproxy -config /etc/llmsproxy/config.yaml
|
||||
ExecStart=/usr/local/bin/llmsproxy -config /etc/llmsproxy/config.yaml
|
||||
WorkingDirectory=/etc/llmsproxy
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
# ---- 加固(2026-10-01 逐条实测后加入,不是照抄文档)----
|
||||
#
|
||||
# 为什么仍然以 root 运行:master.key 是 0600 root。加 User=llmsproxy 实测直接
|
||||
# 起不来,而且失败方式很隐蔽——
|
||||
# [config] secrets disabled: open /etc/llmsproxy/master.key: permission denied
|
||||
# 只是**一行日志**,服务会带着"敏感值将以明文落盘"继续跑起来。
|
||||
# 也就是说降权在当前文件权限下不是加固,而是把密钥降级。要降权必须先把
|
||||
# master.key 交给服务用户并统一 /etc/llmsproxy 的属主,那是一次独立的、有回滚
|
||||
# 需求的变更,不该和加固混在一起。
|
||||
#
|
||||
# 下面每一条都在一个独立探针单元(临时端口 + 独立 runtime_file/adapter_dir)
|
||||
# 上真实验证过:鉴权 401/200 正常、发一次真实 /v1/chat/completions 走通
|
||||
# (证明 LuaJIT 适配器路径没被 seccomp 打断)、审计文件可写可轮转、连续重启 3 次
|
||||
# 与 kill -9 后行为符合预期。systemd 对非法指令值不报错只"忽略",所以逐条实测
|
||||
# 是唯一可靠做法。
|
||||
NoNewPrivileges=yes
|
||||
# 读路径全部落在 /etc/llmsproxy;写路径经核对只有 config.yaml / runtime.json /
|
||||
# audit.jsonl / adapters/*.lua / master.key,全在该目录下(internal/{config,gateway,
|
||||
# core,lua} 里的 WriteFile|Rename|Remove 调用点)。
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc/llmsproxy
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
RestrictRealtime=yes
|
||||
LockPersonality=yes
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
# CapabilityBoundingSet 置空:本服务不需要任何 capability(不建 netns、不改
|
||||
# 资源限制、不 chown)。留空即"一个都不给",比列一份允许清单更难写错。
|
||||
CapabilityBoundingSet=
|
||||
# @system-service 已实测通过(含一次真实推理请求),它挡掉的是 mount/pivot_root/
|
||||
# keyctl 这类与网关无关的系统调用。
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallArchitectures=native
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user