服务器部署Hermes【超详细版本】(一):基础环境、Docker 镜像、目录挂载与模型配置
注:服务器部署Hermes超详细指南,由于过于详细,所以分为三部分;结尾有踩坑点说明。
Hermes Agent 云服务器部署(一):基础环境、Docker 镜像、目录挂载与模型配置
Hermes Agent 云服务器部署(二):微信 Weixin Gateway 与 Docker Compose 常驻运行
Hermes Agent 云服务器部署(三):面试题库、Cron 定时任务与故障排查
1. 安装基础工具
最开始在服务器上执行:
sudo apt update && sudo apt install -y git docker.io docker-compose-v2
命令解释
sudo apt update
更新 Ubuntu 软件包索引。
它不会升级软件本身,只是刷新系统能看到的软件包版本列表。后续安装软件前通常都要先执行它。
sudo apt install -y git docker.io docker-compose-v2
安装三个工具:
| 工具 | 作用 |
|---|---|
git |
用于拉取 GitHub 仓库源码 |
docker.io |
Ubuntu 软件源里的 Docker 引擎 |
docker-compose-v2 |
Docker Compose v2,用于用 compose.yml 管理容器 |
其中 -y 表示自动回答 yes,避免安装过程中反复确认。
2. 将当前用户加入 docker 组
执行:
sudo usermod -aG docker $USER
newgrp docker
命令解释
sudo usermod -aG docker $USER
把当前用户加入 docker 用户组。
默认情况下,普通用户执行 Docker 命令可能需要加 sudo,例如:
sudo docker ps
加入 docker 组之后,当前用户可以直接执行:
docker ps
参数说明:
| 参数 | 含义 |
|---|---|
usermod |
修改用户信息 |
-aG docker |
追加加入 docker 组 |
$USER |
当前登录用户 |
注意这里的 -a 很重要,表示“追加”。如果没有 -a,可能会覆盖用户原来的组。
newgrp docker
让当前 shell 立即应用新的用户组。
正常情况下,加入用户组后需要退出 SSH 再重新登录才生效。newgrp docker 可以让当前会话立即使用新组权限。
3. 拉取 Hermes Agent 源码
执行:
git clone https://gitclone.com/github.com/NousResearch/hermes-agent.git
cd hermes-agent
命令解释
git clone https://gitclone.com/github.com/NousResearch/hermes-agent.git
从 GitHub 镜像站拉取 Hermes Agent 源码。
这里使用的是:
gitclone.com/github.com/NousResearch/hermes-agent.git
而不是直接使用:
github.com/NousResearch/hermes-agent.git
原因是国内云服务器直接访问 GitHub 可能较慢或失败,使用镜像站可以提高成功率。
cd hermes-agent
进入刚刚 clone 下来的源码目录。
4. 是否需要删除源码目录?
当时已经拉取了源码目录:
/root/hermes-agent
但后续我们采用的是官方 Docker 镜像:
nousresearch/hermes-agent:latest
因此源码目录不是必须的。
不过在 Docker 镜像成功拉取之前,不建议删除源码,因为如果 Docker Hub 一直拉不下来,还可以用源码本地构建作为备选方案。
结论
镜像没拉成功前:
先不要删除 /root/hermes-agent
镜像成功拉取、setup 成功、微信网关跑通后,可以删除:
cd /root
rm -rf /root/hermes-agent
命令解释
cd /root
切换到 root 用户主目录。
rm -rf /root/hermes-agent
删除源码目录。
参数说明:
| 参数 | 含义 |
|---|---|
rm |
删除文件或目录 |
-r |
递归删除目录 |
-f |
强制删除,不逐个确认 |
注意:
rm -rf
是危险命令,必须确认路径正确后再执行。
删除 /root/hermes-agent 不会删除 Hermes 的配置、API Key、微信登录状态、cron 任务。真正要保留的是:
/root/.hermes
5. 创建 Hermes 数据目录
执行:
mkdir -p ~/.hermes
chmod 700 ~/.hermes
后来因为当前用户是 root,所以实际路径是:
/root/.hermes
命令解释
mkdir -p ~/.hermes
创建 Hermes 的数据目录。
其中:
~
表示当前用户的 home 目录。
如果当前用户是 root:
~ = /root
所以:
~/.hermes
等价于:
/root/.hermes
参数:
| 参数 | 含义 |
|---|---|
mkdir |
创建目录 |
-p |
如果父目录不存在就一起创建;如果目录已存在也不报错 |
chmod 700 ~/.hermes
设置目录权限为 700。
权限含义:
| 数字 | 含义 |
|---|---|
7 |
所有者可读、可写、可执行 |
0 |
同组用户无权限 |
0 |
其他用户无权限 |
也就是说,只有 root 用户自己能访问这个目录。
这么做的原因是 .hermes 目录后续会保存:
- API Key
- Hermes 配置文件
- 微信登录状态
- 会话数据
- cron 定时任务
- skills
- 面试题文件
所以权限应该收紧。
6. 拉取 Hermes Agent Docker 镜像
执行:
docker pull nousresearch/hermes-agent:latest
命令解释
docker pull
从镜像仓库下载 Docker 镜像。
nousresearch/hermes-agent:latest
表示下载 NousResearch 发布的 Hermes Agent 最新镜像。
镜像名拆解:
| 部分 | 含义 |
|---|---|
nousresearch |
Docker Hub 组织名 |
hermes-agent |
镜像名 |
latest |
标签,表示最新版本 |
7. Docker Hub 拉取超时问题
第一次拉取时遇到类似错误:
failed to resolve reference "docker.io/nousresearch/hermes-agent:latest"
failed to do request
dial tcp ...:443: i/o timeout
这个错误表示服务器访问 Docker Hub 超时。
不是镜像名写错,也不是 Hermes 项目有问题,而是网络连不上 Docker Hub。
8. 配置腾讯云 Docker 镜像加速
因为服务器看起来是腾讯云机器,所以配置腾讯云内网 Docker 镜像源:
mkdir -p /etc/docker
cp /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S) 2>/dev/null || true
cat > /etc/docker/daemon.json <<'EOF'
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
],
"dns": [
"119.29.29.29",
"223.5.5.5",
"8.8.8.8"
]
}
EOF
systemctl daemon-reload
systemctl restart docker
命令解释
mkdir -p /etc/docker
创建 Docker 配置目录。
Docker daemon 的配置文件通常在:
/etc/docker/daemon.json
如果 /etc/docker 不存在,这条命令会创建它。
cp /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S) 2>/dev/null || true
备份原有 Docker 配置文件。
拆解说明:
cp /etc/docker/daemon.json ...
复制原配置文件。
/etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S)
生成带时间戳的备份文件名。
例如:
daemon.json.bak.20260508143025
$(date +%Y%m%d%H%M%S)
执行 date 命令并插入结果,格式是:
年月日时分秒
2>/dev/null
把错误输出丢弃。
如果原来的 daemon.json 不存在,cp 会报错。这里把报错隐藏掉。
|| true
即使前面的 cp 失败,也让整条命令返回成功。
这样做是为了避免“没有旧配置文件”时中断流程。
cat > /etc/docker/daemon.json <<'EOF'
...
EOF
把中间的 JSON 内容写入 /etc/docker/daemon.json。
这是 shell heredoc 写法。
写入内容为:
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
],
"dns": [
"119.29.29.29",
"223.5.5.5",
"8.8.8.8"
]
}
字段解释:
| 字段 | 作用 |
|---|---|
registry-mirrors |
Docker 镜像加速地址 |
dns |
Docker daemon 使用的 DNS 服务器 |
DNS 说明:
| DNS | 说明 |
|---|---|
119.29.29.29 |
腾讯 DNS |
223.5.5.5 |
阿里 DNS |
8.8.8.8 |
Google DNS |
systemctl daemon-reload
让 systemd 重新加载服务配置。
虽然这里只改了 Docker 的 daemon.json,但重启服务前执行一下没有坏处。
systemctl restart docker
重启 Docker 服务,让新的镜像源配置生效。
9. 检查 Docker 镜像源是否生效
执行:
docker info | sed -n '/Registry Mirrors/,+10p'
命令解释
docker info
查看 Docker daemon 的详细信息。
sed -n '/Registry Mirrors/,+10p'
只打印包含 Registry Mirrors 的那一行,以及后面的 10 行。
如果配置成功,应该能看到:
Registry Mirrors:
https://mirror.ccs.tencentyun.com/
10. 再次拉取镜像
配置镜像源后,再执行:
docker pull nousresearch/hermes-agent:latest
中间曾经出现过:
error from registry: unknown error
但再次重试后成功:
Digest: sha256:634f9b15c02d4693f9c48c6763152efc0af75670de1b77d22c54e4333d730bab
Status: Downloaded newer image for nousresearch/hermes-agent:latest
docker.io/nousresearch/hermes-agent:latest
说明
Docker 拉镜像时会分层下载。
即使最后一步失败,前面已经下载完成的 layer 通常会保留。再次执行 docker pull 时会复用已下载的层,不一定从头开始。
所以遇到这种中途失败,不要急着执行:
docker system prune
因为这会清理缓存,可能导致重新下载。
11. 检查镜像是否完整可用
执行:
docker image inspect nousresearch/hermes-agent:latest >/dev/null 2>&1 && echo "IMAGE_OK" || echo "IMAGE_NOT_READY"
命令解释
docker image inspect nousresearch/hermes-agent:latest
查看本地是否存在这个镜像,以及镜像元数据是否完整。
>/dev/null
把标准输出丢弃。
2>&1
把错误输出也重定向到标准输出,也就是一起丢弃。
&& echo "IMAGE_OK"
如果前面的 docker image inspect 成功,就输出:
IMAGE_OK
|| echo "IMAGE_NOT_READY"
如果前面的命令失败,就输出:
IMAGE_NOT_READY
最终用来判断镜像是否已经完整可用。
12. 运行 Hermes 初始化向导
镜像成功后,执行:
docker run -it --rm \
-v /root/.hermes:/opt/data \
-e TZ=Asia/Shanghai \
nousresearch/hermes-agent setup
命令解释
docker run
创建并运行一个新的容器。
-it
表示交互式运行。
拆开看:
| 参数 | 含义 |
|---|---|
-i |
保持标准输入打开 |
-t |
分配一个伪终端 |
因为 setup 是交互式向导,所以必须加 -it。
--rm
容器退出后自动删除容器本身。
注意:这不会删除挂载到宿主机的 /root/.hermes 数据。
-v /root/.hermes:/opt/data
挂载目录。
这是非常关键的一行。
含义是:
宿主机 /root/.hermes 映射到 容器内 /opt/data
所以 Hermes 在容器里看到的:
/opt/data
实际上就是服务器上的:
/root/.hermes
后续所有配置、API Key、cron、微信登录状态等都会存放在这里。
-e TZ=Asia/Shanghai
设置容器环境变量 TZ 为上海时区。
这会影响日志时间、cron 定时任务时间等。
nousresearch/hermes-agent
使用 Hermes Agent 镜像。
setup
传给 Hermes 镜像的命令,表示进入初始化向导。
13. Quick setup 与 Full setup
初始化时出现:
How would you like to set up Hermes?
→ Quick setup — provider, model & messaging (recommended)
Full setup — configure everything
选择:
Quick setup
原因
当前目标是尽快跑通:
- 模型调用
- 微信聊天
- 后续 cron 定时任务
不需要一开始配置所有高级选项。
Quick setup 会引导配置:
- provider
- model
- messaging platform
对于首次部署更合适。
14. 选择模型 Provider
Hermes 显示了很多 provider,例如:
1. Nous Portal
2. OpenRouter
...
6. Xiaomi MiMo
...
15. DeepSeek
...
如果使用小米模型,选择:
6
也就是:
Xiaomi MiMo
如果使用 DeepSeek,选择:
15
也就是:
DeepSeek
15. 小米 MiMo 模型选择问题
最初考虑的模型包括:
mimo-v2.5-pro
mimo-v2-pro
mimo-v2.5
mimo-v2-omni
mimo-v2-flash
当时建议轻量任务优先使用:
mimo-v2-flash
原因是当前场景主要是:
- 微信文字聊天
- 定时提醒
- 抽取面试题
- 简单批改
理论上不需要最强模型。
但是实际运行后出现错误:
Provider: xiaomi
Model: mimo-v2-flash
Endpoint: https://token-plan-cn.xiaomimimo.com/v1
Error: HTTP 400: Not supported model mimo-v2-flash
错误解释
这说明当前 API Key 对应的 endpoint:
https://token-plan-cn.xiaomimimo.com/v1
不支持:
mimo-v2-flash
不是 Hermes 坏了,也不是 API Key 一定错了,而是模型名和当前 API endpoint 或套餐不匹配。
处理方式
将模型从:
mimo-v2-flash
改为更稳妥的:
mimo-v2-pro
或者如果当前小米 Token Plan 支持:
mimo-v2.5-pro
也可以使用它。
推荐顺序
对于当前微信 Agent 场景,建议按这个顺序尝试:
mimo-v2-pro
mimo-v2.5-pro
mimo-v2.5
mimo-v2-omni
如果 mimo-v2-flash 被 endpoint 明确拒绝,就不要继续使用它。
16. 进入终端聊天界面测试模型
setup 后进入终端聊天界面:
Welcome to Hermes Agent! Type your message or /help for commands.
输入:
你好
如果模型配置错误,会出现类似:
HTTP 400: Not supported model mimo-v2-flash
如果模型配置正确,会正常回复中文。
终端聊天界面的意义
终端聊天只验证:
Hermes Agent 能不能调用模型
它不代表微信网关已经正常运行。
后续微信能不能回复,还要单独配置和启动 gateway。
17. 退出终端聊天界面
在终端聊天界面中,可以输入:
/exit
或者按:
Ctrl + C
退出聊天。
注意
退出终端聊天不会影响 Docker 镜像和 /root/.hermes 配置。
但是如果你运行的是临时前台 gateway,按 Ctrl+C 会停止 gateway。
18. /root/.hermes 和 /opt/data 的关系
后续多次遇到疑问:
为什么在服务器上创建 /root/.hermes/interview,
却让 Hermes 读取 /opt/data/interview?
原因是 Docker volume 映射:
-v /root/.hermes:/opt/data
或者在 compose 文件中:
volumes:
- /root/.hermes:/opt/data
含义是:
服务器宿主机路径:/root/.hermes
容器内部路径: /opt/data
所以:
| 宿主机路径 | 容器内路径 |
|---|---|
/root/.hermes |
/opt/data |
/root/.hermes/interview |
/opt/data/interview |
/root/.hermes/interview/questions.md |
/opt/data/interview/questions.md |
重要结论
在 SSH 里编辑文件,用:
/root/.hermes/...
在 Hermes 提示词或 cron 任务里,让 Agent 读取:
/opt/data/...
19. 容器的 /opt 不是服务器的 /root
曾经有一个疑问:
容器的 /opt 目录就是我的 /root 目录吗?
答案是:
不是
只有明确挂载的这一段路径有关联:
/root/.hermes <=> /opt/data
容器里的:
/opt
不是服务器的:
/root
容器里的:
/opt/data
才是服务器的:
/root/.hermes
其他容器目录和宿主机没有直接关系。
20. 检查实际挂载路径
可以用下面命令查看容器实际挂载:
docker inspect hermes --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
命令解释
docker inspect hermes
查看名为 hermes 的容器详细信息。
--format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
只输出挂载信息。
正常应该看到:
/root/.hermes -> /opt/data
这表示宿主机 /root/.hermes 已经挂载到容器内 /opt/data。
21. 在服务器上进入 Hermes 数据目录
推荐直接在宿主机进入:
cd /root/.hermes
ls -la
命令解释
cd /root/.hermes
进入 Hermes 数据目录。
ls -la
显示目录内容。
参数说明:
| 参数 | 含义 |
|---|---|
-l |
以长格式显示 |
-a |
显示隐藏文件 |
因为 .hermes 本身是隐藏目录,所以查看 /root 时要用:
ls -la /root
否则普通:
ls /root
可能看不到 .hermes。
22. 进入容器查看 /opt/data
如果需要进入容器查看:
docker exec -it hermes sh
进入后:
cd /opt/data
ls -la
退出容器:
exit
命令解释
docker exec -it hermes sh
在正在运行的 hermes 容器中启动一个 shell。
| 部分 | 含义 |
|---|---|
docker exec |
在已运行容器里执行命令 |
-it |
交互式终端 |
hermes |
容器名称 |
sh |
启动 shell |
注意:容器里可能没有 nano 或 vim,所以编辑文件通常还是在宿主机 /root/.hermes 中完成。
23. 不进入容器直接查看容器内文件
可以执行:
docker exec -it hermes sh -lc 'ls -la /opt/data'
命令解释
docker exec -it hermes
进入正在运行的 hermes 容器执行命令。
sh -lc 'ls -la /opt/data'
在容器内启动 shell,并执行:
ls -la /opt/data
其中:
| 参数 | 含义 |
|---|---|
-l |
让 shell 以 login-like 方式处理环境 |
-c |
执行后面的字符串命令 |
24. 本阶段最终状态
完成第 1 阶段后,应该达到这些结果:
Docker 镜像已成功拉取
docker image inspect nousresearch/hermes-agent:latest >/dev/null 2>&1 && echo "IMAGE_OK" || echo "IMAGE_NOT_READY"
输出:
IMAGE_OK
Hermes 数据目录存在
ls -ld /root/.hermes
可以看到目录存在。
模型可以正常回复
执行:
docker run -it --rm \
-v /root/.hermes:/opt/data \
-e TZ=Asia/Shanghai \
nousresearch/hermes-agent chat -q "你好,用一句中文回复我。"
如果能返回中文回复,说明模型/API 已经配置成功。
已理解路径映射
宿主机:/root/.hermes
容器内:/opt/data
后续:
- SSH 编辑文件用
/root/.hermes - Hermes 读取文件用
/opt/data
25. 第 1 部分常用命令汇总
查看 Docker 镜像
docker images | grep hermes
检查 Hermes 镜像是否可用
docker image inspect nousresearch/hermes-agent:latest >/dev/null 2>&1 && echo "IMAGE_OK" || echo "IMAGE_NOT_READY"
查看 Docker 镜像源
docker info | sed -n '/Registry Mirrors/,+10p'
运行 Hermes setup
docker run -it --rm \
-v /root/.hermes:/opt/data \
-e TZ=Asia/Shanghai \
nousresearch/hermes-agent setup
测试模型回复
docker run -it --rm \
-v /root/.hermes:/opt/data \
-e TZ=Asia/Shanghai \
nousresearch/hermes-agent chat -q "你好,用一句中文回复我。"
查看 Hermes 数据目录
ls -la /root/.hermes
查看容器挂载
docker inspect hermes --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
26. 本阶段易踩坑汇总
坑 1:Docker Hub 超时
表现:
dial tcp ...:443: i/o timeout
解决:
配置腾讯云 Docker 镜像源:
https://mirror.ccs.tencentyun.com
坑 2:镜像最后一步 unknown error
表现:
error from registry: unknown error
解决:
不要清理缓存,直接重试:
docker pull nousresearch/hermes-agent:latest
坑 3:误以为源码目录必须保留
实际:
使用官方 Docker 镜像后,源码目录可以删除。
真正需要保留的是:
/root/.hermes
坑 4:mimo-v2-flash 不支持
表现:
HTTP 400: Not supported model mimo-v2-flash
解决:
改成:
mimo-v2-pro
或根据套餐支持尝试:
mimo-v2.5-pro
坑 5:混淆 /root/.hermes 和 /opt/data
正确理解:
/root/.hermes 是服务器宿主机路径
/opt/data 是容器内部路径
两者通过 Docker volume 映射到一起
第 2 部分将记录:
Hermes Agent 云服务器部署笔记(二):微信 Weixin Gateway 与 Docker Compose 常驻运行
会详细解释:
- 为什么终端聊天能回复,不代表微信能回复
gateway run是什么- 临时
docker run和 Docker Compose 常驻运行的区别 - 如何创建
/root/compose.hermes.yml - 微信 pairing code 是什么
- 为什么
docker exec hermes hermes ...会失败 - 正确批准微信配对的方法
/status和/sethome的作用- 两个 SSH 窗口应该怎么用
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)