# 备份与恢复说明

当前站点的内容已经是 **DB-only**：

- PostgreSQL 数据库
  - 文章结构化字段
  - 文章 Markdown 原文（`posts.source_markdown`）
  - 分类 / 标签
  - 版本历史 / 审计日志 / 订阅数据
  - 站点配置
- 媒体文件 / 对象存储

因此生产上最重要的是：

1. **数据库备份**
2. **媒体资源备份**
3. 定期做恢复演练

> 不再需要单独备份 `backend/content/posts` 之类的本地 Markdown 目录。

## 1. 建议的最小备份策略

### PostgreSQL
- **频率**：每天至少 1 次；高频站点建议每 6~12 小时 1 次
- **工具**：`pg_dump --format=custom`
- **脚本**：`deploy/scripts/backup/backup-postgres.sh`
- **说明**：文章内容原文已经跟随数据库一起备份

### 媒体文件
- 如果是本地目录：打包归档
- 如果是 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

# 单独备份媒体（本地目录）
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
```

### 恢复媒体

```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: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. 用媒体备份恢复对象
3. 校验：
   - 首页可打开
   - 文章详情可打开
   - 图片可访问
   - 后台可登录
   - 审计 / 版本 / 订阅表存在数据

也可以直接用恢复演练脚本：

```bash
DATABASE_URL=postgres://... \
POSTGRES_BACKUP=./backups/postgres/latest.dump \
MEDIA_BACKUP=./backups/media/latest.tar.gz \
./deploy/scripts/backup/verify-restore.sh
```

## 7. 当前架构下的恢复优先级

发生事故时建议按这个顺序：

1. 恢复数据库
2. 恢复媒体资源
3. 启动 backend / frontend / admin
4. 进入后台检查：
   - 审计日志
   - 文章版本历史
   - 订阅目标与最近投递

## 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，而不是只靠手工执行。
