feat: refresh content workflow and verification settings
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

This commit is contained in:
2026-04-01 18:47:17 +08:00
parent f2c07df320
commit 7de4ddc3ee
66 changed files with 1455 additions and 2759 deletions

View File

@@ -204,10 +204,8 @@ Caddy -> frontend Node server
当前仓库内已经补了:
- `deploy/scripts/backup/backup-postgres.sh`
- `deploy/scripts/backup/backup-markdown.sh`
- `deploy/scripts/backup/backup-media.sh`
- `deploy/scripts/backup/restore-postgres.sh`
- `deploy/scripts/backup/restore-markdown.sh`
- `deploy/scripts/backup/restore-media.sh`
- `deploy/docker/BACKUP_AND_RECOVERY.md`

View File

@@ -1,13 +1,22 @@
# 备份与恢复说明
这套博客现在已经有
当前站点的内容已经是 **DB-only**
- PostgreSQL 数据库
- Markdown 原文内容
- 文章结构化字段
- 文章 Markdown 原文(`posts.source_markdown`
- 分类 / 标签
- 版本历史 / 审计日志 / 订阅数据
- 站点配置
- 媒体文件 / 对象存储
- 版本历史 / 审计日志 / 订阅数据
所以生产上最重要的不是再多一两个功能,而是**出事后能不能快速恢复**。
因此生产上最重要的是:
1. **数据库备份**
2. **媒体资源备份**
3. 定期做恢复演练
> 不再需要单独备份 `backend/content/posts` 之类的本地 Markdown 目录。
## 1. 建议的最小备份策略
@@ -15,11 +24,7 @@
- **频率**:每天至少 1 次;高频站点建议每 6~12 小时 1 次
- **工具**`pg_dump --format=custom`
- **脚本**`deploy/scripts/backup/backup-postgres.sh`
### Markdown 原文
- **频率**:每次发布后 + 每天定时 1 次
- **脚本**`deploy/scripts/backup/backup-markdown.sh`
- **原因**Markdown 是内容源,恢复速度最快
- **说明**:文章内容原文已经跟随数据库一起备份
### 媒体文件
- 如果是本地目录:打包归档
@@ -35,9 +40,6 @@
# 单独备份数据库
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
@@ -53,12 +55,6 @@ MEDIA_S3_SOURCE=s3://bucket-name ./deploy/scripts/backup/backup-media.sh
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
@@ -75,9 +71,6 @@ MEDIA_S3_TARGET=s3://bucket-name ./deploy/scripts/backup/restore-media.sh ./back
# 每天 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
@@ -88,7 +81,7 @@ MEDIA_S3_TARGET=s3://bucket-name ./deploy/scripts/backup/restore-media.sh ./back
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. 建议你们再加一层异地备份
## 5. 建议再加一层异地备份
仅仅把备份留在同一台服务器上不够。
@@ -101,9 +94,8 @@ MEDIA_S3_TARGET=s3://bucket-name ./deploy/scripts/backup/restore-media.sh ./back
建议每个月至少做 1 次演练:
1. 用最新数据库备份恢复到临时环境
2. Markdown 备份恢复内容目录
3. 用媒体备份恢复对象
4. 校验:
2.媒体备份恢复对象
3. 校验:
- 首页可打开
- 文章详情可打开
- 图片可访问
@@ -115,7 +107,6 @@ MEDIA_S3_TARGET=s3://bucket-name ./deploy/scripts/backup/restore-media.sh ./back
```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
```
@@ -125,17 +116,16 @@ MEDIA_BACKUP=./backups/media/latest.tar.gz \
发生事故时建议按这个顺序:
1. 恢复数据库
2. 恢复 Markdown 原文
3. 恢复媒体资源
4. 启动 backend / frontend / admin
5. 进入后台检查:
2. 恢复媒体资源
3. 启动 backend / frontend / admin
4. 进入后台检查:
- 审计日志
- 文章版本历史
- 订阅目标与最近投递
## 8. 说明
这些脚本是**仓库内参考实现**,没有在你们生产机上自动执行。
这些脚本是**仓库内参考实现**,没有在生产机上自动执行。
正式上线前请按你们实际目录、R2/S3 桶、数据库连接串、cron 规范再过一遍。
另外仓库里已经提供:

View File

@@ -4,7 +4,6 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"${SCRIPT_DIR}/backup-postgres.sh"
"${SCRIPT_DIR}/backup-markdown.sh"
"${SCRIPT_DIR}/backup-media.sh"
echo "All backup jobs finished successfully."

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SOURCE_DIR="${MARKDOWN_SOURCE_DIR:-./backend/content/posts}"
BACKUP_DIR="${BACKUP_DIR:-./backups/markdown}"
RETENTION_DAYS="${RETENTION_DAYS:-30}"
TIMESTAMP="$(date -u +%Y%m%dT%H%M%SZ)"
FILE_PATH="${BACKUP_DIR}/markdown-${TIMESTAMP}.tar.gz"
if [[ ! -d "${SOURCE_DIR}" ]]; then
echo "Markdown source directory not found: ${SOURCE_DIR}" >&2
exit 1
fi
mkdir -p "${BACKUP_DIR}"
tar -czf "${FILE_PATH}" -C "${SOURCE_DIR}" .
ln -sfn "$(basename "${FILE_PATH}")" "${BACKUP_DIR}/latest.tar.gz"
find "${BACKUP_DIR}" -type f -name 'markdown-*.tar.gz' -mtime +"${RETENTION_DAYS}" -delete
echo "Markdown backup written to ${FILE_PATH}"

View File

@@ -3,7 +3,6 @@ set -euo pipefail
BACKUP_ROOT="${BACKUP_ROOT:-./backups}"
POSTGRES_RETENTION_DAYS="${POSTGRES_RETENTION_DAYS:-14}"
MARKDOWN_RETENTION_DAYS="${MARKDOWN_RETENTION_DAYS:-30}"
MEDIA_RETENTION_DAYS="${MEDIA_RETENTION_DAYS:-14}"
DRY_RUN="${DRY_RUN:-false}"
@@ -42,7 +41,6 @@ prune_dirs() {
}
prune "${BACKUP_ROOT}/postgres" 'postgres-*.dump' "${POSTGRES_RETENTION_DAYS}"
prune "${BACKUP_ROOT}/markdown" 'markdown-*.tar.gz' "${MARKDOWN_RETENTION_DAYS}"
prune "${BACKUP_ROOT}/media" 'media-*.tar.gz' "${MEDIA_RETENTION_DAYS}"
prune_dirs "${BACKUP_ROOT}/media" 'media-*' "${MEDIA_RETENTION_DAYS}"

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <backup-file.tar.gz>" >&2
exit 1
fi
TARGET_DIR="${MARKDOWN_TARGET_DIR:-./backend/content/posts}"
BACKUP_FILE="$1"
if [[ ! -f "${BACKUP_FILE}" ]]; then
echo "Backup file not found: ${BACKUP_FILE}" >&2
exit 1
fi
mkdir -p "${TARGET_DIR}"
rm -rf "${TARGET_DIR}"/*
tar -xzf "${BACKUP_FILE}" -C "${TARGET_DIR}"
echo "Markdown restore completed into ${TARGET_DIR}"

View File

@@ -3,15 +3,12 @@ set -euo pipefail
: "${DATABASE_URL:?DATABASE_URL is required}"
: "${POSTGRES_BACKUP:?POSTGRES_BACKUP is required}"
: "${MARKDOWN_BACKUP:?MARKDOWN_BACKUP is required}"
: "${MEDIA_BACKUP:?MEDIA_BACKUP is required}"
POSTGRES_RESTORE_CMD="${POSTGRES_RESTORE_CMD:-./deploy/scripts/backup/restore-postgres.sh}"
MARKDOWN_RESTORE_CMD="${MARKDOWN_RESTORE_CMD:-./deploy/scripts/backup/restore-markdown.sh}"
MEDIA_RESTORE_CMD="${MEDIA_RESTORE_CMD:-./deploy/scripts/backup/restore-media.sh}"
"${POSTGRES_RESTORE_CMD}" "${POSTGRES_BACKUP}"
"${MARKDOWN_RESTORE_CMD}" "${MARKDOWN_BACKUP}"
"${MEDIA_RESTORE_CMD}" "${MEDIA_BACKUP}"
echo "Restore rehearsal completed. Please verify homepage, article detail, media assets, admin login, revisions, audit logs, and subscriptions manually."