沒有瀏覽器的機器要怎麼授權 Google Drive、保留策略為什麼用版次不用天數、量 repo 大小不能用 restic stats,以及只在失敗時通知的理由。
發布於 2026-09-06・約 6 分鐘
我把一台自架機器的資料備份到 Google Drive,用 restic 做加密與去重、rclone 當儲存後端。跑了一段時間,記一下設計上想過的取捨跟踩到的東西。
第一個卡住的地方。Google 的 OAuth 授權完成後會把你導回 http://127.0.0.1:53682/,那個位址必須是你按下同意的那台機器的 localhost。
http://127.0.0.1:53682/
伺服器上沒有瀏覽器,容器裡的 127.0.0.1 跟你桌機的 127.0.0.1 也不是同一個東西。所以授權沒辦法在目標機器上完成。
127.0.0.1
rclone 對這件事的官方作法是兩台機器分工:有瀏覽器的那台負責拿 token,沒瀏覽器的那台負責用 token。
在你自己的電腦上下載一份 rclone(用完就可以刪),先驗檔案沒被掉包:
$expected = "<官方 SHA256SUMS 上的值>" (Get-FileHash rclone.zip -Algorithm SHA256).Hash -eq $expected.ToUpper()
印出 False 就停手。這支程式等一下會拿到你 Google Drive 的存取權,值得多花三十秒。
False
然後:
.\rclone.exe authorize "drive"
瀏覽器會打開,選帳號按允許,回到終端機會印出一段 JSON:
Paste the following into your remote machine ---> {"access_token":"...","refresh_token":"...","expiry":"..."} <---End paste
把大括號那整段(含括號)複製起來,在伺服器上跑 rclone config,走到問 token 的那一步貼進去。之後 refresh token 會自己續期,這件事只做一次。
rclone config
那段 JSON 是完整的存取憑證,不要貼進聊天視窗、不要進 git、不要留在剪貼簿歷史裡。
set -euo pipefail export RESTIC_REPOSITORY="rclone:gdrive:homelab-restic" export RESTIC_PASSWORD_FILE="/root/.codeman/restic-password" restic backup \ --exclude-file="$EXCLUDES" \ --one-file-system \ --tag homelab \ /workspace /root/.claude /root/.codeman /backup-src
--one-file-system 避免跨掛載點爬進別的 volume 重複備份。在容器裡這條特別重要,因為掛載點很多。
--one-file-system
排除清單的判準是重建成本小於儲存成本:node_modules、建置產出、快取、日誌全部排掉。這些東西一行指令就能重建,備份它們只是在燒配額。
node_modules
[ -s "$RESTIC_PASSWORD_FILE" ] || die "找不到密碼檔" [ -f "$EXCLUDES" ] || die "找不到排除清單" command -v restic >/dev/null || die "restic 沒裝" command -v rclone >/dev/null || die "rclone 沒裝" # remote 名稱錯的話 restic 會拿到一個空 repo,然後「成功」備份進去 if [[ "$RESTIC_REPOSITORY" == rclone:* ]]; then remote="${RESTIC_REPOSITORY#rclone:}"; remote="${remote%%:*}" rclone listremotes | grep -qx "${remote}:" || die "rclone 沒有名為 '${remote}' 的 remote" fi
最後那條是重點。remote 名稱打錯的話,restic 不會報錯,它會建一個新的空 repo 然後成功地備份進去。你會有一份每天跑成功的備份紀錄,和一個還原不了任何東西的 repo。
restic forget --tag homelab --keep-last 30 --prune
--keep-last 30 是只留最近 30 個快照,不是 30 天。日備一次的話大約等於一個月的歷史深度。
--keep-last 30
這個區別在你手動多跑幾次備份的時候會咬人:跑了五次測試,歷史深度就從 30 天變成 25 天,而且沒有任何提示。要按天數留就用 --keep-daily 30。
--keep-daily 30
--prune 才會真的釋放空間。不加的話快照被移除了但資料塊還在,配額不會降。
--prune
Google Drive 免費是 15 GB,而且跟 Gmail 共用。爆掉的話收不到信比備份失敗更痛,所以要有警戒線。
但 restic stats 給的是去重前的邏輯大小,跟你在 Drive 上實際佔用的空間差很多。拿它來判斷會嚴重高估,然後你會為了一個不存在的問題去刪歷史。
restic stats
要問 rclone:
repo_bytes="$(rclone size "gdrive:homelab-restic" --json \ | grep -o '"bytes":[0-9]*' | head -1 | cut -d: -f2 || true)"
那個 || true 一定要留。set -e 之下命令替換失敗會直接中止整個腳本,備份都跑完了卻因為量不到大小而算失敗,很冤。量不到就跳過這次檢查,記一行 warning 就好。
|| true
set -e
超過警戒線只通知,不自動刪版次。 自動刪的話你會在完全沒注意到的那天失去歷史,而歷史正是備份的全部意義。真的滿了要嘛降 --keep-last、要嘛加排除規則,這兩個都該由人決定。
--keep-last
restic check --read-data-subset=5%
全量檢查太慢,而且會把 Drive 的流量拉滿。每次抽 5%,二十天就輪過一遍,對「repo 有沒有默默壞掉」這個問題來說夠了。
注意 restic check 失敗是警告不是致命錯誤,set -e 抓不到它。要另外檢查:
restic check
if grep -q "WARNING: restic check" "$LOG"; then notify "⚠️ 備份完成但完整性檢查有問題,請人工介入" fi
這是我覺得最容易做錯的一個決定。
成功也發通知的話,每天一則很快就會被當成雜訊忽略,等到真的失敗那天你也不會注意到。 這不是假設,是每個裝過監控的人都經歷過的事。
所以通知只在三種情況發出:備份失敗、完整性檢查有問題、超過大小警戒線。
但「沒有消息」有一個致命的歧義:備份正常,跟排程整個沒在跑,看起來一模一樣。
補法是讓它在每次跑完寫一筆時間戳,然後由別的東西看「上次跑完到現在多久」。我的門檻是 30 小時(日備一次,留一點餘裕)。超過就代表排程死了,而這件事本身會發通知。
一次性腳本沒辦法持續回報「我還活著」,所以健康度只能用這種「最後一次完成時間」的方式判斷。這個模式適用於所有 cron 型的工作。
沒試過還原的備份不算備份。
restic snapshots # 看有哪些版次 restic restore <snapshot-id> --target /tmp/restore-test --include /workspace/某個檔案
至少還原一個檔案,確認密碼檔是對的、repo 讀得到、內容正確。我建議把這件事寫進行事曆,每季做一次。
真的需要全量還原的那天,你不會想在那時候才第一次讀 restic 的文件。
標籤:restic、rclone、備份、Google Drive、Docker、自架服務