Files
cnphpbb c157e9a418 fix(honcho): 容器端口必须用容器内端口,不能用 host 映射端口
vm61 honcho-api 一直 unhealthy + deriver 反复重启,根因是 stack.yml 把
宿主机映射端口 (HONCHO_DB_PORT=25432) 当成了容器间互访端口:
- DB_CONNECTION_URI 里 database:${HONCHO_DB_PORT} 应为 database:5432
- healthcheck URL localhost:18000 应为 localhost:8000
HONCHO_API_PORT/DB_PORT/REDIS_PORT 仅用于宿主机 ports 映射段,
容器之间互访必须硬编码容器内端口 (5432/6379/8000)。

- 改 stack.yml api + deriver 段 DB_CONNECTION_URI 端口为 5432
- 改 stack.yml api 段 healthcheck URL 为 localhost:8000
- readme 关键陷阱加第 6 条:"容器端口 vs 宿主机端口不可混用"
- vm61 4 honcho 容器全部 healthy,deriver queue processor 已正常运行
2026-06-19 18:39:17 +08:00

374 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Honcho Self-Hosted 部署栈
[plastic-labs/honcho](https://github.com/plastic-labs/honcho) 是 Plastic Labs 开源的 **AI Agent 长期记忆后端**v3.0.xAGPL-3.0)。Hermes Agent 用它做跨会话的用户上下文管理(peer-centric 记忆、推理、检索)。本目录部署的是 **honcho-self-hosted**:基于 [elkimek/honcho-self-hosted](https://github.com/elkimek/honcho-self-hosted) 配置的本地化版本,集成到 `deploy.stack` 仓库规范下。
与官方 `docker-compose.yml.example` 的差异:本目录用 **PostgreSQL 18 + Redis 8**(非官方默认的 pg15/redis 8.2)、`${Volumes_Path}` bind 挂载(非 docker volume)、固定到内网可访问的端口。
## 目录结构
| 文件 | 说明 |
|------|------|
| `stack.yml` | Docker Compose 主文件(4 服务:api + deriver + database + redis |
| `env.cfg.example` | 公共环境变量模板(不含敏感信息,可提交) |
| `env.cfg` | **敏感配置(gitignore,不提交)** — 实际部署时从 example 复制后填密码/API Key |
| `readme.md` | 本文档 |
## 架构
```mermaid
flowchart TB
subgraph src["源码构建期(无运行时 bind"]
source["${Volumes_Path}/honcho/source<br/>git clone plastic-labs/honcho<br/>api/deriver Dockerfile build context"]
end
subgraph run["运行时 — honcho-net bridge"]
api["<b>honcho-api</b><br/>FastAPI 主服务<br/>:8000 (0.0.0.0)<br/>build from source"]
deriver["<b>honcho-deriver</b><br/>后台推理 worker<br/>消息→观察→peer representation<br/>build from source"]
database["<b>honcho-database</b><br/>pgvector/pgvector:pg18<br/>:5432 (0.0.0.0)<br/>scram-sha-256"]
redis["<b>honcho-redis</b><br/>redis:8<br/>:6379<br/>CACHE_URL"]
end
subgraph host["宿主机持久化 (WSL ext4)"]
pgdata["${Volumes_Path}/pgdata<br/>(bind mount)"]
redisdata["${Volumes_Path}/redis<br/>(bind mount)"]
end
subgraph external["外部调用方"]
hermes["Hermes Agent<br/>memory.provider=honcho"]
sdk["Python / TS SDK<br/>(honcho-ai / @honcho-ai/sdk)"]
tools["DBeaver / psql<br/>PG 5432 直连"]
siliconflow["SiliconFlow<br/>api.siliconflow.cn/v1<br/>Qwen3-Embedding-8B<br/>dimensions=1536<br/>(云端默认)"]
ollama["本地 Ollama<br/>host.docker.internal:11434<br/>qwen3-embedding:0.6b<br/>(备选,零成本)"]
end
source -.->|docker build<br/>首次 5-10 min| api
source -.->|docker build| deriver
hermes -->|HTTP :8000| api
sdk -->|HTTP :8000| api
tools -->|:5432| database
api -->|:5432| database
deriver -->|:5432| database
api -->|:6379| redis
deriver -->|:6379| redis
deriver -.->|轮询<br/>pending messages| api
api -->|HTTPS embedding<br/>Qwen3-8B 1536d| siliconflow
deriver -->|HTTPS embedding<br/>Qwen3-8B 1536d| siliconflow
database --- pgdata
redis --- redisdata
classDef ext fill:#e1f5ff,stroke:#01579b,color:#000
classDef build fill:#fff3e0,stroke:#e65100,color:#000
classDef data fill:#f3e5f5,stroke:#4a148c,color:#000
classDef host fill:#e8f5e9,stroke:#1b5e20,color:#000
class hermes,sdk,tools,siliconflow,ollama ext
class source build
class api,deriver,database,redis ext
class pgdata,redisdata data
```
> **源码不在运行时 bind mount**api/deriver 通过 `build: context: .` 从 `git clone` 的源码目录(`${Volumes_Path}/honcho/source`)构建,**不**挂源码进运行容器。`source/` 仅作为构建缓存,方便后续 `git pull` 后增量 rebuild。
**四个服务的职责:**
| 服务 | 角色 | 关键依赖 |
|------|------|----------|
| `api` | FastAPI 主服务,对外提供 REST API(端口 8000 | database、redis |
| `deriver` | **后台推理 worker**:消息→观察→peer representation→session 摘要 | api(健康后才起)、database、redis |
| `database` | PostgreSQL + pgvector 扩展,存所有 messages、peers、workspaces | — |
| `redis` | 缓存层(`CACHE_URL=redis://redis:6379/0` | — |
**⚠️ deriver 不可省**:没它,消息能写入 DB,但不会生成记忆、不会提取观察、不会做 session 摘要。Honcho 退化成纯 KV 存储。
## 端口
| 端口 | 服务 | 用途 |
|------|------|------|
| `8000` | api | Honcho REST API(供 Hermes / Python SDK / TypeScript SDK 调用) |
| `5432` | database | PostgreSQL 对外访问(DBeaver、psql 等工具连接) |
| `6379` | redis | Redis 对外访问(一般无需直连) |
宿主机端口可通过 `env.cfg` 中的 `HONCHO_API_PORT``HONCHO_DB_PORT``HONCHO_REDIS_PORT` 自定义。
## 环境变量
### 公共变量(`env.cfg.example`
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `HONCHO_VERSION` | `main` | Honcho 主仓库 git reftag / branch / SHA 都可;源码 build 用) |
| `HONCHO_BRANCH` | `main` | 源码 checkout 分支(`HONCHO_VERSION` 不是 branch 时生效) |
| `HONCHO_DB_VERSION` | `18` | PostgreSQL 大版本号(pgvector 镜像 tag 后缀) |
| `HONCHO_REDIS_VERSION` | `8` | Redis 大版本号 |
| `HONCHO_DB_IMAGE` | `pgvector/pgvector` | DB 镜像仓库 |
| `HONCHO_REDIS_IMAGE` | `redis` | Redis 镜像仓库 |
| `HONCHO_DB_USER` | `honcho` | PostgreSQL 用户名 |
| `HONCHO_DB_NAME` | `honcho` | PostgreSQL 数据库名 |
| `HONCHO_DB_PASSWORD` | `honcho` | PostgreSQL 密码(**部署时必须改** |
| `POSTGRES_HOST_AUTH_METHOD` | `scram-sha-256` | PG 认证方式 |
| `Volumes_Path` | `/data/Volumes/honcho` | 宿主机持久化数据根路径 |
| `HONCHO_API_PORT` | `8000` | API 宿主机端口 |
| `HONCHO_DB_PORT` | `5432` | PostgreSQL 宿主机端口 |
| `HONCHO_REDIS_PORT` | `6379` | Redis 宿主机端口 |
| `HONCHO_LOG_LEVEL` | `INFO` | Honcho 日志级别 |
| `HONCHO_AUTH_USE_AUTH` | `false` | 是否启用 JWT 鉴权(生产建议 `true` |
| `HONCHO_NAMESPACE` | `honcho` | 全局命名空间前缀 |
| `HONCHO_EMBED_MESSAGES` | `true` | 是否对消息做向量化(关闭可省 embedding 费用) |
| `HONCHO_EMBEDDING_MODEL` | `Qwen/Qwen3-Embedding-8B` | Embedding 模型名(默认 SiliconFlow,可换本地 Ollama |
| `HONCHO_EMBEDDING_BASE_URL` | `https://api.siliconflow.cn/v1` | Embedding API Base URLOpenAI 兼容;Ollama 改 `http://host.docker.internal:11434/v1` |
| `HONCHO_DERIVER_MODEL` | `gpt-5.4-mini` | Deriver 用的 LLM 模型(必须支持 tool calling |
| `HONCHO_LLM_BASE_URL` | `https://api.openai.com/v1` | LLM API Base URLOpenAI 兼容端点即可) |
| `HONCHO_DERIVER_WORKERS` | `1` | Deriver worker 数 |
### 敏感变量(`env.cfg`,不提交)
| 变量 | 说明 |
|------|------|
| `HONCHO_LLM_API_KEY` | LLM API Key**必填**server 启动检查,没它起不来) |
| `HONCHO_EMBEDDING_API_KEY` | Embedding API Key**必填**仅当走云端:SiliconFlow 在 [cloud.siliconflow.cn/account/ak](https://cloud.siliconflow.cn/account/ak) 生成;走 Ollama 时留空) |
| `HONCHO_DB_PASSWORD` | PostgreSQL 密码(**必填**,用强密码) |
| `HONCHO_AUTH_JWT_SECRET` | JWT 密钥(仅在 `HONCHO_AUTH_USE_AUTH=true` 时需要;用 `python scripts/generate_jwt_secret.py` 生成) |
**关键约束**Honcho 启动时会**校验** `HONCHO_LLM_API_KEY``HONCHO_EMBEDDING_API_KEY` 都非空 — 缺失则立刻退出。这意味着 `env.cfg` 里这两项**不能用占位符**(如 `***`),必须填真实值,否则 `docker compose up -d` 后 deriver/api 容器会反复重启。
## 部署步骤
### 首次部署
```bash
# 1. 准备数据目录(必须原生 ext4,不能放 9P drvfs
sudo mkdir -pv /data/Volumes/honcho/{pgdata,redis,source}
sudo chown -R 999:999 /data/Volumes/honcho/pgdata
sudo chown -R 999:999 /data/Volumes/honcho/redis
# 2. 复制 env 模板并填入真实值
cp honcho/env.cfg.example honcho/env.cfg
$EDITOR honcho/env.cfg
# 必填:HONCHO_LLM_API_KEY(不能用空值/默认值,否则 deriver 起不来)
# 必填:HONCHO_DB_PASSWORD(改成强密码)
# 推荐改:HONCHO_DB_USER / HONCHO_DB_NAME(默认值 honcho 仅 dev 可用)
# 3. 拉镜像(PG + Redis 是预构建;api/deriver 从源码 build
docker compose --env-file ./honcho/env.cfg -f ./honcho/stack.yml pull
# 4. 构建 + 启动(首次 api/deriver 构建需 5-10 分钟,依赖网络)
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml up -d --build
```
### 验证
```bash
# 容器状态(必须 4 个都 healthy)
docker ps -f name=honcho
# API 健康检查
curl -s http://localhost:8000/health
# 数据库连接
docker exec -it honcho-database psql -U honcho -d honcho -c '\dt'
# pgvector 扩展确认
docker exec -it honcho-database psql -U honcho -d honcho \
-c "SELECT extname FROM pg_extension WHERE extname='vector';"
# Redis 连接
docker exec -it honcho-redis redis-cli ping
# 期望输出:PONG
# deriver 日志(看是否成功处理消息)
docker logs -f honcho-deriver --tail 50
# 端口监听
ss -tlnp | grep -E '8000|5432|6379'
```
### 停止/重启
```bash
# 停止(保留数据)
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml stop
# 完全销毁(**数据不删**,bind 挂载保留在宿主机)
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml down
# 重启
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml restart
```
## 关键设计决策
| 决策点 | 决定 | 原因 |
|--------|------|------|
| 镜像源 | api/deriver 从 [plastic-labs/honcho](https://github.com/plastic-labs/honcho) **源码 build** | 官方**没有预构建镜像**,Docker Hub 也没 — 必须 build |
| DB 版本 | PostgreSQL 18pgvector 镜像 `pg18` tag) | 用户指定,比官方默认 pg15 新 |
| Redis 版本 | Redis 8 | 用户指定 |
| 数据卷方案 | bind 挂载到 `${Volumes_Path}/{pgdata,redis,source}` | 直观、可直接 `rsync`/`pg_dump`、跨机迁移用 `tar` 整个目录即可 |
| 端口绑定 | 0.0.0.0,含 DB 5432 | PVE LAN 上其他 VM 也可访问;DB 端口暴露方便外部工具(DBeaver 等)连接 |
| 认证 | 默认 `HONCHO_AUTH_USE_AUTH=false`(dev 模式) | 本地 LAN 自用,跳过 JWT 校验;公网暴露必须改 `true` |
| LLM 默认 | `gpt-5.4-mini`(主 LLMOpenAI 兼容);embedding 默认 `Qwen/Qwen3-Embedding-8B`dimensions=1536 强制输出,兼容已有 1536 维 schema)走 SiliconFlow**备选** 本地 Ollama `qwen3-embedding:0.6b`(零成本、隐私优先) | LLM 走 OpenAI 兼容;embedding 双轨:SiliconFlow(云端,独立 base URL / Ollama(本地 `host.docker.internal:11434/v1` |
| Honcho 版本 | 默认 `main`(源码 build),可锁 tag 如 `v3.0.10` | 当前最新稳定版 v3.0.x,支持 peer card、dialectic、dream consolidation |
| deriver 必须 | api + deriver 双容器 | deriver 是后台推理 worker,没它记忆功能不工作 |
| PG 认证 | `scram-sha-256` | 比 md5 更安全,`POSTGRES_INITDB_ARGS` 同步设置 `--auth-host` |
## 关键陷阱(必读)
### 1. 首次构建时间长且需要 BuildKit
```bash
# 必须开启 BuildKit(默认 20.10+ 已启用,但确认下)
DOCKER_BUILDKIT=1 docker compose ...
```
- 首次 build api/deriver 镜像需 **5-10 分钟**(拉源码 + uv sync Python 依赖 + pip install ~300MB
- 后续增量构建快(除非 Honcho 自身依赖变更)
- 构建失败常见原因:网络拉 `astral-sh/uv` 慢、Python wheel 编译失败 — 配置 Docker 镜像加速
### 2. deriver 必须健康,否则记忆不工作
如果只看到 `honcho-api``healthy``honcho-deriver` 反复重启或卡在 startup,**消息会写入但不会产生任何记忆**。检查:
```bash
docker logs honcho-deriver --tail 100 | grep -iE "error|fatal"
```
deriver 起不来最常见原因:
- `HONCHO_LLM_API_KEY` 为空/无效 — server 启动立即校验
- LLM 模型不支持 tool calling — deriver 强依赖 function calling
- LLM API base URL 配错(如少了 `/v1` 后缀)
### 3. AGPL-3.0 传染条款
Honcho 是 **AGPL-3.0**,对网络服务部署有"用户可获取源码"的要求。本地 LAN 自用不触发,但若对外提供服务(哪怕只是 API 反代),需考虑:
- 对外服务时 `AUTH_USE_AUTH=true` + 公开 `AUTH_JWT_SECRET` 之外,**还需要向用户公开 Honcho 源码修改**
- 详见 [AGPL-3.0 §13](https://www.gnu.org/licenses/agpl-3.0.html)
### 4. WSL 9P `fsync` 陷阱
**PG/Redis 数据绝不能放 `/mnt/c/`、`/mnt/d/` 等 9P drvfs 路径**`${Volumes_Path}` 必须指向 WSL 原生 ext4`/data/Volumes/honcho`),否则可能静默数据损坏。
### 5. `POSTGRES_HOST_AUTH_METHOD=trust` 已删除
honcho-self-hosted 相对官方 compose 的一个改进:**移除了**`trust` 认证(官方默认的 dev 用法),改用强密码 + scram-sha-256。生产环境务必保留这个设置。
### 6. 容器端口 vs 宿主机端口不可混用
**容器之间互访必须用容器内端口(5432/6379/8000**,不能用宿主机映射端口(如 `HONCHO_DB_PORT=25432`)。错误示例:
```yaml
# ❌ 错:${HONCHO_DB_PORT} 是宿主机端口 25432,容器内根本没监听这个
DB_CONNECTION_URI=postgresql+psycopg://honcho:pw@database:${HONCHO_DB_PORT}/honcho
# ✅ 对:硬编码容器内端口 5432
DB_CONNECTION_URI=postgresql+psycopg://honcho:pw@database:5432/honcho
```
同样 healthcheck 也用容器内端口 `localhost:8000`**不是** `localhost:18000`(宿主映射端口)。
## 故障排查
| 症状 | 排查命令 |
|------|----------|
| api 容器起不来 | `docker logs -f honcho-api` — 通常是 `LLM_OPENAI_API_KEY is required` 或 DB 连接失败 |
| deriver 反复重启 | `docker logs -f honcho-deriver` — 检查 LLM key、模型名、base URL |
| DB 连不上(容器内) | `docker exec -it honcho-database psql -U honcho -d honcho` |
| DB 连不上(外部工具) | 确认 `HONCHO_DB_PORT` 已映射、`ss -tlnp` 检查 5432 监听;密码含特殊字符试改简单 |
| API `/health` 502/超时 | 检查 deriver 是否 healthy`depends_on` 会卡住 api |
| pgvector 扩展缺失 | `docker exec -it honcho-database psql -U honcho -d honcho -c "CREATE EXTENSION IF NOT EXISTS vector;"` |
| 端口冲突 | `ss -tlnp \| grep -E '8000\|5432\|6379'` — 检查是否与 hindsight/dbSer 等服务撞车 |
| 慢查询 / DB 锁 | `docker exec -it honcho-database psql -U honcho -d honcho -c "SELECT * FROM pg_stat_activity;"` |
| 密码含特殊字符连不上 | `HONCHO_DB_PASSWORD` 最好只用字母数字,避免 URI 编码问题;如必须用,把 URL 里特殊字符 percent-encode |
## 与 Hermes Agent 集成
Hermes plugin 通过 HTTP 调用 Honcho 的 REST API`localhost:8000`),不直连 DB。配置在 `~/.hermes/config.yaml`
```yaml
memory:
provider: honcho
honcho:
api_url: http://localhost:8000
# api_key 不需要(本地自托管,AUTH_USE_AUTH=false
workspace_id: hermes
auto_recall: true
auto_retain: true
```
切换命令:`hermes config set memory.provider honcho`
**与 Hindsight 的差异**
- Hindsight 强调 **跨会话长期记忆**(基于时序、bi-temporal
- Honcho 强调 **peer-centric 用户画像**(多 peer 互观察、推理、deduction
- 两者可并存;Hermes 当前用 Honcho 做主记忆层,Hindsight 作为补充
## 备份与恢复
### 自动备份(推荐)
`backup.job`(待补)— 用 `pg_dump` 热备份 PG + `redis-cli BGSAVE` 备份 Redis。接入 cron
```bash
# /etc/cron.d/honcho-backup
30 3 * * * /path/to/deploy.stack/honcho/backup.job >> /var/log/honcho-backup.log 2>&1
```
或参考 `crontab/` 目录的统一任务管理方式。
### 手动备份
```bash
# PG 热备份
docker exec honcho-database pg_dump -U honcho -d honcho | \
gzip > /data/Volumes/honcho/backups/honcho_$(date +%Y%m%d).sql.gz
# Redis 快照
docker exec honcho-redis redis-cli BGSAVE
# 触发后 /data/Volumes/honcho/redis/dump.rdb 是最新快照
```
### 恢复
```bash
# 从 pg_dump 恢复(需要先创建空 DB)
gunzip -c /data/Volumes/honcho/backups/honcho_20260619.sql.gz | \
docker exec -i honcho-database psql -U honcho -d honcho
# 从 Redis dump 恢复
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml stop honcho-redis
sudo cp /data/Volumes/honcho/backups/dump.rdb /data/Volumes/honcho/redis/dump.rdb
sudo chown 999:999 /data/Volumes/honcho/redis/dump.rdb
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml start honcho-redis
```
## 升级
```bash
# 1. 拉取最新源码(在 host 上或临时容器)
cd /data/Volumes/honcho/source && git pull
# 2. 重建 api + deriver 镜像
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml build api deriver
# 3. 滚动重启
docker compose -p honcho --env-file ./honcho/env.cfg -f ./honcho/stack.yml up -d
# 4. 跑迁移(honcho entrypoint.sh 会自动执行;若需手动跑)
docker exec -it honcho-api sh -c "cd /app && .venv/bin/alembic upgrade head"
```
**PG 大版本升级**(如未来 18→19)需 `pg_dump` → 新版本空 DB → restore**不能直接换 tag**。
## 相关文档
- [plastic-labs/honcho](https://github.com/plastic-labs/honcho) — 上游仓库
- [elkimek/honcho-self-hosted](https://github.com/elkimek/honcho-self-hosted) — 一键安装器,本目录配置基于此
- [Honcho 自托管官方文档](https://honcho.dev/docs/v3/contributing/self-hosting)
- `hindsight/readme.md` — 同仓库姊妹服务,部署模式高度相似
- 仓库根 `AGENTS.md``deploy.stack` 项目规范
- `crontab/` — 定时任务集成参考
## 已知限制
详见上文 [关键陷阱](#关键陷阱必读) — 主要为:无预构建镜像(必须源码构建)/ AGPL-3.0 传染 / deriver 强依赖 LLM。