ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Nginx反向代理安全暴露Ollama服务:三步配置与避坑指南

用Nginx反向代理安全暴露Ollama服务:三步配置与避坑指南 本地跑起 ollama 之后我第一反应是这玩意儿真香。写脚本、整理文档、临时查点什么直接拉一个开源模型到本地就开干速度比线上 API 还稳定。但没过几天需求就变了人在公司想调家里的机器或者同事想连你部署的模型跑个测试怎么办答案通常是把 ollama 服务通过 Nginx 反向代理暴露到公网。很多人一听“暴露公网”就慌其实搞清楚链路之后动手只需三步——配置监听地址、签发 SSL 证书、写一份反代配置。这篇文章不聊花里胡哨的骚操作只讲我反复踩坑之后沉淀下来的一套稳妥方案。适合刚接触 ollama 和 Nginx 的新手也适合已经配过但总出幺蛾子的朋友。配置过程中常见的 502、流式响应卡顿、大模型上传 413 这些问题我也会逐条给你排查明白。1. 为什么非要用反向代理暴露 ollama三个绕不开的理由1.1 裸奔端口的三个坑我见过不少人图省事直接在云服务器安全组里放行 11434然后顺手改一下 ollama 的监听地址为 0.0.0.0。看似一分钟搞定实际上隐患不少。第一11434 是一个没有任何鉴权的 API 端口。公网上的扫描器每天都在扫常见端口一旦暴露任何人都可以直接调用你部署的模型轻则消耗算力重则被滥用甚至可能因为高频调用把机器搞挂。你辛苦拉的几个模型就成了别人的免费算力池。第二裸奔时走的是 HTTP 明文协议。你的对话内容、传入的文档、返回的推理结果在链路里都是裸奔状态。如果只是测试玩具模型还好一旦涉及内部数据或隐私信息这口锅谁都背不动。第三裸奔端口很难做精细化访问控制。你想限制某个 IP 访问、想给服务加个密码、想看谁在调用什么模型这些需求在纯 ollama 层面都很难优雅实现。而 Nginx 天然就干这个所有请求先过一层门卫再决定放不放行、发给谁。1.2 Nginx 反向代理具体帮你解决了什么Nginx 反向代理在这个场景下承担四个职责。一是 TLS 终止也就是把 HTTPS 的加密解密都放在 Nginx 这一层内部链路仍然走 HTTP搞定证书和加密的同时后端服务不用做任何改动。二是统一入口你可以让 ollama、Open WebUI、其他 API 服务都挂在同一个域名下用不同 location 分流。比如/v1走 OpenAI 兼容端点/api走 ollama 原生接口这样外部用户只看到一个标准 HTTPS 地址。三是连接优化Nginx 可以复用后端连接、调整超时时间、关闭缓冲以适配流式输出。ollama 的/api/generate和/api/chat接口是 SSE 流式返回如果网关层不做特殊处理用户侧会感觉一个字一个字往外蹦都卡顿。四是安全加固配合 Basic Auth、IP 白名单、limit_req 限流这些模块可以在入口层挡住大部分恶意请求而不需要改 ollama 一行代码。1.3 什么时候其实不需要反向代理反向代理不是银弹。如果 ollama 只是本机自用、或者只在公司内网访问那完全没必要暴露公网保持 127.0.0.1 监听是最稳妥的。如果你只是为了临时给朋友演示个 demo用网盘或者内网穿透工具可能更省事。再比如你用的云服务器本身就带了负载均衡和 HTTPS 证书托管那也可以直接用云产品来做不一定非得上 Nginx。一句话链路越短越好暴露面越小越好。只有当你的确需要让公网设备稳定、安全地访问 ollama 时才值得上 Nginx 反向代理这套方案。2. 动手前的环境准备拓扑判断、监听地址与 Nginx 本体2.1 先搞清楚你的部署拓扑配置反向代理之前先想清楚一个问题Nginx 和 ollama 是装在同一个机器上还是分开部署如果是同一台机器配置最简单Nginx 监听公网端口 80/443然后把请求转发到127.0.0.1:11434本机回环流量不走网卡速度快也安全。这是我推荐的方式。如果是不同机器例如 ollama 跑在一台内网 GPU 机器上Nginx 跑在另一台云服务器上那 proxy_pass 就要指向 ollama 的内网 IP例如http://192.168.1.10:11434。此时要格外注意防火墙Nginx 机器到 ollama 机器的 11434 端口必须放行但公网到 ollama 机器的 11434 仍然要封死流量只能走 Nginx 中转。还有一种情况是 Nginx 跑在 Docker 容器里。如果你用了 bridge 网络容器内的127.0.0.1指向的是容器自己不是宿主机此时 proxy_pass 要写宿主机内网 IP例如http://172.17.0.1:11434。如果你用 host 网络那直接写 127.0.0.1 没问题。2.2 修改 ollama 监听地址别急着改成 0.0.0.0ollama 默认只监听127.0.0.1:11434也就是说只有本机才能访问。如果你打算用 Nginx 反代而且 Nginx 和 ollama 在同一台机器其实保持默认监听 127.0.0.1 就足够了没必要把监听地址改成 0.0.0.0。改得越开放风险越大。只有 Nginx 和 ollama 在不同机器时才需要让 ollama 监听内网地址或 0.0.0.0。修改方式取决于你启动 ollama 的方式。如果用的是 Linux 下的 systemd 服务执行sudo systemctl edit ollama在打开的 override 文件里加入[Service] EnvironmentOLLAMA_HOST0.0.0.0:11434保存后重载并重启sudo systemctl daemon-reload sudo systemctl restart ollama如果你习惯直接命令行启动那就用环境变量方式OLLAMA_HOST0.0.0.0:11434 ollama serveWindows 用户在系统环境变量里新建一个OLLAMA_HOST值填0.0.0.0:11434重启 ollama 桌面端或服务即可。改完不要急着往下走先验证一下curl http://127.0.0.1:11434/api/tags能返回 JSON 模型列表就说明 ollama 正常。注意这里即使改成了 0.0.0.0本机用 127.0.0.1 访问也一定通如果这里就不通后面 Nginx 配置得再久也是白搭。2.3 安装 Nginx 并做基础检查Nginx 安装本身不复杂Ubuntu/Debian 系可以直接用系统源sudo apt update sudo apt install nginxCentOS/RHEL 系则是sudo dnf install nginx如果你想用官方源装更新版本可以去 nginx.org 按操作系统添加仓库不过对反代 ollama 这个场景系统自带版本完全够用。装完先启动并设置开机自启sudo systemctl enable --now nginx然后在浏览器访问服务器 IP能看到 Nginx 默认欢迎页就说明 Web 服务正常。如果你本来就在服务器上跑了其他站点注意别让端口冲突。防火墙方面先确认 80 和 443 端口已经放行。以 firewalld 为例sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --permanent --add-servicehttps sudo firewall-cmd --reload这里有个很容易被忽略的点无论 Nginx 和 ollama 是否同机公网侧的防火墙千万不要直接放行 11434 端口。所有外部流量只通过 80/443 进入 Nginx再由 Nginx 内部转发到 ollama。3. 三步配置 Nginx 反向代理证书、反代、验证3.1 第一步让 Nginx 接管 HTTPS 并完成证书配置先说证书。公网生产环境下强烈建议用 HTTPS否则你的 api_key、对话内容全部明文传输风险太大。最省心的方案是用 Lets Encrypt 免费证书配合 certbot 自动续期。安装 certbot 和 Nginx 插件sudo apt install certbot python3-certbot-nginx申请证书的前提是你有一个域名并且解析已经指向你的服务器 IP。假设你的域名是ollama.example.com执行sudo certbot --nginx -d ollama.example.comcertbot 会自动修改 Nginx 配置、帮你配好证书和 HTTPS 跳转。过程中按提示填邮箱、同意条款即可。证书申请成功后访问https://ollama.example.com会看到一个小锁标志说明 TLS 生效了。没有域名的情况下可以用 IP 自签名证书做一个功能验证但客户端访问时会有不受信任的警告自动脚本调用时还得额外跳过证书校验实际使用体验很差。所以但凡能做尽量申请域名和免费证书。3.2 第二步编写核心反代配置并逐行解释证书搞定后在/etc/nginx/conf.d/下新建一个配置文件比如ollama.conf。我的最终配置长这样server { listen 80; server_name ollama.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name ollama.example.com; ssl_certificate /etc/letsencrypt/live/ollama.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ollama.example.com/privkey.pem; client_max_body_size 20g; 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_http_version 1.1; proxy_set_header Connection ; proxy_buffering off; proxy_read_timeout 600s; proxy_send_timeout 600s; } }逐行说几个关键点。client_max_body_size 20g很多人不写但在 ollama 场景下几乎是必填项。因为 ollama 的/api/create或者模型导入接口会接收大体积文件而 Nginx 默认的 body 上限只有 1m不调大传点东西直接给你返回 413。这里我习惯按单文件最大可能体积来留余量20g 对绝大多数模型包都够用了。proxy_pass http://127.0.0.1:11434;是核心转发指令把请求转发给本机 ollama。如果你的 Nginx 和 ollama 不在同一台机器就改成你 ollama 的实际 IP。注意这里不带 URI只写到端口这样客户端请求的原始路径会原样传给后端。proxy_set_header Host $host;很重要。后端服务有时候会校验 Host 头如果你不传Nginx 默认会把内部地址塞进 Hostollama 可能返回异常。传原始域名是最稳妥的做法。proxy_set_header X-Real-IP $remote_addr;和X-Forwarded-For是为了让后端日志和业务逻辑拿到真实的客户端 IP。默认情况下后端看到的是 Nginx 的 IP排错时会很痛苦。proxy_buffering off;是流式响应不生效的罪魁祸首开关。ollama 的/api/chat接口是按 token 流式返回的Nginx 如果开启了缓冲会攒一批数据再发给客户端表现就是输出卡顿、不实时。关掉之后SSE 流就能顺畅地推给客户端。proxy_read_timeout 600s;是把读取后端响应的超时放到 10 分钟。大模型推理耗时很不稳定一个长上下文对话可能跑几分钟默认 60 秒超时会直接把你从网关层掐断表现为客户端收到 504。你可以直接把这个配置文件原样复制替换域名和证书路径然后执行sudo nginx -t看到syntax is ok和test is successful之后重新加载sudo systemctl reload nginx3.3 第三步验证反代是否生效配置完不要急着开心先在本机验证一遍。先测试 ollama 原生接口curl https://ollama.example.com/api/tags正常情况下会返回模型列表的 JSON。如果看到ollama.example.com证书相关的报错先检查系统时间和证书状态如果返回 502说明 Nginx 到 ollama 后端的链路有问题按下一章排查。再测试 OpenAI 兼容端点curl https://ollama.example.com/v1/modelsollama 从某个版本开始提供了/v1的 OpenAI 兼容 API很多现有代码可以直接切 base_url 过来无需改动。这一步能通说明你后续用 LangChain、OpenAI SDK 之类的工具都没问题。如果你想用 OpenAI SDK 写个小脚本验证Python 代码长这样from openai import OpenAI client OpenAI( base_urlhttps://ollama.example.com/v1, api_keyollama, # 只要非空就行服务端不校验 ) resp client.chat.completions.create( modelqwen2.5:7b, messages[{role: user, content: 你好介绍一下你自己}], ) print(resp.choices[0].message.content)跑通这段代码反向代理基本就大功告成了。此时外面的设备只要能访问你的域名就能用上你家里那台机器的算力。4. 避坑指南与常见问题排查从 502 到流式卡顿4.1 流式响应不生效输出一卡一卡这个现象很典型Open WebUI 里对话时文字不是一个个蹦出来而是停顿很久后一次性冒出来一大段看起来特别难受。原因就是proxy_buffering没关。Nginx 默认会把后端响应整个缓冲起来等攒够了再发给客户端。SSE 流式接口最怕这个所以要确保 location 里加上了proxy_buffering off;还有一个隐藏点是proxy_cache如果你在全局或者 server 层开启了缓存也对流式输出有影响。ollama 反代场景里建议不要开 proxy_cache。如果你改了配置依旧卡检查是不是有上层 CDN 或者云负载均衡又在做缓冲。有些 CDN 默认会缓冲动态请求需要在 CDN 控制台关掉缓存或者开启 SSE 支持。4.2 模型文件上传/下载直接 413有次我在配置完反代后用/api/create从现有模型创建一个新模型结果请求直接返回 413 Request Entity Too Large。看了半天才发现 Nginx 的client_max_body_size默认才 1m模型文件别说几个 G几百 M 都过不去。解决办法就是在 server 或 location 层显式调大上限client_max_body_size 20g;如果你把值设为 0表示不限制。但建议还是给个合理上限防止有人往你服务器上灌大文件把磁盘撑爆。4.3 502 Bad Gateway 与 504 Gateway Timeout502 表示 Nginx 连不上 ollama 后端。排查顺序是这样先确认 ollama 进程还活着systemctl status ollama curl http://127.0.0.1:11434/api/tags如果直接 curl 都失败问题在 ollama 侧和后端配置无关。接着确认监听地址对不对ss -tlnp | grep 11434如果看到的是127.0.0.1:11434而你的 Nginx 配置 proxy_pass 写的是别的 IP那就必然 502。反过来如果你让 ollama 监听 0.0.0.0但系统防火墙把 Nginx 所在机器的来源 IP 挡了同样会 502。504 则是 Nginx 连上了 ollama但 ollama 在超时时间内没返回结果。大模型推理耗时长需要调大proxy_read_timeout和proxy_send_timeout。我一般直接设 600s长对话时也够用。4.4 常见问题速查表现象排查思路解决方案502 Bad Gatewayollama 进程、监听地址、防火墙、Nginx 日志systemctl status ollamacurl 127.0.0.1:11434/api/tags检查 proxy_pass 地址504 Gateway Timeout模型推理耗时超过 Nginx 超时设置调大 proxy_read_timeout 和 proxy_send_timeout流式输出不实时Nginx 默认缓冲了 SSE 响应在 location 中加 proxy_buffering off413 Request Entity Too Largeclient_max_body_size 默认 1m模型文件超限在 server 或 location 中设置 client_max_body_size 20g证书报错自签名证书或证书链不完整用 certbot 申请 Lets Encrypt 免费正式证书403 ForbiddenBasic Auth 认证失败或 IP 白名单拦截检查 auth_basic 文件和 allow/deny 规则404 Not Foundlocation 路径未匹配到 ollama 路由用 location / 整体反代不要只写 /api后端日志只见内网 IP没设置 X-Forwarded-For 头添加 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for这些坑我基本都是逐个踩过来的尤其是 413 超时和流式卡顿属于“不遇到根本想不到”的类型。配置完先跑一个流式对话测试能实时输出才算真正过关。5. 进一步加固认证、IP 限制与日志监控5.1 用 Basic Auth 给 ollama 加一层密码ollama 本身不提供用户认证暴露到公网后理论上任何人都能访问你的 API。一个简单有效的补救方法是在 Nginx 层加 Basic Auth。先创建密码文件sudo mkdir -p /etc/nginx/conf.d/auth printf admin:$(openssl passwd -apr1 你的密码)\n /etc/nginx/conf.d/auth/ollama.htpasswd然后在 Nginx 配置的 server 或 location 里加上auth_basic ollama access; auth_basic_user_file /etc/nginx/conf.d/auth/ollama.htpasswd;重载 Nginxsudo nginx -t sudo systemctl reload nginx这样再访问https://ollama.example.com/api/tags浏览器会弹用户名密码框用 curl 需要加-u admin:你的密码。OpenAI SDK 那边直接填 Basic Auth 的用户名密码作为 api_key 也能通过。不过 Basic Auth 只是最基础的防护如果追求更精细的鉴权建议后面在应用层做 API Key 管理或者接入 OAuth2 代理这里不展开。5.2 用 IP 白名单缩小暴露面如果你的 ollama 服务只给自己或固定同事用IP 白名单是比密码更硬的限制。location / { allow 192.168.1.0/24; allow 114.114.114.114; deny all; proxy_pass http://127.0.0.1:11434; # 其余 proxy_set_header 和超时配置保持不变 }注意 allow/deny 的顺序Nginx 按从上到下匹配先 allow 再 deny all。如果你的用户访问时经常换 IP白名单会比较痛苦这种情况还是用 Basic Auth 更实际。5.3 日志与实时监控干了什么得留底暴露到公网后日志就是你的审计依据。在 Nginx 配置文件里显式指定日志路径access_log /var/log/nginx/ollama.access.log; error_log /var/log/nginx/ollama.error.log;然后实时看日志tail -f /var/log/nginx/ollama.access.log日志会记录每个请求的客户端 IP、请求路径、状态码和响应时间。万一真有人扫到你的服务日志里能看得清清楚楚。如果发现日志里大量出现非预期来源 IP第一时间用防火墙封掉再把 Basic Auth 或白名单补上。如果有防刷需求还可以加上 limit_req 限流limit_req_zone $binary_remote_addr zoneollama_limit:10m rate5r/s;然后在 location 里引用limit_req zoneollama_limit burst10 nodelay;这样单个 IP 每秒超过 5 个请求会被直接拒绝或排队大幅降低被脚本刷爆的风险。最后说一个我自己的习惯就算 Nginx 和 ollama 同机我也会在系统防火墙里单独限制 11434 端口只允许本机回环访问确保哪怕 Nginx 配置出错11434 也不会意外暴露到公网。每次改完配置先nginx -t再 reload这个两步操作我已经坚持了很多年因为踩过改错配置直接让整个站点掉线的坑实在不想再去第二次了。
返回列表