LEEHPC 集群中部署 Open-WebUI + Ollama 大模型推理服务的完整记录

作者: LEEHPC 一粒海

一句话总结: 在 LEEHPC 集群 GPU 节点部署 Ollama + Open-WebUI,通过管理节点 Nginx 反向代理实现多用户统一入口访问大模型,含完整 systemd 配置、并发调优和踩坑记录。

核心结论:这套方案把 Ollama 推理服务和 Open-WebUI 都跑在 GPU 节点 gpu02 上,用户只通过管理节点 mgmt01 的 8088 端口访问,GPU 节点的真实地址不需要暴露。实测 4 张 RTX 4090D 的配置足够支撑 4 个用户的并发推理,下面记录具体配置步骤和踩过的坑。

测试环境硬件平台:GPU 节点 gpu02,4 × RTX 4090D操作系统:Rocky Linux(管理节点 mgmt01 + GPU 节点 gpu02)软件版本:Ollama(最新稳定版)、Open-WebUI(pip 安装)、Nginx本文由 LEEHPC 一粒海团队基于实际项目经验整理

整体架构是什么样的?

先说一下最终效果 —— 用户访问的链路是这样:

用户浏览器
    ↓
http://管理节点IP:8088
    ↓
管理节点 mgmt01 Nginx 反向代理
    ↓
GPU 节点 gpu02 Open-WebUI:8088
    ↓
gpu02 Ollama:11434
    ↓
GPU 本地大模型推理

用户最终只需要记住一个地址:

http://mgmt01_ip:8088

环境关键信息:

项目 配置
管理节点 mgmt01
GPU 节点 gpu02
Web 入口 mgmt01:8088
Open-WebUI 节点 gpu02
Open-WebUI 端口 8088
Ollama 节点 gpu02
Ollama 端口 11434
Python 环境 /public/softwares/anaconda3/envs/python311
Open-WebUI 数据目录 /LLM/bin
Ollama 模型目录 /LLM/models
GPU 4 × RTX 4090D
推荐访问方式 http://mgmt01_ip:8088

基础目录怎么规划?

在 gpu02 上创建三个目录就够了:

mkdir -p /LLM/bin
mkdir -p /LLM/models
mkdir -p /LLM/src

用途分配如下:

目录 用途
/LLM/bin Open-WebUI 工作目录、数据库、日志
/LLM/models Ollama 模型存放目录
/LLM/src 安装包、源码、临时文件目录

验证一下:

ls -ld /LLM/bin /LLM/models /LLM/src

Ollama 怎么安装?

以下操作都在 GPU 节点 gpu02 上执行。

能连外网的话,在线装最快

curl -fsSL https://ollama.com/install.sh | sh

装完确认路径和版本:

which ollama   # 正常应该是 /usr/local/bin/ollama
ollama --version

外网太慢或者不能联网,离线装

如果服务器访问不了外网,可以在能联网的机器上下载 Ollama Linux 安装包再传上去。

下载地址:https://github.com/ollama/ollama/releases

可以用迅雷拖下来,文件名一般是 ollama-linux-amd64.tar.zst。把包丢到 /LLM/src

cd /LLM/src
zstd -d ollama-linux-amd64.tar.zst && tar -xvf ollama-linux-amd64.tar

确认二进制文件:

ls -l /LLM/bin/ollama

没执行权限的话加上:

chmod +x /LLM/bin/ollama

建个软链接到系统目录,后面用着方便:

ln -s /LLM/bin/ollama /usr/local/bin/ollama

不同版本 Ollama 离线包结构可能略有不同,以实际下载的包为准。

Ollama 的 systemd 服务和关键参数怎么配?

在 gpu02 上创建或编辑服务文件:

vim /etc/systemd/system/ollama.service

我们实际用的配置:

[Unit]
Description=Ollama LLM Service
After=network-online.target
Wants=network-online.target
​
[Service]
Type=simple
User=root
Group=root
ExecStart=/LLM/bin/ollama serve
Restart=always
RestartSec=5
​
# 监听所有接口,允许主节点访问
Environment="OLLAMA_HOST=0.0.0.0:11434"
​
# 模型别放默认目录,独立挂一个大容量分区
Environment="OLLAMA_MODELS=/LLM/models"
​
# 日志重定向(可选)
StandardOutput=append:/LLM/bin/nohup.out
StandardError=append:/LLM/bin/nohup.out
​
# 并发和性能相关 —— 下面这几个参数后面会细说
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_FLASH_ATTENTION=1"
​
[Install]
WantedBy=multi-user.target

加载并启动:

systemctl daemon-reload
systemctl enable --now ollama
systemctl status ollama

怎么确认 Ollama 跑起来了?

看端口

ss -lntp | grep 11434

正常应该输出类似:

LISTEN 0 4096 0.0.0.0:11434 users:(("ollama",pid=xxxx,fd=xx))

API 测试一把

curl http://127.0.0.1:11434/api/tags

服务正常的话会返回 JSON。

看日志

journalctl -u ollama -f

模型怎么下载和验证?

在线拉模型

gpu02 能访问外网的话,直接:

ollama pull nomic-embed-text

大语言模型,比如 gemma4:

ollama pull gemma4:31b-it-bf16

具体模型名以实际使用的为准,可查看:https://ollama.com/library/gemma4

确认已安装的模型:

ollama list

测一下推理能不能跑

ollama run gemma4:31b-it-bf16

进去后输入:

你好,请简单介绍一下你自己。

能正常回复就说明推理服务没问题。

Embedding 模型也要装一下

如果 Open-WebUI 打算用 RAG 或文档知识库功能,建议装上 embedding 模型:

ollama pull nomic-embed-text

Open-WebUI 里对应的环境变量:

Environment="RAG_EMBEDDING_ENGINE=ollama"
Environment="RAG_EMBEDDING_MODEL=nomic-embed-text"

Python 环境怎么准备?

Open-WebUI 要求 Python 3.11 或 3.12。我们用 Conda 创建环境:

source /public/softwares/anaconda3/bin/activate
conda env create -n python311 python=3.11

激活并升级 pip:

conda activate python311
python -m pip install --upgrade pip

Open-WebUI 怎么安装?

以下都在 gpu02 上执行,确保已经进入 python311 环境。

在线安装

默认源慢的话走国内镜像:

pip install open-webui -i https://pypi.tuna.tsinghua.edu.cn/simple

或者:

pip install open-webui -i https://mirrors.aliyun.com/pypi/simple/

确认一下装好了

which open-webui
# 正常输出:/public/softwares/anaconda3/envs/python311/bin/open-webui
​
open-webui --help

配 systemd 之前,手动启动测一下

建议先手动跑一遍,确认没问题再写成 systemd 服务。在 gpu02 上:

cd /LLM/bin

设环境变量:

export OLLAMA_BASE_URL=http://localhost:11434
export DATA_DIR=/LLM/bin
export HF_DATASETS_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
export HF_HUB_OFFLINE=1
export ENABLE_SIGNUP=true

启动,指定 8088 端口:

/public/softwares/anaconda3/envs/python311/bin/open-webui serve --host 0.0.0.0 --port 8088

另开一个终端测试:

curl -I http://127.0.0.1:8088

返回 HTTP/1.1 200 OKHTTP/1.1 307 Temporary Redirect 都算正常。

手动测试没问题后 Ctrl + C 停掉,开始配 systemd。

Open-WebUI 的 systemd 服务怎么配?

在 gpu02 上创建服务文件:

vim /etc/systemd/system/open-webui.service

当前推荐配置(做了不少参数调优):

[Unit]
Description=Open WebUI for Ollama
After=network-online.target ollama.service
Wants=network-online.target
​
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/LLM/bin
​
Environment="PATH=/public/softwares/anaconda3/envs/python311/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
Environment="OLLAMA_BASE_URL=http://localhost:11434"
Environment="DATA_DIR=/LLM/bin"
​
# 用户注册控制 —— 初始开一下,注册完记得关
Environment="ENABLE_SIGNUP=true"
Environment="DEFAULT_USER_ROLE=user"
​
# 离线模式,避免启动时去拉 HuggingFace 的东西
Environment="HF_DATASETS_OFFLINE=1"
Environment="TRANSFORMERS_OFFLINE=1"
Environment="HF_HUB_OFFLINE=1"
​
# 性能
Environment="WEBUI_WORKERS=4"
​
# 联网搜索配置(需要搭 searxng 或购买 API 才能用)
Environment="ENABLE_RAG_WEB_SEARCH=true"
Environment="RAG_WEB_SEARCH_ENGINE=searxng"
Environment="SEARXNG_QUERY_URL=http://localhost:8080/search?q=<query>&format=json&language=zh"
Environment="RAG_WEB_SEARCH_RESULT_COUNT=5"
Environment="RAG_WEB_SEARCH_CONCURRENT_REQUESTS=10"
​
# 文档解析与 RAG
Environment="RAG_EMBEDDING_ENGINE=ollama"
Environment="RAG_EMBEDDING_MODEL=nomic-embed-text"
Environment="CONTENT_EXTRACTION_ENGINE=default"
Environment="MAX_UPLOAD_SIZE=100"
Environment="ENABLE_RAG_LOCAL_WEB_FETCH=true"
​
# 如果要启用 Apache Tika 做文档解析,取消下面两行注释
# Environment="CONTENT_EXTRACTION_ENGINE=tika"
# Environment="TIKA_SERVER_URL=http://localhost:9998"
​
ExecStart=/public/softwares/anaconda3/envs/python311/bin/open-webui serve --host 0.0.0.0 --port 8088
​
Restart=always
RestartSec=10
StandardOutput=append:/LLM/bin/webui.log
StandardError=append:/LLM/bin/webui.log
​
[Install]
WantedBy=multi-user.target

加载并启动:

systemctl daemon-reload
systemctl enable --now open-webui
systemctl status open-webui

重启:

systemctl restart open-webui

怎么验证 Open-WebUI 服务?

在 gpu02 上:

ss -lntp | grep 8088
# 正常:LISTEN 0 2048 0.0.0.0:8088
​
curl -I http://127.0.0.1:8088
# 或
curl -I http://gpu02:8088

返回 200 或 307 都算正常。看日志:

tail -f /LLM/bin/webui.log

管理节点 Nginx 反向代理怎么配?

Open-WebUI 部署在 gpu02,但用户要从管理节点 mgmt01 的 8088 端口访问。需要在 mgmt01 上配 Nginx 反代。

装 Nginx

Rocky Linux 8/9:

dnf install -y nginx

反代配置文件

在 mgmt01 上创建:

vim /etc/nginx/conf.d/open-webui.conf
server {
    listen 8088;
    server_name _;
​
    client_max_body_size 10G;
​
    access_log /var/log/nginx/open-webui.access.log;
    error_log  /var/log/nginx/open-webui.error.log;
​
    location / {
        proxy_pass http://gpu02:8088;
​
        proxy_http_version 1.1;
​
        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;
​
        # WebSocket 支持,Open-WebUI 的流式对话依赖这个
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
​
        # 关闭缓冲,大模型流式输出不能缓冲,不然用户看到的是卡住不动的
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_cache off;
​
        # 超时设长一点,防止长回答时断连
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        send_timeout 3600s;
    }
}

如果管理节点解析不了 gpu02 主机名,把 proxy_pass 里的 gpu02 换成实际 IP:

proxy_pass http://10.10.10.xx:8088;

检查配置并启动

nginx -t
# 正常输出:syntax is ok 和 test is successful
​
systemctl restart nginx && systemctl enable nginx

Nginx 启动报 80 端口占用怎么处理?

这个坑挺常见。管理节点上往往已经有别的服务占了 80 端口,而 Nginx 默认配置会尝试监听 80,启动就报:

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()

排查步骤:

# 看谁在占 80
ss -lntp | grep ':80'
​
# 找 Nginx 里哪些配置监听了 80
grep -R "listen .*80" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf

如果 /etc/nginx/nginx.conf 里有默认的 80 监听,改成:

listen       127.0.0.1:18080 default_server;
# listen       [::]:80 default_server;

或者如果是 /etc/nginx/conf.d/default.conf 在监听 80,直接禁用它:

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled

改完检查并重启:

nginx -t
systemctl restart nginx

防火墙要开哪些端口?

管理节点开放 8088

firewall-cmd --permanent --add-port=8088/tcp
firewall-cmd --reload
firewall-cmd --list-ports

GPU 节点也需要开 8088(如果节点间有防火墙)

firewall-cmd --permanent --add-port=8088/tcp
firewall-cmd --reload
firewall-cmd --list-ports

集群内部节点间如果防火墙没限制,GPU 节点这一步可以跳过。

多用户怎么管理?

Open-WebUI 支持多用户。我们用的账号结构:

账号 邮箱 角色 用途
leehpc admin@qq.com 管理员 管理系统、用户、模型
user1 user1@leehpc.com 普通用户 用户 1 使用
user2 user2@leehpc.com 普通用户 用户 2 使用
user3 user3@leehpc.com 普通用户 用户 3 使用

第一个注册用户

Open-WebUI 第一个注册的用户自动成为管理员,管理员可以在后台管其他用户。

开启用户注册

管理员登录后:管理员面板 > 设置 > 允许新用户注册

建议短暂开放,注册完立即关闭,防止无限增加用户。

管理员手动创建用户

管理员登录 > 管理员面板 > 用户 > 新建用户(界面右侧 + 号)

模型权限设置

管理员登录 > 管理员面板 > 设置 > 模型 > 模型编辑(名称后面的笔符号)> 访问 > 公共 > 添加访问 > 刷新

并发和性能怎么调?

当前是 4 个用户用的场景。

Open-WebUI 并发

通过环境变量设置:

Environment="WEBUI_WORKERS=4"

注意:open-webui serve 命令本身不接受 --workers 参数,只能用 WEBUI_WORKERS 环境变量。

Ollama 并发

Environment="OLLAMA_NUM_PARALLEL=2"

如果模型比较小、显存充裕,可以试:

Environment="OLLAMA_NUM_PARALLEL=4"

出现显存不够或推理失败就退回 2。

Flash Attention

支持的 GPU 和模型建议开:

Environment="OLLAMA_FLASH_ATTENTION=1"

能降低显存占用,加载和推理都会快一些。在 4090D 上实测有效。

常用检查命令

管理节点 mgmt01

systemctl status nginx                             # Nginx 状态
ss -lntp | grep 8088                               # 是否监听 8088
curl -I http://127.0.0.1:8088                       # 本地测试
curl -I http://gpu02:8088                            # 测试到 GPU 节点连通性
tail -f /var/log/nginx/open-webui.access.log        # 访问日志
tail -f /var/log/nginx/open-webui.error.log         # 错误日志

GPU 节点 gpu02

systemctl status open-webui                         # Open-WebUI 状态
ss -lntp | grep 8088                                # Open-WebUI 端口
tail -f /LLM/bin/webui.log                          # Open-WebUI 日志
systemctl status ollama                             # Ollama 状态
journalctl -u ollama -f                             # Ollama 日志
ollama list                                         # 已安装模型
nvidia-smi                                          # GPU 状态

开机自启确认

gpu02:

systemctl is-enabled ollama      # 应为 enabled
systemctl is-enabled open-webui  # 应为 enabled

mgmt01:

systemctl is-enabled nginx       # 应为 enabled

最终的安全建议

管理员账号和所有普通用户都创建好之后,建议关掉注册入口:

Environment="ENABLE_SIGNUP=false"

然后:

systemctl daemon-reload
systemctl restart open-webui

运行建议:

1. 管理员账号只由系统管理员使用;
2. 每个用户使用独立账号,不要多人共用一个;
3. 创建完用户后关闭注册入口;
4. Nginx 只对外开放 8088;
5. Ollama 仅在内部节点访问,不暴露到公网;
6. 定期检查 /LLM/bin/webui.log 和 journalctl -u ollama 的日志。

踩坑记录

下面这几个坑当时排查得比较久,记录一下。

报错现象 原因分析 解决方案
bind() to 0.0.0.0:80 failed (98: Address already in use) 管理节点已有服务占用 80 端口,Nginx 默认配置尝试监听 80 ss -lntp | grep ':80' 查占用,禁用或修改默认 80 监听后重启 Nginx
Open-WebUI 启动后立即退出,日志显示 HuggingFace 下载失败 没有开启离线模式,启动时尝试连接 HuggingFace Hub 拉模型文件 确保设置了 HF_DATASETS_OFFLINE=1TRANSFORMERS_OFFLINE=1HF_HUB_OFFLINE=1
用户访问 mgmt01:8088 无响应 可能是 Nginx 没跑、防火墙没开、或 Open-WebUI 服务挂了 分别在 mgmt01 和 gpu02 检查监听端口和防火墙,在管理节点 curl 测试到 gpu02 的连通性
Open-WebUI 连接不上 Ollama OLLAMA_BASE_URL 配置错误或 Ollama 没监听正确地址 检查 Ollama 是否绑定 0.0.0.0:11434,确认 OLLAMA_BASE_URL 地址正确
多个用户同时推理时显存溢出 OLLAMA_NUM_PARALLEL 设太大,单张卡同时加载模型太多 建议默认设为 2,显存充裕再尝试调到 4

FAQ

Q:Ollama 默认把模型下载到系统盘,怎么改到数据盘上?

A:在 Ollama 的 systemd 服务文件里加一行 Environment="OLLAMA_MODELS=/LLM/models",然后 systemctl daemon-reload && systemctl restart ollama。模型目录需要提前创建好,Ollama 不会自己建。配完之后 ollama list 能看到路径变化。

Q:Nginx 反代时为什么要关 buffering?

A:因为大模型的输出是逐 token 流式返回的,如果 Nginx 开了缓冲,会把数据攒到一定量才发给客户端,用户看到的就是页面卡住、然后突然刷出一大段,体验很差。proxy_buffering off 之后每个 token 都能实时推到浏览器。这个在长回答场景下区别特别明显。

Q:Open-WebUI 启动就退出,日志里全是 HuggingFace 相关的下载报错,怎么解决?

A:一般都是服务器访问不了 HuggingFace Hub。在 Open-WebUI 的环境变量里加上这三行就行:

Environment="HF_DATASETS_OFFLINE=1"
Environment="TRANSFORMERS_OFFLINE=1"
Environment="HF_HUB_OFFLINE=1"

加上之后重启服务,应该就不会再去尝试联网下载了。

Q:4 张 RTX 4090D,OLLAMA_NUM_PARALLEL 设多少比较合适?

A:这个得看模型大小。当前测下来,如果模型显存占用在一张卡以内,设 4 问题不大;如果模型比较大、单卡显存紧张,建议设 2。显存不够的时候 OLLAMA_NUM_PARALLEL 设大了反而会导致推理失败,可以先从 2 开始,跑稳了再往上调。

Q:第一个注册 Open-WebUI 的用户就是管理员吗?后面怎么添加更多用户?

A:是的,第一个注册的自动成为管理员。之后管理员登录后可以在"管理员面板 > 用户"里手动创建新用户,也可以在设置里短暂开启"允许新用户注册",让别人自己注册完再关掉。根据 LEEHPC 团队的实操经验,建议走管理员手动创建的方式,可以严格控制用户数量。

其他

实时联网检索功能需要额外购买相关搜索 API 才能生效,文中配置的 searxng 也需要自行部署。

关于 LEEHPC 一粒海

LEEHPC 一粒海专注于高性能计算、AI 服务器与科学计算软件编译优化,提供 GPU/CPU 服务器定制、Slurm 集群调度、InfiniBand 网络部署、Lustre/BeeGFS 并行存储,以及 VASP、LAMMPS、CP2K、QE、ABACUS、GROMACS 等科研软件的编译与性能调优服务。

更多技术文章,欢迎关注公众号「服务器与科学计算」官网:www.leehpc.cn

标签:#HPC 集群 #Ollama 部署 #OpenWebUI #Nginx 反代 #大模型推理 #多用户管理 #LEEHPC 一粒海 #科学计算

posted @ 2026-08-11 21:12  llzz0309  阅读(4)  评论(0)    收藏  举报