主题
09 — 决策记录
2026-11-08,用户授权"问题全部由我决定"后所做的全部决策。 记录做了什么、没做什么、为什么,便于日后复核或推翻。
一、执行了(已落地)
| # | 决策 | 理由 | 验证方式 |
|---|---|---|---|
| 1 | ✅ 关闭 SSH 密码登录 PasswordAuthentication no | 免密登录已稳定可用,密码认证是唯一可被爆破的入口。这是性价比最高的加固 | 密钥登录成功 + 密码登录被拒(Permission denied (publickey)) |
| 2 | ✅ 关闭 X11 转发 X11Forwarding no | 服务器无 X11,该功能仅扩大攻击面 | sshd -T 确认 |
| 3 | ✅ 安装 fail2ban 0.11.2 | ufw 只能被动拒绝,没有速率限制;fail2ban 主动封禁扫描源 | fail2ban-client status sshd 运行中 |
| 4 | ✅ 添加 2 GB Swap + vm.swappiness=10 | 1.7 GB 内存 0 Swap 是最大稳定性隐患;装 Docker 后更明显 | swapon --show + free -h |
| 5 | ✅ 启用 ufw(放行 22/80/443) | 主机层防火墙完全缺失 | ufw status active |
| 6 | ✅ DEFAULT_FORWARD_POLICY DROP→ACCEPT | 否则 Docker 容器无外网,故障隐蔽 | 容器内 wget 出网成功 |
| 7 | ✅ 安装 Docker + 清理失效镜像源 | 9 个源里 6 个已死,逐个重试会显著拖慢拉取 | docker pull 两种镜像均成功 |
| 8 | ✅ 按需代理(美国 Z01) 而非全局代理 | 全局代理会让 apt / 阿里云内网变慢,且 100.100.100.200 元数据可能异常 | 出口 IP 对比 + GitHub Raw 由 000→200 |
| 9 | ✅ 系统升级 18 个包 | 补齐安全补丁 | apt list --upgradable 仅剩 1 个 |
关键安全措施:改动 SSH 时的自动回滚保险
关闭密码登录是唯一可能导致失联的操作,因此采用了两阶段保护:
bash
# 1) 先挂 10 分钟后自动还原的 at 任务
echo "cp -a $BACKUP $DROPIN && systemctl reload sshd" | at now + 10 minutes
# 2) 应用变更并重载
# 3) 从外部验证密钥登录仍可用
# 4) 验证通过后才 atrm 取消回滚实际过程中触发过一次意外:脚本混入非 ASCII 字符导致 bash 引号解析失败, 配置已落盘但 sshd 未重载。通过
Permission denied (publickey,password)这一响应差异(正确应为只publickey)及时发现,随后重新加载并验证。 教训:远程 SSH 配置脚本必须纯 ASCII。
二、明确不做(附理由)
| # | 事项 | 决定 | 理由 |
|---|---|---|---|
| 1 | 升级 cloud-init(23.2.2 → 26.1) | ❌ 不做 | 被前人 apt-mark hold 刻意钉住;它是开机实例初始化关键组件,跨大版本跳变一旦出问题,需控制台 VNC 抢救。当前无人值守,风险不可控 |
| 2 | 升级 intel-microcode | ❌ 不动 | 同为 hold 状态;微码更新需重启,云实例微码由平台层管理 |
| 3 | 收窄阿里云安全组 22 端口 | ❌ 做不到 | 安全组规则在云控制台,服务器内部无权限操作。已列入交接待办 |
| 4 | 建立非 root 运维账号 | ❌ 不做 | 需交付初始密码给你本人;在无人确认的情况下新增登录入口反而增加风险 |
| 5 | 启用 Ubuntu Pro / ESM | ❌ 不做 | 需要绑定订阅 token,属账号级操作 |
| 6 | 系统大版本升级 22.04 → 24.04 | ❌ 不做 | 你只要求"升级系统"(打补丁),大版本升级是另一回事:需停机、可能破坏 cloud-init/网络配置,且当前配置低(1.7G)升级风险更高。如需请单独确认 |
| 7 | 停用 fwupd / snapd / multipathd 省内存 | ⏸ 暂缓 | 装上 2 GB Swap 后内存压力已缓解;停用系统服务属"优化"而非"修复",收益(约 200 MB)与潜在副作用不成比例。留作后续可选项 |
| 8 | 移除 lxd(snap) | ⏸ 暂缓 | 同上,当前无内存压力,不做无谓改动 |
| 9 | 把 apt / dockerd 也走代理 | ❌ 不做 | 阿里云内网镜像 0.09s(apt)、镜像加速器 0.2s(docker),走代理只会更慢。已刻意配置 NO_PROXY 排除 |
| 10 | 业务部署(TenoDX2) | ❌ 不做 | 技术栈未知(Node/Java/Python/静态?),无法替你决定架构 |
三、遗留风险与交接说明
🔴 需要你本人处理
| 项 | 动作 |
|---|---|
| 阿里云安全组 | 登录控制台,确认入方向只放行必要端口;建议把 22 收窄到你的固定 IP |
| 确认 VNC 可用 | 阿里云控制台 → 远程连接(VNC)。这是密钥失效时唯一的抢救通道,建议现在就打开确认一次 |
🟡 已知但可接受
| 项 | 说明 |
|---|---|
PermitRootLogin yes | 未改动。密码认证已关闭,现在只能凭密钥登录 root,风险已大幅降低。若要更严格可改 prohibit-password(效果相同,语义更清晰) |
| 1 个包仍可升级 | cloud-init,见上表决策 #1 |
| Swap 落在系统盘 | /swapfile 在 /(40 GB,用了 5.9 GB),空间充裕。生产环境若有数据盘可迁过去 |
| 阿里云 ToS | 代理仅作客户端出站,未对外提供服务;但仍属条款灰色地带,请自行评估 |
建议的下一步(按优先级)
- 确认 VNC 可登录 ← 最重要,5 分钟可完成
- 控制台收窄安全组
- 决定 TenoDX2 技术栈 → 我再规划部署方案(2C1.7G 跑 Java 偏紧,建议先评估)
- 可选:配置阿里云自动快照策略(比脚本备份可靠)
- 可选:停用 fwupd/snapd/multipathd 进一步省内存
四、本次所有系统变更的完整清单
| 类别 | 变更 |
|---|---|
| 防火墙 | ufw 启用;放行 22/80/443;FORWARD 策略改 ACCEPT |
| SSH | PasswordAuthentication no;X11Forwarding no(密钥免密 + 双向保活已于早些时候完成) |
| 入侵防护 | fail2ban 0.11.2,sshd jail,5 次/10 分钟 → 封 1 小时,白名单本机与运维 IP |
| 内存 | 新增 2 GB swapfile;vm.swappiness=10 |
| 补丁 | 升级 18 个包(cloud-init/intel-microcode 因 hold 保留) |
| 容器 | Docker 29.9.3 + Compose v5.7.0;daemon.json 镜像源 9→6(剔除 6 个失效源);日志轮转 50MB×3;live-restore |
| 网络 | ss-local(SOCKS5 :1080)+ privoxy(HTTP :8118);/usr/local/bin/px 助手 |
| 服务管理 | 停用 shadowsocks-libev.service、shadowsocks-libev-local@us01.service;自建 ss-local-us01.service |
未改动:cloud-init、intel-microcode、内核版本、系统大版本、SSH 端口、root 登录许可、阿里云 Agent(aegis/aliyun 均保留)。
六、第二轮决策(2026-11-08 04:20~04:22)
用户指示:「软件除非必应该使用 docker 运行」,然后安装 PostgreSQL。 因此本轮的核心决策是「如何把这条原则落地」。
| # | 决策 | 理由 |
|---|---|---|
| 1 | ✅ 立规 10-部署规范.md | 把"容器优先"写死成制度,而不只是一次性操作,避免以后又散装安装 |
| 2 | ✅ PostgreSQL 用容器,不用 apt | 遵循新规范。apt install postgresql 会装在宿主机、与容器版抢 5432 端口、且卸载残留多 |
| 3 | ✅ 选 postgres:18-alpine | 18 是当前稳定主版本;alpine 变体体积小、攻击面小。不用 :latest(锁版本才能回滚) |
| 4 | ✅ 数据用 named volume(tenodx-pgdata) | bind mount 需手工对齐容器内 uid(alpine 是 70),否则权限报错;named volume 由 docker 管理 uid,更稳。备份走 pg_dump 而非拷文件 |
| 5 | ⚠️ 卷挂载点用 /var/lib/postgresql | PG18 镜像把 PGDATA 改成了 /var/lib/postgresql/18/docker,声明卷是父目录。沿用老教程的 /var/lib/postgresql/data 会让数据落进匿名卷,重建容器即丢失 |
| 6 | ✅ 端口只绑 127.0.0.1:5432 | Docker 发布端口绕过 ufw,绑 0.0.0.0 就等于向公网开放数据库。已实测公网不可达 |
| 7 | ✅ 加 tenodx-net 共享网络 | 后续应用容器可用服务名 postgres 直连,不必走宿主机端口 |
| 8 | ✅ 加健康检查 + stop_grace_period: 60s | 健康检查用于判断就绪;60 秒优雅关闭避免 PostgreSQL 非干净关机导致损坏 |
| 9 | ✅ 加自动备份(每日 03:30,保留 7 天) | 数据库没有备份是不可接受的默认状态。用逻辑备份 pg_dump,并做 gzip -t 完整性校验 |
| 10 | ✅ effective_cache_size 调为 768MB | 默认 4GB 是按更大内存估算的,传给查询规划器的缓存信息偏乐观。仅改规划器提示,无风险,pg_reload_conf() 即时生效、无需重启 |
| 11 | ❌ 不调整 max_connections/shared_buffers | 默认 shared_buffers=128MB、max_connections=100 对 1.7 GB 机器已够用;动这两个需要重启且可能引入抖动,收益不明确 |
| 12 | ❌ 不装 pgAdmin / 不开远程 5432 | 管理走 docker exec 或 SSH 隧道即可,多开一个管理界面等于多一个攻击面 |
| 13 | ❌ 不装 postgresql-client 到宿主机 | 遵循规范;用 docker exec -it tenodx-postgres psql 即可,无需宿主客户端 |
本轮遗留
| 项 | 说明 |
|---|---|
| 数据库密码 | 存于 /opt/stacks/postgres/.env(600)。需要时自己 cat,未写入任何文档或日志 |
| 备份尚未异地化 | 当前只落本地 /var/backups/postgres。生产建议加阿里云 OSS 同步(需你提供凭证) |
| ✅ 2026-11-08 04:32 已完成,见第七节 |
七、第三轮决策(2026-11-08 04:30~04:35,用户睡眠中)
用户指示:「标记,我睡觉了,重要!!!,你自己决定事情」
关键判断:这个项目不需要 Web 服务
我先读了 项目总览.md 等文档,确认 TenoDX2 是一个嵌入式/桌面项目:
| 子工程 | 技术栈 | 需要服务器? |
|---|---|---|
PSoC Creator/ ×2 | C,CY8C4245 CapSense 固件 | ❌ 本地烧录 |
TenoDXController-H503/ | C,STM32H503 固件 | ❌ 本地烧录 |
TouchHost-kaede/ | Python 桌面上位机 | ❌ 本地运行 |
melonloader-mod/ | C#,MelonLoader 游戏 mod | ❌ 本地运行 |
touch_core/ | 共享判定核心(Python/C#/C) | ❌ 本地链接 |
文档里的"判定后端"指算法实现(DLL vs Python),
aime.mumur.net是外部游戏服务 —— 没有任何需要自建的服务端组件。
因此的决策
| # | 决策 | 理由 |
|---|---|---|
| 1 | ❌ 不部署 nginx 反向代理 | 没有 Web 应用可服务。装个空 nginx 只是多一个无用攻击面,违反最小化原则 |
| 2 | ✅ 做 PostgreSQL 备份恢复演练 | 备份"能打包"≠"能恢复"。这是数据库生命线,值得用这段时间验证清楚 |
| 3 | ✅ 验证 docker 守护进程重启韧性 | 等价验证 restart: unless-stopped 是否真生效,无需重启整机 |
| 4 | ❌ 不做整机重启测试 | 风险不对称:fstab 已验证 0 错误、服务全部 enabled,把握很大;但万一启动失败,无人值守 + VNC 未确认 → 长时间失联。宁可不做 |
| 5 | ✅ 提供 scripts/tunnel.ps1 | 安全组只开 22,SSH 隧道是当前唯一可用的服务访问路径 |
| 6 | ❌ 不碰安全组 | 无权限、无 AccessKey,且你已确认「不想弄 AccessKey」 |
| 7 | ✅ 补齐全部档案文档 | 你明确要求"标记",文档一致性是交接基础 |
为什么"不装 nginx"是正确决定
我原本计划装个占位 nginx,安全组一开就能用。读完项目文档后推翻了这个想法:
- 项目没有 Web 应用,nginx 无事可做
- 安全组当前根本不放行 80/443,装了也验证不了
- 装一个无人使用、无人维护的容器,几个月后会变成"这玩意儿为什么在这"的谜团
- 真需要时,起个 nginx 容器是 30 秒的事,
10-部署规范.md已写明做法
原则:不确定要不要的服务就不装。 少一个容器 = 少一份内存、少一个漏洞面、少一份困惑。
本轮遗留(需你本人处理,均非紧急)
| 项 | 优先级 | 说明 |
|---|---|---|
| 安全组放行 80/443 | 🔴 阻塞(但当前无 Web 需求,实际影响有限) | 步骤见 02-防火墙与端口.md 第 7 节 |
| 确认控制台 VNC | 🔴 建议 | 唯一救援通道 |
| 在场时做一次重启验证 | 🟡 中 | 见 07-变更记录.md 04:32 节说明 |
| 告知服务器实际用途 | 🟡 中 | 目前唯一容器是 PostgreSQL;若另有用途(下载站 / API / CI)告诉我再规划 |
八、当前健康状态(2026-11-08 04:35)
| 指标 | 值 |
|---|---|
| SSH 密钥登录 | ✅ 正常 |
| 密码登录 | ✅ 已禁用(拒绝) |
| 失败 systemd 单元 | 0 |
| 待处理 at 回滚任务 | 0 |
| 需重启 | 否 |
磁盘 / | 6.3 GB / 40 GB(17%,含 2 GB swapfile + 433 MB postgres 镜像) |
| 内存 | 389 MB / 1.7 GB 已用 |
| Swap | 2.0 GB,1 MB 已用 |
| 容器 | tenodx-postgres running + healthy(26 MB) |
| 数据库 | PostgreSQL 18.6,库 tenodx 可查 |
| 备份 | 每日 03:30 自动,恢复演练已通过 |
| 关键服务 | ssh / ufw / docker / ss-local-us01 / privoxy / fail2ban 全部 enabled + active |
| 代理出口 | 142.249.36.77(美国 洛杉矶) |
| Docker 镜像源 | 6 个,实测可用 |
| 公网暴露 | 仅 22/tcp(安全组只放 22 + ICMP) |
九、第四轮决策(2026-11-08 05:00~05:15,用户睡眠中)
用户指示:「使用docker安装NapCat,uptime,标记,我睡觉了,重要!!!,你自己决定事情」 追加要求:「uptime 应该及时追加新服务的检测,所有服务都应该被监测,由你来添加,加入到定期维护内」
决策
| # | 决策 | 理由 |
|---|---|---|
| 1 | ✅ NapCat 用 Docker 部署 | 遵循 10-部署规范.md |
| 2 | ⚠️ 接受 NapCat 以 privileged 运行 | 不是选择,是硬约束:镜像 entrypoint 用 mount --bind 伪造 procfs/DMI 让 QQ 认为在真机上,没有 CAP_SYS_ADMIN 就起不来。已记录为高权限风险 + 缓解措施,并建议后续迁到独立机器 |
| 3 | ✅ NapCat 端口只绑 127.0.0.1 | Docker 发布端口绕过 ufw;安全组本来也只开 22 |
| 4 | ❌ 不自动设置 NAPCAT_ACCOUNT | 不知道你的 QQ 号,且首次登录必须扫码;留空让它走二维码流程,由你本人完成 |
| 5 | ✅ Uptime Kuma 2.5.9(不是 1.23.x) | 2.x 有更完整的类型体系(postgres / push / port 等原生支持),且 2.5.9 是稳定版 |
| 6 | ✅ 监控做成"声明式"而不是点界面 | 你要求"由你来添加、纳入定期维护"。只有配置化的方案才是可维护的:monitors.json + 幂等 sync.sh |
| 7 | ✅ 新增服务必须同时加监控(写入 10-部署规范.md) | 把"装服务就要配监控"变成制度,否则一定会漏 |
| 8 | ✅ loopback-only 的宿主服务用 push 类型 | ss-local/privoxy 只绑 127.0.0.1,任何容器都连不到;宿主 cron 是唯一可行视角 |
| 9 | ✅ 加了栈配置备份 | 你自己没要求,但 kuma.db(监控配置)和 NapCat 配置(登录态)一旦丢失重建成本高,36 KB 换这份保险很值 |
| 10 | ❌ 不给 Uptime Kuma 挂 docker.sock | 挂上就能做容器级监控,但等于把宿主 root 交给它。当前用容器名 + HTTP 探测已够覆盖 |
| 11 | ⏸ OneBot 的两条监控先暂停 | 登录 QQ 前它本来就不会监听,红点只会造成噪音;文档写明登录后如何一键启用 |
本轮踩坑(都已记录进 11-应用服务.md 第 5 节)
- Uptime Kuma 2.x 有"选数据库"启动向导 → 用
UPTIME_KUMA_DB_TYPE=sqlite跳过 - 0 字节
kuma.db被误判为已有库 → 迁移不执行,必须删空文件 - TCP 类型名是
port不是tcp→ 否则Unknown Monitor Type - 容器内
127.0.0.1是自己 → 必须用容器名 - docker-proxy 让 TCP 监控假阳性 → 对发布端口要用 HTTP 类型
- push 的 msg 含空格会让推送静默失败(http 000)
需要你本人完成的
| 项 | 说明 |
|---|---|
| 🔴 QQ 扫码登录 | 开隧道 → http://127.0.0.1:16099/webui/ → 输入 token → 扫码 |
| 🟡 登录后启用 OneBot 监控 | 改 monitors.json 里 "active": false → true,跑 sync.sh |
| 🟡 确认 Uptime Kuma 面板可用 | 隧道 → http://127.0.0.1:13001,账号 admin |
| 🟡 评估 NapCat privileged 风险是否可接受 | 若不可接受,考虑迁到独立 VPS |
十、第五轮决策(2026-11-08 05:18~05:25,用户睡眠中)
用户指示:「安装Caddy,然后配置基本信息,标记,我睡觉了,重要!!!,你自己决定事情」
先纠正我自己上一轮的判断
第三轮我写过"不装 nginx,因为没有 Web 应用可服务"。这一轮情况变了:
- 现在有了 Uptime Kuma 和 NapCat 两个 Web 面板
- 用户明确要求装 Caddy
所以装 Caddy 是正确的,之前的结论是基于当时的事实,不是错的,但已过时。 (这条记下来是为了说明:决策要随事实更新,不要拿旧结论当教条。)
关键决策
| # | 决策 | 理由 |
|---|---|---|
| 1 | ✅ 用 Host 虚拟主机,不用路径式反代 | 实测确认两个应用都不支持子路径(Kuma 无 base-path 支持;NapCat 资源是绝对路径 /webui/assets/...)。路径式配法必然坏 |
| 2 | ✅ 锁版本 caddy:2.11.9-alpine | caddy:2-alpine 从镜像站拉到的是 v2.4.6(2021),缓存过期。且 basic_auth 指令 2.8+ 才有 |
| 3 | ✅ auto_https off | 无公网域名 + 安全组封 80/443,ACME 不可能成功。留好注释块,条件成熟一键切换 |
| 4 | ✅ 只绑 127.0.0.1:80 | 与现有全部服务一致;等安全组放开再改公网映射 |
| 5 | ✅ /healthz 不鉴权且放在 basic_auth 之前 | 否则监控拿到 401,会把健康服务误判为宕机 |
| 6 | ✅ basic_auth 哈希内联进 Caddyfile | 走 compose 环境变量会被 $ 插值破坏(已实际踩坑,恒 401)。bcrypt 哈希不可逆,放在 640 配置里可接受 |
| 7 | ✅ 保留直连通道(-Service uptime/napcat) | *.localhost 解析在部分环境不可靠,直连是永远可用的兜底 |
| 8 | ✅ 落地页用 JS 自适应隧道端口 | 硬编码端口会在换隧道端口时失效 |
| 9 | ❌ 不做 TLS / 不自签证书 | 没有域名时自签证书只会让浏览器报错,纯噪音。等真域名再开自动 HTTPS |
| 10 | ❌ 不给 Caddy 开 admin API(admin off) | 纯静态配置,不需要动态管理面,少一个攻击面 |
| 11 | ✅ Caddy 立即纳入监控 | 遵守我自己写进 10-部署规范.md 的"新增服务必须配监控" |
本轮踩坑
| 坑 | 现象 | 正解 |
|---|---|---|
compose $ 插值吃掉 bcrypt 哈希 | 带正确密码仍 401,日志 The "j6giqe3" variable is not set | 哈希内联进 Caddyfile(引号 heredoc + 占位符 + sed) |
-Service web,postgres 被拆成两个参数 | 无法将值"postgres"转换为 Int32 | 脚本内对逗号再拆一次,两种写法都支持 |
| 镜像站 tag 缓存过期 | caddy:2-alpine 是 2021 年的 v2.4.6 | 查 tag 列表,用具体版本 2.11.9-alpine |
需要你本人确认的
| 项 | 说明 |
|---|---|
🟡 浏览器能否解析 *.localhost | 能就直接用 http://kuma.localhost:13080/;不能就往 hosts 加一行,或用直连 |
| 🟡 Caddy basic auth 密码 | 在服务器 /opt/stacks/caddy/.env 的 CADDY_BASIC_PASSWORD |
| 🟡 是否需要我把 basic auth 去掉 | 目前是双层鉴权(隧道 + basic auth),嫌麻烦可关 |
十一、第六轮决策(2026-11-08 05:26~05:32,用户睡眠中)
用户指示:「选择一个资源管理器…之后可能要鉴权,你也可以自己写。确定好之后先把资源服务器的文档整理好。 然后写一个本地 hub,用于我的 h503 项目。hub 要 ui 现代化,轻量,左边列表… 资源服务器应该全部都是使用 api 访问,不需要有浏览器 ui 页面。所以你要给我一个上传接口,注意鉴权。」
选型:自己写,不用现成制品库
| 候选 | 否决理由 |
|---|---|
| MinIO | 自带 Web Console,与"API-only"直接冲突;常驻 ≥200 MB |
| Gitea Releases | 同样带 Web UI;为发固件引入整套 issue/PR 体系 |
| Nexus / Artifactory | Java 栈,500 MB 内存起步,2C1.7G 跑不动 |
| nginx/Caddy 静态目录 | 无版本元数据、无更新说明、无鉴权上传 |
关键决策
| # | 决策 | 理由 |
|---|---|---|
| 1 | ✅ 自建 FastAPI 服务 | 只做"发固件"一件事:版本 + 时间 + 更新说明 + SHA256 + 鉴权上传 |
| 2 | ✅ 元数据存进已有的 PostgreSQL(新库 tenodx_fw) | 让"每日 pg_dump 备份"和"数据库监控"自动覆盖新服务,不新增有状态组件 |
| 3 | ✅ 显式关闭 docs_url/redoc_url/openapi_url | 用户要求"不要浏览器 UI",连 API 文档页也一并关掉 |
| 4 | ✅ 版本号智能比较(1.10 > 1.9) | 按上传时间排序会让"补传旧版"变成最新版,是错的行为 |
| 5 | ✅ 上传边写边算 SHA256 + 临时文件原子 rename | 半途失败不留残缺文件;端到端完整性可校验 |
| 6 | ✅ 下载鉴权做成开关 FW_REQUIRE_DOWNLOAD_TOKEN | 用户说"之后可能要鉴权" —— 留开关而不是现在就锁死 |
| 7 | ✅ Hub 用标准库 http.server,不引 Web 框架 | 用户要求"轻量"。唯一第三方依赖 pyserial(现有 DFU 工具本来就需要),UI 单文件无构建 |
| 8 | ✅ Hub 刷写逻辑移植自 tools/h503_dfu_flasher | 不重写协议;Magic 0x84/0xA5 进 DFU → 等 0483:DF11 → STM32_Programmer_CLI |
| 9 | ✅ 控制器识别发 Magic light info,不按 COM 号猜 | Windows 换 USB 拓扑会重新分配 COM 号,按端口号会连错设备 |
| 10 | ❌ Hub 不内置 dfu-util 兜底 | 避免重复打包;找不到 CLI 时明确指向 h503_dfu_flasher |
| 11 | ✅ 两个新服务立即纳入监控 | 遵守自己写的 10-部署规范.md 第 8 条 |
本轮踩坑
| 坑 | 现象 | 正解 |
|---|---|---|
| 部署脚本长连接被重置 | 建库完成后 SSH 断,脚本停在 .env 之前 | 改用 systemd-run 后台单元 + 日志轮询 |
docker manifest inspect 对镜像站无效 | 全部报"不存在",误以为镜像没有 | 该命令走官方 registry;只有 docker pull 才走加速器 |
publish.ps1 用了 $args | PowerShell 保留自动变量,参数丢失 | 改名 $curlArgs |
端到端验证(关键证据)
隧道 18000→8000 → 上传 v1.0.0 (2048 B, sha256 b2a81706…)
→ Hub /api/versions 返回 ok/count=1 + 完整 changelog(含换行)
→ POST /api/update → 固件下载到 .cache/ (2048 B,SHA256 校验通过)
→ 刷写任务启动 → 因无硬件优雅报错「没有找到 TenoDX Debug 端口」
→ 轮询 /api/flash/status 正确反映 running=False ok=False
→ 错误 id → 400;非法 registry 协议 → 400除"物理刷入"这一步(需要真机)外,整条链路已实测跑通。
十二、第七轮决策(2026-11-08 05:33~05:40,用户睡眠中)
用户指示:「部署 VitePress,标记,我睡觉了,重要!!!,你自己决定事情」
关键决策
| # | 决策 | 理由 |
|---|---|---|
| 1 | ✅ 不把 VitePress 当常驻服务跑 | 它是静态生成器,运行时无事可做。常驻 Node 白吃 ~150 MB;构建进镜像后运行时只 39 MB |
| 2 | ✅ 多阶段镜像:node 构建 → caddy 静态托管 | 运行镜像只含产物 + Caddy,不含 node_modules |
| 3 | ✅ 容器内自带 Caddyfile,不用 caddy file-server 子命令 | 该子命令无法表达 try_files,而 VitePress 的 cleanUrls 必需 |
| 4 | ✅ 内容由 prepare.ps1 从仓库源文件装配,不手工编辑 src/ | 保持单一事实源;侧边栏自动生成,加文档不用改配置 |
| 5 | ✅ lastUpdated: false | 该功能需构建环境有 git + 完整 .git 历史;不为它把整个历史塞进镜像 |
| 6 | ✅ 站点独立 vhost docs.localhost,不做子路径 | 与前面一致:VitePress 资源默认根路径,子路径需额外 base 配置且易错 |
| 7 | ✅ 纳入监控 | 同前,第 12 项 |
本轮踩坑
| 坑 | 现象 | 正解 |
|---|---|---|
lastUpdated: true 让构建直接失败 | [vitepress] spawn git ENOENT | 关掉该特性 |
prepare.ps1 中文被 PS 5.1 按 ANSI 解析 | 语法崩溃(refresh.ps1 同款问题) | 脚本改纯 ASCII,中文标题运行时从 md 文件读 |
| 180 KB 单行 base64 走 SSH 管道 | base64: invalid input(被截断) | 二进制用 scp,不要 echo | ssh |
caddy file-server 无 try_files | cleanUrls 页面 404 | 容器内自带 Caddyfile |
待你确认
| 项 | 说明 |
|---|---|
| 🟡 站点内容范围 | 当前收录:项目总览 + docs/*.md(3) + server-info/*.md(14) + tools/*/README.md(4),共 24 页。要加/减告诉我 |
🟡 docs/PDF-psoc/ 参考资料 | 故意未收录(体积大、属只读参考)。需要的话可以加 |