给我的博客服务器做一次异地备份:七牛云低频存储 + Restic
博客搭起来以后,人很容易有一种错觉:页面能打开,后台能登录,文章能正常发布,这件事就算结束了。
但我后来想了一下,其实不是。
博客本身重新搭一遍并不难。难的是里面那些慢慢积累出来的东西,比如文章、数据库、图片、配置文件、反向代理、Docker Compose、环境变量、定时任务。服务器如果哪天硬盘坏了,或者我手滑删错目录,再或者系统升级的时候出问题,这些东西不一定能靠“重新部署”找回来。
所以我最后还是决定给博客服务器做一个异地备份。
我这里选的是七牛云的低频存储,备份工具用 Restic,频率是一周一次。不是多高级的方案,但对个人博客来说已经够用了。
这篇文章主要是记录我自己的操作过程。以后如果服务器真出问题,我至少还能照着这篇文章把东西恢复回来。
为什么要做异地备份
很多人说备份,第一反应就是在服务器本地复制一份。
比如:
cp -r /www /backup/www
这种当然也算备份,但问题是它还在同一台机器上。
如果只是误删一个文件,本地备份有用。 但如果是硬盘坏了、服务器系统崩了、整台机器访问不了了,本地备份也一起没了。
所以我觉得比较稳的方式应该是:
- 服务器本地跑博客。
- 备份放到另外一个地方。
- 平时不用管它。
- 真出事的时候能拉回来恢复。
这就是我这次选择对象存储的原因。
为什么选七牛云低频存储
七牛云对象存储有不同类型,比如标准存储、低频存储、归档存储。
博客备份这种东西有个特点:平时基本不会下载,只有真的出问题的时候才会拿出来恢复。
所以标准存储有点浪费,归档存储又太麻烦。低频存储刚好在中间,适合这种“不经常访问,但又希望需要的时候能取回来”的数据。
不过低频存储也不是完全没有坑。
它一般会有最短存储时间,比如低频存储通常有 30 天最短保存时间。如果你上传以后很快删除,可能还是要按最低保存时间计费。
还有一个点是,低频存储在恢复下载的时候会有取回费用。也就是说,平时放在那里比较便宜,但你真要下载恢复的时候,会额外产生一点费用。
所以我的策略很简单:
- 一周备份一次。
- 不要天天删。
- 不要只保留一个备份。
- 保留最近几个月的备份就够了。
我最后设置的是保留最近 12 个每周备份,也就是差不多 3 个月。
为什么不用压缩包直接上传
一开始我想过最简单的方法:每周打一个压缩包,然后上传到七牛云。
比如:
tar -czf blog-backup.tar.gz /www /etc/nginx
这个方法确实简单,但我想了一下,后面会有几个麻烦。
第一,每次都是全量备份。 如果网站目录有 30GB,每周就要重新打包、重新上传 30GB。哪怕这一周只改了一篇文章,也得重新传一遍。
第二,版本不好管理。 时间久了以后,会有很多压缩包。哪个是好的,哪个包含数据库,哪个恢复过,自己都容易忘。
第三,加密要自己处理。 博客里面可能有数据库、配置文件、密钥、环境变量,如果只是普通压缩包,直接放到对象存储里,我总觉得不太放心。
第四,恢复体验一般。 真要恢复的时候,还得下载压缩包、解压、确认路径、手动覆盖。
后来我看了一下,七牛 Kodo 支持 S3 兼容接口,而 Restic 可以直接备份到 S3,所以最后就选了 Restic。
Restic 是什么
Restic 是一个备份工具。它不是单纯把文件打包上传,而是会把备份做成一个仓库。
它有几个优点:
- 支持增量备份。
- 支持去重。
- 默认加密。
- 可以查看历史快照。
- 可以恢复到指定时间点。
- 可以对接 S3 兼容对象存储。
简单说就是,第一次备份会上传比较多,后面每次只上传变化的部分。
比如我这周只改了几篇文章,Restic 不会傻傻地把整个博客重新上传一遍。它会识别变化,然后只上传需要上传的内容。
这对每周备份来说比较合适。
先确认自己要备份什么
备份之前,我觉得最重要的一步不是写命令,而是先想清楚:到底要备份哪些东西。
因为很多人一上来就想备份整个服务器根目录:
/
这个看起来最稳,其实不一定。
整个系统里有很多东西是不需要备份的,比如缓存、日志、临时文件、Docker 镜像层。这些东西体积很大,而且恢复的时候也不一定有用。
我真正关心的是这些:
/www
/var/www
/opt
/etc/nginx
/etc/systemd/system
不同人的服务器路径不一样,所以不能直接照抄。
如果你是用 1Panel 部署的博客,可能要重点看:
/opt/1panel
/opt/1panel/apps
/www
如果你是用 Docker Compose 部署的博客,要重点备份:
docker-compose.yml.env- 挂载出来的数据目录
- 数据库导出文件
如果你的博客有数据库,一定要单独导出数据库。 只备份网站文件,不备份数据库,恢复以后很可能只有程序,没有文章数据。
不建议备份的东西
下面这些目录,我一般不建议直接备份进去:
/var/log
/tmp
/var/tmp
/var/lib/docker/overlay2
node_modules
.cache
logs
原因也简单。
日志会一直增长,恢复博客的时候一般用不上。
临时目录没有必要备份。
node_modules 可以重新安装。
Docker 的 overlay2 很大,而且不适合直接复制恢复。
缓存目录备份了也只是浪费空间。
备份不是越多越好。 该备份的东西必须备份,不该备份的东西不要往里面塞。
安装 Restic
我的服务器是 Ubuntu,所以直接用 apt 安装:
sudo apt update
sudo apt install -y restic
装完以后看一下版本:
restic version
能看到版本号,就说明安装好了。
准备七牛云的信息
接下来需要准备七牛云的几个信息:
- Access Key
- Secret Key
- Bucket 名
- Region ID
Access Key 和 Secret Key 在七牛云后台可以看到。
Bucket 名就是你创建的对象存储空间名称。
Region ID 要看你的空间在哪个区域。比如华东、华南、华北、新加坡这些区域,对应的 Region ID 不一样。
Restic 连接七牛 Kodo 的 S3 地址格式大概是这样:
s3:s3.<Region-ID>.qiniucs.com/<bucket_name>
举个例子,如果你的 Region ID 是:
cn-east-1
Bucket 名是:
my-blog-backup
那仓库地址可以写成:
s3:s3.cn-east-1.qiniucs.com/my-blog-backup/blog-server
最后这个 blog-server 是我自己加的路径,用来区分这个 bucket 里面的不同备份内容。
如果你以后还想备份 NAS、照片、其他服务器,也可以在同一个 bucket 里分不同目录。
创建 Restic 配置文件
我不想每次命令都手动输入 AK、SK、仓库地址和密码,所以把这些东西单独放到一个配置文件里。
先创建目录:
sudo mkdir -p /etc/restic
然后创建配置文件:
sudo nano /etc/restic/blog.env
写入下面内容:
这里需要改成自己的:
- 你的七牛AccessKey
- 你的七牛SecretKey
cn-east-1- 你的bucket名
- 你自己设置一个很长的备份密码
RESTIC_PASSWORD 一定要保存好。
这个密码不是七牛云密码,而是 Restic 用来加密备份仓库的密码。以后恢复备份的时候也要用它。
如果这个密码丢了,就算七牛云里的文件还在,也恢复不出来。
保存以后,把配置文件权限收紧一点:
sudo chmod 600 /etc/restic/blog.env
这样普通用户就不能随便读取里面的密钥。
初始化备份仓库
第一次使用 Restic,需要初始化仓库。
执行:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" init'
如果成功,会看到类似这种提示:
created restic repository ...
如果这里报错,先不要继续往下做。一般要检查这几个地方:
- Access Key 有没有写错。
- Secret Key 有没有写错。
- Bucket 名有没有写错。
- Region ID 有没有写错。
- 服务器能不能访问七牛的 S3 接口。
这一步跑通以后,再继续。
先用小目录测试,不要直接备份正式数据
我建议先不要急着备份整个博客。
先拿一个小目录测试一下,确认上传和恢复都没问题。
创建测试目录:
mkdir -p /tmp/qiniu-test
echo "hello backup" > /tmp/qiniu-test/test.txt
备份这个小目录:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" backup /tmp/qiniu-test'
查看快照:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
如果能看到刚刚生成的快照,就说明备份已经传上去了。
接着测试恢复:
查看恢复出来的文件:
cat /tmp/qiniu-restore/tmp/qiniu-test/test.txt
如果能看到:
hello backup
说明备份和恢复都没问题。
这一步虽然看起来有点多余,但我觉得很重要。因为备份工具不是只要能上传就行,必须确认能恢复。
写正式备份脚本
测试没问题以后,就可以写正式的备份脚本了。
创建脚本:
sudo nano /usr/local/bin/backup-blog-to-qiniu.sh
写入下面内容:
保存以后,给脚本执行权限:
sudo chmod +x /usr/local/bin/backup-blog-to-qiniu.sh
这里有几个地方要根据自己的服务器改。
如果你没有 /var/www,可以删掉。
如果你没有 /www,也可以删掉。
如果你的博客数据在其他目录,就把对应目录加进去。
如果你的数据库在 Docker 里,要把数据库导出命令改成自己的容器名。
不要照抄路径以后就不管了。 备份脚本最重要的是符合自己的服务器实际情况。
第一次手动运行
脚本写好以后,先手动跑一次:
sudo /usr/local/bin/backup-blog-to-qiniu.sh
第一次会慢一点,因为它需要上传所有需要备份的数据。
执行完以后看日志:
tail -n 100 /var/log/blog-qiniu-backup.log
再看快照:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
如果能看到新的快照,就说明正式备份成功。
设置每周自动备份
我这里准备每周备份一次,比如每周一凌晨 4 点。
编辑 root 的定时任务:
sudo crontab -e
加入这一行:
0 4 * * 1 /usr/local/bin/backup-blog-to-qiniu.sh
这行的意思是:
每周一凌晨 4 点,执行备份脚本。
保存后查看一下:
sudo crontab -l
如果能看到刚才那行,就说明定时任务已经加好了。
还可以看一下服务器时区:
timedatectl
如果服务器时区不是自己想要的,可以改成韩国时间:
sudo timedatectl set-timezone Asia/Seoul
恢复备份的方法
备份只是第一步,恢复才是关键。
先查看有哪些快照:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
恢复最新备份到 /restore/blog:
如果要恢复指定快照,可以把 latest 换成快照 ID:
我不建议恢复的时候直接覆盖线上目录。
更稳的做法是先恢复到一个临时目录,比如:
/restore/blog
确认文件完整、数据库 dump 存在、配置没问题以后,再决定怎么覆盖回去。
如果有 MySQL 备份文件,恢复时可以类似这样:
mysql -u root -p < mysql-all.sql
如果 MySQL 在 Docker 容器里,可能是这样:
docker exec -i mysql容器名 mysql -u root -p数据库密码 < mysql-all.sql
具体命令要看自己的数据库环境。
关于费用
低频存储的费用主要不是“上传流量”,而是这几部分:
- 存储容量费用。
- 请求费用。
- 恢复时的数据取回费用。
- 下载到外网时的流出流量费用。
如果只是每周备份一次,平时不恢复,费用一般不会很夸张。
真正容易让费用变高的情况是:
- 把整个 Docker 目录都备份进去。
- 把日志、缓存、临时文件都备份进去。
- 备份里有大量图片、视频、附件。
- 频繁删除低频存储里的对象。
- 频繁从低频存储下载恢复。
所以我才没有选择“一周备份一次,然后只保留一个”。 低频存储不适合频繁删除,保留最近 12 个每周备份会更稳一点。
Restic 的保留命令是:
restic forget --keep-weekly 12 --prune
这代表保留最近 12 个每周备份。
如果以后博客数据越来越大,可以再调整策略,比如保留 8 周、12 周、24 周,具体看自己的数据量和预算。
我最后的备份思路
整理一下,我自己的备份思路大概是这样:
- 博客文件要备份。
- Nginx 配置要备份。
- Docker Compose 和环境变量要备份。
- 数据库要单独导出。
- 缓存、日志、node_modules 不备份。
- 每周自动跑一次。
- 保留最近 12 个每周快照。
- 隔一段时间手动恢复测试一次。
对个人博客来说,这个方案不算复杂,也不会太贵。
最重要的是,服务器真出问题的时候,自己不会完全没办法。
以前我总觉得备份是“以后再说”的事情。 但服务器这种东西,真正出问题的时候,一般不会提前通知你。
所以这次干脆把它补上。
博客可以慢慢写,服务器也可以慢慢折腾,但数据最好不要只放在一个地方。