Files
hermes-glass-ui-personal/.memory/deployment-kang.md
2026-04-21 13:42:29 +08:00

153 lines
7.1 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.
---
name: Hermes Glass UI 个人版 · kang-kang.com 部署
description: 从公司版 hermes.milejoy.com fork + 合规隔离重建的个人 VPS 部署完整细节
type: project
---
# 架构
```
浏览器
↓ https://hermes.kang-kang.com/
Coolify Traefik (443, letsencrypt 自动签)
↓ Host(`hermes.kang-kang.com`) → http://10.0.0.1:8088
宿主 nginx 1.24 (listen 10.0.0.1:8088, /etc/nginx/sites-available/hermes.kang-kang.com)
├─ /login.html + /_auth/verify + /_auth/logout cookie 门禁
├─ / /var/www/hermes-kang/Glass UI 静态)
├─ /v1/ + /api/v1/(rewrite) + /api/jobs 注入 Bearer → LXC
├─ /memory/ + /hermes-skills/ + /classic/ 空目录占位
└─ /health 免门禁
Incus LXC hermes-personal (10.3.73.137, Debian trixie, privileged + nesting)
└─ Docker 26.1.5 (hermes-agent container)
└─ Hermes Agent v0.7, gateway run, 0.0.0.0:8642
└─ OpenRouter → google/gemini-3.1-pro-preview
```
# 关键决策
## CORS 白名单必须配2026-04-21 事后补的坑)
- Hermes gateway 的 API Server 会检查 `Origin` header 白名单
- `.env` 里必须 `API_SERVER_CORS_ORIGINS=https://hermes.kang-kang.com`
- 不配的话curl 测试一切 200curl 不发 Origin但**真实浏览器发 POST /api/v1/chat/completions 会返回 403 body=0**Hermes CORS 拒绝)
- 公司版 .env 原本就配了 `https://hermes.milejoy.com`,我 fork 时抄漏了
- 修复:加环境变量 → `docker compose down && up`(不能 restart
## 为什么用 Debian trixie 不用 Ubuntu 24.04
- Ubuntu 24.04 + Docker 29 在非/特权 LXC 内启动容器报 `net.ipv4.ip_unprivileged_port_start: permission denied`
- Debian trixie + Docker 26 没这个 bug公司版 hermes-box 用的就是这个组合,直接照搬)
- 也加了 `security.syscalls.intercept.mknod/setxattr=true`(跟公司版对齐)
## 为什么宿主 nginx 听 10.0.0.1:8088 不是 127.0.0.1:8088
- Coolify-proxy (Traefik) 跑在 docker coolify 网络,从容器内访问宿主要走 docker0 gateway
- 宿主 docker0 IP 是 `10.0.0.1`非标准Coolify 自定义)
- 127.0.0.1 从 Traefik 容器里访问是容器自己的 localhost不是宿主
- Traefik 容器 /etc/hosts 有 `10.0.0.1 host.docker.internal` —— 用宿主 docker0 IP 直连宿主 nginx
## 为什么 gitea.yaml 和 notebooklm-mcp.yaml 被改了
- Traefik watcher 解析 `dynamic/` 目录时遇到这两个文件里 `dialTimeout/responseHeaderTimeout` **不在 forwardingTimeouts 下**,报 `field not found`
- 这个错误**阻止了整个 directory 的 reload**(不是 per-file 隔离),所以我新写的 hermes-kang.yaml 一直没被 pick up
- 修复:把两个文件里的 `dialTimeout`/`responseHeaderTimeout` 包到 `forwardingTimeouts:`Traefik v3 正确嵌套)
- 备份:`gitea.yaml.bak-<ts>`, `notebooklm-mcp.yaml.bak-<ts>`
- gitea/lobehub/notebooklm-mcp 都继续工作verified via curl 200/302
## 为什么不用 Traefik basicauth middleware / forwardAuth sidecar
- 保留公司版的自定义 Liquid Glass login.html + cookie 门禁体验
- 单用户场景 Authelia sidecar 不划算
- nginx 熟悉度高,排障快
# 凭证
`credentials.md` 不在本文件重复。
# 文件清单
## 宿主 76.13.31.179
| 路径 | 作用 | 备注 |
|---|---|---|
| `/etc/nginx/sites-available/hermes.kang-kang.com` | nginx 站点listen 10.0.0.1:8088 | sites-enabled 软链已建 |
| `/etc/nginx/.htpasswd-hermes-kang` | bcrypt 密码 | 只 `kang` 一个用户 |
| `/data/coolify/proxy/dynamic/hermes-kang.yaml` | Traefik 路由+letsencrypt | owner 9999:root, mode 700 |
| `/var/www/hermes-kang/` | Glass UI 静态 | rsync 自本机个人版 src/ |
| `/var/www/hermes-memory-kang/` | `/memory/` 路由空目录 | 自己以后填 |
| `/var/www/hermes-skills-kang/` | `/hermes-skills/` 路由空目录 | 自己以后填 |
| `/opt/hermes-build/` | 镜像 build 源码rsync 自本机)| 32MB |
| `/tmp/hermes-build.log` | build 过程 log | 留作参考 |
## Incus LXC hermes-personal
| 路径 | 作用 |
|---|---|
| `/opt/hermes-agent/docker-compose.yml` | compose |
| `/opt/hermes-agent/config.yaml` | Hermes gateway 配置OpenRouter + gemini-3.1-pro-preview|
| `/opt/hermes-agent/.env` | `OPENROUTER_API_KEY` + `API_SERVER_KEY`, mode 600 |
| `/opt/hermes-agent/data/` | Hermes workspaceHERMES_HOME|
# 常用操作
## 改前端代码后同步
```bash
cd ~/Projects/code/20260421-hermes-glass-ui-personal
# 编辑 src/*
rsync -az --delete src/ root@76.13.31.179:/var/www/hermes-kang/
# sw.js 如需强刷bump CACHE 版本号
```
## 改后端配置/模型
```bash
ssh root@76.13.31.179
incus exec hermes-personal -- bash
cd /opt/hermes-agent
vi config.yaml # 改模型
vi .env # 改 key
docker compose down && docker compose up -d
# ⚠️ docker restart 不 reload env_file必须 down + up
```
## 换 OpenRouter key
```bash
incus exec hermes-personal -- bash -c "sed -i 's|^OPENROUTER_API_KEY=.*|OPENROUTER_API_KEY=<新key>|' /opt/hermes-agent/.env && cd /opt/hermes-agent && docker compose down && docker compose up -d"
```
## 查日志
```bash
incus exec hermes-personal -- docker logs hermes-agent --tail 50
ssh root@76.13.31.179 tail -f /var/log/nginx/error.log
ssh root@76.13.31.179 docker logs coolify-proxy --since 2m 2>&1 | grep -i hermes
```
# 不破坏的约束
- ✅ 不碰 Coolify 现有 22+ 容器 + Coolify-proxy 本体
- ✅ 不碰 `/opt/lobechat-mirror/` 独立 docker compose
- ✅ 不碰 `/opt/gitea/` `/opt/postgres/` `/opt/mysql/`
- ✅ hermes-kang 走独立 LXC + 独立 nginx 站点 + 独立 Traefik dynamic file
- ✅ 宿主 nginx 独自启动systemd nginx.service 新启用)
- ✅ 禁用了 sites-enabled/default 和 sites-enabled/styles.kang-kang.com冲突 listen 80且 styles 实际由 style-gallery-nginx docker 容器跑)
# 与公司版的差异
| 维度 | 公司版 hermes.milejoy.com | 个人版 hermes.kang-kang.com |
|---|---|---|
| 宿主 | 公司 VPS 2.24.28.41 | 个人 VPS 76.13.31.179 |
| 入口 | 宿主 nginx 直听 443 | Coolify Traefik 443 → 宿主 nginx 10.0.0.1:8088 |
| 证书 | certbot ai.milejoy.com 复用 | Traefik letsencrypt certresolver |
| LXC | hermes-box, Debian trixie, 10.146.223.10 | hermes-personal, Debian trixie, 10.3.73.137 |
| 模型 | Gemini 3 Pro Preview 直连GOOGLE_API_KEY| Gemini 3.1 Pro Preview via OpenRouter |
| 认证 | basic auth boss/mile | basic auth kang |
| Skills/Memory | 78 真实 skill + 同步真实 memory | 空目录(未来按需填充) |
# 合规边界(离职场景)
**可搬**
- 个人编写的 Glass UI 前端源码fork 到 `code/20260421-hermes-glass-ui-personal/`
- Hermes Agent 开源代码NousResearch 上游)
- 架构和 nginx/Traefik 配置思路
**未搬**
- 公司 API Server Key `ffd2f8af...`(重新用 openssl 生成新的)
- 公司 GOOGLE_API_KEY换 OpenRouter + 个人 key
- 公司 LXC 里的 memory/skills/sessions/对话历史(个人版从零起)
- 公司 basic auth 账号 `boss/mile`(改 `kang` 单账号)
- 公司 nginx 证书letsencrypt 新签)