用一台腾讯云轻量服务器 + 宝塔面板,把字节开源的 AI Agent 上下文数据库 OpenViking 部署上线,并通过自己的域名跑通 HTTPS、语义检索和对话机器人。全文记录每一步命令、每一处报错和原因。

一、这东西是干什么的,为什么值得部署
OpenViking 是火山引擎开源的、专门给 AI Agent 用的上下文数据库。它把 Agent 需要的三类东西——记忆(Memory)、资源(Resource)、技能(Skill)——统一成一套虚拟文件系统,用 viking:// 协议寻址。
和传统 RAG 最大的区别有两点:
- 分层供给:写入时自动生成三层——
L0 摘要(256 字符,用于向量召回)、L1 概览(4000 字符,用于精排)、L2 全文(按需加载)。不用一次性把海量内容塞进提示词。 - 目录递归检索:先向量定位到高分目录,再在目录里二次检索、逐层下探。比平铺式向量搜索更能理解”这句话在什么语境里说”。
说白了:它让你的 AI 助手有长期记忆,而且这套记忆是可以用 ls、find、read 直接查看和调试的,不是黑箱。
二、开工前的准备
2.1 你需要什么
| 项目 | 说明 |
|---|---|
| 一台云服务器 | 本文用腾讯云 2 核 3.5G 轻量服务器,系统 OpenCloudOS 9.6(RHEL 系,用 dnf) |
| 宝塔面板 | 本文用 宝塔 Linux 面板 11.8 腾讯云专享版,用来做反向代理和 SSL |
| 一个域名 | 需要已备案(国内服务器必须) |
| 模型 API Key | 需要两个模型:一个 Embedding(向量化)、一个 VLM(视觉多模态)。本文用 MiniMax |
关键认知:为什么需要”两个”模型?
Embedding 负责把文本变成向量(检索用),VLM 负责读图和理解内容(解析用)。这两个是 OpenViking 的硬依赖,缺一个
doctor就不过。
2.2 先做环境体检
cat /etc/os-release | head -3
uname -m
python3 -V
free -h
df -h /
ss -lntp | grep 1933 || echo "1933 端口空闲"
本文环境的实测结果:
| 检查项 | 实测值 | 结论 |
|---|---|---|
| 系统 | OpenCloudOS 9.6 | RHEL 9 兼容,用 dnf,不要用 apt |
| 架构 | x86_64 | 有预编译包,不需要源码编译 |
| Python | 3.11.6 | 满足 ≥3.10 要求 |
| 内存 | 3.5G 总量 / 2.3G 可用 | 超过 2G 及格线 |
| 1933 端口 | 空闲 | OpenViking 默认端口,无冲突 |
三、安装
3.1 装 uv,建独立虚拟环境
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrc
# 建一个专用虚拟环境(不要装进系统 Python,也不要动宝塔自己的 pyenv)
uv venv /opt/openviking/venv --python 3.11
为什么必须用独立虚拟环境? 宝塔面板自己的 Python 在
/www/server/panel/pyenv,那是面板的命根子,装任何东西进去都可能把面板搞挂。
3.2 安装 OpenViking
source /opt/openviking/venv/bin/activate
uv pip install openviking
openviking-server --version # 本文实测 0.4.20
deactivate
四、写配置文件 ov.conf
配置文件放在 /etc/openviking/ov.conf:
mkdir -p /etc/openviking
cat > /etc/openviking/ov.conf <<'EOF'
{
"server": {
"host": "127.0.0.1",
"port": 1933,
"root_api_key": "CHANGE_ME_ROOT_KEY"
},
"storage": {
"workspace": "./data",
"agfs": { "backend": "local" },
"vectordb": { "backend": "local" }
},
"embedding": {
"dense": {
"provider": "minimax",
"model": "embo-01",
"api_key": "CHANGE_ME_EMBEDDING_KEY",
"api_base": "https://api.minimax.cn/v1/embeddings"
}
},
"vlm": {
"provider": "openai",
"model": "MiniMax-M3",
"api_key": "CHANGE_ME_VLM_KEY",
"api_base": "https://api.minimax.cn/v1"
}
}
EOF
chmod 600 /etc/openviking/ov.conf
python3 -m json.tool /etc/openviking/ov.conf > /dev/null && echo "JSON 合法"
⚠️ 坑 1:Embedding 的 api_base 必须写到 /embeddings 这一级
这是全文最容易踩、也最难查的一个坑。
MiniMax 的 Embedding 端点是
https://api.minimax.cn/v1/embeddings,而 OpenViking 源码里是直接 POST 到api_base这个值,不会自动帮你拼/embeddings路径。所以如果你只写https://api.minimax.cn/v1,请求会 404。正确写法:
api_base一路写到/embeddings为止。另外,网上一些老教程会让你配
GroupId/extra_headers——那是针对 MiniMax 老平台的。新版平台不需要,加了反而可能报token not match group。
五、自检 doctor
/opt/openviking/venv/bin/openviking-server doctor
跑完应该看到各组件全绿。如果 embedding 报错,回到第四章检查 api_base。
你会看到一条 WARN,不用慌:
VikingBot: WARN bot.ov_server not configured and ovcli.conf api_key not configured这条是给可选的对话机器人组件 VikingBot 用的,和核心功能(文件系统 / 检索 / 会话)完全无关。它是”功能开关没打开”,不是”坏了”——后面第十一章我们会把它正式启用。
六、用 systemd 做成常驻服务
cat > /etc/systemd/system/openviking.service <<'EOF'
[Unit]
Description=OpenViking HTTP Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/openviking
ExecStart=/opt/openviking/venv/bin/openviking-server
Restart=always
RestartSec=5
Environment="OPENVIKING_CONFIG_FILE=/etc/openviking/ov.conf"
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now openviking
systemctl status openviking --no-pager | head -12
curl -s http://127.0.0.1:1933/health; echo
为什么
ExecStart要写绝对路径? 这样 systemd 不依赖任何 shell 环境变量,也不需要预先activate虚拟环境,更稳。
七、宝塔反向代理 + HTTPS

7.1 建站 + 加反向代理
- 宝塔面板 → 网站 → 添加站点,域名填你的(例如
your-domain.com) - 站点设置 → 反向代理 → 添加,目标 URL 填
http://127.0.0.1:1933,代理目录填/(结尾不要带斜杠)
宝塔 11.8 的反代配置在哪儿? 不在站点主配置里,而在独立目录:
/www/server/panel/vhost/nginx/proxy/your-domain.com/*.conf。站点 conf 只是include了它。改反代参数要改这个目录里的文件。
7.2 补转发头和超时(重要)
AI 服务响应慢,而且需要知道真实的协议和域名。把下面这几行加进反代配置的 location 块里面:
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto $schema;
proxy_set_header X-Forwarded-Host $host;
⚠️ 坑 2:转发头必须写在 location 内部,不能写在 server 级
nginx 的
proxy_set_header/add_header继承规则是全有或全无:本层只要出现任意一条,就会完全覆盖上层的全部,而不是逐条合并。宝塔会在 server 级预置一批转发头。如果你在 server 级再补一条,反而会把宝塔那批全部顶掉。所以:要加就加在 location 里。
另外
proxy_buffering off对 SSE 流式输出是必须的,否则你会看到”回答卡住不吐字”。
7.3 申请 SSL 证书
宝塔站点设置 → SSL → Let’s Encrypt → 申请(勾选自动续签)。
⚠️ 坑 3:先申请证书,再开”强制 HTTPS”
Let’s Encrypt 的 HTTP-01 校验是通过 80 端口来验证域名所有权的。如果你先开了强制 HTTPS,80 的请求会被 301 跳到 443——而这时候证书还没签下来,443 用不了,校验必然失败,死锁。
正确顺序:申请证书 → 验证
https://能通 → 再开强制 HTTPS。
7.4 验证
curl -s https://your-domain.com/health
# {"status":"ok","healthy":true,"version":"0.4.20","auth_mode":"api_key"}
八、建租户,拿 API Key
因为配置里设了 root_api_key,系统处于多租户模式。先建一个租户:
export OV=/opt/openviking/venv/bin/ov
curl -s -X POST https://your-domain.com/api/v1/admin/accounts \
-H "X-API-Key: YOUR_ROOT_KEY" \
-H "Content-Type: application/json" \
-d '{"account_id":"myteam","admin_user_id":"admin"}' \
| python3 -m json.tool
返回里会带一个 user_key(一长串),这就是日常使用的凭据。
🔒 安全三原则:
user_key/root_api_key绝不要贴进聊天、截图、日志、Git 仓库;- 只把 key 输出到一个 600 权限的文件里,屏幕上只打印长度确认;
- 终端里的明文 key 记得清理,浏览器登录框里的也别忘了。
另外注意:
.../users/{user_id}/key这个接口是 POST = 重新生成(轮换),不是”读取”。调一次旧 key 就失效了,别乱试。
九、命令行验证
# 配置(非交互,key 从 stdin 读,不进 shell 历史)
ov config add custom --name myblog \
--url https://your-domain.com \
--api-key-stdin --activate
# 看全局状态
ov status
# 语义检索(这是"能用"而不是"活着"的证据)
ov find "你的问题"
当 ov find 返回带相关性分数排序、带 L0/L1/L2 分层标记、带内容摘要的结果时,说明向量库、Embedding 模型、检索排序、分层阅读这整条 AI 能力链路全部可用。
关于
add-resource抓取失败: 如果你灌入的是 GitHub 之类的境外 URL,可能会遇到PROCESSING_ERROR: Parse error: HTTP request failed: timeout。注意错误码是
PROCESSING_ERROR——说明请求已经到了 OpenViking、也开始处理了,是它去下载那个 URL 时超时。这不是部署问题,是服务器访问境外网络的问题。对策:优先用国内可达的源,或先把文件
wget到本地再用本地路径导入。
十、验证:看整体健康
ov status
全组件健康 + 语义检索有结果 = 部署成功。这时候浏览器打开 https://your-domain.com/studio 就能看到 Web 管理界面了。
十一、启用 VikingBot(对话机器人)

打开管理后台的 /studio/monitoring,你会看到一条提示:
请启用 VikingBot
当前服务未启用 Agent 对话功能。请使用以下参数启动服务后重试。
openviking-server --with-bot
核心就一句话:让服务带 --with-bot 启动。 你是 systemd 托管的,所以把它写进服务文件:
# 1) 先备份,方便一条命令回滚
cp /etc/systemd/system/openviking.service /root/openviking.service.bak
# 2) 给启动命令加上 --with-bot
sed -i '/^ExecStart=/ s|$| --with-bot|' /etc/systemd/system/openviking.service
grep '^ExecStart' /etc/systemd/system/openviking.service
# 3) 生效
systemctl daemon-reload && systemctl restart openviking
⚠️ 坑 4:VikingBot 是”可选依赖”,基础版安装不带它
加完
--with-bot重启,日志里出现:Warning: vikingbot not found. Please install vikingbot first. Error: --with-bot was requested, but VikingBot could not be started.而且因为
Restart=always,服务开始崩溃循环(systemctl is-active显示activating),网站直接 502。先止血:systemctl stop openviking然后排查。
vikingbot not found有两个完全不同的原因,必须看详细报错才能区分:
坑 4-A:systemd 的 PATH 里没有虚拟环境的 bin
ExecStart写的是绝对路径,所以 server 本身能启动;但它去启动vikingbot子进程时是按名字找的,走 PATH——而 systemd 服务的 PATH 里没有/opt/openviking/venv/bin,于是”找不到”。验证:
ls -l /opt/openviking/venv/bin/vikingbot——文件明明在,就是找不着。修复:给 unit 补一行 PATH。
Environment="PATH=/opt/openviking/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
坑 4-B:依赖没装全(本次真正的根因)
补完 PATH 后仍然失败,日志给出了详细原因:
File "/opt/openviking/venv/bin/vikingbot", line 4, in <module> from vikingbot.cli.commands import app ModuleNotFoundError: No module named 'prompt_toolkit' Error: vikingbot gateway exited early (code 1)脚本在、包在,但运行时依赖缺失。安装时用了基础包
openviking,没有装可选依赖openviking[bot]。修复(注意钉住版本,避免顺带把 OpenViking 升级):
source /opt/openviking/venv/bin/activate uv pip install "openviking[bot]==0.4.20" vikingbot --version deactivate systemctl restart openviking
注意日志里的建议命令是”源码安装”写法。 报错会告诉你
uv pip install -e ".[bot,dev]",但那是给git clone源码装的人用的。你是 PyPI 安装,照抄会失败——正确写法是openviking[bot]。
验证 Bot 起来了
systemctl is-active openviking
curl -s http://127.0.0.1:1933/bot/v1/health; echo
ss -lntp | grep 18790
journalctl -u openviking -n 30 --no-pager | grep -iE 'vikingbot|gateway'
然后回管理后台点「重新检测」,状态从”未启用”变为运行中;控制台里 ov chat -m "你好" 能正常回复,就成功了。
一个容易误判的细节:
grep -i error会命中uvicorn.error这样的日志器名字,看起来像报错其实不是。判断要看内容,别只看关键词。
十二、日常运维

12.1 备份
tar -czf /root/ov-backup-$(date +%F).tar.gz \
-C /opt/openviking data /etc/openviking/ov.conf
建议加进 crontab 每天凌晨跑一次,保留最近 7 份。
12.2 升级
source /opt/openviking/venv/bin/activate
uv pip install openviking --upgrade
systemctl restart openviking
curl -s http://127.0.0.1:1933/ready
升级前先备份。向量库的 schema 跨版本可能有变更,这一步不能省。
12.3 让知识库自动更新
OpenViking 支持给资源设定自动重抓周期。对做电商运营的人来说,这相当于把你的”平台规则页 / 类目政策 / 竞品页面”变成会自动刷新的知识源:
ov add-resource https://example.com/类目规则页 \
-p viking://resources/平台规则 --watch-interval 1440
--watch-interval 单位是分钟,1440 就是每天重抓一次。
12.4 调用量对账
curl -s https://your-domain.com/api/v1/console/tokens \
-H "X-API-Key: YOUR_USER_KEY" | python3 -m json.tool
建议每周看一次,确认调用量和实际使用行为相符——这是发现 key 泄露最直接的办法。
12.5 常用排障
systemctl status openviking --no-pager
journalctl -u openviking -n 200 --no-pager
ss -lntp | grep -E '1933|18790'
实测更正: 网上一些旧文档提到要手动
pkill agfs清理子进程。在 0.4.20 上不需要——日志里的Loaded RAGFS Rust binding说明 AGFS 是以进程内 Rust 绑定运行的,和主进程同生共死。systemctl stop一次就收干净,正常只有 1 个进程。
十三、踩坑总清单
| # | 现象 | 原因 | 对策 |
|---|---|---|---|
| 1 | Embedding 404 | 源码直接 POST api_base,不拼路径 |
api_base 写到 /embeddings 这一级 |
| 2 | 转发头不生效 | proxy_set_header 继承是”全有或全无” |
写在 location 内,不要写 server 级 |
| 3 | SSL 申请失败 | 先开了强制 HTTPS,80 被 301 走 | 先签证书,验证 https 通,再开强制跳转 |
| 4 | Bot 启用后服务崩溃循环 + 502 | 服务找不到 vikingbot |
先 stop 止血;给 unit 补 PATH |
| 5 | 补 PATH 后仍失败 | 缺可选依赖 prompt_toolkit |
uv pip install "openviking[bot]==版本号" |
| 6 | 回答”卡住不吐字” | nginx 缓冲了 SSE | 加 proxy_buffering off |
| 7 | 导入境外 URL 超时 | 服务器访问境外网络不稳 | 换国内源,或先下到本地再导入 |
十四、小结
整套流程跑下来说实话并不复杂,真正花时间的是四处”看起来一样、原因完全不同”的报错。
回头看,最有价值的一条经验是:
给 systemd 托管的 Python 服务启用”可选子组件”时,按这个顺序查:
- 子组件可执行文件在不在(
ls -l .../bin/xxx)- service 的 PATH 有没有含虚拟环境的 bin——
ExecStart用绝对路径能启动,不等于子进程也能按名字找到- 依赖装全了没——必须看详细报错,官方建议的命令可能是源码安装写法,与你无关
- 万一进了崩溃循环——先
systemctl stop止血,改 unit 前先备份,一条命令就能回滚
还有一条心得:每次动生产配置之前,花 10 秒确认”零件在不在”。这次就是漏了 vikingbot --version 这一句检查,代价是一轮崩溃循环加一次 502。它不是多余的步骤,它是保险。
本文记录于 2026 年 9 月,OpenViking v0.4.20。软件版本迭代较快,命令与配置项请以官方文档为准。
发表回复