☰
Ollama公网访问最佳实践:Nginx反向代理配置与安全加固
2026/10/2 1:36:04 网站建设 项目流程

先别急着去改OLLAMA_HOST=0.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 反向代理的强项。

反向代理在这套结构里相当于小区门卫。外部请求先到达 Nginx,Nginx 做完身份验证、访问控制、TLS 加密之后,再把干净的请求转发给内网的 Ollama。Ollama 本身继续监听内网地址,不直接面对公网流量。这种“收敛入口、隐藏后端、统一管控”的方式,是所有对外暴露服务的基本盘。

2. 部署形态选择:Ollama 监听本机还是 0.0.0.0

开始配 Nginx 之前,先把网络拓扑定下来。这一步直接决定你要不要改 Ollama 的监听地址,也决定后续防火墙该怎么配。

最常见的部署方式有两种。

第一种,Nginx 和 Ollama 装在同一台服务器上。这个形态最推荐,配置最简单也最安全。Ollama 保持默认监听127.0.0.1:11434,Nginx 监听公网 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写入Environment="OLLAMA_HOST=0.0.0.0:11434",然后daemon-reload+restart推荐用systemctl edit,不要直接改/etc/systemd/system/ollama.service,升级会被覆盖
Windows设置系统环境变量OLLAMA_HOST=0.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 和 443,11434 端口根本不用对外开放。如果 Ollama 在另一台机器,安全起见不要放行allow 11434/tcp这种无差别规则,而是限定来源 IP:

sudo ufw allow from <nginx服务器IP> to any port 11434 proto tcp

云服务器还要检查安全组规则,很多云厂商的安全组默认全放行或全拒绝,规则叠加后会覆盖本机 ufw 的效果。曾经遇到一个案例,本机防火墙配得严严实实,结果安全组没改,11434 照样公网可扫到。排查顺序一定是:先看安全组,再看本机防火墙,不要搞反。

3. Nginx 反向代理三步实操:装、配、验

环境理清楚之后,Nginx 这边的配置其实就是三个动作:装好 Nginx、写一份反代配置、校验并重启。每一步都不复杂,但每一步都有值得注意的地方。

3.1 第一步:安装 Nginx 并确认服务状态

Nginx 的安装在不同系统上略有差异,但都不难。Debian/Ubuntu 直接用 apt:

sudo apt update sudo apt install nginx -y sudo systemctl start nginx sudo systemctl enable nginx

CentOS/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而不是restart,reload 可以实现平滑升级,不会断开现有连接:

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/tags,Ollama 根本不认识这个路径,返回 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 并开启 keepalive:

upstream 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 zone=ollama_limit:10m rate=5r/s; server { ... location / { limit_req zone=ollama_limit burst=20 nodelay; ... } }

这里rate=5r/s表示平均每秒最多 5 个请求,burst=20允许瞬时 20 个请求排队处理,nodelay表示排队时不额外延迟。对于多人的团队协作场景,5r/s 可能偏紧,可以根据实际调整。但这个配置解决的是“防止入口被刷”,解决不了“单请求推理时间过长”的问题,后者更多依赖 Ollama 和 GPU 的调度。

5.4 用 Let's Encrypt 免费证书上 HTTPS

有了域名后,最省事的 HTTPS 方案是 certbot:

sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d ollama.example.com

certbot 会自动修改 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 到 504:Nginx 日志排错链路复盘

最后分享一个我自己排查问题的标准链路。反代上线后,最常遇到的就是 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 -f

Ollama 日志里如果出现CUDA error: out of memory,说明并发请求把显存打满了。这时候调 Nginx 超时没有意义,应该在业务侧限制并发,或者换更大的显存卡、改用量化版本模型。

6.3 connection refused / address already in use

Nginx 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,从本地联调到公网排障,基本都能在几分钟内定位。如果你也遇到了类似问题,按照这个顺序走一遍,大概率能省下不少折腾的时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询