云端部署

用 restic 把 Linode 服务器上的重要目录每天加密备份到 Linode Object Storage(S3 兼容)

用 restic 把 Linode 服务器上的重要目录每天加密备份到 Linode Object Storage(S3 兼容),自动保留 7 天、4 周、6 个月的快照,每次备份后抽查数据能否读回,并演示如何恢复单个文件。

BINBHO · 图文教程

用 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 和密码

项目资源

用途 地址
Object Storage 文档 https://techdocs.akamai.com/cloud-computing/docs/object-storage
端点类型和主机名 https://techdocs.akamai.com/cloud-computing/docs/endpoint-types
通过 URL 访问桶 https://techdocs.akamai.com/cloud-computing/docs/access-buckets-and-files-through-urls
restic 准备仓库(S3) https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html
restic 删除快照策略 https://restic.readthedocs.io/en/stable/060_forget.html
价格 https://www.linode.com/pricing/

建议先备份一个小目录跑通全流程,并立刻演练一次恢复。

确认能恢复后再加入真正重要的目录,把密码和 backup.env 存到服务器以外的安全位置。