可靠性: 完善 R2 备份恢复与对象生命周期

This commit is contained in:
tamakyi
2026-11-05 08:41:55 +08:00
parent 3e7719f200
commit 937e688cfa
32 changed files with 4151 additions and 231 deletions
+56 -5
View File
@@ -32,7 +32,7 @@ ps -eo pid,lstart,cmd | grep '[t]amabox' # 看进程启动时间,与二进
```bash
./tamabox --help | sed -n '/COMMANDS/,/GLOBAL/p'
# web / censor / uid / ban / restore / reports / restrict / unrestrict / hide-public / honeypot
# web / censor / uid / ban / restore / reports / restrict / unrestrict / hide-public / honeypot / backup / restore-images
```
> 想确认某个字符串有没有编进二进制,**不要用 `strings`** —— 它默认只输出可打印 ASCII,
@@ -77,10 +77,13 @@ pg_dump -Fc <dbname> > before-$(date +%F-%H%M).dump
| `censor` | 重新审核历史内容 | 是 | 审核规则变更后复检 |
| `uid` | 为用户生成/补齐 uid | 是 | 数据修复 |
| `honeypot` | 扫描器诱捕取证(假登录页) | 部分是(`prune` / `purge-creds`) | 看谁在扫、拿到了什么字典 |
| `backup` | 备份 PostgreSQL 与配置 bucket 的全部 R2 对象 | 写本地备份目录 | 灾难恢复前留档 |
| `restore-images` | 校验并恢复 R2 图片及元数据 | 是(除 `--dry-run`) | 图片灾难恢复、隔离恢复演练 |
| `web` | 启动 Web 服务 | — | 生产入口 |
除 `reports`、`honeypot hits/stats/paths/size` 外,所有写操作都要求交互式输入大写 `YES` 确认;
除 `reports`、`honeypot hits/stats/paths/size` 外,既有运营写操作要求交互式输入大写 `YES` 确认;
脚本化时加 `--yes`。注意 `honeypot prune` / `purge-creds` 的确认词是 **`yes`**(小写)。
`restore-images` 不做交互确认:实际写入必须显式提供 `--yes`,`--dry-run` 除外。
---
@@ -329,7 +332,55 @@ pg_dump -Fc <dbname> > before-$(date +%F-%H%M).dump
---
## 8. 典型处置流程
## 8. `backup` / `restore-images` —— 数据库与 R2 图片
### 8.1 备份
```bash
# 数据库 + 配置 bucket 的全部对象
./tamabox backup --output /var/backups/tamabox
# 只备份对象,或只备份数据库
./tamabox backup --images-only --output /var/backups/tamabox
./tamabox backup --db-only --output /var/backups/tamabox
```
图片备份使用**空前缀**分页列举配置 bucket 的全部对象,不再只查 `tamabox/`。根日期 key、
`picture/`、`tamabox/` 和静态资源都会按原 key 保存到 `<output>/images/`。
备份会先完成全部分页 List、key 与本地路径预检,再开始下载;非法路径、目录 key、文件/目录碰撞会中止备份。
`images-manifest.json` 记录实际下载字节的 `size`、`sha256`,以及 GET 返回的 `etag`、
`content_type`、`cache_control`。对象与 manifest 都采用临时文件原子落盘;下载流中断会整对象重试,
最终失败不会留下 `.part`。空 bucket 的 manifest 是 `[]`。
### 8.2 恢复与隔离演练
```bash
# 校验全部本地文件并检查默认防覆盖,不写远端
./tamabox restore-images --input /var/backups/tamabox --dry-run
# 实际恢复到原 key;必须显式 --yes
./tamabox restore-images --input /var/backups/tamabox --yes
# 明确允许替换已存在对象
./tamabox restore-images --input /var/backups/tamabox --yes --overwrite
# 在原完整 key 前加隔离前缀,不覆盖生产 key
./tamabox restore-images --input /var/backups/tamabox --yes \
--target-prefix tamabox-backup-test/manual-restore/
```
`--input` 可指向备份目录,也可直接指向 `images-manifest.json`。恢复会在任何远端操作前校验全部
manifest 条目和本地文件(普通文件、非 symlink、大小、实际 SHA-256)。默认先 Head 目标;任一目标已存在
即失败且零 Put,只有 `--overwrite` 才允许替换。`--dry-run` 不写对象,实际写入必须 `--yes`。
`--target-prefix` 会加在 manifest 的完整 key 前;非空前缀末尾没有 `/` 时会自动补一个。
Put 保留内容、原 key 路径(额外添加指定前缀)、`ContentType` 与 `CacheControl`,并使用单对象超时和有限重试。
**恢复不是事务**:中途失败会明确报告已成功数量,已上传对象不会自动回滚。
---
## 9. 典型处置流程
1. **发现**:收到告警邮件(同一箱主 24h ≥ 8 条 或 7d ≥ 20 条)→ 或箱主后台出现「被举报 N 次」。
2. **取证**:`reports --domain <domain>` 看条目、占比、历史处置。
@@ -351,7 +402,7 @@ pg_dump -Fc <dbname> > before-$(date +%F-%H%M).dump
---
## 9. 排错
## 10. 排错
| 现象 | 原因 | 处理 |
|---|---|---|
@@ -374,7 +425,7 @@ pg_dump -Fc <dbname> > before-$(date +%F-%H%M).dump
---
## 10. 明确不做的事
## 11. 明确不做的事
- **不做自动处置**:举报数达标只发邮件,不自动封禁。这个场景里举报本身就是攻击武器。
- **不做申诉后台**:申诉走邮件,处置结果由 CLI 写入。