$ cat post.md

服务器数据安全实战:3-2-1 备份策略与自动化方案

防入侵之外更要防丢失。基于 3-2-1 原则搭建自动化备份体系:本地定时打包、异地加密同步、定期恢复演练,含可直接使用的脚本。

前面的文章聊了怎么把服务器「防入侵」——SSH 加固、防火墙、fail2ban。但还有一类事故防火墙挡不住:误 rm -rf、磁盘暴毙、数据库写坏、勒索软件。这些场景的共同点是一旦发生,唯一能救你的只有备份。

这篇记录我在 Ubuntu Server 上搭建的自动化备份体系,核心是一条行业经验法则:3-2-1 原则。

3-2-1 原则

3 份数据副本 · 2 种不同介质 · 1 份保存在异地

拆开看就是三道防线:原始数据出故障 → 本地备份顶上;整台机器报废 → 异地备份顶上。缺任何一条,都只是在赌运气。

第一步:想清楚要备份什么

不要上来就全盘备份,又慢又占空间。按「重建成本」分类:

数据类型 例子 备份优先级
不可再生 数据库、用户上传、笔记、密钥 必须异地备份
重建昂贵 /etc 配置、Nginx 站点、crontab、Docker compose 文件 必须备份
可再生 系统本身、apt 装的软件、node_modules 不备份,重装即可

我的博客内容本身就是 git 仓库,GitHub 和 Cloudflare Pages 各存一份,天然满足 3-2-1——真正需要操心的只有服务器上的配置和运行数据。

第二步:本地定时备份

一个够用的小脚本,tar 打包 + 按日期命名 + 自动清理旧备份:

#!/bin/bash
# /opt/scripts/backup-local.sh
set -euo pipefail

BACKUP_DIR=/var/backups/daily
KEEP_DAYS=14
STAMP=$(date +%Y%m%d-%H%M%S)

mkdir -p "$BACKUP_DIR"

# 配置与站点文件
tar -czf "$BACKUP_DIR/etc-$STAMP.tar.gz" /etc /home/*/projects 2>/dev/null || true

# SQLite 数据库(用 .backup 命令,避免复制写入中的文件损坏)
sqlite3 /var/lib/myapp/data.db ".backup '$BACKUP_DIR/db-$STAMP.sqlite3'"

# 清理 14 天前的旧备份
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +$KEEP_DAYS -delete
find "$BACKUP_DIR" -name "*.sqlite3" -mtime +$KEEP_DAYS -delete

echo "[$(date)] backup done" >> /var/log/backup.log

挂上 cron,每天凌晨 3 点执行:

chmod +x /opt/scripts/backup-local.sh
sudo crontab -e
# 加入一行:
# 0 3 * * * /opt/scripts/backup-local.sh

⚠️ MySQL/PostgreSQL 请用 mysqldump --single-transaction / pg_dump,SQLite 用 .backup。直接 cp 正在写入的数据库文件,恢复时大概率是坏的——这是新手备份最大的坑。

第三步:异地加密同步

本地备份防误删,防不了整机报废或机房火灾。异地备份用 rclone,支持几乎所有对象存储(Cloudflare R2、Backblaze B2、AWS S3),还能客户端加密——数据离开服务器前就加密,云端存的是密文:

# 安装并配置(以 Cloudflare R2 为例)
curl https://rclone.org/install.sh | sudo bash
rclone config        # 交互式添加远端,假设命名为 r2:backup

# 先做一次完整同步验证
rclone sync /var/backups/daily r2:backup/daily --progress

然后在 cron 里追加一行,本地备份完成后自动上云:

30 3 * * * rclone sync /var/backups/daily r2-crypt:backup/daily >> /var/log/backup.log 2>&1

如果数据敏感,配置 rclone 的 crypt 类型远端(上面的 r2-crypt 即是叠加在 R2 之上的加密远端)做透明加密;或者先用 gpg -c 加密压缩包再同步。异地备份必须加密,否则等于把数据明文交给第三方。

💡 选 sync 还是 copy 要想清楚:sync 会让远端和本地完全一致(本地删了远端也删),如果本地备份被勒索软件加密,下一次 sync 会把坏文件同步上去。更稳妥的做法是云端开启版本控制/对象锁定(R2、B2 都支持),让历史版本不可被覆盖。

第四步:恢复演练——备份不算数,能恢复才算

备份界最扎心的真相:没恢复过的备份,约等于没有备份。每季度做一次演练:

# 1. 从云端拉回某天的备份到临时目录
rclone copy r2:backup/daily/etc-20260801-030000.tar.gz /tmp/restore-test/

# 2. 解压检查内容完整性
tar -tzf /tmp/restore-test/*.tar.gz | head

# 3. 数据库恢复到临时实例,抽查几张表
sqlite3 /tmp/restore-test/db-xxxx.sqlite3 "SELECT count(*) FROM posts;"

演练通过标准:文件能解开、数据库能查询、关键配置(如 nginx.conf)内容正确。

常见坑清单

  • 备份和生产在同一块硬盘 —— 盘坏了两个一起没;
  • 从不清理旧备份 —— 三个月后磁盘被备份塞满,业务先崩;
  • 备份脚本失败无人知晓 —— 给 cron 加 MAILTO 或用 healthchecks.io 这类「失联报警」服务,备份没按时上报就发告警;
  • 密钥没备份 —— 服务器 SSH 私钥、rclone 配置、加密口令,建议离线存一份在密码管理器里;
  • 权限乱放 —— /var/backups 应 chmod 700,备份文件里可是有 /etc/shadow 的。

小结

数据安全的核心不是某个工具,而是一组纪律:3-2-1 分层、自动化执行、异地加密、定期演练。四个脚本加起来不到五十行,却能让你面对任何硬件故障和误操作时,心里都有底。