用 restic 把 Linode 服务器上的重要目录每天加密备份到 Linode Object Storage(S3 兼容),自动保留 7 天、4 周、6 个月的快照,每次备份后抽查数据能否读回,并演示如何恢复单个文件。
先看清成品
成品是
backup.sh加一组 systemd 定时器。本文用 restic 0.19.1 对着本机的 S3 兼容服务(RustFS,代替 Linode Object Storage)实际运行了两次:第一次自动初始化仓库并备份,restic check显示no errors were found;第二次按保留策略清理;最后从最新快照恢复出修改后的note.txt,内容正确。本文没有 Linode 账号,没有连接真实的 Object Storage。
注意:Linode(现属 Akamai Cloud)按小时计费,关机也照常收费,不用的实例要删除才停止计费。官方价格页的例子是 1 GB 实例每小时 0.0075 美元,具体价格以下单页面为准。注册需要绑定信用卡。云服务器只用于合法用途,遵守 Akamai 的可接受使用政策和所在地法律。
注意:Object Storage 单独计费,具体计费方式以官方价格页为准。备份密码丢失后数据无法恢复,务必另外保存。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
| 加密备份 | restic 在本地加密后再上传 |
| 去重增量 | 只上传变化的数据 |
| 保留策略 | 7 日、4 周、6 月 |
| 自动校验 | 每次抽查 5% |
| 每日定时 | systemd timer,错过会补跑 |
需要准备哪些环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| 服务器 | Ubuntu 24.04 等 | 任何 Linux 都可以 |
| restic | apt install restic 或官方二进制 |
本文使用 0.19.1 |
| Object Storage | 已在 Cloud Manager 启用 | |
| 访问密钥 | 只给备份桶读写权限 |
第一步:怎样准备存储桶?
1. 创建桶和密钥
Cloud Manager → Object Storage → Create Bucket,名称例如 my-backups。然后在 Access Keys 里创建密钥,权限限定为这个桶的读写。
2. 找到 S3 端点
桶名下方显示的就是它的完整地址,端点部分形如 us-ord-10.linodeobjects.com。不同地区、不同端点类型的主机名不同,以 Cloud Manager 显示或下面的命令为准:
linode-cli object-storage endpoints
第二步:要准备哪些文件?
1. backup.env
# 复制为 /etc/restic/backup.env,权限 600
AWS_ACCESS_KEY_ID=你的访问密钥
AWS_SECRET_ACCESS_KEY=你的私密密钥
# 端点在 Cloud Manager 的存储桶详情里查看,下面是格式示例
RESTIC_REPOSITORY=s3:https://us-ord-10.linodeobjects.com/my-backups/server1
RESTIC_PASSWORD_FILE=/etc/restic/password
BACKUP_PATHS="/etc /home /var/lib/guestbook"
sudo mkdir -p /etc/restic
sudo cp backup.env.example /etc/restic/backup.env
openssl rand -base64 32 | sudo tee /etc/restic/password >/dev/null
sudo chmod 600 /etc/restic/*
把密码文件内容抄到密码管理器里。
2. backup.sh
#!/usr/bin/env bash
# restic 备份到 S3 兼容的对象存储,并按保留策略清理旧快照
set -euo pipefail
ENV_FILE=${ENV_FILE:-/etc/restic/backup.env}
set -a; source "$ENV_FILE"; set +a
# 仓库不存在时初始化(只在第一次执行)
if ! restic cat config >/dev/null 2>&1; then
echo "初始化仓库 $RESTIC_REPOSITORY"
restic init
fi
# shellcheck disable=SC2086 # BACKUP_PATHS 需要按空格拆分
restic backup $BACKUP_PATHS --tag auto --exclude-caches --exclude '*.tmp'
restic forget --tag auto --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
# 每次抽查 5% 的数据,确认能读回
restic check --read-data-subset=5%
echo "备份完成:$(date '+%F %T')"
| 要点 | 说明 |
|---|---|
restic cat config |
判断仓库是否已初始化 |
--tag auto |
只清理自动备份,手动备份不受影响 |
forget --prune |
删除过期快照并释放空间 |
--read-data-subset=5% |
定期真正读回部分数据 |
3. systemd 服务和定时器
[Unit]
Description=restic backup to Object Storage
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Nice=10
IOSchedulingClass=idle
[Unit]
Description=Daily restic backup
[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=15m
Persistent=true
[Install]
WantedBy=timers.target
Persistent=true 表示服务器在 3:30 关机时,开机后会补跑一次。
第三步:怎样运行和恢复?
1. 手动跑一次
sudo apt install restic
sudo install -m 755 backup.sh /usr/local/bin/backup.sh
sudo /usr/local/bin/backup.sh
本文第一次运行的末尾输出:
no errors were found
备份完成:2026-10-21 13:42:23
第二次运行:
snapshot 9af04a8c saved
Applying Policy: keep 7 daily, 4 weekly, 6 monthly snapshots
no errors were found
2. 启用定时器
sudo cp restic-backup.service restic-backup.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer
3. 查看快照
sudo bash -c 'set -a; . /etc/restic/backup.env; restic snapshots'
4. 恢复单个文件
sudo bash -c 'set -a; . /etc/restic/backup.env; restic restore latest --target /tmp/restore --include /etc/caddy/Caddyfile'
ls /tmp/restore/etc/caddy/
恢复到临时目录,确认无误后再手动复制回原位置。建议每季度演练一次。
出问题时该怎么调?
1. 看定时任务日志
journalctl -u restic-backup --no-pager | tail -40
2. 报 repository is already locked
上一次备份异常中断留下了锁。确认没有正在运行的 restic 进程后:
sudo bash -c 'set -a; . /etc/restic/backup.env; restic unlock'
3. 连接失败或 403
| 原因 | 解决方法 |
|---|---|
| 端点主机名不对 | 用 Cloud Manager 显示的端点 |
| 密钥没有该桶权限 | 重新创建密钥 |
仓库地址少了 s3: 前缀 |
格式是 s3:https://端点/桶/路径 |
常见问题怎么处理?
| 现象 | 原因 | 解决方法 |
|---|---|---|
wrong password |
密码文件不对 | 找回原密码,否则无法解密 |
| 备份很慢 | 第一次是全量 | 之后只传变化部分 |
| 空间没减少 | 只 forget 没 prune |
脚本已加 --prune |
| 数据库备份不一致 | 直接复制运行中的数据文件 | 先导出(如 pg_dump)再备份导出文件 |
| 想同时备份到别处 | 只有一个仓库 | 再建一个仓库,restic 支持多个后端 |
| 服务器被删备份还在吗 | 存在对象存储里 | 在,但要保存好 env 和密码 |
项目资源
建议先备份一个小目录跑通全流程,并立刻演练一次恢复。
确认能恢复后再加入真正重要的目录,把密码和 backup.env 存到服务器以外的安全位置。