N100 自托管 OpenClaw + Hermes Agent 部署实录
#OpenClaw #Docker #AI Agent #自托管 #服务器运维
背景
在 N100(Ubuntu, 16GB DDR5)上自托管 AI Agent 网关,目标架构:
-
OpenClaw:AI Agent 网关,负责消息路由与 Agent 编排,对接 Ollama(内网推理机)
-
Hermes Agent:自我进化型个人助手,自动写记忆与技能
-
推理主机(i9+2070S 或 9800X3D+5080)运行 Ollama,局域网暴露 11434 端口
N100 已有 FRP 加密公网穿透,所有新服务均监听 127.0.0.1 仅限本机访问。
目录结构
1 | ~/dockerfile/ |
第一步:创建 Docker 网络
OpenClaw 负责创建 agent_net 网络,Hermes 以 external: true 加入。
1 | # openclaw/docker-compose.yml 中的 networks 段 |
第二步:部署 OpenClaw
最终有效的 docker-compose.yml
1 | services: |
.env
1 | NODE_ENV=production |
openclaw.json(正式配置文件)
1 | { |
第三步:部署 Hermes Agent
OpenClaw 启动后 agent_net 已创建,Hermes 直接加入。
1 | # hermes/docker-compose.yml |
1 | # hermes/.env |
1 | cd ~/dockerfile/hermes && docker compose up -d |
踩坑记录
坑 1:配置文件格式错误——YAML vs JSON
现象:容器反复重启,日志一直输出:
1 | [gateway] loading configuration… |
错误尝试:按直觉写了 config.yaml,并在 .env 中设置 OPENCLAW_GATEWAY_MODE=local 和 OPENCLAW_ALLOW_UNCONFIGURED=true,均无效。
根本原因:通过读取容器内 /app/dist/paths-DyelItkH.js 发现:
1 | const CONFIG_FILENAME = "openclaw.json"; // JSON 格式,不是 YAML |
配置文件路径为 ~/.openclaw/openclaw.json,OpenClaw 不读取 OPENCLAW_LLM_* 之类的 env var,环境变量只有 OPENCLAW_GATEWAY_TOKEN、OPENCLAW_STATE_DIR、OPENCLAW_CONFIG_PATH 少数几个被识别。
修复:将 config.yaml 改为 openclaw.json,并用文件级 volume 覆盖挂载:
1 | volumes: |
坑 2:容器以非 root 用户运行,无法访问 /root/
现象:openclaw.json 已正确挂载,容器内 cat /root/.openclaw/config.yaml 执行时:
1 | ls: cannot access '/root/.openclaw/': Permission denied |
根本原因:镜像默认以 node(uid=1000)用户运行。Linux 下 /root/ 目录权限为 700,非 root 用户无法进入,/root/.openclaw/ 自然也无法访问。
修复:在 docker-compose.yml 中加一行:
1 | services: |
坑 3:gateway.bind 容器模式下默认 0.0.0.0,拒绝无鉴权启动
现象:加了 user: root 后,配置文件能正常读取,但新报错:
1 | Refusing to bind gateway to auto without auth. |
根本原因:OpenClaw 检测到容器环境,将 bind 默认改为 auto(即 0.0.0.0),而绑定公共地址必须配置鉴权。
修复:在 openclaw.json 中显式设置绑定模式为 loopback,同时在 .env 中加入 Token 作为双保险:
1 | { |
1 | OPENCLAW_GATEWAY_TOKEN=<your-gateway-token> |
坑 4:gateway.auth 字段类型错误
现象:尝试在 JSON 中设置 "gateway": { "auth": "token" } 时报:
1 | Gateway failed to start: Invalid config at /root/.openclaw/openclaw.json. |
根本原因:gateway.auth 是一个对象,不是字符串。正确格式为:
1 | { |
实际处理:改用 gateway.bind: loopback 后不再需要显式配置 auth,问题绕过。
坑 5:LLM 默认模型为 openai/gpt-5.5
现象:启动日志显示 agent model: openai/gpt-5.5,不是我们期望的 Ollama 模型。
根本原因:.env 中的 OPENCLAW_LLM_* 环境变量 OpenClaw 根本不识别,LLM 配置必须写在 openclaw.json 里。
通过 node openclaw.mjs config schema 查看 JSON Schema,模型配置结构为:
1 | { |
修复后日志确认:
1 | [gateway] auto-enabled plugins for this runtime without writing config: |
NanoClaw 的误解澄清
原计划用 NanoClaw 作为公网安全入口层(代理 OpenClaw),但实际上:
-
NanoClaw 是独立的个人 Claude 助手(同 OpenClaw 是平行竞品关系),不是代理层
-
无预构建 Docker 镜像,需
bash nanoclaw.sh交互式安装 -
NANOCLAW_UPSTREAM_URL之类的 env var 是我们凭空假设的,NanoClaw 并不支持
公网访问替代方案:OpenClaw 本身已有 Token 鉴权,直接调整绑定模式即可:
-
将
openclaw.json的gateway.bind改为lan -
docker-compose.yml端口改为0.0.0.0:3000:3000 -
FRP 增加
local_port=3000隧道
最终运行状态
1 | $ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" |
待完成事项
填入 Ollama 主力机 IP
找到推理机(i9+2070S 或 9800X3D)的局域网 IP 后,更新配置:
1 | ssh MyUbuntuLocal "docker exec openclaw node openclaw.mjs config set \ |
同时 Win11 推理机需设置 Ollama 监听所有接口:
1 | # 环境变量(System > Advanced) |
填入 Anthropic API Key(可选)
1 | ssh MyUbuntuLocal "docker exec openclaw node openclaw.mjs config set \ |
填入 OpenRouter API Key(Hermes Agent)
1 | # 编辑 ~/dockerfile/hermes/.env,填入 OPENROUTER_API_KEY |
WeChat 渠道(可选)
取消注释 ~/dockerfile/openclaw/.env 中的微信配置后重启:
1 | OPENCLAW_CHANNEL=wechat |
快速运维参考
1 | # 查看容器状态 |
