Debian 使用 Restic 建立每日增量備份:從安裝、systemd Timer 到還原驗證
分類:Linux
在 Linux NAS 上,如果已經有一份本地資料,希望每天建立具有歷史版本、去重、壓縮與加密功能的增量備份,Restic 是一個相當適合的工具。
本文以 Debian 為例,從零開始建立:
/data
│
│ Restic Backup
▼
/backup/restic
最後完成:
每日自動備份
↓
保留 7 個 daily
保留 4 個 weekly
保留 12 個 monthly
↓
每月 repository check + prune
↓
實際 restore + checksum 驗證
排程使用 systemd timer,而不是 cron。
Restic 是什麼?
Restic 是一套支援 snapshot、deduplication、compression 與 encryption 的備份工具。
假設 /data 有:
/data
├── Documents
├── Photos
└── Videos
第一次執行:
restic backup /data
會建立第一個 snapshot。
隔天再次執行:
restic backup /data
如果大部分檔案都沒有改變,Restic 不會重新儲存所有相同資料。
每個 snapshot 在使用者看來仍然是一份完整備份,但 repository 底層會重複利用已經存在的資料。
因此:
Snapshot Day 1
Snapshot Day 2
Snapshot Day 3
並不代表磁碟空間變成:
資料量 × 3
實際增加的空間主要來自新增或修改過的資料。
環境
本文使用以下目錄:
Source:
/data
Repository:
/backup/restic
Password File:
/root/.config/restic/passwd
備份策略:
Daily 7
Weekly 4
Monthly 12
排程:
每天 03:00
↓
Backup + Forget
每月 1 日 04:00
↓
Check + Prune
安裝 Restic
Debian:
apt update
apt install -y restic
確認版本:
restic version
建立 Restic 密碼檔
Restic repository 預設會加密。
先建立設定目錄:
mkdir -p /root/.config/restic
chmod 700 /root/.config/restic
建立密碼檔:
vim /root/.config/restic/passwd
裡面只放一行密碼,例如:
your-very-strong-password
設定權限:
chmod 600 /root/.config/restic/passwd
這個密碼非常重要。
Restic repository 即使完整存在,如果遺失密碼,也無法解密還原資料。
因此密碼應該另外保存一份,而且不要只存在被備份的同一台機器。
建立 Repository
假設備份 repository 放在:
/backup/restic
先建立目錄:
mkdir -p /backup/restic
初始化:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
init
完成後可以測試:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
snapshots
如果 repository 剛建立,目前應該還沒有任何 snapshot。
第一次完整備份
來源資料:
/data
執行:
time restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
backup /data
第一次沒有 parent snapshot,因此 Restic 必須讀取全部檔案:
no parent snapshot found, will read all files
完成後會看到類似:
Files: xxxx new
Dirs: xxx new
Added to the repository: xxx GiB
processed xxxx files, xxx GiB
snapshot xxxxxxxx saved
第一次通常是最耗時間的一次,因為 Restic 必須進行:
讀取檔案
↓
Chunking
↓
Hash
↓
Compression
↓
Encryption
↓
寫入 Repository
測試增量備份
第一次完成後,如果資料沒有變更,立刻再執行完全相同的 command:
time restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
backup /data
這次應該會看到:
using parent snapshot xxxxxxxx
Files:
0 new
0 changed
xxxx unmodified
Added to the repository: 0 B
snapshot xxxxxxxx saved
這裡可以看到 Restic 增量備份的重要特性。
即使每次都建立一個新的完整 snapshot:
Day 1
Day 2
Day 3
沒有改變的資料並不會每次重新儲存一份。
設定 Snapshot Retention
如果每天備份一次,不可能永遠保留所有 snapshot。
本文使用:
Daily 7
Weekly 4
Monthly 12
也就是:
最近一週 → 每天一份
最近一個月 → 每週一份
過去一年 → 每月一份
Restic 使用 forget 管理 snapshot retention:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12
正式執行前,也可以先使用 --dry-run:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--dry-run
先確認 Restic 打算保留與移除哪些 snapshots。
建立每日 Backup Script
建立:
mkdir -p /root/bin
vim /root/bin/restic-backup.sh
完整內容:
#!/bin/bash
set -euo pipefail
SOURCE="/data"
RESTIC_REPOSITORY="/backup/restic"
RESTIC_PASSWORD_FILE="/root/.config/restic/passwd"
echo "=== Backup started: $(date) ==="
echo "=== Starting Restic backup ==="
restic \
-r "$RESTIC_REPOSITORY" \
--password-file "$RESTIC_PASSWORD_FILE" \
backup "$SOURCE"
echo "=== Restic backup completed ==="
echo "=== Applying Restic retention policy ==="
restic \
-r "$RESTIC_REPOSITORY" \
--password-file "$RESTIC_PASSWORD_FILE" \
forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12
echo "=== Restic retention completed ==="
echo "=== Backup finished: $(date) ==="
設定權限:
chmod 700 /root/bin/restic-backup.sh
其中:
set -euo pipefail
很重要。
如果 restic backup 發生錯誤,script 就會停止,不應該假裝後面的流程仍然正常完成。
先手動測試:
/root/bin/restic-backup.sh
確認沒有問題後,再交給 systemd。
建立 systemd Service
建立:
vim /etc/systemd/system/restic-backup.service
內容:
[Unit]
Description=Daily Restic Backup
RequiresMountsFor=/data /backup
[Service]
Type=oneshot
ExecStart=/root/bin/restic-backup.sh
Type=oneshot 表示 service 執行指定工作,完成後就結束。
因此備份完成後看到:
Active: inactive (dead)
是正常現象。
真正應該確認的是:
status=0/SUCCESS
建立每日 systemd Timer
建立:
vim /etc/systemd/system/restic-backup.timer
內容:
[Unit]
Description=Daily Restic Backup Timer
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
Unit=restic-backup.service
[Install]
WantedBy=timers.target
代表每天:
03:00
執行備份。
其中:
Persistent=true
很適合 NAS。
例如:
03:00 原本應該備份
↓
NAS 當時關機
↓
08:00 NAS 開機
timer 重新啟動後,可以補觸發停機期間錯過的 calendar 排程。
啟用 Backup Timer
重新載入 systemd:
systemctl daemon-reload
可以先檢查 unit:
systemd-analyze verify \
/etc/systemd/system/restic-backup.service \
/etc/systemd/system/restic-backup.timer
沒有問題後:
systemctl enable --now restic-backup.timer
查看 timer:
systemctl list-timers restic-backup.timer
例如:
NEXT LEFT UNIT
Tue 2026-09-29 03:00:00 6h restic-backup.timer
手動測試 systemd Backup
不需要等到凌晨 3 點,可以直接:
systemctl start restic-backup.service
查看:
systemctl status restic-backup.service
成功應該可以看到:
code=exited, status=0/SUCCESS
以及:
Finished restic-backup.service
查看完整 log:
journalctl -u restic-backup.service
查看最近 100 行:
journalctl -u restic-backup.service -n 100 --no-pager
即時追蹤:
journalctl -fu restic-backup.service
這也是 systemd timer 相較單純 cron 很方便的地方。
Forget 和 Prune 的差異
Restic 有兩個容易混淆的動作:
forget
prune
forget:
Snapshot
↓
依 retention policy
↓
移除不需要保留的 snapshot
prune:
Repository
↓
尋找已經沒有 snapshot 引用的資料
↓
整理並實際回收 repository 空間
因此不一定需要每天:
forget --prune
本文採用的方式是:
每天
restic backup
↓
restic forget
每月
restic check
↓
restic prune
把每日備份與較重的 repository maintenance 分開。
建立每月 Repository Maintenance
建立:
vim /etc/systemd/system/restic-maintenance.service
內容:
[Unit]
Description=Restic Repository Maintenance
RequiresMountsFor=/backup
[Service]
Type=oneshot
ExecStart=/usr/bin/restic -r /backup/restic --password-file /root/.config/restic/passwd check
ExecStart=/usr/bin/restic -r /backup/restic --password-file /root/.config/restic/passwd prune
執行順序:
restic check
↓
成功
↓
restic prune
如果第一個 command 失敗,service 會失敗,不應繼續執行後面的 prune。
建立 Maintenance Timer
建立:
vim /etc/systemd/system/restic-maintenance.timer
內容:
[Unit]
Description=Monthly Restic Repository Maintenance Timer
[Timer]
OnCalendar=*-*-01 04:00:00
Persistent=true
Unit=restic-maintenance.service
[Install]
WantedBy=timers.target
代表:
每月 1 日 04:00
執行 repository maintenance。
重新載入:
systemctl daemon-reload
檢查:
systemd-analyze verify \
/etc/systemd/system/restic-maintenance.service \
/etc/systemd/system/restic-maintenance.timer
啟用:
systemctl enable --now restic-maintenance.timer
現在可以一次查看兩個 timer:
systemctl list-timers \
restic-backup.timer \
restic-maintenance.timer
整體排程變成:
每天 03:00
restic-backup.timer
↓
restic-backup.service
↓
restic backup
↓
restic forget
每月 1 日 04:00
restic-maintenance.timer
↓
restic-maintenance.service
↓
restic check
↓
restic prune
驗證備份
備份 command 成功並不代表整個備份流程已經驗證完成。
真正重要的是:
能不能 Restore?
因此整套設定完成後,至少應該做一次實際還原測試。
查看 Snapshot
先查看目前有哪些 snapshot:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
snapshots
查看最新 snapshot 裡的內容:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
ls latest
假設選一個測試檔案:
/data/test.png
Restore 單一檔案
建立測試目錄:
mkdir -p /restore-test
從最新 snapshot 還原:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
restore latest \
--target /restore-test \
--include '/data/test.png'
Restic 會保留 snapshot 中的路徑,因此還原後可能是:
/restore-test/data/test.png
使用 SHA-256 驗證
原始檔:
sha256sum /data/test.png
還原檔:
sha256sum /restore-test/data/test.png
例如:
abcdef123456... /data/test.png
abcdef123456... /restore-test/data/test.png
兩個 SHA-256 完全一致,就表示還原後的檔案內容與原始資料一致。
也可以直接使用 cmp:
cmp \
/data/test.png \
/restore-test/data/test.png \
&& echo "RESTORE VERIFIED: files are identical"
成功會顯示:
RESTORE VERIFIED: files are identical
測試完成後刪除測試目錄:
rm -rf /restore-test
最終架構
完成後整套系統如下:
/data
│
│ restic backup
▼
/backup/restic
│
├── Daily × 7
├── Weekly × 4
└── Monthly × 12
每天 03:00
restic-backup.timer
│
▼
restic-backup.service
│
├── restic backup
└── restic forget
每月 1 日 04:00
restic-maintenance.timer
│
▼
restic-maintenance.service
│
├── restic check
└── restic prune
日常查看排程:
systemctl list-timers \
restic-backup.timer \
restic-maintenance.timer
查看最近備份結果:
systemctl status restic-backup.service
查看備份 log:
journalctl -u restic-backup.service -n 100 --no-pager
查看 snapshots:
restic -r /backup/restic \
--password-file /root/.config/restic/passwd \
snapshots
備註
Restic 的優點不只是「增量備份」。
它把幾個 NAS 備份很需要的功能整合在一起:
Snapshot
Deduplication
Compression
Encryption
Retention
Integrity Check
Restore
再配合 systemd timer,可以得到一套不需要額外 GUI、相對簡單而且容易維護的 Linux 備份架構。
最重要的是,整套備份建立完成後,不應該停在:
snapshot saved
而應該至少完成一次:
Backup
↓
Snapshot
↓
Restore
↓
SHA-256 / cmp
↓
VERIFIED
只有真正還原過的備份,才算完成了最基本的復原驗證。
最後還有一個不能忽略的原則:
Restic repository 和 repository password 不應該成為同一個故障點。
密碼應另外安全保存。
如果 /backup/restic 與 /data 位於同一台機器,這套架構主要提供的是版本、誤刪與資料損壞保護;若還需要防範整台 NAS、磁碟陣列或實體設備故障,則應再把備份 repository 複製到另一台設備或異地儲存。
這也是從「有備份」走向真正備份策略的下一步。