ARTICLE DETAIL

资讯详情

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

Ollama公网访问最佳实践:Nginx反向代理配置与安全加固

Ollama公网访问最佳实践:Nginx反向代理配置与安全加固 先别急着去改OLLAMA_HOST0.0.0.0我见过太多人一上来就把 Ollama 暴露到公网然后被人扫到模型接口裸奔了几天才反应过来。去年年底帮一个朋友调团队协作工具对方把 Ollama 部署在公司一台高性能机器上想让外地同事也能远程调用结果折腾半天发现默认装完的 Ollama 只监听127.0.0.1:11434外网根本连不上。问题不在网络而在服务本身的监听地址。这个场景特别典型ollama 本地部署好了模型也拉下来了但要怎么让公网访问最合理的方案就是用 Nginx 做反向代理把 Ollama 的 API 隐藏在一个受控的入口后面。整个过程分成三步理清部署形态、写好 Nginx 反代配置、验证和加固。这篇文章把原理和坑都摊开讲适合三类人本地部署了 Ollama 想远程调用的人、准备用 OpenAI 兼容接口对接外部应用的人、以及想彻底搞懂 Nginx 反向代理配置的初学者。1. 先说清楚一个问题Ollama 到底要不要暴露公网很多人拿到这个标题的第一反应是“直接改配置让公网访问不就行了”但真正动手之前得先想明白你现在处于什么场景以及公网暴露意味着什么。Ollama 默认安装完以后服务绑定的是127.0.0.1:11434也就是只有本机能访问。这个设计是合理的因为模型服务本身没有用户认证机制/api/tags能列出所有模型/api/chat能直接对话/api/delete能删除模型。一旦端口暴露到公网等于把家门钥匙挂在大门口任何知道地址的人都能调用你的算力和数据。这里没有任何夸张我见过公网裸奔的 Ollama 被扫描工具扫到后模型被人删掉的事故。所以判断标准很直接如果你只是在自己电脑上折腾curl http://127.0.0.1:11434/api/tags能通就够了根本不需要暴露公网。如果你是团队共用一台 GPU 服务器想让外地同事、外部系统或者 Web 前端调用 Ollama 的 API那才需要一个公网可访问的入口。如果你想让外部系统走 OpenAI 兼容的/v1接口那入口不仅要通还得支持 HTTPS、鉴权、限流这些恰恰是 Nginx 反向代理的强项。反向代理在这套结构里相当于小区门卫。外部请求先到达 NginxNginx 做完身份验证、访问控制、TLS 加密之后再把干净的请求转发给内网的 Ollama。Ollama 本身继续监听内网地址不直接面对公网流量。这种“收敛入口、隐藏后端、统一管控”的方式是所有对外暴露服务的基本盘。2. 部署形态选择Ollama 监听本机还是 0.0.0.0开始配 Nginx 之前先把网络拓扑定下来。这一步直接决定你要不要改 Ollama 的监听地址也决定后续防火墙该怎么配。最常见的部署方式有两种。第一种Nginx 和 Ollama 装在同一台服务器上。这个形态最推荐配置最简单也最安全。Ollama 保持默认监听127.0.0.1:11434Nginx 监听公网 80/443 端口收到请求后转发到本机的127.0.0.1:11434。因为 Nginx 转发请求走的是本机回环地址流量根本不经过物理网卡Ollama 不需要暴露到外网。第二种Nginx 和 Ollama 分别装在两台机器上。这种适合“反代机在公网、GPU 机在内网”的拆分架构这时候 Ollama 必须监听0.0.0.0才能让局域网内的 Nginx 转发过来。但注意0.0.0.0意味着所有网卡接口都会监听如果这台 GPU 机本身有公网 IP风险会成倍上升必须靠防火墙或安全组把 11434 端口的访问源限制死在 Nginx 那台机器的 IP。判断你属于哪种只需要看一个事实Nginx 能不能用127.0.0.1访问到 Ollama。能就别改OLLAMA_HOST不能再考虑改监听地址。如果真的需要改各平台方式如下平台修改方式说明Linux (systemd)sudo systemctl edit ollama写入EnvironmentOLLAMA_HOST0.0.0.0:11434然后daemon-reloadrestart推荐用systemctl edit不要直接改/etc/systemd/system/ollama.service升级会被覆盖Windows设置系统环境变量OLLAMA_HOST0.0.0.0重启 Ollama命令行setx OLLAMA_HOST 0.0.0.0后新开终端生效macOSlaunchctl setenv OLLAMA_HOST 0.0.0.0重启 Ollama.app注意重启后环境变量会丢失需要写成脚本Dockerdocker run -d -p 127.0.0.1:11434:11434 ollama/ollama如果 Ollama 在 Docker 里、Nginx 在宿主机映射到127.0.0.1就够了别写-p 11434:11434暴露所有接口这里有个容易栽跟头的细节修改监听地址后一定要确认 Ollama 真的重启成功了。很多人改了环境变量服务还在跑旧进程导致外网依旧不通。验证命令很简单ss -lntp | grep 11434如果看到*:11434说明监听了所有网卡如果只有127.0.0.1:11434说明还在监听本机。防火墙这关也别忘了。Linux 本机如果开了 ufw需要放行 Nginx 用到的端口原则是最小化放行。比如 Nginx 在同一台机器只需要放行 80 和 44311434 端口根本不用对外开放。如果 Ollama 在另一台机器安全起见不要放行allow 11434/tcp这种无差别规则而是限定来源 IPsudo ufw allow from nginx服务器IP to any port 11434 proto tcp云服务器还要检查安全组规则很多云厂商的安全组默认全放行或全拒绝规则叠加后会覆盖本机 ufw 的效果。曾经遇到一个案例本机防火墙配得严严实实结果安全组没改11434 照样公网可扫到。排查顺序一定是先看安全组再看本机防火墙不要搞反。3. Nginx 反向代理三步实操装、配、验环境理清楚之后Nginx 这边的配置其实就是三个动作装好 Nginx、写一份反代配置、校验并重启。每一步都不复杂但每一步都有值得注意的地方。3.1 第一步安装 Nginx 并确认服务状态Nginx 的安装在不同系统上略有差异但都不难。Debian/Ubuntu 直接用 aptsudo apt update sudo apt install nginx -y sudo systemctl start nginx sudo systemctl enable nginxCentOS/RHEL 用 dnf 或 yum 也是一样装完先看状态sudo systemctl status nginx这一步我习惯顺手验证一下默认页面能不能通避免后面出问题分不清是 Nginx 没起来还是配置写错。curl -I http://127.0.0.1能返回 200 或 304 就说明 Nginx 服务本身没问题。如果本机都访问不到先解决 Nginx 启动问题不要急着写反代配置。启动失败最常见的原因是 80 端口被占用ss -lntp | grep :80一看便知多半是 Apache、Caddy 或者其他 Web 服务占了端口。3.2 第二步编写 Ollama 反向代理站点配置Nginx 的配置放在/etc/nginx/conf.d/下比较干净我习惯给每个服务单独建一个文件比如/etc/nginx/conf.d/ollama.conf。最小可用配置长这样server { listen 80; server_name ollama.example.com; 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 ; } }如果你连域名都没有可以先用server_name _;匹配所有请求用服务器公网 IP 直接访问也能跑通。但正式对外提供服务时还是建议配域名因为后面上 HTTPS 证书会省很多事。解释几个关键配置新手最容易在这几个地方出问题。proxy_pass http://127.0.0.1:11434;是转发目的地Nginx 收到外部请求后把请求原封不动转发给这个地址。如果 Ollama 在另一台机器这里就写那台机器的内网 IP比如http://192.168.1.10:11434。proxy_set_header Host $host;这句特别重要。Nginx 默认转发时会带上本地反向代理的主机名而不是用户请求的原始 Host。Ollama 虽然对 Host 头不敏感但如果你在同一个 Nginx 上托管多个服务或者日后加鉴权、限流Host 头混乱会非常难排查。统一传$host是最保险的做法。proxy_http_version 1.1;和proxy_set_header Connection ;这两行必须一起出现。Ollama 的/api/chat接口是 SSE 流式输出客户端连接需要保持较长时间。HTTP/1.0 默认每请求一个连接代理到上游时很快会断开设置为 HTTP/1.1 并且清空 Connection 头Nginx 才能复用和 Ollama 之间的 keep-alive 连接流式响应才不会中途断开。3.3 第三步语法校验、重启与连通性测试配置文件写完之后养成先校验再重启的习惯Nginx 提供了一个很好的工具sudo nginx -t看到syntax is ok和test is successful再执行重载。我的建议是用reload而不是restartreload 可以实现平滑升级不会断开现有连接sudo systemctl reload nginx验证分为三层逐层往上测。第一层本机验证反代是否生效curl http://127.0.0.1/api/tags正常会返回一个 JSON里面是模型列表。这一步能直接确认 Nginx 转发到 Ollama 的链路是否通畅。如果返回 502看错误日志后面排错章节单独讲。第二层用域名或公网 IP 验证外部访问curl http://ollama.example.com/api/tags如果本机能通、外网不通先检查云服务器安全组是否放行了 80/443 端口再检查本机防火墙。很多用户卡在这一步问题根本不在 Nginx 配置是安全组根本没放行 80 端口。第三层测试真实接口带上模型名发起一次对话curl http://ollama.example.com/api/chat \ -H Content-Type: application/json \ -d {model: qwen2.5:7b, messages: [{role: user, content: 你好}]}如果能看到流式返回的内容说明整个链路已经通了。我建议每次改完配置都按这个顺序验证一遍能省下大量排查时间。4. 我踩过的坑超时中断、大文件失败与路径解析配置能跑通只是开始上线后的稳定性才是真正考验。下面这几个坑是我在真实使用中踩过、也在帮别人排查时反复遇到的每一个都值得提前规避。4.1 SSE 流式响应被 Nginx 缓冲切断用 Ollama 的/api/chat接口时模型是边生成边输出的响应头是text/event-stream。默认情况下 Nginx 会对上游响应做缓冲先把内容攒到一定量再发给客户端。问题来了大模型生成速度完全取决于显存和模型规模如果生成慢、首 token 迟迟不来Nginx 的proxy_read_timeout默认 60 秒就会触发直接把连接掐断。表现就是前端界面一直转圈60 秒后报错。解决办法分两步。第一步关闭缓冲让内容实时流向客户端proxy_buffering off; proxy_cache off;第二步把超时调大。一个几十秒上百 token 的长回答推理时间很容易超过 60 秒尤其是用小显存显卡跑大模型时proxy_read_timeout 600s; proxy_send_timeout 600s;我实测在 4090 上跑 32B 模型单次回答最长能到 3 分多钟600 秒足够覆盖绝大多数场景。如果还不够可以结合proxy_connect_timeout一起调大但真正问题大概率不在连接阶段而是读响应阶段。4.2 client_max_body_size 导致请求体被拒Nginx 默认client_max_body_size是 1m超过 1MB 的请求体直接返回 413。Ollama 的接口通常只传文本看起来不会超但一旦你传 Base64 图片给多模态模型比如 llama3.2-vision、qwen2-vl一张几 MB 的图片转成 Base64 后体积还要膨胀三分之一分分钟触发 413。还有另一个场景如果你用 Ollama 做 Embedding 接口处理大批量文本请求体也很容易超过 1m。提前在 server 块里放开client_max_body_size 10g;设置成 10g 是因为模型文件、大图、批量文本都覆盖到了不会成为瓶颈。这个配置对安全性影响不大因为真正该限制的是访问频率和来源而不是请求体大小。4.3 Host 头与子路径重写使用域名反代时如果忘记设置proxy_set_header Host $host;Ollama 收到的请求头里 Host 可能是127.0.0.1:11434。大多数情况下 Ollama 不关心 Host 头但如果你在 Nginx 里还挂了其他服务或者客户端依赖 Host 拼接回调 URL就会莫名其妙出问题。所以统一建议永远加上 Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto 这四件套。更隐蔽的是子路径场景。有人不想为 Ollama 单独配一个域名想在已有域名的/ollama/路径下暴露服务比如https://example.com/ollama/api/tags。如果直接写location /ollama/ { proxy_pass http://127.0.0.1:11434; }转发到 Ollama 的路径会变成/ollama/api/tagsOllama 根本不认识这个路径返回 404。正确写法是用 rewrite 把子路径前缀去掉location /ollama/ { rewrite ^/ollama/(.*)$ /$1 break; proxy_pass http://127.0.0.1:11434; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Connection ; }不过这里要劝一句子路径方案能不用就别用。它虽然省了一个域名但很多 OpenAI SDK 的 base_url 拼接逻辑对子路径支持不友好客户端配起来容易出幺蛾子。有条件的直接上独立子域名省心太多了。4.4 并发场景下的 keepalive 配置多人共用同一个 Ollama 服务时如果每个请求都新建上游连接Nginx 和 Ollama 之间会频繁握手显存本来就紧张连接开销还会挤占 CPU。优化方法是定义 upstream 并开启 keepaliveupstream ollama_backend { server 127.0.0.1:11434; keepalive 32; } server { listen 80; server_name ollama.example.com; location / { proxy_pass http://ollama_backend; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; } }注意keepalive 32是 Nginx 与上游之间保持的空闲连接数不是最大并发数。模型推理本身的并发瓶颈在显存和 Ollama 的并发队列调度Nginx 这层的连接复用能减少握手开销但解决不了算力瓶颈。如果你的 GPU 显存只有 8G同事同时发起两个 7B 模型请求就可能 OOM这时候该做的是在 Ollama 层面控制并发或排队而不是盲目调大 Nginx 连接数。5. 公网访问的安全底线认证、限流、HTTPS 一个都不能少很多教程讲完反向代理就结束了但以我帮别人排查的经验来看真正上公网之前安全加固这步必须做否则出事的概率和代价都远超想象。再说一遍Ollama 没有任何认证机制。没有登录、没有 API Key、没有用户隔离。任何能访问到服务的人都能列出你的模型、调用你的推理、删除你的模型。这不是危言耸听公网裸奔的 Ollama 被扫到后模型被删的事故我是亲眼见过的。5.1 配置 HTTP Basic Auth 做第一道门最简单的做法是 Nginx 的 basic auth。先生成密码文件sudo apt install apache2-utils -y sudo htpasswd -c /etc/nginx/.htpasswd ollama_user然后在 server 块内加上auth_basic Ollama Access; auth_basic_user_file /etc/nginx/.htpasswd;这样所有请求在进入反代前都必须通过账号密码。注意basic auth 的账号密码是明文 base64 传输的必须配合 HTTPS 使用否则等于把密码明文贴在公网上。5.2 用 allow/deny 限制来源 IP如果使用者都是固定出口 IP直接在 location 里限制来源比任何认证都更严格location / { allow 203.0.113.10; allow 198.51.100.0/24; deny all; proxy_pass http://127.0.0.1:11434; }注意deny all 在 allow 之后执行Nginx 从上往下匹配先放行白名单再拒绝其余。这个方案适合公司内部团队共用场景配合 HTTPS 后基本可以挡住绝大多数陌生扫描。5.3 用 limit_req 做限流模型推理是重资源操作如果入口被恶意刷请求显存可能瞬间被塞满甚至影响同一台机器上的其他服务。Nginx 的限流模块可以做一个简单的保护limit_req_zone $binary_remote_addr zoneollama_limit:10m rate5r/s; server { ... location / { limit_req zoneollama_limit burst20 nodelay; ... } }这里rate5r/s表示平均每秒最多 5 个请求burst20允许瞬时 20 个请求排队处理nodelay表示排队时不额外延迟。对于多人的团队协作场景5r/s 可能偏紧可以根据实际调整。但这个配置解决的是“防止入口被刷”解决不了“单请求推理时间过长”的问题后者更多依赖 Ollama 和 GPU 的调度。5.4 用 Lets Encrypt 免费证书上 HTTPS有了域名后最省事的 HTTPS 方案是 certbotsudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d ollama.example.comcertbot 会自动修改 Nginx 配置、加载证书、配置自动续期。执行完后访问https://ollama.example.com/api/tags就能看到地址栏的小锁。这一步既是安全要求也是很多客户端 API 调用的硬性门槛——不少 SDK 默认拒绝明文 HTTP 请求。如果不想用 certbot也可以买云厂商的免费证书每年到期手动换一次但能自动化就别手动早晚会忘。5.5 端口收敛只留 443安全加固最后一步是收敛暴露面。云服务器安全组里只放行 443或者 80 跳转 443不要放行 11434。很多人配完 Nginx 忘了关 11434等于前门装了防盗门后门却敞开着。Nginx 监听端口和 Ollama 监听端口是两个概念外部只需要知道 Nginx 的入口即可Ollama 的端口应该隐藏在防火墙或安全组之后。6. 从 502 到 504Nginx 日志排错链路复盘最后分享一个我自己排查问题的标准链路。反代上线后最常遇到的就是 502 和 504这里把每条链路完整走一遍以后遇到类似问题可以照着查。6.1 502 Bad Gateway先查 Ollama 进程再查转发地址502 表示 Nginx 无法连接到上游。排错顺序固定三连ss -lntp | grep 11434 curl http://127.0.0.1:11434/api/tags systemctl status ollama第一句看进程是否在监听第二句看服务是否真正能响应第三句看进程状态。如果 curl 能通问题出在 Nginx 配置里的 proxy_pass 写错或端口写错如果 curl 不通问题在 Ollama 或网络层。还有一个容易被忽略的点SELinux。CentOS 上经常遇到 Nginx 能访问外网、但访问本机 11434 被拒的情况/var/log/nginx/error.log里会看到Permission denied。临时验证可以先关掉 SELinux 试试sudo setenforce 0如果关掉后立刻好了说明是 SELinux 策略问题需要给 11434 端口设置 httpd_can_network_connect 布尔值而不是长期关闭 SELinux。6.2 504 Gateway Timeout先看有没有首 token再看日志504 表示 Nginx 等上游响应超时。大多数情况是模型推理慢尤其 7B 以上模型在无 GPU 或小显存环境下首 token 可能就要几十秒甚至几分钟。此时直接把proxy_read_timeout调大重启 Nginx 观察。如果调大后还是频繁 504就要去 Ollama 日志里看是不是出现了 OOM 或显存不足journalctl -u ollama -fOllama 日志里如果出现CUDA error: out of memory说明并发请求把显存打满了。这时候调 Nginx 超时没有意义应该在业务侧限制并发或者换更大的显存卡、改用量化版本模型。6.3 connection refused / address already in useNginx error.log 里如果出现connect() failed (111: Connection refused)说明 Ollama 没在监听或者监听地址不是 Nginx 转发的地址。比如 Ollama 只监听了 127.0.0.1而 Nginx 转发到内网 IP 的 11434就会拒绝。解决办法是保持两边一致都走 127.0.0.1或者都走实际监听地址。如果重启 Ollama 时报address already in use说明上一次启动的进程没有退干净常见于 Windows 上改环境变量后旧进程残留。先杀掉旧进程再启动pkill -f ollama然后重新启动服务。6.4 日志是排错的地图排错到最后一定回到日志。Nginx 这边两个文件最关键/var/log/nginx/error.log记录连接错误/var/log/nginx/access.log记录请求状态码。Ollama 这边用journalctl -u ollama -f看运行日志。我的习惯是同时开三个终端窗口一个 tail access.log一个 tail error.log一个看 Ollama 日志然后用 curl 复现问题。哪个日志先有动静就顺着哪条线往下查。日志是最诚实的配置对不对、网络通不通、上游挂没挂它都会告诉你。这套链路我反反复复用了一年多从 502 到 504从本地联调到公网排障基本都能在几分钟内定位。如果你也遇到了类似问题按照这个顺序走一遍大概率能省下不少折腾的时间。
返回列表