Linux 服务器部署配置指南¶
服务器:
<SERVER_HOST>| 部署用户:<deploy-user>| 项目路径:/home/<deploy-user>/source_code/myopenclaw⚠️ 本页是那台服务器上早期部署的记录,不是仓库现状。 仓库当前的
docker-compose.yml是 16 个服务 + profile-gatedopenclaw-cli(另有 zhixun / tianyi 两个独立 bot 栈),下面几节的 挂载表、gc挂载、MCP 脚本目录都来自旧版本,git pull后对不上 —— 排查时以仓库里的docker-compose.yml为准。
服务架构¶
早先部署时 docker-compose.yml 启动四个服务(myopenclaw-net 桥接网络):
hermes :8642 自定义镜像,AI agent gateway
hermes-dashboard :9119 只读 dashboard,监控 hermes(depends_on hermes)
openclaw-gateway :18789 OpenClaw gateway(含 /healthz 健康检查)
backup-cron - 定时快照备份(默认每天凌晨 2:00)
关键目录¶
hermes 容器挂载¶
| 宿主机路径 | 容器内路径 | 说明 |
|---|---|---|
/home/<deploy-user>/.hermes |
/opt/data |
Hermes 主数据目录(home) |
/home/<deploy-user>/.config/gh |
/opt/gh-config |
gh CLI 认证信息 |
/home/<deploy-user>/.config/opencode |
/opt/opencode-config |
opencode 配置 |
/home/<deploy-user>/.claude |
/opt/claude-config |
Claude Code 配置 |
./hermes/mcp/ |
/opt/mcp(只读) |
MCP server 脚本(仓库里已无此目录,见下方 MCP 一节) |
openclaw-gateway 容器挂载¶
| 宿主机路径 | 容器内路径 | 说明 |
|---|---|---|
/home/<deploy-user>/.openclaw |
/home/node/.openclaw |
OpenClaw 数据(含 SQLite DB) |
/home/<deploy-user>/.config/gc |
/home/node/.config/gc |
GitCode CLI 配置 |
backup-cron 容器挂载¶
⚠️ 必须用
./scripts/start.sh启动。docker-compose.yml的挂载写的是${BACKUP_ROOT:-/tmp/myopenclaw-backups}:/backup,而BACKUP_ROOT由start.sh从.cloud.conf解析后 export —— 裸跑docker compose up -d backup-cron会静默 回退到/tmp(macOS 每天清理该目录,备份会被系统删掉)。 为此容器启动时会校验备份根目录里的哨兵文件.myopenclaw-backup-root: 缺失即拒绝启动(不会静默写错地方)。详见 备份系统。
| 宿主机路径 | 容器内路径 | 说明 |
|---|---|---|
/home/<deploy-user>/.hermes |
/root/.hermes(只读) |
Hermes 数据快照源 |
/home/<deploy-user>/.hermes/cron |
/root/.hermes/cron(可写) |
cron 活库热备:executions.db 是 WAL,读者要写 -shm |
/home/<deploy-user>/.openclaw |
/root/.openclaw(只读) |
OpenClaw 数据快照源 |
/home/<deploy-user>/.myagentdata |
/.myagentdata(只读) |
agent 附加数据快照源 |
/home/<deploy-user>/.myagentdata/{paper-queue,tdai-memory,repo-scanner} |
/.myagentdata/<同名>(可写) |
WAL 库热备:读者也要写 -shm,只读挂载连 SELECT 都打不开 |
${BACKUP_ROOT} |
/backup |
快照写入目标(云盘挂载点) |
重要:必须以 <deploy-user> 身份运行 docker compose,否则 ${HOME} 变为 /root,导致数据挂载到错误目录。
容器内文件权限:hermes 服务进程以 UID 10000 运行,其创建的文件在宿主机上显示为 UID 10000(非具名用户);hermes 内的 bash 子进程以 root 运行,其创建的文件在宿主机显示为 root。操作 ~/.hermes/ 下非 sudo。
首次部署¶
# 以 <deploy-user> 身份在宿主机执行
cd /home/<deploy-user>/source_code/myopenclaw
# 1. 创建环境变量文件
cp .env.example .env
nano .env # 填写 API key(见下方说明)
# 2. 配置云盘备份路径(必须完成,start.sh 依赖 .cloud.conf)
./scripts/setup-cloud.sh
# 3. 构建镜像并启动(首次必须 --build)
./scripts/start.sh --build
# 4. 确认服务状态
docker compose ps
docker compose logs -f hermes
start.sh 首次运行会自动从模板初始化以下文件(如不存在):
~/.config/opencode/opencode.json~/.claude/settings.json~/.hermes/config.yaml(不由start.sh创建:仓库里没有它的模板,这个文件由 Hermes 容器自己生成;start.sh只在它已存在时追加 zotero-mcp、mylibrary-skills 等配置)
注意:start.sh 在 .cloud.conf 不存在时只告警、不中断(Linux 兼容的降级路径),但跳过云盘配置后备份会落到 /tmp(backup-cron 缺哨兵文件会拒绝启动)—— 所以仍应先运行 setup-cloud.sh。
API Key 配置¶
.env 文件¶
路径:/home/<deploy-user>/source_code/myopenclaw/.env
# ZAI / 智谱 GLM(同时作为 Claude Code 的 ANTHROPIC_API_KEY 使用)
GLM_API_KEY=xxxxx.xxxxx
# 以下三个 key 被 Hermes 安全黑名单拦截,无法直接传给子进程。
# entrypoint-wrapper.sh 启动时会将其写入 /opt/data/secrets/ 文件,
# opencode.json 通过 {file:} 语法引用。
DEEPSEEK_API_KEY=sk-xxx
OPENROUTER_API_KEY=xxx
OPENAI_API_KEY=sk-xxx
# MCP server 自定义环境变量(非黑名单,可直接透传到容器)
# 在 docker-compose.yml environment: 段添加对应字段后,Python 脚本用 os.environ 读取
# HYDRO_API_BASE_URL=http://<SERVER_HOST>:8000
# GitCode CLI(OpenClaw 容器内 gc 使用)
GITCODE_TOKEN=gitcode_xxxxx
Hermes 内部凭证库 auth.json¶
路径:/home/<deploy-user>/.hermes/auth.json(UID 10000 所属,需 sudo)
存储 Hermes 自身使用的 provider credentials。ZAI/GLM key 在 credential_pool.zai。
# 查看 ZAI 凭证
sudo python3 -c "import json; d=json.load(open('/home/<deploy-user>/.hermes/auth.json')); print(json.dumps(d['credential_pool'].get('zai'), indent=2))"
Hermes 模型配置¶
文件:/home/<deploy-user>/.hermes/config.yaml(UID 10000 所属,需 sudo)
修改后需重启容器才能生效(gateway 进程重新读取配置):
MCP Server 配置¶
⚠️ 仓库里已没有
hermes/mcp/目录,docker-compose.yml也不再挂/opt/mcp。 当前做法是把 MCP 服务做成独立容器(zotero-mcp/repo-scanner-mcp/aisecretary/paper-queue-mcp,SSE 或 streamable HTTP),在~/.hermes/config.yaml的mcp_servers里按url:注册。下面这套「脚本挂进容器 + stdio」的写法只在旧版本上成立。
MCP server 脚本放在 hermes/mcp/<name>/server.py,容器内挂载为 /opt/mcp/<name>/server.py。
在 ~/.hermes/config.yaml 中注册¶
mcp_servers:
hydro_forecast:
command: "/usr/local/bin/uv" # 必须用绝对路径(Hermes 子进程 PATH 不含 /usr/local/bin)
args:
- "run"
- "--quiet" # 必须加,否则 uv 安装日志污染 JSON-RPC stdout
- "--with"
- "mcp"
- "--with"
- "httpx"
- "/opt/mcp/hydro-forecast/server.py"
timeout: 60
MCP 配置修改后无需重启容器,在 Hermes CLI 或 Dashboard 中执行热加载:
验证是否加载成功:启动日志中出现 hydro_forecast (stdio) — N tool(s) 表示正常。
为 MCP Server 透传环境变量¶
MCP server 通过 os.environ 读取配置(如 HYDRO_API_BASE_URL)。透传步骤:
-
在
.env中添加变量: -
在
docker-compose.yml的hermes.environment:中添加: -
重启 hermes 容器使环境变量生效:
uv 依赖缓存¶
uv 的包缓存目录为 /opt/data/.cache/uv(即宿主机 ~/.hermes/.cache/uv),持久化在 hermes 数据卷中。重建镜像不会丢失已下载的依赖,首次冷启动后后续热加载速度快。
GitCode CLI 配置¶
⚠️ 本章已过时:现在不需要外部提供
gc——docker/hermes/Dockerfile里npm install -g opencode-ai gitcode-cli已把它装进镜像(实测容器内/usr/local/bin/gc), claude-code 镜像同样自带;GitCode 写入能力现在由 tianyi bot 栈承担(其 entrypoint 启动时npm install -g gitcode-cli)。本仓的docker-compose.yml里没有任何gc挂载, 也没有把~/.openclaw/bin加进PATH(主网关容器内实测gc不存在)。 下面这套「源码编译 + 挂载」只在早于该改动的版本上成立。
1. 编译 GitCode CLI
在服务器上从源码编译:
git clone https://gitcode.com/gitcode-cli/cli.git
cd cli
go env -w GOPROXY=https://goproxy.cn,direct
go build -o gc ./cmd/gc
然后放到 OpenClaw 持久化目录:
2. 容器获得 gc 命令
~/.openclaw 已挂载到容器:
所以容器内可以访问:
Compose 又把该目录加入 PATH:
environment:
- PATH=/home/node/.openclaw/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
因此 OpenClaw 可以直接执行:
如果 GitCode 请求来自飞书等 Hermes 渠道,Hermes 容器也要能找到 gc —— 现在的镜像是自带的(见本章开头),无需挂载。早期版本靠下面这几行(本仓 docker-compose.yml 现已不含):
volumes:
- ${HOME}/.openclaw/bin/gc:/usr/local/bin/gc:ro
- ${HOME}/.config/gc:/root/.config/gc
environment:
- GITCODE_TOKEN=${GITCODE_TOKEN:-}
GITCODE_TOKEN 现在仍由 .env → compose 注入 hermes / hermes-coder / claude-code;gc 二进制则来自镜像。
3. 配置认证
通过环境变量传入 GitCode Token:
实际 token 写在项目 .env:
同时挂载 gc 配置目录:
更新 .env 或 docker-compose.yml 后,需要重新创建容器让环境变量生效:
验证:
4. 告诉机器人怎么使用
在 OpenClaw 工作区指令中添加 GitCode 规则:
例如:
当用户提到 GitCode、仓库、Issue、PR、项目列表时,不要凭记忆回答,必须先调用 `gc` 查询实时结果,再根据结果回复。
查询全部仓库时运行:
`gc repo list --limit 100 --json`
创建 Issue 时运行:
`gc issue create -R <owner>/<repo> --title "<标题>" --body "<正文>"`
审查 PR 时运行:
`gc pr view <number> -R <owner>/<repo>`
`gc pr diff <number> -R <owner>/<repo>`
完整调用链
飞书用户 @机器人
→ openclaw-gateway 收到消息
→ Agent 读取 AGENTS.md
→ Agent 判断需要操作 GitCode
→ 通过 exec/shell 执行 gc
→ gc 使用 GITCODE_TOKEN 调用 GitCode API
→ Agent整理结果并回复飞书
日常运维¶
# 以 <deploy-user> 身份,在项目目录执行
# 启动 / 重启
./scripts/start.sh
docker restart hermes
# 查看日志
docker compose logs -f hermes
docker compose logs -f openclaw-gateway
# 停止所有服务
./scripts/stop.sh
# 修改 Hermes 配置(UID 10000 所属,需 sudo)
sudo nano /home/<deploy-user>/.hermes/config.yaml
sudo nano /home/<deploy-user>/.hermes/auth.json
# 手动备份
docker compose exec backup-cron /scripts/backup-all-docker.sh
# 从快照恢复
./scripts/restore.sh all latest
./scripts/restore.sh hermes 2026-04-23_090000
代码更新 / 镜像重建¶
cd /home/<deploy-user>/source_code/myopenclaw
# 拉取最新代码
git pull
# 重新构建镜像并重启(Dockerfile 有变更时必须 --build)
./scripts/stop.sh
./scripts/start.sh --build
# 仅 MCP server 脚本变更(server.py 修改),无需重建镜像,热加载即可:
# 在 Hermes CLI / Dashboard 执行 /reload-mcp
已知问题¶
| 问题 | 原因 | 解决方案 |
|---|---|---|
command: uv 报 not found |
Hermes 子进程 PATH 不含 /usr/local/bin |
改为 command: /usr/local/bin/uv |
数据挂载到 /root/.hermes |
以 root 身份执行了 docker compose |
改为 <deploy-user> 用户执行 |
config.yaml / auth.json 无法直接编辑 |
文件 owner 是 UID 10000 或 root(容器进程创建) | 用 sudo 操作,或写 Python 脚本 scp 到服务器执行 |
| DeepSeek v4 多轮对话 400 错误 | 推理模型返回 reasoning_content,Hermes 重发时 API 报错 |
使用 ZAI GLM 等标准模型,避免 DeepSeek 推理模型 |
/model 命令更改不持久 |
仅改当前 CLI session,不影响 gateway | 必须修改 config.yaml + docker restart hermes |
start.sh 提示未找到 .cloud.conf |
跳过了 setup-cloud.sh 步骤(当前版本只告警不中断) |
执行 ./scripts/setup-cloud.sh 配置云盘路径;否则备份落到 /tmp,backup-cron 会因缺哨兵文件拒绝启动 |