幫助中心

伺服器、網路和帳戶的分步教程。

Linux 伺服器

用 restic 和 rclone 實現 VPS 自動加密備份(每日異地備份並驗證恢復)

用 restic 和 rclone 實現 VPS 自動加密備份(每日異地備份並驗證恢復)

Linux VPS 最穩妥的備份方式是:每天用 restic 把加密快照傳送到伺服器之外的儲存,設定清晰的保留策略,並定期測試恢復。本文在 Debian 12/13、Ubuntu 22.04/24.04 和 Rocky Linux / AlmaLinux 上完成整套配置:安裝 restic、選擇異地倉庫(S3 相容儲存、SFTP 或 rclone)、匯出資料庫、用 systemd 定時器自動執行,並驗證資料確實能恢復。

為什麼備份必須放在 VPS 之外

放在同一臺伺服器上的副本不算備份:任何刪除伺服器的操作都會把副本一起刪掉。在 JUSTG 雲伺服器上,以下幾種正常操作都會永久刪除資料:

  • 更換機房(Change location):系統會新裝一臺 VPS,分配新 IP,不復制任何資料。新 VPS 就緒後,舊 VPS 及其全部資料會被刪除。
  • 逾期未續費:未付款的服務會在到期日自動暫停;到期 7 天后帳單仍未支付,服務會被取消,資料隨之刪除。
  • 重灌系統會清空硬碟;選擇 Immediate 方式取消服務,請求處理後服務和資料會立即刪除。

再加上誤敲的 rm -rf、失敗的升級或伺服器被入侵,結論很簡單:唯一可靠的備份,是你自己做、並存放在別處的備份。在更換機房、重灌系統或取消服務之前,請先手動執行一次備份,並確認新快照已經生成。

restic 在 VPS 本機完成加密後才上傳,儲存服務商只能看到加密後的資料塊。它還會去重:首次完整上傳之後,每天的快照只傳送有變化的部分。

步驟 1:安裝 restic

Debian 12/13、Ubuntu 24.04 和 EPEL 自帶的版本已經足夠新:

# Debian 12/13, Ubuntu 24.04
apt update && apt install -y restic
restic version

# Rocky Linux / AlmaLinux 8, 9 (from EPEL)
dnf install -y epel-release && dnf install -y restic

Ubuntu 22.04 自帶的是 restic 0.12,不支援壓縮,也無法使用當前的倉庫格式。在這個系統上,請安裝官方二進位制檔案並校驗 checksum:

# Official static binary (Ubuntu 22.04 or any distro with an old restic)
VER=0.18.1   # check https://github.com/restic/restic/releases for the latest version
cd /tmp
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/restic_${VER}_linux_amd64.bz2
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS      # must print: OK
bunzip2 restic_${VER}_linux_amd64.bz2
install -m 0755 restic_${VER}_linux_amd64 /usr/local/bin/restic
restic version

步驟 2:選擇異地倉庫

倉庫就是存放加密快照的地方。任選一種方案,儲存為 /etc/restic/env(每行一個 NAME=value)。

方案 A:S3 相容物件儲存

任何提供 S3 API 的服務商都可以。建立一個儲存桶和只限該儲存桶的訪問金鑰,並在 URL 中填寫服務商的 endpoint:

# /etc/restic/env  (S3-compatible object storage)
RESTIC_REPOSITORY=s3:https://s3.example.com/example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=REPLACE_WITH_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET_KEY
# Optional: monitoring ping URL (Step 11)
HC_PING_URL=

方案 B:透過 SFTP 備份到另一臺伺服器

使用你自己的另一臺伺服器,最好位於不同機房或不同服務商,並建立專用的 backup 使用者,由它擁有 /srv/restic:

# /etc/restic/env  (SFTP to a second server)
RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
HC_PING_URL=

# One-time SSH key login for root on the VPS
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519   # skip if the key exists
ssh-copy-id [email protected]
ssh [email protected] true      # accept the host key once

方案 C:rclone 後端

rclone 能讓 restic 連線幾十種儲存服務(Backblaze B2、Google Drive、OneDrive、WebDAV 等):

# Install and configure rclone (interactive wizard, run as root)
apt install -y rclone        # Rocky/Alma: dnf install -y rclone (EPEL)
rclone config                # create a remote, for example named "offsite"

# /etc/restic/env  (any rclone backend)
RESTIC_REPOSITORY=rclone:offsite:example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
RCLONE_CONFIG=/root/.config/rclone/rclone.conf
HC_PING_URL=
/etc/restic/env 裡的憑據通常也有刪除備份的許可權,攻擊者一旦控制 VPS,就可能清空倉庫。想要更強的保護,可以為儲存桶開啟版本控制或 object lock,或使用只能追加寫入的目標,並且不要把儲存帳號的登入密碼放在伺服器上。

步驟 3:建立密碼檔案並初始化倉庫

install -d -m 0700 /etc/restic
openssl rand -base64 32 > /etc/restic/password
chmod 600 /etc/restic/password
nano /etc/restic/env          # paste one of the examples above
chmod 600 /etc/restic/env

# Load the settings into the current shell and create the repository
set -a; . /etc/restic/env; set +a
restic init
沒有密碼,任何人都無法解密備份,包括你自己。請立即把 /etc/restic/password 和 /etc/restic/env 複製到密碼管理器或伺服器以外的安全位置:VPS 一旦不在了,恢復只需要這兩個檔案。

步驟 4:確定備份哪些內容、排除哪些內容

只備份配置和資料,不必備份整個作業系統:重灌系統比恢復系統檔案更快,快照也更小。

# /etc/restic/include  - one path per line; delete lines that do not exist
/etc
/root
/home
/srv
/var/www
/opt
/usr/local
/var/spool/cron
/var/backups/db

# /etc/restic/excludes
/root/.cache
/home/*/.cache
**/node_modules
**/*.tmp
/var/www/*/cache
  • 需要備份:/etc、使用者主目錄、網站根目錄、應用資料、crontab 以及資料庫匯出目錄。
  • 無需備份:/proc、/sys、/dev、/run、/tmp、swap 檔案和各類快取。它們不在列表裡,restic 根本不會讀取。
  • 資料庫原始檔案(/var/lib/mysql、/var/lib/postgresql)在資料庫執行時直接複製,可能得到不一致的副本。請備份匯出檔案(步驟 5)。
  • Docker:不要整體備份 /var/lib/docker,應備份 compose 檔案以及存放資料的卷或目錄。

步驟 5:每次備份前先匯出資料庫

下面的指令碼把壓縮後的匯出檔案寫入 /var/backups/db,該目錄已在備份列表中。請按伺服器實際情況設定 MYSQL 和 POSTGRES:

#!/bin/bash
# /usr/local/sbin/db-dump.sh - consistent database dumps before each backup
set -euo pipefail
umask 077
MYSQL=yes        # yes / no
POSTGRES=no      # yes / no
OUT=/var/backups/db
mkdir -p "$OUT"

if [ "$MYSQL" = yes ]; then
  DUMP=$(command -v mariadb-dump || command -v mysqldump)
  "$DUMP" --all-databases --single-transaction --quick \
          --routines --events --triggers | gzip > "$OUT/mysql-all.sql.gz.tmp"
  mv "$OUT/mysql-all.sql.gz.tmp" "$OUT/mysql-all.sql.gz"
fi

if [ "$POSTGRES" = yes ]; then
  cd /tmp
  runuser -u postgres -- pg_dumpall | gzip > "$OUT/postgres-all.sql.gz.tmp"
  mv "$OUT/postgres-all.sql.gz.tmp" "$OUT/postgres-all.sql.gz"
fi

--single-transaction 能在不鎖住網站的情況下得到一致的 InnoDB 匯出。在 Debian 和 Ubuntu 上,root 透過本地 socket 連線 MariaDB/MySQL,無需密碼;如果你的伺服器需要密碼,請寫入 /root/.my.cnf(許可權 600),不要寫在命令列裡。

步驟 6:建立備份指令碼

一個指令碼完成資料庫匯出、備份、按策略清理和每週檢查,並向可選的監控 URL 彙報結果(步驟 10)。任何一步失敗都會讓指令碼報錯退出,問題不會被悄悄忽略:

#!/bin/bash
# /usr/local/sbin/restic-backup.sh - dump databases, back up, apply retention
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set -a; . /etc/restic/env; set +a

fail() {
  [ -n "${HC_PING_URL:-}" ] && curl -fsS -m 10 --retry 3 "$HC_PING_URL/fail" >/dev/null || true
}
trap fail ERR

/usr/local/sbin/db-dump.sh

restic backup \
  --files-from /etc/restic/include \
  --exclude-file /etc/restic/excludes \
  --exclude-caches \
  --tag daily

restic forget --prune \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6

# Sundays: verify the repository and read back 5% of the data
if [ "$(date +%u)" = 7 ]; then
  restic check --read-data-subset=5%
fi

if [ -n "${HC_PING_URL:-}" ]; then
  curl -fsS -m 10 --retry 3 "$HC_PING_URL" >/dev/null
fi

為指令碼加上執行許可權,並手動執行第一次備份。首次執行會上傳全部資料,之後只上傳變化部分。

chmod 700 /usr/local/sbin/db-dump.sh /usr/local/sbin/restic-backup.sh
/usr/local/sbin/restic-backup.sh      # first run by hand, watch for errors
restic snapshots

步驟 7:用 systemd 定時器(或 cron)定時執行

推薦使用 systemd 定時器:日誌會寫入 journal,錯過的任務會在開機後補跑(Persistent=true),還能降低任務的 CPU 和磁碟優先順序,不拖慢網站。

# /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup to off-site repository
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Daily restic backup

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer

# Test the service once and read its log
systemctl start restic-backup.service
journalctl -u restic-backup.service -n 50 --no-pager

如果你更習慣 cron,可以用下面這行代替定時器(二者只選其一):

# /etc/cron.d/restic-backup  (only if you do not use the systemd timer)
30 3 * * * root /usr/local/sbin/restic-backup.sh >> /var/log/restic-backup.log 2>&1
在夜間以低優先順序執行備份,對硬碟更友好,也有助於遵守儲存 I/O 的合理使用規則。

步驟 8:用 restic forget --prune 設定保留策略

restic forget 決定保留哪些快照,--prune 刪除已不被任何快照引用的資料。指令碼中的策略會保留:

引數保留內容
--keep-daily 7最近 7 天中每天最後一個快照
--keep-weekly 4最近 4 周每週一個快照
--keep-monthly 6最近 6 個月每月一個快照

啟用新策略之前,先用 --dry-run 預覽效果:

set -a; . /etc/restic/env; set +a
restic snapshots
# Preview what a policy would remove, without deleting anything
restic forget --dry-run --keep-daily 7 --keep-weekly 4 --keep-monthly 6
restic stats --mode raw-data

指令碼還會在每週日執行 restic check,檢查倉庫結構;--read-data-subset=5% 每次下載並校驗不同的 5% 資料,讓損壞在你真正需要備份之前就被發現。需要更放心時,也可以隨時手動執行 restic check。

步驟 9:測試恢復

從未恢復過的備份只是一種希望。每月一次,把真實資料恢復到臨時目錄並進行比對:

set -a; . /etc/restic/env; set +a
restic snapshots
restic ls latest /etc/nginx

# Restore one directory to a scratch location, then compare
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx && echo "restore OK"

# Check that the database dump is complete (last line: "-- Dump completed on ...")
restic dump latest /var/backups/db/mysql-all.sql.gz | zcat | tail -n 1
rm -rf /tmp/restore-test

最壞的情況也要演練一次,例如在一臺備用 VPS 上:一臺全新伺服器,手裡只有儲存好的那兩個檔案。

# On the NEW server: install restic, then restore the two saved files
install -d -m 0700 /etc/restic
nano /etc/restic/password && nano /etc/restic/env
set -a; . /etc/restic/env; set +a

restic restore latest --target /srv/restore
rsync -a /srv/restore/var/www/ /var/www/          # copy back what you need
zcat /srv/restore/var/backups/db/mysql-all.sql.gz | mariadb     # or: mysql
不要在執行中的系統上執行 restic restore latest --target /:它會覆蓋正在使用的檔案,包括可能不適合新伺服器的系統配置。請恢復到單獨的目錄,再把需要的內容複製回去。

步驟 10:備份失敗時及時收到提醒

備份往往是悄無聲息地失敗的:金鑰過期、儲存桶滿了、密碼被改了。“dead man's switch”類服務可以解決這個問題:指令碼每次成功後訪問一個 URL,若沒有按時收到訪問,就會向你發出提醒。你可以自建(例如開源的 Healthchecks),也可以使用任何類似服務,然後把檢查 URL 寫入 /etc/restic/env:

HC_PING_URL=https://hc.example.com/ping/REPLACE-WITH-YOUR-CHECK-ID

指令碼成功時訪問該 URL,出錯時訪問 $HC_PING_URL/fail。把檢查週期設為一天,並留出幾個小時的寬限時間。如果不用這類服務,至少每週檢視一次 restic snapshots 和 journalctl -u restic-backup.service。

FAQ

需要多大的儲存空間?

首次快照大約等於你的資料量(壓縮後通常更小),之後每天只增加少量變化資料。執行幾周後執行 restic stats --mode raw-data,即可看到實際用量。

restic 提示倉庫被鎖定,怎麼辦?

說明上一次執行被中斷,留下了過期的鎖。先確認沒有 restic 程序在執行(pgrep -a restic),再執行 restic unlock,然後重新執行備份。

在 512 MB 方案上 restic 佔用記憶體太多,能降低嗎?

可以在 /etc/restic/env 中加入 GOGC=20,讓 restic 更頻繁地釋放記憶體;同時精簡備份路徑,並確認 VPS 已配置 swap。如果記憶體仍然不夠,可以在服務頁面升級方案。需要幫助請提交工單:JUSTG 提供 7×24 小時 AI 客服(工單),需要人工處理的問題會由工程師跟進。

這篇文章有幫助嗎?
幫助中心
Linux 伺服器 Linux SSH 金鑰登入教程:設定 ed25519 金鑰並禁用密碼登入 只要伺服器有公網 IPv4,上線幾分鐘內就會遇到 SSH 暴力破解機器人,而密碼登入正是它們的首要目標。本文說明如何用較新的 ed25519 金鑰完成 Linux SSH 金鑰登入,再禁用 SSH 密碼登入,全程避免把自己鎖在門外。步驟適用於 Debian… Linux 伺服器 Linux VPS 修改 SSH 連接埠與 root 密碼教程(安全不斷線) 把 SSH 從 22 連接埠移走雖然擋不住有心的攻擊者,卻能讓日誌裡大部分自動掃描消失;而任何新伺服器的第一件事,就是換一組新的 root 密碼。本文說明如何在 Linux VPS 修改 SSH 連接埠與 root 密碼且不斷線:修改 sshd_config、在 Rocky… Linux 伺服器 Linux 防火牆設定教程:VPS 使用 UFW 與 firewalld(含 IPv6) 新安裝的 Linux 伺服器,任何服務開啟的連接埠都會直接對外響應,因此主機防火牆是最先要設定的專案之一。本文說明如何在 Debian / Ubuntu 用 UFW 設定 Linux 防火牆,以及在 CentOS、Rocky Linux、AlmaLinux 使用… Linux 伺服器 Linux VPS 新增 Swap 交換空間教程(適合 512MB / 1GB 小記憶體套餐) 在 512 MB 或 1 GB 的雲伺服器上,資料庫、PHP-FPM 加上一次軟體包更新,很容易在同一時間用光記憶體。這時核心的 OOM killer 會強制終止程序,最常被犧牲的就是 MySQL 或 MariaDB。在 Linux VPS 新增 Swap… Linux 伺服器 Linux 硬碟空間已滿怎麼辦?VPS 找出並釋放磁碟空間教程 “No space left on device”幾乎會讓伺服器上所有東西出問題:資料庫無法寫入、網站返回錯誤、軟體包更新失敗,有時甚至無法正常登入。本文一步步說明如何排除 Linux 硬碟空間已滿:先確認是資料塊還是 inode 用完,再用 du 與 ncdu…
AlipayUnionPayVISAMastercardPayPalUSDTstripe