Files
dsh_shenxian/dsh-server-docs/DEPLOY-本部署.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

102 lines
6.3 KiB
Markdown
Raw 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.
# DEPLOY — 本部署说明(alotbuy.com / 47.77.182.89)
> 用途:把"这套平台到底部署在哪、装了什么、改了什么、怎么重建/回滚"一次讲清,供后来人(或未来的我)在**不翻聊天记录**的前提下独立重建。
> 对应档案 19 §C9。最后更新:2026-09-11
## 1. 拓扑与入口
| 项 | 值 |
|---|---|
| 服务器 | `47.77.182.89`(Alibaba Cloud Linux 8,阿里云)|SSH 别名 `bt-server`(端口 32022,root) |
| 门户 / 用户实例 | **`https://alotbuy.com`** / **`https://<用户名>.alotbuy.com`**(Cloudflare 代理,回源走 443) |
| 旧域名 | `dsh.alotbuy.com`(含 `*.dsh.*`)→ **301** 到新域(保留用户名映射) |
| 面板 | 宝塔(站点 vhost 由面板管理,注意:面板保存会**重写** vhost,可能抹掉自定义指令) |
| 编排器 | 自研 `dshs`(Node/TS),systemd 单元 `dshs`,监听 `127.0.0.1:3080` |
| 被托管运行时 | 官方 **`@deepseek-ai/[email protected]`**(全局安装于 `/usr/local/lib/node_modules/@deepseek-ai/dsh`,**平台不改其任何文件**) |
## 2. 目录布局
| 路径 | 说明 |
|---|---|
| `/opt/dshs` | 编排器**源码仓库**(也是 git 仓库;`lib/` 被 .gitignore 忽略 → 需构建) |
| `/var/lib/dshs` | dataRoot:`dshs.db`(better-sqlite3)、`users/<uuid>/` |
| `<userRoot> = dataRoot/users/<uuid>` | 每用户根:`ws/`(工作区,用户可见)、`home/`(DSH_HOME:profiles/sessions/storages/skills)、`tmp/`(1777) |
| `<profile> = <userRoot>/home/profiles/web` | 该用户的 dsh profile:`node_modules/`、`cordis.patch.yml`、`package.json`、`pnpm-lock.yaml` |
| `/opt/dsh/` | 运维脚本与备份:`switch-domain-alotbuy.sh`、`backups/`、`artifacts/`(插件 tgz) |
| `/www/server/panel/vhost/nginx/` | `alotbuy.com.conf`(现役)、`dsh.alotbuy.com.conf`(301 跳转)+ 多份 `.bak-*` |
| `/etc/letsencrypt/live/{alotbuy.com,dsh.alotbuy.com}/` | 证书(DNS-01 via `/etc/cloudflare.ini`) |
## 3. 环境变量(`/etc/dshs.env`)
| 键 | 作用 |
|---|---|
| `DSHS_PORT` | 编排器监听端口(127.0.0.1:3080) |
| `DSHS_DATA_ROOT` | dataRoot |
| `DSHS_BASE_DOMAIN` | 门户/用户子域基域(现 `alotbuy.com`) |
| `DSHS_COOKIE_DOMAIN` | 会话 Cookie 域(现 `.alotbuy.com`;见档案 22 §五 取舍说明) |
| `DSHS_SECURE_COOKIES` | Cookie `Secure` 标记(HTTPS 下应开) |
| `DSHS_DSH_BIN` | 子实例可执行路径 |
| `DSHS_ISOLATION_MODE` | 隔离模式(本部署 `account` = bwrap + setpriv + systemd-run scope) |
| `DSHS_BASE_UID` | 每用户 uid 起始值 |
> 其余可调项走代码默认值(崩溃退避/熔断、idle-reap、bundled skill dir 等),见 `src/config.ts` 的 `DEFAULT_*` 与档案 20。
## 4. 外部依赖(版本为实测)
| 依赖 | 版本 | 用途 |
|---|---|---|
| Node | **22.23.2** | 编排器与子实例运行时 |
| pnpm | **9.15.9** | profile 侧插件安装账本(`pnpm-lock.yaml`) |
| bubblewrap | **0.4.0** | 每用户沙箱(合成根 + 只读系统 + 私有 tmp + `--unshare-pid`) |
| systemd-run | — | per-instance scope(**MemoryHigh=448M(基础/软限) + MemoryMax=1024M(上界/硬限)**,**与插件开关无关**(档案 **96**)/ CPUQuota=150% / TasksMax=128) |
| nginx | 1.28.3(宝塔) | 站点与反代(关键自定义指令见档案 21/22) |
| nftables | — | 出网护栏(`/etc/nftables-dsh-egress.nft` + `dsh-egress.service`) |
| sqlite3 CLI | 3.26 | 仅运维排查(平台内置用 better-sqlite3) |
| certbot + dns-cloudflare | — | 证书签发/续期(**必须** `--dns-cloudflare-propagation-seconds 60`,否则失败) |
## 5. 平台侧脚本族
| 脚本 | 作用 |
|---|---|
| `ensure-role-profile-patch.cjs` | 角色化 profile patch(非 admin 隐藏模型分区/收归插件开关) |
| `ensure-workspace-picker.cjs` | 目录选择器收敛**全量/新用户铺开**(写平台段 + 逐用户 pnpm add;幂等,`--dry-run/--restart`) |
| `scripts/install-workspace-picker.sh <tgz>` | 逐用户安装插件包(自动判断是否加 `pnpm -w`) |
| `/opt/dsh/switch-domain-alotbuy.sh` | 域名切换(改 env → drain → 重启) |
| `/usr/local/bin/provision-new-users.sh` | 新用户供应(建 OS 账号 + chown + **调用 picker 铺开**);由 `dsh-provision.path` 触发 |
| `scripts/ci.sh` | 类型检查 + 构建 + 单测(不含需要实例/凭据的 smoke) |
## 6. 构建 / 部署 / 回滚(三步)
```bash
# 构建(改代码后必做;lib/ 不入库)
cd /opt/dshs && npm run build && bash scripts/ci.sh
# 部署(drain: 停服务 → 清残留实例 → 起服务)
systemctl stop dshs; for p in $(ps -eo pid,user,args | awk '$2 ~ /^dsh-/ {print $1}'); do kill $p; done; systemctl start dshs
# 回滚(示例:回滚到某个提交)
git -C /opt/dshs revert <sha> && npm run build && systemctl restart dshs
```
- **本机 ↔ 服务器同步**:服务器无 Gitea 凭据 → 服务器 `git bundle create` → 本机 `git fetch <bundle>`(**路径必须用 `D:/…`**)→ `merge --ff-only` → `push`。
- **文档库**:`bash scripts/docs-sync-check.sh`(双端 md5 对账,0 = 全绿);服务器侧 `/opt/dsh/docs`(root 600)。
## 6.5 定时维护(cron,2026-09-11 建立)
| 任务 | 文件 | 时间 |
|---|---|---|
| 存储用量快照 | `/etc/cron.d/dsh-maintenance` | 每小时 :05 |
| 工作区清理 / 会话回收 / 回收站清空 | 同上 | 04:10 / 04:20 / 04:40 |
| **平台全量备份 + 旧备份清理** | `/etc/cron.d/dsh-backup` | 每周日 05:00 / 05:30 |
> 备份脚本 `/opt/dsh/backup.sh`(入库副本 `scripts/backup-platform.sh`)含 SQLite 一致性快照;恢复步骤见档案 02 附录 C.8。
## 7. 默认红线(改任何东西前先读)
1. **不自动升级 dsh**;升级必须走"测试 → 评估 → 修复",并按档案 26 回归清单逐项验。
2. **不改官方 dsh 主程序与缓存**(`/usr/local/lib/node_modules/@deepseek-ai/dsh/**` 保持原封)。
3. client bundle **禁 `exports.default`**(R3)。
4. 未明确要求**不擅自 commit/push**(服务器 git 与文档 git 都一样)。
5. 服务器 `/opt/dsh/docs` 保持 root 600。
> 相关档案:01(架构)|02(运维,含附录 C 速查)|21(nginx 性能/流式)|22(域名迁移)|26(升级耦合点与回归清单)