配置指南
分享数据库不花钱-每天自动备份
Created: 02/10/2026
写在前面
如果你使用的数据库已经花钱开启使用了自动备份功能,那么可以忽略我这篇文章;
这篇文章主要解决咱们网站上线后,不花钱进行数据库自动备份的问题;用户数据很重要,很有必要每天备份一份,而且还不占用你本地空间。接下来跟我操作;
原理
这是PostgreSQL 数据库自动化备份方案(主要是面向Supabase、Neon数据库),通过 GitHub Actions 定时执行脚本,将备份文件自动提交到 Git 仓库中。
- 执行环境:利用 GitHub Actions 的云端环境,无需自备服务器。
- 备份工具:使用
pg_dump工具进行数据库导出。 - 定时触发:通过 GitHub Actions 的
schedule(cron)功能,每天定时运行。 - 文件存储:备份导出的
.sql文件按日期存储在backups/目录下,并自动 commit/push 回仓库。
实操
1、github新建一个私有仓库
2、将仓库弄到本地
(1)根目录下新建 config.json
配置项说明:
name: 数据库的标识名称,也将作为备份文件夹名。description: 项目描述,方便备注。url: PostgreSQL 的连接字符串(例如:postgresql://user:password@host:port/dbname)。tables: 可选。- 为
null时:执行全量备份。 - 为数组时(如
["users", "orders"]):仅备份指定的表。
- 为
示例 config.json:
{
"databases": [
{
"name": "xxx-app",
"description": "A网站数据库 - 全量备份",
"url": "postgresql://postgres:password@db-host:5432/postgres",
"tables": null
},
{
"name": "xxx-site",
"description": "B网站数据库 - 指定表备份",
"url": "postgresql://user:pass@host:5432/db",
"tables": ["posts", "categories"]
}
]
}
3、新建scripts/backup.sh(先新建scripts,再新建backup.sh)
将下面内容复制粘贴进去
#!/bin/bash
set -e
CONFIG_FILE="config.json"
BACKUP_DIR="backups"
DATE=$(date +%Y%m%d)
YEAR=$(date +%Y)
MONTH=$(date +%m)
# Cleanup logic: on the last day of the month, delete the previous month's backup directory
if [ "$(date -v+1d +%d)" = "01" ]; then
PREV_YEAR=$(date -v1d -v-1d +%Y)
PREV_MONTH=$(date -v1d -v-1d +%m)
echo "Last day of the month. Cleaning up backups for $PREV_YEAR-$PREV_MONTH..."
for DB_DIR in "$BACKUP_DIR"/*; do
if [ -d "$DB_DIR/$PREV_YEAR/$PREV_MONTH" ]; then
echo "Removing: $DB_DIR/$PREV_YEAR/$PREV_MONTH"
rm -rf "$DB_DIR/$PREV_YEAR/$PREV_MONTH"
fi
done
fi
if [ ! -f "$CONFIG_FILE" ]; then
echo "Error: config.json not found"
exit 1
fi
DB_COUNT=$(jq '.databases | length' $CONFIG_FILE)
echo "Found $DB_COUNT databases to backup"
for ((i=0; i<$DB_COUNT; i++)); do
DB_NAME=$(jq -r ".databases[$i].name" $CONFIG_FILE)
DB_DESC=$(jq -r ".databases[$i].description" $CONFIG_FILE)
DB_URL=$(jq -r ".databases[$i].url" $CONFIG_FILE)
TABLES=$(jq -r ".databases[$i].tables" $CONFIG_FILE)
echo "=========================================="
echo "Backing up: $DB_NAME ($DB_DESC)"
echo "=========================================="
if [ -z "$DB_URL" ] || [ "$DB_URL" == "null" ]; then
echo "Warning: No database URL found for $DB_NAME"
continue
fi
mkdir -p "$BACKUP_DIR/$DB_NAME/$YEAR/$MONTH"
BACKUP_FILE="$BACKUP_DIR/$DB_NAME/$YEAR/$MONTH/${DATE}.sql"
if [ "$TABLES" == "null" ]; then
echo "Mode: Full backup"
pg_dump "$DB_URL" \
--clean \
--if-exists \
--quote-all-identifiers \
--no-owner \
--no-privileges \
-f "$BACKUP_FILE"
else
TABLE_ARGS=""
TABLE_LIST=$(jq -r ".databases[$i].tables[]" $CONFIG_FILE)
for TABLE in $TABLE_LIST; do
TABLE_ARGS="$TABLE_ARGS -t public.$TABLE"
done
echo "Mode: Partial backup - tables: $TABLE_LIST"
pg_dump "$DB_URL" \
--clean \
--if-exists \
--quote-all-identifiers \
--no-owner \
--no-privileges \
$TABLE_ARGS \
-f "$BACKUP_FILE"
fi
echo "Backup saved: ${BACKUP_FILE}"
echo "Done: $DB_NAME"
echo ""
done
echo "All backups completed!"
4、GitHub Actions 设置
根目录下新建.github/workflows/backup.yml(先新建.github,再新建workflows,再新建backup.yml)
将下面内容复制粘贴进去
name: Daily Database Backup
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
permissions:
contents: write
jobs:
backup:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq
- name: Run backup script with PostgreSQL 17
run: |
chmod +x scripts/backup.sh
# 使用Docker运行PostgreSQL 17客户端
docker run --rm -v $(pwd):/workspace -w /workspace \
postgres:17 bash -c "apt-get update && apt-get install -y jq && ./scripts/backup.sh"
- name: Commit and push backups
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add backups/
git diff --staged --quiet || git commit -m "backup: $(date +%Y-%m-%d)"
git push
- 定时执行:默认设置在每天协调世界时 (UTC) 02:00(北京时间 10:00)运行。【这个时间可以改】
on: schedule: - cron: '0 2 * * *' - 手动触发:支持
workflow_dispatch,你可以在 GitHub 仓库的 Actions 标签页找到 "Daily Database Backup" 手动点击 "Run workflow" 立即执行。 - Postgres 版本:脚本默认使用
postgres:17镜像执行备份。
然后将其提交到仓库,然后第二天就开始执行了。
5、执行成功后,备份文件将按照以下结构生成:
backups/
└── {数据库名称}/
└── {年}/
└── {月}/
└── {年月日}.sql

6、安全建议 (重要)
- 私有仓库:务必将此仓库设为 Private(私有),因为
config.json中包含数据库的明文密码。