用 restic 跟 Backblaze 自動備份
備份是一件一直在我的任務清單裡,但一直沒有做的事。雖然我一直覺得我沒有什麼重要的資料,但還是會有一種不安全感跟心虛感。但是從今以後就不一樣了,以後我就是一個可以在街上昂首闊步、資料都有備份的人了。
要備份的裝置有 homelab 跟筆電,而其中要備份的資料都滿清楚的。我的 homelab 上的 services 全部都是用 docker-compose 部署的,所以只需要備份 docker-compose.yaml
跟 volumes。我的筆電是 NixOS + Impermanence,只要沒有在 Nix config 裡宣告的資料會在重開機時清掉,而有宣告的資料則會儲存在 /persist
裡,所以我只要備份 /persist
就沒問題了。
備份的程式我選擇的是 restic,因為我的需求並不多,是增量式儲存跟有加密就好了。
雲端空間是用 Backblaze。主要是價格我覺得很不錯,尤其是考慮到有一些其他的雲端空間,上傳下載都還要另外收費。
雖然依照大家推薦的 best practice,3-2-1 Backup Strategy,我應該還要有一份備份放在本地。但我最近真的沒有很想要再設置一個 server,而且我覺得 off-site copy 是最重要的,所以這次我就只備份資料到雲端了。
Backblaze 設置
在 Backblaze 上要新增一個 bucket 做儲存空間跟一個 APP key 讓 restic 可以存取。
新增 bucket 的話,基本上點 create bucket 然後按確認就可以了。我自己是沒有啟用 Backblaze 的加密,因為 restic 自己就有,我就保持它預設的設定。
在 Backblaze 上新增 APP key 也很簡單,點左邊選單的 Application Keys,往下滑一點,點 Add a New Application Key,裡面的選項 Allow access to Bucket 選擇想要的 bucket 就可以了。新增完成後,會跑出這個,要記得保存好:
Success! Your new application key has been created. It will only appear here once.
keyID: <secret>
keyName: <name>
applicationKey: <secret>
restic 設置
開始正式用 restic 之前,要先初始化 repository。
restic 支援的後端很多,雖然它也有直接支援 Backblaze API,但 restic 自己是推薦使用 S3-compatible API 效果會比較好。所以這次我會用 S3 的方式來設置,使用的環境變數有這些:
export AWS_ACCESS_KEY_ID="<secret>"
export AWS_SECRET_ACCESS_KEY="<secret>"
export RESTIC_REPOSITORY="s3://<bucket-endpoint>/<bucket-name>"
export RESTIC_PASSWORD="<secret>"
其中 AWS_ACCESS_KEY_ID
就等於 Backblaze 的 KeyID
、AWS_SECRET_ACCESS_KEY
就等於 Backblaze 的 ApplicationKey
。而 bucket-endpoint
可以在 bucket 頁面找到:
然後跑這個指令:
restic init
備份 HomeLab
restic 的備份很簡單,跑 restic backup [data]...
就可以了,每次跑完後會創建一個新的 snapshot。
先手動跑第一次備份:
restic backup containers data
因為要上傳資料,所以會跑一段時間。跑完後,確認 snapshots 的狀況:
restic snapshots
# repository <hash> opened (version 2, compression level auto)
# ID Time Host Tags Paths Size
# -------------------------------------------------------------------------------------------
# 0263a086 2025-10-05 14:55:09 orangepi5plus /home/uima/containers 38.646 GiB
# /home/uima/data
# -------------------------------------------------------------------------------------------
# 1 snapshots
這樣就確定沒有問題了。
接下來就使用 cron 來自動運行備份。Script 長這樣:
BACKUP_BIN='/home/restic/bin/restic'
LOG_FILE='/var/log/restic-backup.log'
export AWS_ACCESS_KEY_ID='secret'
export AWS_SECRET_ACCESS_KEY='secret'
export RESTIC_REPOSITORY='secret'
export RESTIC_PASSWORD='secret'
"$BACKUP_BIN" backup \
--verbose \
--tag=auto \
/home/uima/containers /home/uima/data \
>> "$LOG_FILE" 2>&1
"$BACKUP_BIN" forget \
--verbose \
--tag auto \
--host="$(hostname)" \
--group-by=host,paths \
--prune \
--keep-last=10 \
--keep-daily=3 \
--keep-weekly=4 \
--keep-monthly=4 \
>> "$LOG_FILE" 2>&1
tail -n 1000 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE"
基本上就是跑備份(restic backup
)然後把舊的 snapshots 刪掉(restic forget --prune
)只保留 --keep-*
flag 指定的備份。有一點要注意的是,restic forget
只會把 snapshots 刪掉,但不會把資料從硬碟上移除,所以還要在跑 restic prune
或是使用 --prune
flag,才會真的把沒用的資料刪除。
Note
要記得設定有 APP key 的檔案的權限,像 chmod 700 the-script
,只有擁有檔案的人或 root 可以存取、執行。
然後新增 script 到 cron 上:
sudo crontab -e
0 */3 * * * flock -n /tmp/restic.lock /home/restic/bin/backup-to-b2
每三個小時會跑一次。flock
是為了防止上一次備份跑太久又開始執行下一次備份用的。
HomeLab 的備份就好了!
備份筆電
最後我的 NisOS config 長這樣:
services.restic.backups = {
remote = {
# repository is in the env file
paths = [
"/persist"
];
exclude = [
"src/*/target"
"src/*/.direnv"
"/persist/var"
];
environmentFile = "/persist/secrets/restic-remote-env";
passwordFile = "/persist/secrets/restic-password";
timerConfig = {
OnBootSec = "15min";
OnUnitActiveSec = "3hour";
Persistent = true;
};
extraBackupArgs = [
"--tag auto"
];
pruneOpts = [
"--tag auto"
"--host=${config.networking.hostName}"
"--group-by=host,paths"
"--keep-last 10"
"--keep-daily 7"
"--keep-weekly 4"
];
inhibitsSleep = true;
};
};
Rebuild 後就會自己運行 restic 備份了,跟 homelab 上的設置差不多。
Note
要記得設定有 APP key 的檔案的權限,像 chmod 600 /persist/secrets/restic-remote-env /persist/secrets/restic-password
,只有擁有檔案的人或 root 可以存取。
如果要手動觸發,可以用:
systemctl restart restic-backups-remote.service
BTW,因為 createWrapper
選項是預設啟用,所以還會多一個 restic-remote
wrapper script。這個 script 會幫你把環境變數設好,所以可以直接跑 restic-remote snapshots
等指令而不需要手動管理 API keys 等。我愛 NixOS。
讀資料
最後記錄一下怎麽讀資料。我有看到有兩種方式:
Restore
restic restore --target <target-dir> <snapshot-hash>
第一種是 restic restore
指令,運行上面的指令後會把所有在指定的 snapshot 裡的東西下載到 target 目錄裡。
如果只要下載其中一個目錄的話,可以用 <snapshot-hash>:<dir>
語法,像:
restic restore d2e8449d:/data/download --target /tmp
這樣就會把 download
目錄下載到 /tmp/download
。
也可以用 --include
flag 來指定一個檔案:
restic restore d2e8449d --include /data/download/abc.png --target /tmp
這個檔案會被載到 /tmp/data/download/abc.png
。
ps. 用 restic ls
可以列出 snapshot 裡的東西:
restic ls d2e8449d /data/download
Mount
另一個方式是用 restic mount
。這個會直接把整個 repository 掛載到一個目錄下:
mkdir /tmp/restic
restic mount /tmp/restic
# repository <repo-hash> opened (version 2, compression level auto)
# [0:00] 100.00% 7 / 7 index files loaded
# Now serving the repository at /tmp/restic
# Use another terminal or tool to browse the contents of this folder.
# When finished, quit with Ctrl-c here or umount the mountpoint.
之後就可以像普通目錄一樣瀏覽資料,掛載後的結構長這樣:
cd /tmp/restic
ls --tree --level=3
# .
# ├── hosts
# │ ├── orangepi5plus
# │ │ ├── 2025-10-06T12:00:01+08:00
# │ │ └── latest -> 2025-10-06T12:00:01+08:00
# │ └── uifw
# │ ├── 2025-10-06T10:42:45+08:00
# │ └── latest -> 2025-10-06T10:42:45+08:00
# ├── ids
# │ └── fc0e4e48
# │ └── home
# ├── snapshots
# │ ├── 2025-10-06T10:42:45+08:00
# │ │ └── persist
# │ ├── 2025-10-06T12:00:01+08:00
# │ │ └── home
# │ └── latest -> 2025-10-06T12:00:01+08:00
# └── tags
# └── auto
# ├── 2025-10-06T12:00:01+08:00
# └── latest -> 2025-10-06T12:00:01+08:00
總結
我的備份方案暫時就長這樣了。
我覺得設置起來沒有很麻煩,但還是要觀察一段時間看看備份的頻率之類的需不需要調整,或是如果要新增一份本地備份的話,一些沒那麼重要的資料也許不用傳到雲端上。
Anyway,備份用好了,感覺人都有底氣了。