手头那台 32G 内存、RTX 4090 的主机,装了 Ollama 0.3.10,顺手拉了 llama3:8b 和 llama3:70b。结果呢?手机、MacBook、老婆的 iPad 全跑来要接口。每台设备都 pull 一遍 5GB 起步的模型?脑子进水。70B 模型放 M2 MacBook 上跑,风扇响得跟直升机起飞似的。

让全家设备都连上同一个大模型

核心就三点:一台机器扛模型,其他设备当「哑终端」直连调用。所有 prompt 和响应全程不离内网,连 DNS 查询都不出墙。运维从「五台设备各自更新 Ollama 版本+重拉模型」缩成「只改 host 服务器上一个 systemd 进程和 Nginx 配置」。

对比每台设备单独部署,省的不只是磁盘空间——是每次模型升级时你蹲在终端前等 ollama pull 的 23 分钟,是 Mac Mini 突然卡死时全家投来的目光,是某天发现 iPad 上跑的还是三个月前的 llama3:4b 而不是刚发布的 llama3.1:8b

Nginx 在这里干的活,和它在微服务里当网关一模一样:把 http://服务器IP:80 统一收口,再悄悄转发给 ollamaPHP中文网提到的统一入口逻辑),顺便把流式响应的 SSE 和 CORS 头稳稳托住——毕竟 Llama 3 的 API 默认可不管跨域。

Ollama terminal command line

为什么 Ollama 比别的方案省心

别折腾了,直接上 Ollama。不是因为它“最火”,而是它把三件事干得特别干净:模型拉取自动解压、CPU/GPU 自适应调度、REST API 开箱即用——连 curl http://localhost:11434/api/chat 都不用改端口或加 middleware。

LM Studio 0.2.29 确实有漂亮 UI,但它的 API 是可选插件,默认不启;开起来占 1.2G 内存,还硬塞了个 Electron 框架。更麻烦的是——它不认 q4_K_M 这种量化名,非要你手动点选 GGUF 文件路径,一换模型就得重配一遍。

Ollama 不是“另一个封装器”。 启动后,本地所有设备只要能访问 host 的 11434 端口,就能直调 /api/chat 流式接口;ollama list 输出带模型哈希和大小,ollama rm 干净删,没残留 JSON 配置或孤立 bin 目录。我试过在树莓派 5(8GB)上跑 llama3:8bollama run 后 12 秒内就 ready,没报一句 CUDA error

对比 llama.cpp 单独编译,Ollama 少了 17 行 Makefile 和 3 次 git submodule update 失败;对比 text-generation-webui,它不依赖 Python 环境隔离,也不需要你记住 --load-in-4bit--trust-remote-code 的组合陷阱。

选它,不是因为完美,而是因为今天下午三点前,你得让 iPad 上的 Obsidian 插件连上 70B 模型——而 Ollama 是唯一一个 brew install ollama && ollama pull llama3:70b 跑完就能 curl 通的。

Nginx configuration file edit

装好 Ollama,拉下模型,先本地跑通

Linux 下一条命令完事:curl -fsSL https://ollama.com/install.sh | sh。macOS 用户更简单, 就搞定。Windows 嘛,去官网下个 exe 双击,装在 D 盘就行——别问为什么,C 盘迟早要炸。

装完别急着跑,先看一眼服务状态。终端里敲 systemctl status ollama,看到 active (running) 就对了。这时候打开另一个终端,用 拉模型。8B 的模型大概 4.7GB,我 100M 宽带拉了七分钟。过程中能看到下载进度条和哈希校验,没报红就等它跑完。

试一下很简单:

curl http://localhost:11434/api/chat -d '{
  "model": "llama3",
  "messages": [{"role": "user", "content": "你好"}],
  "stream": false
}'

返回一堆 JSON 里能找到 "content" 字段,那就是模型在回话了。如果报 curl: (7) Failed to connect,八成是 没跑起来,或者 11434 端口被别的进程占了。用 lsof -i :11434 看一眼是谁在占坑。

显存不够怎么办?我这台旧笔记本只有 6GB 显存,跑 llama3:8b 直接 OOM 崩了。换成 就行——这串后缀是量化版本,显存需求砍到 4GB 左右,回答质量损失肉眼几乎看不出来。Ollama 支持一堆量化标签:q2_K 最省但有点傻,q4_K_M 是甜点,q8_0 几乎无损但显存只省 20%。自己试两次就知道哪个合适。

注意

首次拉取模型必须联网,下载完存到 ~/.ollama/models/ 里。之后断网也能跑——我在地铁上试过,没信号照样调 API,延迟比联网还稳。

想确认模型列表?ollama list 会输出所有已拉取的模型名、哈希和大小。删模型用 ,不会留什么残留目录在硬盘里——比某些 GUI 工具干净多了。

Nginx 反向代理:把 11434 变成 80 端口

单机调通了,接下来就是让局域网里其他设备能访问。Ollama 默认只绑 localhost:11434,别的机器连不上。要么改 OLLAMA_HOST=0.0.0.0 裸奔出去,要么套一层 Nginx——我选后者,毕竟后面还要加鉴权、限流、HTTPS。

Ubuntu/Debian 系:sudo apt install nginx。CentOS 用 yum install nginx。macOS 有 brew:。装完先别急着改配置,看一眼默认页面能不能打开——浏览器访问 http://服务器IP:80,看到「Welcome to nginx」就说明跑起来了。要是端口被占,八成是 Apache 在捣乱。直接 sudo systemctl stop apache2 && sudo systemctl disable apache2,省得下次重启又抢端口。

找到 Nginx 配置文件。Ubuntu 在 /etc/nginx/sites-available/default,macOS 在 /usr/local/etc/nginx/nginx.conf。打开它,把 server 块改成下面这样:

server {
    listen 80;
    server_name _;

    location / {
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

保存后 nginx -t 测试语法。报错就仔细看行号,多半是漏了分号。测试通过就 systemctl reload nginxnginx -s reload。验证一下:局域网里另一台机器 curl http://服务器IP:80/api/chat,能拿到 Ollama 的响应就是成了。注意 Ollama 的 API 路径是 /api/chat/api/generate 这些,Nginx 会把整个 location 块透传过去。

跑对话模型最怕响应慢。默认 Nginx 会缓冲后端响应,攒够一定大小才发给客户端——这对流式 API 是灾难。用户在 Web 界面打字,等半天才看到第一个字蹦出来。在 location 块里加两行:

proxy_buffering off;
proxy_cache off;

这俩组合拳能让 Ollama 的流式响应实时推送到前端。实测关掉缓冲后,首字延迟从 1.2 秒降到 200 毫秒以内。代价是 Nginx 会增加一点 CPU 开销——但本地跑模型,那点负载根本不算事。

还有个坑:跨域。前端 JavaScript 直接调 Ollama API 会报 CORS 错误。加一行:

add_header Access-Control-Allow-Origin *;

放到 server 块里或 location 里都行。如果只想让特定域名访问,把 * 换成具体域名。安全要求高的话,再加 add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";OPTIONS 请求是浏览器的预检,Nginx 默认能处理,不用额外写条件。

贴一份我目前在用的完整配置,Ubuntu 22.04 + Ollama 0.1.32:

server {
    listen 80;
    server_name ollama.local;

    # 加大上传体积,防止模型请求被截断
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 流式传输优化
        proxy_buffering off;
        proxy_cache off;

        # 超时拉长,大模型响应慢
        proxy_read_timeout 600;
        proxy_connect_timeout 30;
    }

    # CORS
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}

重启 Nginx:sudo nginx -s reload。然后用局域网另一台设备测试:

curl http://192.168.1.100/api/chat \
  -d '{ "model": "llama3", "messages": [{"role": "user", "content": "你好"}] }'

看到流式输出一行行蹦出来,就说明配置生效了。如果卡住没反应,先 telnet 192.168.1.100 80 看端口通不通,再查 Nginx 错误日志 /var/log/nginx/error.log——八成是 proxy_pass 写成了 127.0.0.1:11434 但 Nginx 没权限访问,或者防火墙拦了。

配完这一步,局域网里任何设备都可以把 http://服务器IP:80 当成 Ollama 的 API 端点。手机上的 Termux、同事的 Windows 笔记本、甚至树莓派都能调。离线大模型共享,就这么简单。

真机实测:两台设备同时提问,看看扛不扛得住

现在你家路由器的 DHCP 池里,192.168.1.100 这台机器已经是个“AI 服务基站”了——不靠云、不走公网,连着 Wi-Fi 的设备全都能直连。

我拿 iPhone Safari 打开 ,页面空白?正常。直接改地址栏为:,回车——405 Method Not Allowed。好,说明 Nginx 接到了,只是没配 POST 前端界面。换用 Chatbox(v1.12.3)App,填入 API 地址、选 llama3 模型,发问:“Llama 3 的 tokenizer 是什么?”——三秒后字一个一个蹦出来,带流式光标。iPad 上也试了 Open WebUI v0.7.2,OLLAMA_BASE_URL=http://192.168.1.100 启动,完全无感切换。

别只盯着单请求,试试两人同时问“写个 Python 冒泡排序”。笔记本 curl + 手机 Chatbox 并发触发,Ollama 日志里能看到两个 inference 的推理线程在跑;top 看 CPU 到 82%,但没卡死,响应延迟从 2.1s 涨到 3.8s。Nginx access.log 里每条记录都带着 X-Real-IP,是真把源设备 IP 透传过去了——这点对后续加鉴权或限流很关键。

顺手关掉防火墙再开,结果断连两分钟。Ubuntu 默认 ufw 开着,sudo ufw allow 80 之后才恢复。别信“局域网就安全”的惯性思维:ufw 默认 deny incoming,连本机 telnet 自己的 80 都通不过。这个坑,我在树莓派 5 上踩过两次。

离线共享这事,最怕的不是性能瓶颈,而是你以为通了,其实中间某层静默丢包。

安全加固:别让隔壁小孩连 Wi-Fi 就调你 API

服务跑起来了,全家都能用——然后呢?最怕隔壁小孩连上 Wi-Fi 顺手给你喂个 prompt 把显存放爆。

Nginx 配个 allow/deny 也就三行的事。我习惯在 location / 里先写 allow 192.168.1.0/24;,然后 deny all;——这样只有你家的 DHCP 池能碰,访客网络或者 VLAN 隔离段直接 403。要是你有个固定办公位的私网段,再加一行 allow 10.0.0.0/8; 就行。千万别只靠防火墙。Nginx 这层先拦掉,日志里连 400 都不给返回,省得被扫端口的人盯着 access.log 看。

说实话,纯局域网里跑 HTTP 也不是不行——流量不经过公网,中间人攻击的概率极低。但如果你像我一样在树莓派上开了个自签名证书,那 server 块里加两行就够了:

listen 443 ssl;
ssl_certificate /etc/ssl/certs/ollama.crt;
ssl_certificate_key /etc/ssl/private/ollama.key;

自签的浏览器会弹警告,但 Chatbox 或 Open WebUI 里直接信任证书就安静了。要是你想省事,Let's Encrypt 在内网用 DNS challenge 也能签,但为了个离线服务折腾 DNS API 我觉得不值。

把 Ollama 注册成 systemd 服务跑起来以后,查日志其实就一行命令完事。

journalctl -u ollama -f

-f 跟踪输出,能看到每次推理的加载时间和请求来源 IP。有次我发现半夜两点有个 IP 在疯狂调 /api/generate,追过去一看是家里 NAS 上跑的定时脚本写死了轮询——写代码的人早忘了这茬。模型更新也别落下。Llama 3 的官方镜像在 ollama 仓库里会迭代,隔几周跑一次 拉最新的 tag。注意这命令会覆盖本地已有版本,如果你的微调模型也叫 llama3,记得改个名字再 pull。

离线大模型这玩意儿,跑通一次不难,难的是哪天突然想用、一敲命令它还在——那种踏实感,才是真正让人愿意一直跑下去的理由。