149 lines
4.4 KiB
Markdown
149 lines
4.4 KiB
Markdown
# 备份与恢复说明
|
||
|
||
这套博客现在已经有:
|
||
|
||
- PostgreSQL 数据库
|
||
- Markdown 原文内容
|
||
- 媒体文件 / 对象存储
|
||
- 版本历史 / 审计日志 / 订阅数据
|
||
|
||
所以生产上最重要的不是再多一两个功能,而是**出事后能不能快速恢复**。
|
||
|
||
## 1. 建议的最小备份策略
|
||
|
||
### PostgreSQL
|
||
- **频率**:每天至少 1 次;高频站点建议每 6~12 小时 1 次
|
||
- **工具**:`pg_dump --format=custom`
|
||
- **脚本**:`deploy/scripts/backup/backup-postgres.sh`
|
||
|
||
### Markdown 原文
|
||
- **频率**:每次发布后 + 每天定时 1 次
|
||
- **脚本**:`deploy/scripts/backup/backup-markdown.sh`
|
||
- **原因**:Markdown 是内容源,恢复速度最快
|
||
|
||
### 媒体文件
|
||
- 如果是本地目录:打包归档
|
||
- 如果是 R2 / S3 / MinIO:定时 `aws s3 sync`
|
||
- **脚本**:`deploy/scripts/backup/backup-media.sh`
|
||
|
||
## 2. 一键脚本
|
||
|
||
```bash
|
||
# 全量备份
|
||
./deploy/scripts/backup/backup-all.sh
|
||
|
||
# 单独备份数据库
|
||
DATABASE_URL=postgres://... ./deploy/scripts/backup/backup-postgres.sh
|
||
|
||
# 单独备份 Markdown
|
||
MARKDOWN_SOURCE_DIR=./backend/content/posts ./deploy/scripts/backup/backup-markdown.sh
|
||
|
||
# 单独备份媒体(本地目录)
|
||
MEDIA_SOURCE_DIR=./uploads ./deploy/scripts/backup/backup-media.sh
|
||
|
||
# 单独备份媒体(R2 / S3)
|
||
MEDIA_S3_SOURCE=s3://bucket-name ./deploy/scripts/backup/backup-media.sh
|
||
```
|
||
|
||
## 3. 恢复步骤
|
||
|
||
### 恢复 PostgreSQL
|
||
|
||
```bash
|
||
DATABASE_URL=postgres://... ./deploy/scripts/backup/restore-postgres.sh ./backups/postgres/latest.dump
|
||
```
|
||
|
||
### 恢复 Markdown
|
||
|
||
```bash
|
||
MARKDOWN_TARGET_DIR=./backend/content/posts ./deploy/scripts/backup/restore-markdown.sh ./backups/markdown/latest.tar.gz
|
||
```
|
||
|
||
### 恢复媒体
|
||
|
||
```bash
|
||
# 本地目录方式
|
||
MEDIA_TARGET_DIR=./uploads ./deploy/scripts/backup/restore-media.sh ./backups/media/latest.tar.gz
|
||
|
||
# R2 / S3 方式
|
||
MEDIA_S3_TARGET=s3://bucket-name ./deploy/scripts/backup/restore-media.sh ./backups/media/media-20260331T120000Z
|
||
```
|
||
|
||
## 4. 推荐的生产 Cron 示例
|
||
|
||
```cron
|
||
# 每天 03:10 备份 PostgreSQL
|
||
10 3 * * * cd /opt/termi-astro && DATABASE_URL=postgres://... ./deploy/scripts/backup/backup-postgres.sh >> /var/log/termi-backup.log 2>&1
|
||
|
||
# 每天 03:25 备份 Markdown
|
||
25 3 * * * cd /opt/termi-astro && MARKDOWN_SOURCE_DIR=./backend/content/posts ./deploy/scripts/backup/backup-markdown.sh >> /var/log/termi-backup.log 2>&1
|
||
|
||
# 每天 03:40 备份媒体
|
||
40 3 * * * cd /opt/termi-astro && MEDIA_S3_SOURCE=s3://bucket-name ./deploy/scripts/backup/backup-media.sh >> /var/log/termi-backup.log 2>&1
|
||
|
||
# 每天 04:15 清理过期备份
|
||
15 4 * * * cd /opt/termi-astro && ./deploy/scripts/backup/prune-backups.sh >> /var/log/termi-backup.log 2>&1
|
||
|
||
# 每天 04:40 异地同步
|
||
40 4 * * * cd /opt/termi-astro && OFFSITE_TARGET=/mnt/offsite/termi-astro-backups ./deploy/scripts/backup/sync-backups-offsite.sh >> /var/log/termi-backup.log 2>&1
|
||
```
|
||
|
||
## 5. 建议你们再加一层异地备份
|
||
|
||
仅仅把备份留在同一台服务器上不够。
|
||
|
||
至少保证:
|
||
- 主机本地保留最近 7~14 天
|
||
- 再同步一份到另一块存储 / 另一台主机 / 对象存储冷备桶
|
||
|
||
## 6. 恢复演练建议
|
||
|
||
建议每个月至少做 1 次演练:
|
||
|
||
1. 用最新数据库备份恢复到临时环境
|
||
2. 用 Markdown 备份恢复内容目录
|
||
3. 用媒体备份恢复对象
|
||
4. 校验:
|
||
- 首页可打开
|
||
- 文章详情可打开
|
||
- 图片可访问
|
||
- 后台可登录
|
||
- 审计 / 版本 / 订阅表存在数据
|
||
|
||
也可以直接用恢复演练脚本:
|
||
|
||
```bash
|
||
DATABASE_URL=postgres://... \
|
||
POSTGRES_BACKUP=./backups/postgres/latest.dump \
|
||
MARKDOWN_BACKUP=./backups/markdown/latest.tar.gz \
|
||
MEDIA_BACKUP=./backups/media/latest.tar.gz \
|
||
./deploy/scripts/backup/verify-restore.sh
|
||
```
|
||
|
||
## 7. 当前架构下的恢复优先级
|
||
|
||
发生事故时建议按这个顺序:
|
||
|
||
1. 恢复数据库
|
||
2. 恢复 Markdown 原文
|
||
3. 恢复媒体资源
|
||
4. 启动 backend / frontend / admin
|
||
5. 进入后台检查:
|
||
- 审计日志
|
||
- 文章版本历史
|
||
- 订阅目标与最近投递
|
||
|
||
## 8. 说明
|
||
|
||
这些脚本是**仓库内参考实现**,没有在你们生产机上自动执行。
|
||
正式上线前请按你们实际目录、R2/S3 桶、数据库连接串、cron 规范再过一遍。
|
||
|
||
另外仓库里已经提供:
|
||
|
||
- `deploy/systemd/README.md`
|
||
- `deploy/systemd/termi-backup-all.timer`
|
||
- `deploy/systemd/termi-backup-prune.timer`
|
||
- `deploy/systemd/termi-backup-offsite-sync.timer`
|
||
|
||
如果宿主机使用 systemd,建议优先启用 timer,而不是只靠手工执行。
|