如何用 VPS 建立異地備份目標?
供應商的 snapshot 不算異地備份。了解如何用 VPS 部署 Proxmox Backup Server 或 restic,並先按保留期限估算實際儲存成本。
實際上的異地備份目標
異地備份目標是存放資料副本的第二台機器,而且其故障應與原始環境相互獨立。對多數讀者而言,位於其他供應商的 VPS 是最便宜且容易取得的選項。實務上有三種形式:在 VPS 上執行 Proxmox Backup Server、透過 SSH 或 S3 存取 restic repository,或由備份主機拉取資料的 rsync mirror。適合哪一種,取決於你要還原的內容,以及需要多快恢復服務。誰有權刪除該副本,則決定了其餘的安全性。
異地代表位於不同的故障網域。這表示應使用不同的供應商,且其帳戶不得與執行伺服器的帳戶共用登入資訊。同一供應商不同區域的第二台伺服器,可以在其中一棟機房發生火災時保留資料。但若控制面板的登入資訊遭竊,這種配置無法因應,因為同一個帳戶可以控制兩份副本。
供應商提供的 snapshot 不算第二份副本。它與伺服器共用同一組控制面板密碼,因此取得該密碼的人可以在同一個工作階段刪除伺服器及其 snapshots。Snapshot 服務也通常按每 GB 每月計費,價格遠高於一般磁碟,因此保存 90 天的 snapshots 會很昂貴。依賴任一種方案前,建議先閱讀VPS snapshots 與 backups 的差異。
適合你的三種架構
- Proxmox Backup Server (PBS):來源是 Proxmox VE(虛擬環境),還原對象是完整的虛擬機器。它在磁碟映像層級進行備份,驗證工作會重新讀取目標端的資料。
- restic repository:來源是一或多台 Linux 主機,還原對象是目錄或資料庫 dump。它在用戶端加密,並支援 SSH、S3 及自己的 REST protocol。
- 由備份主機透過 SSH 拉取的 rsync:如果你希望目標端以一般檔案形式保存資料,可使用
ls和cat讀取,且不需要用戶端軟體即可還原。
如果無法決定,請使用 restic。它會在資料離開主機前先完成加密,目標端只需要 SSH 帳號和磁碟即可。在 VPS 上設定 restic 備份會更深入說明用戶端設定;如果你已經使用 Borg,請參閱比較 restic 與 BorgBackup以選擇合適方案。
目標容量估算:保留一個月需要多少成本
去重是實際數字比預期小的原因。restic 和 PBS 都會將檔案切分成可變大小的區塊,並計算每個區塊的雜湊值。每個不重複的區塊只會儲存一次。500 GB 資料集的第二次備份不會再增加 500 GB,而只會增加已變更的區塊。
因此,儲存庫大小取決於最舊快照的時間,而不是快照數量。假設有 500 GB 資料,且每天新增 5 GB 不重複資料。儲存庫會包含 500 GB 的基礎資料,以及從最舊保留快照起算、每天約 5 GB 的新增資料。
The data behind this chart
[
{
"label": "7 daily",
"repo_size_gb": 535,
"usd_at_10_per_tb": 5.35
},
{
"label": "7 daily, 4 weekly",
"repo_size_gb": 640,
"usd_at_10_per_tb": 6.4
},
{
"label": "7 daily, 4 weekly, 6 monthly",
"repo_size_gb": "1,400",
"usd_at_10_per_tb": 14.0
},
{
"label": "7 daily, 4 weekly, 12 monthly",
"repo_size_gb": "2,325",
"usd_at_10_per_tb": 23.25
}
]美元欄位以每 TB 每月 10 US dollars 計算儲存庫成本。這只是計算用的佔位值,不是任何供應商的報價,因此請替換成你考慮之方案的實際每 TB 價格。一週的每日備份約包含 535 GB。完整保留一年的歷史資料會包含 2,325 GB,每月成本為 $23.25;相較之下,一週的成本為 $5.35。歷史資料的成本很低,真正需要付費的是基礎資料副本。
去重對於一開始就已壓縮或加密的資料沒有作用。經 gzip 壓縮的資料庫傾印檔每次執行都會完全變更,因此每個傾印檔都會以新區塊寫入,儲存庫每晚會增加一個完整傾印檔的大小。請以未壓縮格式寫入傾印檔,再讓備份工具負責壓縮;restic 自 0.14 起支援壓縮儲存庫,而 0.19 版新增了 fastest 和 better zstd 模式。相同原因也會使相片和影片資料庫的去重效果不佳,因此應依其實際成長速率估算容量,不要依照上方的數據。
這裡購買的是閒置磁碟容量,而不是 CPU;這正是 storage VPS 優於一般 VPS 的情況。
頻寬與還原時間決定備份方案
磁碟是便宜的部分。第一次上傳與日後的還原才是昂貴的部分。500 GB 等於 4 兆個位元,因此以連線速度除以資料量,可以算出完整還原所需時間的最低值。
The data behind this chart
[
{
"label": "40 Mbit/s home upload",
"elapsed_h": 27.8
},
{
"label": "100 Mbit/s",
"elapsed_h": 11.1
},
{
"label": "500 Mbit/s",
"elapsed_h": 2.2
},
{
"label": "1 Gbit/s VPS port",
"elapsed_h": 1.1
}
]以上是未計入通訊協定額外負荷的線速數據,因此只能視為最佳情況。在 100 Mbit/s 下,完整還原需要 11.1 小時,之後才能有人存取資料。若使用家用 40 Mbit/s 上傳速度,則需要 27.8 小時。在 1 Gbit/s 連接埠上,相同的還原需要 1.1 小時。大量小檔案的實際速度通常比算術結果更慢,因為當檔案小於幾百 KB 時,單檔額外負荷會成為主要因素。
這會導出兩個結論。如果您的復原時間目標(RTO)是 4 小時,也就是可容忍的中斷時間,那麼透過 100 Mbit/s 連線還原 500 GB 已經超出目標,使用更便宜的磁碟也無法改善。多數 VPS 方案會計算對外傳輸量,因此完整還原一次就會消耗備份主機每月配額中的 0.5 TB。請在需要資料之前確認配額,以及超過配額後供應商會採取的措施。
第一次備份包含整個資料集,也是您執行過的最慢備份。請在星期五開始,並限制傳輸速率,避免佔滿來源端的上行連線:restic 接受 --limit-upload KiB/s,rsync 接受 --bwlimit。
形態 1:將 Proxmox Backup Server 作為遠端 datastore
如果來源是 Proxmox VE,且還原單位是虛擬機器,PBS 就適合這種情境。VPS 無法從 Proxmox ISO 開機,因此請在 Debian 上安裝 PBS。截至 August 2026,4.2 是目前版本,建置於 Debian 13 (trixie)。
wget https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg \
-O /usr/share/keyrings/proxmox-archive-keyring.gpg
sha256sum /usr/share/keyrings/proxmox-archive-keyring.gpg請將該 checksum 與 Proxmox package repositories page 發布的值比對。apt repository 的可信度取決於您驗證過的 key。接著寫入 /etc/apt/sources.list.d/proxmox.sources:
Types: deb
URIs: http://download.proxmox.com/debian/pbs
Suites: trixie
Components: pbs-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpgsudo apt update && sudo apt install -y proxmox-backup-server
sudo proxmox-backup-manager datastore create offsite /mnt/datastore/offsite請為 datastore 配置獨立的 filesystem 或獨立的 volume。datastore 滿載會停止備份;若 datastore 與 root filesystem 共用空間,磁碟填滿時會使整台伺服器停止運作。
接著建立來源端要使用的 account,並改用 token,而不是 password。
sudo proxmox-backup-manager user create backup@pbs
sudo proxmox-backup-manager user generate-token backup@pbs pve1
sudo proxmox-backup-manager acl update /datastore/offsite DatastoreBackup \
--auth-id 'backup@pbs!pve1'token secret 只會顯示一次,之後無法讀回,因此顯示時請立即保存。role 與 token 同樣重要。DatastoreBackup 可以建立及還原自己的備份,但不具備 Datastore.Prune privilege,因此該 token 無法刪除它已寫入的 snapshot。
PBS 的 retention 分為兩個部分,第二個部分經常被忽略。Prune 會移除 snapshot。Garbage collection 會移除任何現存 snapshot 都未參照的 chunk。可用空間會在 garbage collection 後釋出,而不是在 prune 後釋出。
proxmox-backup-client prune host/web1 \
--keep-daily 7 --keep-weekly 4 --keep-monthly 6 --dry-run
sudo proxmox-backup-manager garbage-collection start offsite
sudo proxmox-backup-manager verify offsite當預計移除的 snapshot 清單看起來正確後,請移除 --dry-run。Garbage collection 分兩個階段執行:先更新仍被參照之每個 chunk 的存取時間,再刪除存取時間早於截止時間的 chunk。該截止時間是執行開始前 24 hours and 5 minutes。這段寬限期可避免正在由進行中備份寫入的 chunk 被直接刪除。請在 datastore 上每日排程 prune、每週排程 garbage collection,並加入 verify job,讓目標端重新讀取自己的 chunk,在還原前先回報磁碟上的損毀。
如果來源本身是 PBS instance,異地主機可以採取 pull,而不必由來源推送。
sudo proxmox-backup-manager remote create home1 \
--host pbs.home.example --userid sync@pam --password 'SECRET' \
--fingerprint '64:d3:ff:3a:50:38:53:5a:9b:f7:50:ab:fe'
sudo proxmox-backup-manager sync-job create home1-offsite \
--remote home1 --remote-store main --store offsite --schedule 'Wed 02:30'請在 VPS 上以預設的 pull 方向執行該 sync job。VPS 會存取 home datastore,因此 home box 不會保存任何能操作異地副本的 credential。
形式 2:透過 SSH 或 S3 使用 restic repository
Debian 和 Ubuntu 都有提供 restic 套件,但版本通常落後於 upstream。截至 August 2026,最新版本為 0.19.1。請在來源主機上安裝官方 binary。
curl -LO https://github.com/restic/restic/releases/download/v0.19.1/restic_0.19.1_linux_amd64.bz2
bunzip2 restic_0.19.1_linux_amd64.bz2
sudo install -m 755 restic_0.19.1_linux_amd64 /usr/local/bin/restic
restic versionrestic version 會顯示版本,以及建置該 binary 時使用的 Go compiler。之後升級時使用 sudo restic self-update。這適用於官方 binary,不適用於透過 apt 安裝的副本。
在 backup VPS 上建立一個不擁有其他檔案的帳號,然後將來源主機的 public key 複製到 /home/resticsrv/.ssh/authorized_keys。
sudo adduser --disabled-password --gecos '' resticsrv
sudo install -d -m 700 -o resticsrv -g resticsrv /srv/restic從來源端透過 SFTP 初始化 repository。
sudo sh -c 'umask 077; head -c 32 /dev/urandom | base64 > /root/.restic-password'
export RESTIC_REPOSITORY='sftp:resticsrv@backup.example.net:/srv/restic/web1'
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /etc /srv /var/backups --exclude-caches請將該密碼儲存在既不是這台伺服器、也不是 backup target 的位置。遺失密碼後,repository 將無法讀取,且完全沒有復原途徑。這就是 client-side encryption 的代價。
保留政策只需一個指令,而後半段才是釋放磁碟空間的部分。
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check --read-data-subset=10%forget 會刪除 snapshots。prune 會刪除僅由這些 snapshots 參照的 pack files,而 --prune 會在確實刪除內容後自動執行這項工作。沒有它,repository 永遠不會縮小。restic check 會驗證 repository 結構;--read-data-subset=10% 會重新讀取並重新計算十分之一的 pack files 雜湊值,可在不讀取全部資料的情況下偵測 target 上的損毀。另一種形式 --read-data-subset=1/10 會檢查固定的十分之一,因此每週遞增第一個數字,10 週後即可涵蓋整個 repository。
如果某次執行被強制終止,下一次執行會因 repository is already locked exclusively by PID 而停止。請先確認沒有 backup 正在執行,再使用 restic unlock 清除它。
使用 object storage 時,repository string 會變成 s3:https://s3.example.net/web1,credentials 則放在 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY。其他部分完全相同;restic 就是透過這種方式連線至運行在同一台 VPS 上的 自架 MinIO object store。
形式 3:使用僅限 pull 的金鑰透過 SSH 執行 rsync
此形式的安全特性在於連線方向。備份 VPS 連線至來源端並讀取資料。來源端不持有任何金鑰,也沒有通往備份主機的路由,因此即使來源端遭到入侵,也完全無法存取備份。
在備份 VPS 上產生金鑰組,然後搭配強制命令,將公開金鑰安裝到來源端。
command="rrsync -ro /srv",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA offsite-pullrrsync 隨 Debian 13 和 Ubuntu 24.04 的 rsync 套件安裝於 /usr/bin/rrsync。-ro 僅允許讀取,並隱含啟用 -no-del,因此此金鑰無法在來源端寫入或刪除任何內容。restrict 會關閉此處不需要的 SSH 功能,包括連接埠轉送和 pty,因此無法使用此金鑰進行互動式登入。之後的路徑會以指定的目錄為相對路徑,因此遠端路徑 / 在來源端代表 /srv。
此 pull 流程使用 hardlink 保留歷史版本。新樹狀目錄中的未變更檔案會 hardlink 至上一個樹狀目錄,因此只需額外佔用一個目錄項目,而不需要再複製一份檔案。
DEST=/srv/mirror/web1
TODAY=$(date +%F)
LAST=$(ls -1d "$DEST"/2* 2>/dev/null | tail -1)
LINK=""
if [ -n "$LAST" ]; then LINK="--link-dest=$LAST"; fi
rsync -aH --numeric-ids $LINK -e 'ssh -i /root/.ssh/pull_ed25519' \
pull@web1.example.net:/ "$DEST/.$TODAY.partial/"
mv "$DEST/.$TODAY.partial" "$DEST/$TODAY"結尾的重新命名動作是讓日期目錄可信的關鍵:只有在 rsync 以 0 結束後才會出現該名稱,因此中斷的傳輸不會被誤認為已完成的 snapshot。使用一行命令刪除舊樹狀目錄,保留 30 個。
ls -1d /srv/mirror/web1/2* | sort | head -n -30 | xargs -r rm -rf必須如實說明此形式的成本。Hardlink 只能對完整檔案去重,因此 4 GB 磁碟映像檔內只要變更 1 個位元組,就會複製完整的 4 GB;restic 和 PBS 則只會儲存少量變更的區塊。目標端也會以明文儲存檔案,因此任何在備份 VPS 上取得 root 權限的人都能讀取這些檔案。
用戶端加密,因此目標端永遠看不到明文
將備份 VPS 視為一台你無法完全控制的機器。它由供應商提供,而供應商有工作人員,也可能有故障磁碟需要送出機房。
restic 會在來源端將每個區塊加密後才傳送,因此儲存庫中只有密文,以及與大小和時間相關的中繼資料。PBS 的加密功能預設不啟用:你必須建立金鑰,然後在每次備份時傳入該金鑰。
proxmox-backup-client key create /root/pbs-encryption.key
proxmox-backup-client backup root.pxar:/ --keyfile /root/pbs-encryption.key
proxmox-backup-client key paperkey --output-format text > qrkey.txt將紙本金鑰列印出來,並存放在實體安全位置。Proxmox 文件明確說明其中的風險:沒有該金鑰,就無法存取已備份的檔案。不要將金鑰存放在備份目標端,因為將金鑰與密文放在一起,無法提供任何保護。
rsync 鏡像沒有相應的加密機制。檔案會以檔案形式寫入目標端。如果資料敏感,請接受目標端可以讀取資料,或改用另外兩種架構之一。
阻止遭入侵的來源端刪除自己的備份
攻擊者取得來源端的控制權後,接著會尋找備份,而用來上傳備份的認證資訊就存放在該機器上。如果該認證也具備刪除權限,攻擊者就會加以利用。
PBS 透過角色解決這個問題。僅持有 DatastoreBackup 的 token 可以寫入新的 snapshot,也可以還原自己的 snapshot,但無法執行 prune,因為刪除 snapshot 需要獨立的 Datastore.Prune 權限。請在 PBS 端執行保留政策,讓來源端永遠不持有可刪除任何內容的認證資訊。
restic over SFTP 沒有這種權限分離,因為可寫入 repository 的 SSH key 也能從中刪除資料。解決方式是使用 REST backend。在備份 VPS 上以 --append-only 執行 rest-server。這會允許建立新的備份,但禁止刪除或修改既有備份。接著使用 RESTIC_REST_USERNAME 與 RESTIC_REST_PASSWORD,將 client 指向 rest:https://backup.example.net:8000/web1。此時,來源端執行 restic forget --prune 會失敗,這正是預期結果。因此,保留政策必須由另一台具備獨立認證資訊的機器執行。restic manual 也建議在 append-only repository 上使用 --keep-within,不要使用依數量計算的政策,因為攻擊者若持續以垃圾 snapshot 填滿 repository,否則可能將真正的備份推出 --keep-last 視窗。
rsync 則透過 pull 從架構上解決相同問題,因為來源端不持有目標端的任何認證資訊。
這三種架構都適用同一項規則:具備刪除備份權限的認證資訊,必須存放在不同於備份來源端的機器上。
安排還原演練
從未還原過的備份只是個假設。每季安排 1 小時進行測試。
restic snapshots
restic restore latest --target /var/tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /var/tmp/restore-test/etc/nginxdiff -r 沒有輸出表示還原後的目錄樹與線上目錄樹一致。在 PBS 上,同樣的演練是 proxmox-backup-client restore host/web1/2026-08-13T02:30:00Z root.pxar /var/tmp/restore-test/,另外還要安排 verify job,重新讀取目標端的區塊並回報 checksum 錯誤。
演練必須證明的不只是位元組未損毀。
- 從第三台機器進行還原,不要從來源端還原,因為來源端正是你假設已經遺失的對象。因此,repository password 或 PBS key 必須能在來源端無法使用時取得。
- 計時還原過程並記錄數值,再與你宣告的 RTO 比較。上方圖表提供傳輸的最低時間。實際數值還包括解密、寫入磁碟,以及確認所需 snapshot 的時間。
- 還原具備狀態的資料,例如將 database dump 載入 scratch instance。能夠解開的 tar file 不能證明應用程式可以啟動。
全世界最便宜的磁碟,在你實際從中還原過一次之前都毫無價值。
FAQ
服務商提供的 VPS snapshot 算是異地備份嗎?
不算。服務商的 snapshot 位於與伺服器相同的帳戶、相同的控制面板登入機制,以及相同的帳單中。取得該登入資訊的人,可以在同一個工作階段刪除伺服器及其所有 snapshot。Snapshot 適合在高風險升級前快速回復,但不代表備份位於第二個位置。異地副本應存放在不同帳戶下,理想情況是位於不同服務商,且來源主機不持有其憑證。
保留 1 個月的備份需要多少磁碟空間?
應根據最舊 snapshot 的保存時間估算,而不是根據 snapshot 數量。採用去重的工具只會儲存每個不重複的區塊 1 次,因此儲存庫大小大致等於來源資料大小,加上每天新增的不重複資料量乘以保留天數。若有 500 GB 資料,每天變更 5 GB,保留 1 週的每日備份約需 535 GB,保留完整 1 年的歷史資料則需 2,325 GB。除此之外還要預留空間,因為磁碟已滿會導致下一次備份失敗,而 restic 的 prune 需要可用空間重新封裝 pack files,之後才能釋放空間。
遭入侵的伺服器可以刪除自己的異地備份嗎?
可以,除非你已針對這種情況設計備份架構。使用一般 SSH 或 SFTP 儲存庫時,具備寫入權限的 key 也能刪除資料。應提供來源主機無法移除資料的憑證:使用僅持有 DatastoreBackup role 且不具備 Datastore.Prune privilege 的 PBS API token,或使用以 --append-only 啟動的 rest-server 搭配 restic;此設定會拒絕刪除及修改現有備份。拉取式架構更進一步,因為來源主機完全不持有備份主機的憑證。應從非來源端執行保留政策。
應在備份 VPS 上執行 Proxmox Backup Server 還是 restic?
應根據還原單位選擇工具。如果來源是 Proxmox VE,且希望還原完整虛擬機器,應使用 PBS,因為它在磁碟映像層級進行備份,並可在單一步驟中還原 VM。如果來源是 Linux 主機,且希望還原檔案與資料庫 dump,應使用 restic;它只需要目標端的 SSH 帳戶,並會在傳送前加密資料。兩者並用很常見:hypervisor 使用 PBS,不在 hypervisor 上的伺服器使用 restic。
從 VPS 備份還原需要多久?
先以資料大小除以連線速度,取得理論上的最低時間,再加上解密與寫入所需的時間。透過 100 Mbit/s 連線傳輸 500 GB,依線速計算需要 11.1 小時;透過 1 Gbit/s 埠進行相同還原則需要 1.1 小時。大量小檔案會因每個檔案的處理成本而比上述計算更慢。應實際執行 1 次完整還原並記錄時間,因為只有實測數值能作為復原計畫的可靠依據。