>

适用场景:NAS 里已经有家庭照片、视频、文档、Docker 配置,只有一份数据 = 裸奔
> 策略:3-2-1 原则(3 份副本、2 种介质、1 份异地)
> 工具链:Restic(去重、加密、增量、快照)+ rclone(对接 S3 / 另一台 NAS / 网盘)+ systemd timer(定时自动跑)


0. 为什么选 Restic?

特性Resticrsync / tar网盘同步盘
去重✅ 块级去重,增量极小❌ 全量或文件级❌ 文件级
加密✅ AES-256 + ChaCha20-Poly1305,密码只在你手里❌ 需额外加密⚠️ 厂商可读
快照✅ 每次备份都是完整快照,任意时间点恢复❌ 需手动管理⚠️ 版本历史有限
存储后端✅ 本地 / SFTP / S3 / B2 / rclone 任意后端❌ 仅本地/远程文件系统❌ 绑定厂商
校验✅ restic check 全量校验完整性❌ 手动校验⚠️ 依赖厂商

1. 一次性初始化(只做一次)

1.1 安装

# Debian/Ubuntu
sudo apt update && sudo apt install -y restic rclone
# 或下载最新静态二进制
# https://github.com/restic/restic/releases
# https://rclone.org/downloads/

1.2 准备仓库密码(生成强密码,存入密码管理器)

# 生成 32 字符随机密码
openssl rand -base64 32 | tr -d '\n' > ~/restic-repo-password.txt
chmod 600 ~/restic-repo-password.txt
# 内容示例:K7x9mP2qR4vL8nJ1hG5fD3sA6zX9cV2b

1.3 初始化本地仓库(作为第 1、2 份副本:NAS 本地 + 外接硬盘)

export RESTIC_PASSWORD_FILE=~/restic-repo-password.txt
export RESTIC_REPOSITORY=/data/backup/restic-repo   # 本地 ZFS 数据集 / 单独分区
restic init

1.4 初始化远程仓库(第 3 份异地副本:S3 兼容 / 另一台 NAS / 网盘)

>

rclone 支持 40+ 后端,这里以 S3 兼容(MinIO / AWS S3 / Cloudflare R2 / Backblaze B2 / 阿里云 OSS / 腾讯云 COS)为例,其它后端同理。

# 1) 配置 rclone 远程端
rclone config
# 名称:remote-s3
# 类型:s3
# provider:选对应厂商(MinIO / AWS / Cloudflare / Other)
# env_auth:false
# access_key_id / secret_access_key:填你的 AK/SK
# region / endpoint:按厂商填
# acl / storage_class:默认

# 2) 测试连通性
rclone lsd remote-s3:

# 3) 初始化远程仓库(同一密码、同一仓库 ID,方便同步)
export RESTIC_PASSWORD_FILE=~/restic-repo-password.txt
export RESTIC_REPOSITORY=rclone:remote-s3:restic-repo
restic init
>

关键点:本地和远程用同一个密码、同一个仓库 ID,后续 restic backup 到本地,rclone sync 远程仓库目录即可,保持两地仓库一致。


2. 备份内容清单(按重要性分级)

# /data/backup/include.txt  (只备份这些,排除其它)
/data/media          # 媒体库(Jellyfin 管理,但原始文件要备份)
/data/config         # 所有容器配置(NPM 证书、Jellyfin 元数据、HA 配置、qBittorrent 种子等)
/data/downloads      # 下载完成待整理(可选,视容量)
/etc                 # 系统级配置(nginx、ssh、fstab、systemd 单元)
/root                # root 家目录(脚本、密钥)
/home                # 普通用户家目录
# 排除缓存、临时、大文件重复
# /data/backup/exclude.txt
**/cache/**
**/tmp/**
**/.Trash-*/
**/node_modules/**
**/__pycache__/**
*.tmp
*.log
*.iso
*.qcow2
*.vmdk

3. 备份脚本(放 /usr/local/bin/backup-nas.sh,chmod +x)

#!/usr/bin/env bash
set -euo pipefail

# === 配置区 ===
export RESTIC_PASSWORD_FILE="/root/restic-repo-password.txt"
LOCAL_REPO="/data/backup/restic-repo"
REMOTE_REPO="rclone:remote-s3:restic-repo"
INCLUDE_FILE="/data/backup/include.txt"
EXCLUDE_FILE="/data/backup/exclude.txt"
LOG_FILE="/var/log/restic-backup.log"
RETENTION_KEEP="--keep-last 30 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3"
# === END ===

exec >>"$LOG_FILE" 2>&1
echo "===== $(date -Is) 备份开始 ====="

# 1. 本地备份(快、去重、加密)
echo ">>> 本地仓库备份..."
restic -r "$LOCAL_REPO" backup \
    --files-from "$INCLUDE_FILE" \
    --exclude-file "$EXCLUDE_FILE" \
    --one-file-system \
    --compression max

# 2. 忘记旧快照、清理未引用数据
echo ">>> 本地清理旧快照..."
restic -r "$LOCAL_REPO" forget $RETENTION_KEEP --prune

# 3. 同步仓库到远程(rclone 只同步变化的 pack 文件,极快)
echo ">>> 同步到远程仓库..."
rclone sync "$LOCAL_REPO" "$REMOTE_REPO" \
    --progress \
    --transfers 4 \
    --checkers 8 \
    --retries 3 \
    --low-level-retries 10

# 4. 远程也做一次 forget/prune(保持策略一致)
echo ">>> 远程清理旧快照..."
restic -r "$REMOTE_REPO" forget $RETENTION_KEEP --prune

# 5. 完整性校验(每周做一次,避免每天跑太久)
if [[ $(date +%u) -eq 7 ]]; then   # 周日
    echo ">>> 本地完整性校验..."
    restic -r "$LOCAL_REPO" check --read-data-subset=5%
    echo ">>> 远程完整性校验..."
    restic -r "$REMOTE_REPO" check --read-data-subset=5%
fi

echo "===== $(date -Is) 备份结束 ====="

4. systemd 定时器(每天凌晨 02:30 自动跑)

# /etc/systemd/system/backup-nas.service
[Unit]
Description=NAS Restic Backup
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-nas.sh
# 可选:失败发邮件/Telegram
# OnFailure=backup-failed-notify.service

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/backup-nas.timer
[Unit]
Description=Daily NAS Backup Timer

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=15m

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup-nas.timer
systemctl list-timers --all | grep backup-nas

5. 常用恢复操作(灾难演练建议每季度跑一次)

export RESTIC_PASSWORD_FILE=~/restic-repo-password.txt
export RESTIC_REPOSITORY=/data/backup/restic-repo   # 或远程仓库

# 1. 列出所有快照
restic snapshots

# 2. 浏览某个快照的文件树
restic ls latest --path /data/config/jellyfin

# 3. 恢复单个文件/目录到指定位置
restic restore latest --target /tmp/restore --include /data/config/jellyfin/config.yaml

# 4. 恢复整个快照(灾难恢复)
restic restore latest --target /mnt/recovery-root

# 5. 挂载仓库只读(按需拷贝文件)
mkdir /mnt/restic-mount
restic mount /mnt/restic-mount
# ls /mnt/restic-mount/hosts/nas-ip/...
fusermount -u /mnt/restic-mount

6. 监控 & 告警(别让备份“静默失败”)

6.1 简单版:备份日志尾行推送到 Telegram

# 在 backup-nas.sh 末尾加:
curl -s -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
    -d chat_id=<CHAT_ID> \
    -d text="✅ NAS 备份完成 $(date '+%F %T')"

6.2 进阶版:Prometheus + Grafana(已有监控栈)

# restic 支持 --json 输出,配合 node_exporter textfile collector
restic -r "$LOCAL_REPO" snapshots --json > /var/lib/node_exporter/textfile_collector/restic_snapshots.prom
# 指标示例:restic_snapshots_total、restic_last_backup_timestamp、restic_repo_size_bytes

7. 容量规划参考(按经验值)

数据类型去重后增量/天年增量估算建议保留
家庭照片/视频(原始)50 MB - 500 MB200 GB - 1 TB永久(全量快照)
Docker 配置 / 系统配置< 1 MB< 500 MB全部保留
下载目录(临时)变动大视情况只保留最近 7 天
数据库 dump(如 HA SQLite)10-50 MB5-20 GB按策略保留
>

省钱技巧:Cloudflare R2 / Backblaze B2 无出站流量费,适合做异地仓库;MinIO 自建在另一台 NAS 上则零成本。


8. 一键部署清单(复制粘贴即可)

# 1. 安装工具
sudo apt install -y restic rclone

# 2. 生成密码、初始化本地/远程仓库(按上文 1.2-1.4)

# 3. 写 include/exclude 文件
sudo mkdir -p /data/backup
cat > /data/backup/include.txt <<'EOF'
/data/media
/data/config
/data/downloads
/etc
/root
/home
EOF
cat > /data/backup/exclude.txt <<'EOF'
**/cache/**
**/tmp/**
**/.Trash-*/
**/node_modules/**
**/__pycache__/**
*.tmp
*.log
*.iso
*.qcow2
*.vmdk
EOF

# 4. 部署备份脚本 + systemd timer(上文 3-4 节)

# 5. 手动跑一次验证
sudo /usr/local/bin/backup-nas.sh
tail -30 /var/log/restic-backup.log

# 6. 做一次恢复演练
restic -r /data/backup/restic-repo restore latest --target /tmp/test-restore --include /data/config/npm
ls -la /tmp/test-restore/data/config/npm/

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。