版本:2026年9月12日修订版 用途:供 Codex 按阶段执行、验收、记录和回滚
1 当前结论
站点继续采用 Astro 5、TypeScript strict、Astro Content Collections 和静态生成。设计升级以内容刊物型网站为主体,优先改进排版、图片叙事、页面转场、滚动揭示和细微反馈;沉浸式 3D 或 WebGL 专题暂不建设,出现明确内容方案后单独立项。
域名备案已经通过。纯静态站已于 2026 年 9 月 12 日切换到阿里云 ECS:https://www.doyouhang.live 是规范地址,https://doyouhang.live 保留访问;两个域名都解析到 ECS,HTTP 跳转到同主机名的 HTTPS。GitHub Pages 保留 7 至 14 天作为独立静态回退入口。
当前 ECS 为 2 核 CPU、2 GB 内存、40 GB 系统盘和 3 Mbps 公网带宽。该规格能够运行 Astro 静态站、Nginx 和 Docker Compose,也能在低访问量下增加轻量 API 与保守配置的 PostgreSQL。前端构建继续在本机或 GitHub Actions 完成,不能在 ECS 上长期执行高内存构建任务。
阶段 0 至 3 已完成;阶段 4 已完成切流和即时验收,24 至 48 小时上线观察正在进行。切流基线发布为 a75bbc7,阶段二私有预发布容器和 GitHub Pages 回退入口均暂时保留。后端、PostgreSQL 和完整自动发布不阻塞本次静态上线。
2 技术栈决策
| 层级 | 当前选择 | 后续策略 |
|---|---|---|
| 前端框架 | Astro 5 静态生成 | 保留,不因设计升级迁移到 React、Next.js 或 Vue |
| 内容系统 | Astro Content Collections 与 Markdown | 保留,文章不默认迁入数据库 |
| 样式 | 原生 CSS 与全站设计令牌 | 保留并逐步完善,不预先引入 Tailwind |
| 基础动效 | CSS、View Transitions、ClientRouter | 继续使用,脚本接入现有幂等初始化机制 |
| 高级动效 | 暂不新增运行时依赖 | 有明确时间线或滚动编排后按需评估 GSAP |
| 3D 与 WebGL | 暂不建设 | 沉浸专题单独设计、预算和验收 |
| 静态入口 | Nginx 容器 | 保留,只公开 80 与 443 |
| 容器编排 | Docker Compose | 保留 staging 与 production 独立覆盖文件 |
| 后端 | Node.js、TypeScript 与 Fastify | 仅在首个真实动态功能确定后加入 |
| 数据库 | PostgreSQL | 与首个持久化业务闭环一起加入 |
| 大型资源 | 初期由 ECS 提供 | 视频、3D 或流量成为瓶颈后再引入 OSS 与 CDN |
技术栈重新评估条件:网站主体变成持续运行的客户端应用、全站依赖 WebGL 场景,或 Astro 的岛屿边界已经妨碍核心交互。单纯需要更精细的动画不构成换栈理由。
3 总体架构
3.1 当前静态上线链路
公众浏览器
-> 已备案域名
-> ECS 公网 80 或 443
-> Nginx 容器
-> Astro 静态构建产物
GitHub Actions
-> 检查与构建
-> GitHub Pages 旧站兜底
维护者电脑
-> SSH
-> ECS 私有预发布 127.0.0.1:8080
3.2 未来动态链路
浏览器 -> Nginx
-> / 与静态资源 -> Astro 构建产物
-> /api/* -> API 容器 -> PostgreSQL
前端保持静态生成,动态交互通过同源 /api 完成。只有明确需要请求时渲染时再评估 Astro SSR,不将 SSR 作为当前上线条件。API 和数据库不得发布宿主机公网端口。
3.3 仓库结构
repo/
src/ # 当前 Astro 站点
public/ # 公开静态资源
apps/api/ # 阶段 6 才创建
infra/docker/ # Web 与未来 API 镜像
infra/nginx/ # staging 与 production 配置
infra/compose.yaml # 基础服务,不直接发布端口
infra/compose.staging.yaml # 只绑定 127.0.0.1:8080
infra/compose.production.yaml
scripts/ # 构建、部署、冒烟和回滚工具
docs/migration/ # 方案与阶段记录
docs/operations/ # 运维手册
.github/workflows/ # Pages、CI 与未来 release
Astro 保持在仓库根目录,当前没有迁移到 apps/web 的收益。真实密钥、服务器地址和环境文件不得提交。
4 阶段总览
| 阶段 | 目标 | 状态 |
|---|---|---|
| 阶段 0 | 盘点仓库、服务器和回滚基线 | 已完成 |
| 阶段 1 | 同一源码支持 Pages 与 ECS 两种构建路径 | 已完成 |
| 阶段 2 | ECS 回环端口与 SSH Tunnel 私有预发布 | 已完成 |
| 阶段 3 | 准备静态生产环境 | 已完成(2026-09-12) |
| 阶段 4 | 域名、HTTPS 与正式切流 | 已完成切流,观察中(2026-09-12) |
| 阶段 5 | 视觉系统与动效升级 | 上线稳定后推进 |
| 阶段 6 | 后端与 PostgreSQL 首个闭环 | 有明确业务需求后推进 |
| 阶段 7 | 自动发布、备份和长期运维 | 分步完善 |
5 阶段 0 盘点与冻结基线
目标:掌握真实环境并建立可恢复基线,不改变线上入口。
已完成内容:
- 核对 Astro、Node、锁文件、构建命令、Pages 工作流、
site、base、输出目录和主要路由。 - 记录 ECS 系统、CPU 架构、内存、磁盘、端口和既有服务;敏感值未写入仓库。
- 验证 GitHub Pages 构建、根路径 ECS 构建、主要页面、404、RSS、sitemap 和搜索索引。
- 保存可回滚提交和现有 Pages 入口。
验收:干净环境可按锁文件构建;Pages 保持可访问;未知参数不以猜测值写入配置。
回退:阶段 0 不修改生产状态。
6 阶段 1 双目标 Astro 构建
目标:同一份代码同时支持 GitHub Pages 的 /blog-demo/ 和 ECS 的根路径 /。
已完成内容:
- 使用
SITE_URL控制规范源站,使用SITE_BASE控制路径前缀。 - Pages 工作流继续使用
SITE_BASE=/blog-demo/,ECS 镜像使用SITE_BASE=/。 - 内部链接继续遵循
import.meta.env.BASE_URL,并覆盖深层路由、404、RSS、sitemap 和 Pagefind。 - 完整构建运行
npm run build,包含字体子集和搜索索引生成。
验收:两种 base 构建与浏览器冒烟均通过,产物不能交叉发布。
回退:恢复原 Astro 配置和 Pages 构建参数。
7 阶段 2 ECS 私有预发布
目标:备案期间只通过 ECS localhost 和 SSH Tunnel 验证真实部署。
已完成内容:
- 安装 Docker Engine 与 Compose,建立版本化发布目录。
- Web 镜像只包含 Nginx、配置和 Astro
dist,排除源码、密钥、.git、依赖与备份。 - 基础 Compose 不发布端口;staging 配置只绑定
127.0.0.1:8080:80。 - 配置健康检查、只读文件系统、日志轮转、
no-new-privileges和重启策略。 - 通过 ECS 本机和 SSH Tunnel 验证首页、深层路由、资源与 404;公网访问 8080 不通。
- Docker Hub 不可用时采用经过校验的本地镜像传输方案,并记录替代路径。
验收与实际结果见 ECS 私有预发布搭建记录。
回退:切回上一镜像,或停止容器并恢复已保留的宿主机 Nginx 配置。
8 阶段 3 静态生产环境准备
目标:在不切换 DNS 的情况下完成最终域名、TLS 和公网配置验证。
已完成内容:
- 确认根域名、
www、规范域名和跳转关系,记录当前 A、AAAA、CNAME 与 TTL。 - 新增独立
productionNginx 配置和 Compose 覆盖文件,不与 staging 文件同时叠加。 - 因两个 A 记录已指向 ECS,使用 Certbot webroot 与 HTTP-01 申请最终域名证书;未创建或保存 DNS API 凭据。
- Nginx 加载完整证书链和私钥,HTTPS 提供站点,HTTP 跳转 HTTPS。证书文件不存在时不得启动引用它的配置。
- 配置 HTML、哈希静态资源、404、压缩、日志轮转和必要安全响应头。只有内容哈希资源使用长期 immutable 缓存。
- 页面展示真实备案号和官方查询链接,并核实上线后适用的公安备案要求。
- 使用 SSH Tunnel、本地 hosts 或
curl --resolve验证最终域名、SNI、证书链、首页、深层路由、资源、404、RSS 和 sitemap。 - 检查最终 Compose 端口、宿主机防火墙、阿里云安全组和 IPv6;API、数据库和 staging 端口保持公网关闭。
- 记录当前发布标识、上一发布标识、配置校验值、回滚命令和预计恢复时间。
实际结果:根域名和 www 的 A 记录均为 ECS 地址,TTL 为 600 秒;没有 AAAA。Let’s Encrypt 证书覆盖两个域名,有效期至 2026 年 12 月 10 日;自动续期 timer 与 deploy hook 已启用,certbot renew --dry-run 通过。生产 Compose 只发布 IPv4 的 80 与 443,8080 保持回环绑定。最终 Host、SNI、证书链、首页、文章、404、RSS、sitemap、Pagefind、安全响应头和未知主机拒绝均已通过 ECS 本机验证。
验收:已通过。由于公共 A 记录在执行前已经指向 ECS,本次没有“保持公共 DNS 不变”的前置窗口;改用独立临时 ACME 入口签发证书,并在生产容器接管端口前完成 curl --resolve 验证。上一静态版本和 Pages 回退入口均保留。
回退:停止 production 配置并恢复 staging 回环入口,不修改 DNS。
9 阶段 4 域名与 HTTPS 切换
目标:把公开访问从 GitHub Pages 切换到 ECS 静态站。
已完成内容:
- 阶段 3 验收通过后冻结发布,保存 Pages、DNS 和 ECS 当前状态。
- 确认切换时 TTL 已为 600 秒;DNS 回切不会瞬时完成。
- 启用 production Compose,开放阿里云安全组与主机防火墙的 80、443;SSH 继续限制来源。
- 因两个 A 记录已提前指向 ECS,先用
curl --resolve对容器做最后检查,再让生产容器接管 80 与 443。IPv6 全链路未验证,因此不设置 AAAA。 - 使用多个解析器和真实浏览器验证首页、文章、搜索、资源、404、RSS、sitemap、HTTPS、HTTP 跳转及移动端。
- 检查 Nginx 状态码、5xx、容器重启、CPU、内存、磁盘和公网带宽。
- 已开始 24 至 48 小时观察;GitHub Pages 保留 7 至 14 天作为独立静态兜底入口。
- 备案信息、证书续期和 DNS 最终值写入脱敏运维记录。
实际结果:生产 Compose 项目固定为 blog-demo-production,容器 blog-demo-production-web-1 运行镜像 blog-demo-web:a75bbc7,健康检查通过且零重启;/opt/blog-demo/current 已指向 /opt/blog-demo/releases/a75bbc7。公网两个域名 HTTPS 返回 200,HTTP 返回 308,文章、搜索、Pagefind、RSS 和 sitemap 返回 200,未知路径返回 404,公网 8080 连接超时。Chrome 直接访问公网域名时,桌面和 390px 手机宽度均无横向溢出,成功页面没有脚本或控制台错误。上线验收时未发现 5xx,容器内存约 4 MiB,根盘使用率 19%。原有 SSH、frps 和 AI 网关监听未改动。
验收:切流验收已通过,24 至 48 小时稳定性观察仍在计时。GitHub Pages 的首页与深层文章返回 200,提交 a75bbc7 的 Pages 工作流成功,可承担独立静态回退。
回退:GitHub Pages 默认地址已验证,但本次开始执行时两个 A 记录已经指向 ECS,未观察到更早的自定义域名记录,因此不能把未知旧值写成回切目标。首次生产版本故障时保留 ECS 现场并发布 Pages 默认地址;以后存在已验收的上一生产镜像后,优先在同一 ECS 回退镜像,减少 DNS 缓存带来的双入口时间。
10 阶段 5 视觉系统与动效升级
目标:在生产入口稳定后,把站点升级为以内容刊物为主体、动效服务于阅读的个人档案。
任务:
- 以
.better-web-ui.md为设计上下文,先统一排版、栅格、留白、图片比例、明暗主题和响应式规则。 - 延续纸色、墨色、藏青、朱红和三层字体体系;设计感来自排版、内容证据和精确反馈。
- 第一层使用 CSS、View Transitions 和现有 ClientRouter,实现页面转场、共享元素、滚动揭示、图片进入和导航反馈。
- 只有明确出现时间线编排、复杂滚动同步或 SVG 序列需求时才评估 GSAP,并按页面拆包加载。
- 沉浸专题、Three.js、WebGL、背景视频和大型模型不纳入本阶段;未来作为独立需求评估性能、资源和降级方案。
- 所有动画支持
prefers-reduced-motion;触摸设备不依赖 hover;低性能设备可以获得静态但完整的内容。 - 初始性能目标:主页首次传输约 800 KB 以内,普通文章约 1 MB 以内;以真实构建和浏览器测量为准,不为数字牺牲必要内容。
- 当前 3 Mbps 带宽下优先压缩图片、按需加载和合理缓存。出现视频、3D 或持续流量瓶颈后,再评估 OSS 与 CDN 的成本和接入。
验收:内容在无脚本、窄屏和 reduced-motion 下完整可读;视觉回归通过;普通页面不加载未使用的高级动效库;实际加载体积没有明显倒退。
回退:关闭新增动效入口并恢复上一静态镜像;内容和路由不依赖动画才能访问。
11 阶段 6 后端与 PostgreSQL 首个闭环
目标:只围绕第一个明确业务功能建立 API 与持久化能力。
入口条件:用户已确定真实功能、数据所有者、读写权限、公开范围和成功标准。没有业务需求时不创建示例数据库功能。
任务:
- 创建 TypeScript 与 Fastify 服务,分离路由、业务逻辑、数据访问和配置校验。
- 统一
/api前缀,提供存活与就绪检查;API 在容器网络监听 3000,但不发布宿主机端口。 - Nginx 同源反向代理
/api,不默认开放通配 CORS。静态页面在 API 故障时仍可阅读。 - 请求使用 schema 校验、统一错误体、请求 ID、结构化脱敏日志、大小限制、超时和优雅退出。
- PostgreSQL 只接入 internal data 网络,不写
ports;管理员、迁移任务和应用使用不同身份,应用不使用超级用户。 - 迁移文件随代码版本化,由一次性任务执行;应用启动时不争抢 DDL,也不自动清库。
- 2 GB 内存下使用小连接池和保守数据库配置,持续观察系统余量。图片处理、全文索引、后台任务或持续内存压力出现时,优先升级到 4 GB。
- 为首个功能覆盖正常读写、非法输入、重复数据、事务失败、重启保留和数据库断开降级。
- 建立加密异地备份并向隔离数据库完成一次恢复;只有备份文件而没有恢复验证不算完成。
验收:API 不可被公网绕过 Nginx 直连;权限与输入验证有效;容器重建不丢数据;恢复演练成功;数据库故障不影响静态内容。
回退:关闭动态功能,恢复兼容当前 schema 的上一组 Web 与 API 镜像。禁止自动执行破坏性降级或 docker compose down -v。
12 阶段 7 自动发布与长期运维
目标:把已经验证的人工步骤固化为可追踪、可回滚的发布流程。
任务:
- 保留 GitHub Pages 工作流作为过渡期旧站和回退入口。
- 新增 CI,对锁文件安装、Astro 检查、单元测试、构建、浏览器冒烟和未来 API 测试进行验证;PR 不获取部署凭据。
- 发布工作流构建一次,以提交 SHA 标记镜像并记录不可变摘要。先手动触发,稳定后再评估自动生产发布。
- ECS 默认通过受控出站方式拉取发布清单和镜像,不为 GitHub 公网 Runner 放开任意来源 SSH。
- 部署器先校验来源、摘要、架构、配置、磁盘和所需密钥,再获取部署锁、拉取镜像、更新服务并执行健康检查。
- 健康检查失败时恢复上一份发布清单;数据库迁移存在时遵守 schema 兼容规则,不能仅回退应用而忽略数据结构。
- Docker 日志设置大小和保留上限,旧镜像和临时产物按发布记录清理;40 GB 磁盘在 80% 使用率前告警。
- 监控 CPU、内存、磁盘、容器重启、5xx、证书到期和备份失败。证书续期后先执行 Nginx 配置检查,再重载并验证新证书。
- 数据库上线后每日生成逻辑备份,发布前额外备份;备份加密后传到独立存储,并定期执行隔离恢复。
部署执行契约:
1 校验发布来源、镜像摘要、架构、配置与密钥
2 获取部署锁,保存当前发布清单,检查磁盘
3 拉取全部镜像,失败则保持当前版本
4 检查 Compose 最终配置和预期端口
5 有数据库变更时创建并验证发布前备份
6 运行一次性迁移任务,失败则停止
7 更新服务并等待有时限的健康检查
8 检查首页、资源、深层路由、API 与业务读写
9 成功后更新 current 和发布记录
10 失败时按兼容规则恢复上一镜像组合
验收:成功发布可追踪;失败构建不部署;镜像拉取失败保持原站;健康检查失败可回退;日志和备份不会耗尽磁盘。
13 配置与密钥管理
环境至少分为本地开发、ECS 私有预发布和生产。预发布与生产配置不得混用。
- 构建期公开配置:
SITE_URL、SITE_BASE、未来的PUBLIC_API_BASE和公开功能开关。修改后必须重新构建。 - API 运行配置:
NODE_ENV、PORT、数据库主机、数据库名、应用用户、日志级别和功能开关。 - 密钥:数据库密码、会话签名密钥、镜像仓库凭据、DNS API 凭据和备份加密密钥。
- 密钥不得通过客户端
PUBLIC_变量、Docker ARG、镜像层、命令行明文或代码文件传递。 - 推荐从受保护文件挂载 Compose secrets;源文件本身仍需正确的属主和权限。
.env.example只保留键名和无密钥示例,真实环境文件同时加入.gitignore与.dockerignore。- CI 只获得推送镜像所需权限;数据库与会话密钥保留在 ECS。日志不得打印完整连接串、Authorization、Cookie 或个人数据。
- 轮换顺序为创建新凭据、更新消费者并验证、撤销旧凭据、记录版本与时间。
14 安全 备份与容量
14.1 服务器
- SSH 使用密钥并限制来源;验证替代登录成功后再禁用不需要的密码和 root 登录。
- 公网只开放计划内的 80 与 443,API、PostgreSQL 和 staging 端口保持私有。
- 定期更新系统和容器基础镜像,记录变更并保留上一版本。
- 写接口上线前必须完成身份认证或匿名防滥用设计、授权、输入校验、速率限制和 CSRF 或 Origin 防护。
- Cookie 会话使用 HttpOnly、Secure 和适当的 SameSite;SQL 必须参数化。
14.2 容量
- 不在 ECS 上执行常规前端构建,避免 2 GB 内存被安装和打包任务耗尽。
- Docker 镜像、容器日志、数据库、备份和系统更新共同使用 40 GB 系统盘,达到 80% 前告警。
- 当前 3 Mbps 足以服务优化后的个人静态站,但多个访客会共享带宽。大型媒体出现前先测量,不预先购买 OSS/CDN。
- 若持续出现内存交换、OOM、数据库连接等待或后台任务竞争,升级到至少 2 核 4 GB。
14.3 PostgreSQL 备份
初始目标为 RPO 24 小时、RTO 2 小时,需由恢复演练验证。
- 每日使用匹配数据库版本的
pg_dump -Fc创建逻辑备份,发布前额外备份。 - 临时文件完成且命令退出码为零后,使用
pg_restore --list检查,再计算校验值、加密并上传异地存储。 - 建议保留每日 7 份、每周 4 份、每月 3 份,并为存储配置生命周期和删除保护。
- 至少每月向全新隔离数据库恢复,检查角色、迁移版本、代表性数据和读写。
- ECS 快照可以辅助灾难恢复,但不能替代验证过的数据库备份。
15 回滚与上线清单
15.1 切换前
- 备案通过,备案号和展示要求已经落实。
- 阶段 0 至 3 验收完成;当前生产版本可重建,Pages 独立静态回退已验证。
- 最终域名、
www、A、AAAA 和 TTL 已记录;两个域名都保留,不设置 AAAA。 - TLS 域名匹配、完整证书链、续期路径和失败处理已验证。
- 使用最终 Host 与 SNI 完成切流前检查。
- Compose 实际端口、IPv6、安全组和防火墙已核对。
- GitHub Pages 默认地址已验证,能够承担短期静态回退。
15.2 切换时
- 冻结发布并记录发布标识。
- 启用 production 配置,只为博客发布 80 与 443。
- 用
--resolve验证新 ECS,并确认两个 A 记录均指向 ECS。 - 用真实域名检查首页、文章、资源、404、RSS 和 sitemap。
- 验证 HTTPS、HTTP 跳转和双域名关系,不存在 Pages 路径前缀残留。
- 检查日志、5xx、容器状态、内存、磁盘和带宽。
15.3 切换后
- 观察 24 至 48 小时,记录异常和实际发布版本。
- 验证证书续期任务;到期告警留待阶段 7 自动监控。
- 保留 GitHub Pages 7 至 14 天,确认无需回退后再决定是否停止。
- 清理临时端口、测试凭据和不再需要的镜像。
- 更新搭建记录与运维手册。
静态入口故障时,有已验收的上一生产镜像则优先在 ECS 内回退;当前首次生产版本没有可用的上一生产镜像,应保留现场并使用已验证的 GitHub Pages 默认地址提供静态回退。未来引入数据库后,Pages 只能提供静态降级,不能形成第二套写入口。
16 完成定义
静态迁移完成:正式域名通过可信 HTTPS 稳定提供站点;主要页面、资源、404、RSS 和 sitemap 正常;公网边界正确;发布有记录且可以回退。
设计升级完成:页面保持可读、可访问和可降级,动效按页面加载,真实体积和浏览器回归满足项目约束。
动态能力完成:API 权限明确,PostgreSQL 可恢复,部署与 schema 兼容,故障不会破坏静态阅读入口。
“DNS 已修改”“容器正在运行”或“生成了备份文件”都不足以单独判定对应阶段完成。
17 技术参考
以下官方资料在执行相关阶段时应再次核对版本与规则:
- 阿里云 ICP 备案与 DNS 解析:https://www.alibabacloud.com/help/en/dns/icp-and-dns
- Astro 部署到 GitHub Pages:https://docs.astro.build/en/guides/deploy/github/
- Docker Compose 网络:https://docs.docker.com/compose/how-tos/networking/
- Docker 端口发布:https://docs.docker.com/engine/network/port-publishing/
- Nginx
proxy_pass:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass - Docker Compose secrets:https://docs.docker.com/reference/compose-file/secrets/
- Let’s Encrypt 验证方式:https://letsencrypt.org/docs/challenge-types/
- GitHub Actions 部署环境:https://docs.github.com/en/actions/concepts/workflows-and-actions/deployment-environments
- GitHub Actions 安全使用:https://docs.github.com/en/actions/reference/security/secure-use
- PostgreSQL 逻辑备份:https://www.postgresql.org/docs/current/backup-dump.html