4核4G的破服务器跑Qwen2.5-3B,还顺手接进了WorkBuddy
起因:一个抠门博主的自我修养
我那台腾讯云 CVM——4核、4G内存、40G系统盘,公网 IP 106.53.178.213——已经摆烂三个月了。这三个月它唯一的"事业",是跑着一套 LightClaw AI 助手全家桶:Chrome 无头浏览器常年空转,白吃约 50% CPU,还有个 11382 端口在公网裸奔,谁路过都能进来敲两下。
前阵子我终于看不下去了,连夜大扫除。全家桶全清,内存可用从 1.4G 回到 2.9G;swapfile 从 8G 缩到 2G(swapoff、dd 重建、mkswap、swapon,一套下来 5 秒搞定),磁盘可用回到 31G。趁着机器清爽,凌晨先把博客"进哥小院"架了上去——Halo + Caddy,两个 Docker 容器,它就是后文模型的"室友"。
架完博客我盯着监控看了半天:这机器,好像还有点余力?
于是冒出一个典型的作死念头:要不,在上面跑个大模型?
先交代底子
配置单确实寒碜:TencentOS 4.4,4核 CPU,4G 内存,40G 系统盘,没有 GPU,SSH 密钥登录 root。7B 的模型想都别想,更小的又怕太笨,Qwen2.5-3B(约 31 亿参数)刚好卡在均衡点上,Ollama 里的 tag 是 qwen2.5:3b。
顺便记录大扫除里最疼的一跤:清理 playwright 时我随手敲了 pkill -f ms-playwright,结果这条命令自己的命令行里就带着 "ms-playwright",pkill 顺着 -f 一匹配,把我所在的 SSH 会话当场杀掉,屏幕一黑,exit 255。教训:杀 Chrome 要用精确进程名 pkill -x chrome,别用 -f 匹配子串,容易自杀。
部署:容器是临时工,下载是渡劫
按惯例先起个临时容器试试水:
docker run -d --name ollama-test -v /opt/ollama-test:/root/.ollama ollama/ollama
容器秒起,没什么好说的。真正的劫难在后面:拉模型。qwen2.5:3b 体积 1.9G,Ollama 官方源在国内的速度稳定得令人绝望——100KB/s 上下,理论上要传五个多小时,实际比这还惨,中间断了 N 次。
唯一的安慰是 ollama 的断点续传很厚道:pull 中断不会丢已下载的 blob,重跑接着传就行。于是那晚我的工作流变成了:看进度、断了、重跑、去干别的、回来一看又断了、再重跑……像给一台老拖拉机加油,加一口歇一下。
实测:能跑,室友也没意见
数据全是人肉实测,童叟无欺:
- 生成速度 12.6 token/s,折算下来 100 字的回复约 6 秒
- 冷启动加载模型 7.5 秒
- 模型加载时内存 used 冲到 2.8G,available 只剩 781Mi——4G 内存被吃掉大半,触目惊心但没爆
- 和"进哥小院"共存无压力:模型狂奔时博客响应依然 0.2–0.4 秒,只有模型首次加载那次请求慢了 8 秒
博客和模型当室友,相安无事。
转正 + 上锁:只绑 127.0.0.1
测试通过,临时容器光荣退休,正式版上线:
docker run -d --name ollama \
--restart unless-stopped \
-v /opt/ollama:/root/.ollama \
-p 127.0.0.1:11434:11434 \
ollama/ollama
三个细节:--restart unless-stopped,服务器重启后模型自己爬起来;-p 127.0.0.1:11434:11434,只绑回环地址,公网完全摸不到——大模型端口暴露在公网等于裸奔送算力,我不做慈善;数据落在宿主机 /opt/ollama,容器没了模型还在,不用再渡劫一次。
接入 WorkBuddy:隧道、代理和托盘
模型在服务器跑通了,最后一公里是让本机 Windows 上的 WorkBuddy 用上它。Ollama 兼容 OpenAI 接口,思路就是 SSH 隧道把服务器的 11434 映射到本机:
ssh -i ~/.ssh/id_ed25519_xiaobu -f -N \
-L 11434:127.0.0.1:11434 \
-o ServerAliveInterval=30 -o ExitOnForwardFailure=yes \
root@106.53.178.213
这一步踩了两个坑。
坑一:我起初用后台方式跑这条命令,结果读不了私钥,Permission denied 抽了我一脸。正解是 ssh -f -N,让 ssh 自己守护进程化,密钥该读读该连连。
坑二:本机 curl localhost:11434 验证时直接报 upstream connect failed——被系统代理劫持了。回环地址根本不该走代理,加 --noproxy "*" 立刻清爽。
隧道通了,接着配置 ~/.workbuddy/models.json:走 OpenAI 兼容接口,url 指向 http://localhost:11434/v1/chat/completions,maxInput 设 4096——3B 小模型,别拿长篇大论为难它。这里还有个隐藏关卡:改完必须彻底退出 WorkBuddy(包括托盘里那个)再重启才生效,光关窗口等于白改。
端到端验证:0 积分
实战一把混合模式:云端搜索"西藏吉隆 8·26 泥石流遇难人数",把搜索结果喂给本地的 qwen2.5:3b,让它汇总成 150 字简报。结果汇总准确、要点齐全。最关键的是:这个汇总环节 0 积分消耗——搜索走云端,推理在我自己服务器上白嫖完成。
磁盘账本
部署完盘点这块 40G 的盘:总共用了 20G。其中 Docker 镜像占 9.4G——ollama 官方镜像自带 CUDA 库约 4G,而我压根只用 CPU;Halo 连带 JDK 约 4.5G。再加上模型本体 1.8G,剩下的才是系统。一块 40G 的盘被俩"虚胖"容器吃掉一半,属实心疼。
踩坑清单(给未来的我)
pkill -f会匹配到自己的命令行导致自杀,用精确进程名pkill -x chrome- SSH 隧道别用后台方式硬跑,
ssh -f -N自带守护进程化 - 本机 curl localhost 被系统代理劫持,加
--noproxy "*" - WorkBuddy 改配置要彻底退出(含托盘)重启才生效
- ollama pull 断了就重跑,断点续传可靠,别删缓存从头来
结论与后续
一台 4核4G 的轻量服务器跑 Qwen2.5-3B 完全够用:12.6 token/s,日常问答、总结、润色都能接受;安全上只绑回环加 SSH 隧道,外人摸不到;边际成本为零——服务器本来就在那,电费腾讯出。
后续计划:电脑重启后 SSH 隧道会断、得重拉,打算做成开机任务;frp 内网穿透还没装,装好出门也能用;ollama 镜像换 CPU-only 瘦身版,能省回约 3.5G 磁盘。
至于下一步嘛……先把我自己教会再说。