想把 OpenAI、Claude、Gemini、OpenRouter 和本地模型放进同一个聊天界面,LobeHub 是现在很热门的一套方案。它原来叫 LobeChat,2.x 之后项目名、镜像、登录系统和部署结构都变了。网上不少旧教程还在用 lobehub/lobe-chat、NextAuth 或单容器命令,直接照抄很容易卡在登录、数据库和文件上传上。
这篇按 2026 年 7 月的稳定版 v2.2.12 来部署。官方 Docker Compose 不只有一个 Web 容器,还包括 PostgreSQL、Redis、RustFS 和 SearxNG。目标也不是“页面能打开就算完”,而是把域名、HTTPS、数据持久化、注册限制、更新和备份一起做完整。
先说结论:
- 只连接外部模型 API,2 核 4GB VPS 可以作为个人使用的起点;
- 多人使用、上传文档或知识库较多,建议 4 核 8GB 和 80GB 以上磁盘;
- 普通 CPU VPS 适合跑 LobeHub 界面,不适合硬跑 7B、14B 这类本地大模型;
- 如果你不想维护数据库、对象存储、登录和备份,直接用 LobeHub Cloud 会省很多时间。
2026 年 7 月,官方仓库已经迁移到 lobehub/lobehub,Docker 镜像也是 lobehub/lobehub。当前稳定版是 v2.2.12。
服务端部署的核心组件包括:
| 组件 | 用途 | 要不要持久化 |
|---|---|---|
| LobeHub | Web 界面、API、Agent 和知识库逻辑 | 配置由环境变量管理 |
| PostgreSQL | 用户、会话、Agent、文件元数据 | 必须 |
| Redis | 会话存储与缓存 | 建议 |
| RustFS | S3 兼容对象存储,保存上传文件 | 必须 |
| SearXNG | 联网搜索 | 按需保留 |
这里最容易产生误会的是“自托管”。你自建的是 LobeHub 应用和数据层。如果连接 OpenAI、Anthropic、Google 或 OpenRouter,提示词和请求仍会发送给对应提供商。只有模型也跑在你控制的 Ollama、vLLM 等推理服务上,模型请求才没有离开你的环境。
下面是部署起点,不是并发量承诺。实际占用会被用户数、文档数量、联网搜索、数据库增长和模型位置影响。
| 场景 | 建议起步 | 说明 |
|---|---|---|
| 单人使用,只接外部 API | 2 核 4GB、40GB SSD | 完整 Compose 能跑,别再塞其他重服务 |
| 3–10 人,偶尔上传文档 | 4 核 8GB、80GB SSD | 给 PostgreSQL、Redis、RustFS 留出余量 |
| 知识库和文件较多 | 4 核 8GB 起,独立对象存储 | 文件、索引和备份会持续吃磁盘 |
| 本地运行大模型 | 独立 GPU 服务器 | CPU VPS 即使能加载,速度通常也不实用 |
如果还没决定配置,可以先看 VPS 配置怎么选。这篇部署的是完整服务栈,1 核 1GB 不在推荐范围内。
把拓扑想清楚,后面排错会轻松很多:
浏览器
├─ https://ai.example.com -> Caddy -> LobeHub:3210
└─ https://s3.example.com -> Caddy -> RustFS:9000
LobeHub
├─ PostgreSQL:5432
├─ Redis:6379
├─ RustFS:9000
├─ SearXNG:8080
└─ OpenAI / Anthropic / Gemini / OpenRouter / 自建模型 API
PostgreSQL 和 Redis 不该暴露到公网。RustFS 的 S3 API 需要让浏览器访问,使用独立子域名最清楚;9001 管理端口只绑定本机,需要时用 SSH 隧道访问。
本文使用 Ubuntu 24.04、Docker Engine、Compose v2 和 Caddy。先准备两个 DNS 记录,都指向 VPS 公网 IP:
ai.example.com
s3.example.com
更新系统并安装基础工具:
sudo apt update
sudo apt install -y ca-certificates curl git openssl ufw
安装 Docker 官方仓库版本:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker version
sudo docker compose version
防火墙只开放 SSH、HTTP 和 HTTPS:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
如果你正在远程 SSH 操作,务必先放行 OpenSSH 再启用 UFW;当前连接稳定后,再开启其他防火墙规则。
官方仓库默认分支更新很快,生产实例不要直接跟着 canary 跑。先把稳定版 v2.2.12 拉到本地:
cd /tmp
git clone --depth 1 --branch v2.2.12 \
https://github.com/lobehub/lobehub.git lobehub-v2.2.12
sudo mkdir -p /opt/lobehub
sudo chown "$USER":"$USER" /opt/lobehub
cd /opt/lobehub
运行下载到本地的官方初始化脚本,并明确让它读取 v2.2.12 的配置:
bash /tmp/lobehub-v2.2.12/docker-compose/setup.sh \
-l zh_CN \
--url https://raw.githubusercontent.com/lobehub/lobehub/v2.2.12
选择域名部署,输入 ai.example.com 和 s3.example.com。脚本会下载 docker-compose.yml、.env、RustFS bucket 配置和 SearXNG 配置,并准备 KEY_VAULTS_SECRET、AUTH_SECRET、数据库密码与 RustFS 密码。
不要把终端里显示的密码粘到聊天、工单或 Git 仓库。初始化完成后先备份 .env,权限收紧:
chmod 600 .env
cp .env ".env.initial-$(date +%F-%H%M%S)"
chmod 600 .env.initial-*
官方示例里的 JWKS_KEY 只是示例值。按初始化脚本提示,在官方 JWKS 生成页面创建一套新的密钥,再替换 .env 中的 JWKS_KEY。这一步别跳过。
官方示例为了方便调试,PostgreSQL、Redis、RustFS 都声明了宿主机端口。公网 VPS 上应收紧:
- LobeHub:
127.0.0.1:3210:3210 - PostgreSQL:删除
5432:5432 - Redis:删除
6379:6379 - RustFS API:
127.0.0.1:9000:9000 - RustFS 管理端:
127.0.0.1:9001:9001
同时把 LobeHub 镜像固定为本次验证过的稳定版:
services:
lobe:
image: lobehub/lobehub:v2.2.12
ports:
- "127.0.0.1:3210:3210"
postgresql:
# 删除 ports,数据库只走 lobe-network
redis:
# 删除 ports,Redis 只走 lobe-network
rustfs:
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
检查 .env 里的外部地址:
APP_URL=https://ai.example.com
INTERNAL_APP_URL=http://localhost:3210
S3_ENDPOINT=https://s3.example.com
INTERNAL_APP_URL 在 Compose 部署里要保留容器内部地址。S3_ENDPOINT 不能带 bucket 路径或其他后缀,否则上传后的文件会打不开。RustFS 使用 path-style,官方 Compose 已设置 S3_ENABLE_PATH_STYLE=1。
修改后先校验,不要直接启动:
sudo docker compose config >/tmp/lobehub-compose-rendered.yml
grep -nE "image:|published:|DATABASE_URL|S3_ENDPOINT" \
/tmp/lobehub-compose-rendered.yml
确认渲染结果里没有把密钥意外写进公开日志,也没有 0.0.0.0:5432 或 0.0.0.0:6379。
拉取镜像并启动:
cd /opt/lobehub
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
第一次启动要等 PostgreSQL 健康检查、RustFS 初始化和数据库迁移。查看日志:
sudo docker compose logs --tail=200 lobe postgresql rustfs rustfs-init
本机先测 LobeHub:
curl -I http://127.0.0.1:3210
sudo ss -lntp | grep -E ":3210|:5432|:6379|:9000|:9001"
正常情况只有 3210、9000、9001 绑定在 127.0.0.1,5432 和 6379 不应出现在公网监听列表。
安装 Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/gpg.key |
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt |
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
编辑 /etc/caddy/Caddyfile:
ai.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3210
}
s3.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:9000
}
校验并重载:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://ai.example.com
curl -I https://s3.example.com
Caddy 会自动申请证书。失败时先查 DNS 是否已经指向当前 VPS,再看 journalctl -u caddy -n 100。更完整的配置和排错可以看 VPS 用 Caddy 反向代理完全指南。
LobeHub 2.x 使用 Better Auth。邮箱密码登录默认开启,如果什么都不改,公网实例可能允许陌生人注册。
个人实例最简单的限制方式,是在 .env 里只允许自己的邮箱:
[email protected]
这个变量只限制允许登录或注册的地址,并不验证邮箱所有权。需要密码重置、魔法链接或邮箱验证,还要配置 SMTP。
如果团队统一用 GitHub、Google、Keycloak 或其他 SSO,可以禁用邮箱密码:
AUTH_DISABLE_EMAIL_PASSWORD=1
AUTH_SSO_PROVIDERS=github
AUTH_GITHUB_ID=your-github-oauth-client-id
AUTH_GITHUB_SECRET=your-github-oauth-client-secret
OAuth 回调失败时,先检查 APP_URL 是否和浏览器访问域名完全一致,包括 https://。旧教程里的 NEXT_PUBLIC_AUTH_URL 已经废弃,继续设置反而会导致部署失败。
修改 .env 后重建应用容器:
sudo docker compose up -d --force-recreate lobe
sudo docker compose logs --tail=100 lobe
模型 API Key 可以写入 .env,也可以登录后在 LobeHub 设置中配置。团队实例更适合由管理员统一管理,避免每个人重复粘贴。
例如接入 OpenAI:
OPENAI_API_KEY=your-openai-api-key
如果使用 OpenRouter、LiteLLM 或其他 OpenAI-compatible 服务,要按官方提供商变量配置 Base URL 和 Key,不要凭感觉复用旧变量名。想先把多个上游统一成一个入口,可以配合 VPS 搭建 LiteLLM 统一 LLM API 网关。
改完后重建 LobeHub,并在网页里检查三件事:
- 模型列表能加载;
- 新建会话能收到完整回复;
- 刷新页面或重新登录后,会话仍然存在。
“模型列表为空”通常不是前端坏了,而是 API Key、Base URL、模型白名单或网络代理配置不对。直接看应用日志:
sudo docker compose logs -f --tail=200 lobe
上传一张小图片和一个测试文档,确认刷新页面后文件仍能访问。失败时按顺序查:
curl -I https://s3.example.com
sudo docker compose ps rustfs rustfs-init
sudo docker compose logs --tail=200 rustfs rustfs-init lobe
grep -E "S3_ENDPOINT|RUSTFS_|S3_ENABLE_PATH_STYLE" .env
常见问题有:
S3_ENDPOINT仍是http://localhost:9000,浏览器根本访问不到;- Endpoint 后面错误地加了 bucket 路径;
- RustFS 子域名没有 HTTPS;
- 9000 端口被防火墙或反向代理拦住;
.env中 Access Key、Secret Key 和 Compose 里的值不一致。
不要为了省事把 9000 直接开放公网。走独立 HTTPS 子域名更容易控制,也不会让浏览器遇到混合内容错误。
生产环境不要设置每几分钟自动拉 latest。LobeHub 更新快,数据库迁移也会变化。稳妥流程是:
cd /opt/lobehub
# 1. 记录当前镜像
sudo docker compose images
# 2. 完成下一节的备份
# 3. 把 docker-compose.yml 中的镜像改成已确认的新版本
sudo docker compose pull lobe
sudo docker compose up -d lobe
# 4. 查看迁移和启动日志
sudo docker compose logs --tail=300 lobe postgresql
如果升级后报数据库迁移错误,不要反复重启覆盖现场。保存日志,确认新旧版本的迁移说明;需要回滚时恢复旧镜像和升级前数据库备份。只把镜像 tag 改回去、却继续使用已经被新版本迁移过的数据库,不一定能正常运行。
完整恢复至少需要:
- PostgreSQL 数据;
- RustFS 对象文件;
- Redis 数据(如果希望保留会话缓存状态);
.env、JWKS、Caddyfile 和 Compose 配置;- 当前使用的镜像版本。
建立备份目录并导出数据库:
cd /opt/lobehub
mkdir -p "backups/$(date +%F)"
sudo docker compose exec -T postgresql \
pg_dump -U postgres -d lobechat -Fc \
>"backups/$(date +%F)/lobehub-postgres.dump"
cp .env docker-compose.yml bucket.config.json searxng-settings.yml \
"backups/$(date +%F)/"
sudo cp /etc/caddy/Caddyfile "backups/$(date +%F)/Caddyfile"
sudo chown -R "$USER":"$USER" backups
chmod 600 "backups/$(date +%F)/.env"
数据库名默认是 lobechat;如果改过 LOBE_DB_NAME,导出命令也要跟着改。
RustFS 和 Redis 使用 Docker Volume。先查看真实卷名:
sudo docker volume ls | grep lobehub
在短暂停机窗口里停止写入,再打包卷:
sudo docker compose stop lobe
sudo docker run --rm \
-v lobehub_rustfs-data:/source:ro \
-v "$PWD/backups/$(date +%F)":/backup \
alpine tar -czf /backup/rustfs-data.tar.gz -C /source .
sudo docker run --rm \
-v lobehub_redis_data:/source:ro \
-v "$PWD/backups/$(date +%F)":/backup \
alpine tar -czf /backup/redis-data.tar.gz -C /source .
sudo docker compose up -d
如果 docker volume ls 显示的名字不同,以实际结果替换命令。备份完成后把目录同步到另一台机器或对象存储;备份和生产数据放在同一块 VPS 磁盘上,机器坏了会一起消失。
恢复前要先在测试 VPS 演练。数据库恢复示例:
cat lobehub-postgres.dump |
sudo docker compose exec -T postgresql \
pg_restore -U postgres -d lobechat --clean --if-exists
先还原 .env 和密钥,再恢复 PostgreSQL 与对象文件,最后启动 LobeHub。密钥变了,即使数据库和文件都在,也可能出现登录失效或已保存凭据无法解密。
需要更完整的异地备份流程,可以接着看 VPS 备份恢复演练。
sudo docker compose ps
curl -I http://127.0.0.1:3210
sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 100 --no-pager
本机 3210 能访问、域名不行,问题多半在 DNS、Caddy 或防火墙。3210 本机也不通,再看 LobeHub 日志。
sudo docker compose ps postgresql
sudo docker compose logs --tail=200 postgresql lobe
sudo docker compose exec postgresql \
pg_isready -U postgres -d lobechat
重点核对 POSTGRES_PASSWORD、LOBE_DB_NAME 和渲染后的 DATABASE_URL。不要为了调试把 5432 开到全网。
检查 APP_URL、AUTH_SECRET、系统时间和浏览器 Cookie。域名从 HTTP 改成 HTTPS 后,要重建 LobeHub 容器,让环境变量真正生效:
timedatectl status
grep "^APP_URL=" .env
grep -q "^AUTH_SECRET=." .env && echo "AUTH_SECRET 已设置"
sudo docker compose up -d --force-recreate lobe
不要把 AUTH_SECRET 的值发到公开日志。
sudo docker compose logs --tail=400 lobe postgresql
sudo docker compose images
确认是不是跨了大版本、数据库迁移失败,或者新镜像需要新增环境变量。先保留日志和现有数据,再决定继续迁移还是从备份回滚。
-
ai.example.com和s3.example.com都是 HTTPS; - PostgreSQL、Redis 没有监听公网;
-
.env权限是 600,密钥没有提交到 Git; -
AUTH_ALLOWED_EMAILS或 SSO 已限制陌生人注册; - 模型列表、对话持久化、图片和文档上传都验证过;
- LobeHub 镜像固定到已确认的版本;
- PostgreSQL、RustFS、配置和密钥都有异地备份;
- 至少完成过一次测试环境恢复。
LobeHub 自托管的价值,是把聊天、Agent、文件和多模型入口放到自己控制的服务栈里。代价也很直接:数据库、对象存储、登录和更新都由你负责。个人使用从 2 核 4GB 起步没问题;团队正式使用,先把注册限制、备份恢复和升级回滚做完,再邀请其他人进来。
