Files
termi-blog/deploy/docker/BACKUP_AND_RECOVERY.md
limitcool 7de4ddc3ee
All checks were successful
docker-images / build-and-push (admin, admin, termi-astro-admin, admin/Dockerfile) (push) Successful in 43s
docker-images / build-and-push (backend, backend, termi-astro-backend, backend/Dockerfile) (push) Successful in 25m9s
docker-images / build-and-push (frontend, frontend, termi-astro-frontend, frontend/Dockerfile) (push) Successful in 51s
feat: refresh content workflow and verification settings
2026-04-01 18:47:17 +08:00

3.9 KiB
Raw Blame History

备份与恢复说明

当前站点的内容已经是 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. 一键脚本

# 全量备份
./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

DATABASE_URL=postgres://... ./deploy/scripts/backup/restore-postgres.sh ./backups/postgres/latest.dump

恢复媒体

# 本地目录方式
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 示例

# 每天 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. 校验:
    • 首页可打开
    • 文章详情可打开
    • 图片可访问
    • 后台可登录
    • 审计 / 版本 / 订阅表存在数据

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

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