diff --git a/.spec/specs/2026-10-24_add-blog-infra/spec.md b/.spec/specs/2026-10-24_add-blog-infra/spec.md new file mode 100644 index 0000000..f72d6d6 --- /dev/null +++ b/.spec/specs/2026-10-24_add-blog-infra/spec.md @@ -0,0 +1,78 @@ +# 博客重基建 Phase 0:备份/gitea/Artalk/发布链地基 - 项目范围 + + + +## 1. 问题定义 +- **项目目标**:为博客重建(详见 docs/博客重设计调研报告.md v1.8)铺好基础设施:生产数据备份、gitea 代码托管(双写作流后端)、Artalk 评论服务、域名接入与发布链地基;全程生产博客(Halo 18090)零影响 +- **目标用户**:站长本人(后续 Phase 1-4 的构建/发布/翻译管线都跑在这套地基上) +- **核心价值**:Phase 1 可直接开工;生产可秒级回滚的安全网(备份 + nginx 切换预案) + +## 2. 假设与待确认 + +### 2.1 已确认事实 +- TLS 证书为通配符(`wait4x.online` + `*.wait4x.online`,openssl 实测),git 子域零新增证书 +- postgres 容器用户 `wait4x`,Halo 库名 `halo_db`(docker inspect 实测);Halo 数据目录 `~/docker_apps/halo/halo2` +- `127.0.0.1:3000` 已被 new-api 占用;13020/13030 端口空闲(ss 实测) +- nginx 已有 ESA 回源 snippet(`snippets/esa-origin-ssl.conf`,含回源鉴权 stage 计划) +- 现有评论数 0,评论系统切换零迁移成本 +- 调研决策全部定稿(报告 v1.8 §7):C'' 架构 / Artalk / 分阶段照片管线 / 双语预译 / 多端红线 + +### 2.2 关键假设 +- ESA 控制台添加子域需用户手动操作(本会话无 ESA API 凭据) +- gitea/gitea 与 artalk 官方 docker 镜像可直接拉取(经本机 clash 代理) +- gitea web UI 上传默认限制(单次 5 文件)可在 app.ini 调大,不影响本包验收 + +### 2.3 待确认问题 +- [ ] git.wait4x.online 走 ESA 代理(复用回源鉴权+通配证书)还是 DNS 直连?→ 倾向 ESA +- [ ] gitea 首管理员用户名(默认 wait4x)? +- [ ] gitea SSH 本期不暴露(https-only),后续按需加 13022 → 默认是 + +### 2.4 可选解释与取舍 +- Artalk 挂主域 `wait4x.online/artalk` 路径(零新增子域、评论与博客同源)优于独立子域(多一次 DNS+证书面)→ 选路径 +- gitea 独立子域(完整应用、path 反代需 ROOT_URL 子路径配置、体验差)优于主域路径 → 选子域 + +### 2.5 已证伪路径 +- 无(暂无证伪记录) + +## 3. 功能范围 + +### 3.1 核心功能(MVP) +- [ ] T1 生产备份:pg_dump(halo_db) + halo2 目录归档,落 `~/backups/blog/` +- [ ] T2 翻译引擎确认:new-api 网关模型列表 + 一次真实调用留证 +- [ ] T3 gitea 部署:容器 13020 + 卷 + 管理员 + blog 空仓;nginx conf 草稿(不安装) +- [ ] T4 Artalk 部署:容器 13030 + sqlite 卷 + 站点配置;nginx conf 草稿(不安装) +- [ ] T5 域名接入:用户 ESA 加 git.wait4x.online 后,orchestrator 安装 conf + reload + 公网验证 +- [ ] T6 发布链地基:webhook 接收脚本骨架 + 构建目录 + 回滚预案文档 +- [ ] T7 Phase 0 验收:全部 verify 复跑 + 生产 Halo 无恙复查 + 板房汇报 + +### 3.2 扩展功能 +- gitea SSH(13022)、gitea 镜像仓、ESA 缓存策略调优(二期按需) + +### 3.3 不在范围内 +- Astro 站点本身(Phase 1)、内容迁移(Phase 2)、双语管线(Phase 3)、上线切换(Phase 4) + +## 4. 最小实现路径 +- 两个容器各自独立 compose 于 `~/docker_apps//`,不共用网络外露端口(仅 127.0.0.1 绑定,公网经 nginx) +- nginx 集成(conf 安装/reload)只由 orchestrator 执行;worker 只交草稿——多写者单点集成 +- 暂不引入:watchdog 容器、gitea runner(Phase 4 再上构建)、redis + +## 5. 技术决策 +- 技术栈:docker compose + nginx;gitea/gitea:latest;artalk/artalk:latest +- 证据协议:evidence: runs(verify 命令由 scripts/spec_verify.py 真实执行并记录) +- 本轮允许改动:`~/docker_apps/{gitea,artalk}/`、`/etc/nginx/sites-available/`(仅 T5 且先草稿评审)、`~/backups/blog/`、本仓库 `.spec/` 与 `infra/` 文档 +- 本轮不应触碰:halo-halo-1 容器、postgres-db 数据、`~/docker_apps/halo/`、现有 nginx vhost(除新增文件)、生产 DNS/ESA(仅用户操作) +- Git integration branch:`spec/2026-10-24_add-blog-infra` + +### 5.1 验证策略 +- 范围级别:package(每任务 verify 命令真实执行;T7 全量复跑) + +## 6. 成功标准 +1. 备份三件套存在且可校验(pg_restore --list 可读、tar 抽查、大小>0) +2. `curl -sf http://127.0.0.1:13020/api/v1/version` 返回 JSON;gitea 有管理员与 blog 仓 +3. `curl -sf http://127.0.0.1:13030/api` 返回 JSON;artalk 站点配置含 wait4x.online +4. (T5 用户操作后)`curl -sf https://git.wait4x.online` 与 `https://wait4x.online/artalk` 公网 200 +5. 生产复查:halo-halo-1 healthy + `curl -sf http://127.0.0.1:18090` 200(与本包开工前状态一致) +6. 所有 verify 命令由 spec_verify 真实执行且通过,证据入 runs.jsonl + +## 7. 目录结构审计 +- 仓库现状:`docs/`(调研)+ `design/`(样板)+ `.spec/`(本包)+ `.githooks/`。职责清晰无需重组;Phase 1 再引入 `src/`(Astro)。运行态与源码分离已由 .gitignore 保证(.mesh/.team/node_modules/dist 忽略)。 diff --git a/.spec/specs/2026-10-24_add-blog-infra/tasks.md b/.spec/specs/2026-10-24_add-blog-infra/tasks.md new file mode 100644 index 0000000..33456bf --- /dev/null +++ b/.spec/specs/2026-10-24_add-blog-infra/tasks.md @@ -0,0 +1,52 @@ +# 博客重基建 Phase 0:备份/gitea/Artalk/发布链地基 - 任务拆解 + +## 使用规则 +- 每个任务都要写清楚 `boundary` 和 `verify`;机器任务的 verify 以首个反引号 span 为执行的命令 +- 如果一个任务没有验证方式,就不能开始;确无命令可执行的任务写 `verify: manual: <理由>` +- 发现的可执行问题必须回写本包,并在本轮做完 +- verify 命令不得自引用本包 check 门禁 +- 多 agent 协作:任务可加 `claim:` 行声明在做者(信息约定,非锁);worker 交付物经 orchestrator 验收后由 orchestrator 勾选 + +## 阶段一:实现 + +- [ ] T1 生产备份(halo_db + halo2 目录) + - claim: orchestrator 2026-10-24 + - boundary: 只读 postgres(pg_dump)与只读打包 `~/docker_apps/halo/halo2`;产物只写 `~/backups/blog/halo-20261024/`;不碰任何容器运行状态 + - verify: `bash .spec/specs/2026-10-24_add-blog-infra/evidence/verify_backup.sh` + +- [ ] T2 翻译引擎确认(new-api 网关) + - claim: orchestrator 2026-10-24 + - boundary: 只读调用 127.0.0.1:3000 的模型列表与一次 chat 调用;证据写 `evidence/new-api-check.json`;不改 new-api 配置 + - verify: `test -s .spec/specs/2026-10-24_add-blog-infra/evidence/new-api-check.json` + +- [ ] T3 gitea 部署(容器 13020,nginx conf 草稿不安装) + - claim: op-gitea 2026-10-24 + - boundary: 新建 `~/docker_apps/gitea/`(compose+数据卷);容器仅绑 127.0.0.1:13020;初始化管理员与 blog 空仓;nginx conf 草稿与 app.ini 上传限制调整(MAX_FILES=20)写进 `infra/gitea/`(仓库内);不安装任何 nginx 配置、不 reload、不碰 DNS + - verify: `curl -sf http://127.0.0.1:13020/api/v1/version && docker inspect -f {{.State.Status}} gitea | grep -q running` + +- [ ] T4 Artalk 部署(容器 13030,nginx conf 草稿不安装) + - claim: op-artalk 2026-10-24 + - boundary: 新建 `~/docker_apps/artalk/`(compose+sqlite 卷);容器仅绑 127.0.0.1:13030;站点配置含 wait4x.online;nginx conf 草稿(主域 /artalk location)写进 `infra/artalk/`(仓库内);不安装任何 nginx 配置、不 reload、不碰 DNS + - verify: `curl -sf http://127.0.0.1:13030/api && docker inspect -f {{.State.Status}} artalk | grep -q running` + +- [ ] T5 域名接入(依赖用户 ESA 操作 + T3/T4 草稿) + - depends-on: T3, T4 + - claim: orchestrator 2026-10-24 + - boundary: 用户在 ESA 控制台添加 git.wait4x.online(代理开)后:安装两份 conf 到 sites-available + symlink + nginx -t + reload;仅新增文件,不改既有 vhost + - verify: `curl -skf https://git.wait4x.online -o /dev/null -w '%{http_code}' | grep -q 200` + +- [ ] T6 发布链地基(webhook 脚本骨架 + 回滚预案) + - depends-on: T5 + - claim: orchestrator 2026-10-24 + - boundary: 仓库内新增 `infra/deploy/`(webhook 接收脚本骨架 + 回滚预案文档);宿主机建 `/var/www/blog-staging/` 占位目录;不切换任何 nginx upstream + - verify: `bash infra/deploy/rollback-dryrun.sh` + +- [ ] T7 Phase 0 验收(全量复跑 + 生产无恙复查) + - depends-on: T1, T2, T3, T4, T5, T6 + - claim: orchestrator 2026-10-24 + - boundary: 复跑 T1-T6 全部 verify;复查生产状态;结论写 evidence;向 blog 房 board 汇报 + - verify: `curl -sf http://127.0.0.1:18090 -o /dev/null -w '%{http_code}' | grep -q 200 && docker inspect -f {{.State.Status}} halo-halo-1 | grep -q healthy` + +--- + +**当前进度**:由脚本计算,无需手动维护