如何用VPS搭建异地备份目标
服务商快照不算异地副本:用另一家服务商的VPS部署Proxmox Backup Server或restic,并先按保留策略计算存储成本。
实际的异地备份目标是什么
异地备份目标是另一台保存数据副本的机器,并且其故障不会与原始机器同时发生。对大多数读者来说,另一家服务商提供的 VPS 是最廉价的选择。实际可行的方案有 3 种:在 VPS 上运行 Proxmox Backup Server、通过 SSH 或 S3 访问 restic 仓库,或由备份主机主动拉取的 rsync 镜像。选择哪一种取决于需要恢复的内容,以及对恢复速度的要求。谁有权删除副本,则决定了其余的安全边界。
异地意味着处于不同的故障域。这要求使用不同的服务商,并且该账户不能与运行服务器的账户共享登录凭据。同一服务商不同区域的第二台服务器可以在一栋楼发生火灾时保留数据。但如果控制面板登录凭据遭到入侵,它无法抵御攻击,因为同一个账户可以控制两个副本。
服务商提供的快照不属于第二份副本。快照受同一个面板密码保护,因此获得该密码的人可以在一次会话中删除服务器及其快照。快照服务还会按每月每 GB 计费,价格远高于普通磁盘,因此保存 90 天的快照成本很高。建议先阅读VPS 快照与备份的区别,再决定是否依赖其中任何一种方案。
适合您的三种方案
- Proxmox Backup Server (PBS):源端是 Proxmox VE(虚拟环境),恢复对象是整台虚拟机。它在磁盘映像层级执行备份,验证任务会重新读取目标端已有的数据。
- restic 仓库:源端是一台或多台 Linux 主机,恢复对象是目录或数据库转储。它在客户端加密数据,并支持 SSH、S3 以及自身的 REST 协议。
- 通过 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 美元为该仓库估算费用。这个价格仅用于演示计算,不代表任何服务提供商的报价,因此请替换为您所考虑方案的实际每 TB 价格。一周的每日备份约占 535 GB。保留完整一年的历史记录需要 2,325 GB,每月费用为 $23.25;一周的费用为 $5.35。历史数据的成本很低,真正需要付费的是基础副本。
去重无法减少已经压缩或加密的数据。经过 gzip 压缩的数据库转储文件每次运行都会完全变化,因此每个转储都会作为新数据块写入,仓库每晚增加一个完整转储文件的大小。请以未压缩格式写入转储,再让备份工具负责压缩,因为 restic 从 0.14 起支持压缩仓库,版本 0.19 新增了 fastest 和 better zstd 模式。照片和视频库基于同样的原因也很难有效去重,因此应根据其实际增长率估算容量,而不是使用上表中的数据。
这里购买的是闲置磁盘空间,而不是 CPU 资源。这正是存储型 VPS 优于普通 VPS的场景。
为什么带宽和恢复时间决定方案
磁盘是成本较低的部分。首次上传和最终恢复才是耗时和成本较高的部分。500 GB 等于 4 trillion bits,因此用链路速度相除,就能得出完整恢复所需时间的下限。
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)是四小时,也就是您可以容忍的中断时长,那么通过 100 Mbit/s 链路恢复 500 GB 已经超过目标,降低磁盘成本也无法改善这一点。多数 VPS 方案会限制出站传输量,因此一次完整恢复就会消耗备份主机每月配额中的 0.5 TB。在需要这些数据之前,请确认配额,并确认超过配额后服务商会如何处理。
首次备份包含完整数据集,是您执行的最慢一次备份。请在周五启动,并限制速率,避免占满源端的上行链路:restic 使用 --limit-upload KiB/s,rsync 使用 --bwlimit。
形态 1:将 Proxmox Backup Server 作为远程数据存储
如果源端是 Proxmox VE,且恢复单位是虚拟机,则适合使用 PBS。VPS 无法启动 Proxmox ISO,因此应在 Debian 上安装 PBS。截至 2026 年 8 月,当前版本为 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将该校验和与 Proxmox 软件包仓库页面上发布的值进行比较。apt 仓库是否可信,取决于您验证过的密钥。然后写入 /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为数据存储分配独立的文件系统或独立的卷。数据存储空间用满后,备份会停止;如果数据存储与根文件系统共用空间,用满后会导致整台服务器不可用。
接下来创建源端使用的账户,并向其分配令牌,而不是密码。
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'令牌密钥只会显示一次,之后无法再次读取,因此显示时应立即保存。角色与令牌同样重要。DatastoreBackup 可以创建和恢复自己的备份,但不包含 Datastore.Prune 权限,因此该令牌无法删除它自己写入的快照。
PBS 的保留策略分为两部分,第二部分经常被忽略。Prune 会删除快照。垃圾回收会删除任何仍存留的快照都不再引用的数据块。只有执行垃圾回收后,磁盘空间才会释放,而不是执行 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确认计划删除的快照列表正确后,再执行 --dry-run。垃圾回收分两个阶段运行:先更新所有仍被引用的数据块的访问时间,然后删除访问时间早于截止时间的数据块。该截止时间为任务开始前 24 小时 5 分钟。设置此宽限期,是为了避免正在进行的备份写入的数据块被提前删除。为数据存储安排每日 prune 和每周垃圾回收,并添加 verify 任务,使目标端重新读取自身的数据块,在恢复前发现磁盘上的损坏。
如果源端本身是 PBS 实例,则异地服务器可以主动拉取数据,而不是由源端推送数据。
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 上运行该同步任务,并使用默认的拉取方向。VPS 会访问主站数据存储,因此主站不会保存任何能够操作异地副本的凭据。
形式 2:通过 SSH 或 S3 使用 restic 仓库
Debian 和 Ubuntu 都提供 restic 软件包,但版本都落后于上游。截至 2026 年 8 月,当前版本为 0.19.1。请在源主机上安装官方二进制文件。
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 会输出版本以及构建该程序时使用的 Go 编译器。后续升级使用 sudo restic self-update,该命令适用于官方二进制文件,不适用于通过 apt 安装的副本。
在备份 VPS 上创建一个不拥有其他任何内容的账户,然后将源主机的公钥复制到 /home/resticsrv/.ssh/authorized_keys。
sudo adduser --disabled-password --gecos '' resticsrv
sudo install -d -m 700 -o resticsrv -g resticsrv /srv/restic通过 SFTP 从源主机初始化仓库。
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将该密码存储在既不是本服务器、也不是备份目标的位置。密码丢失后,仓库将无法读取,并且完全没有恢复路径。这就是客户端加密要求您承担的后果。
保留策略只需一条命令,其中后半部分负责释放磁盘空间。
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check --read-data-subset=10%forget 会删除快照。prune 会删除仅由这些快照引用的 pack 文件,--prune 会在确实删除了内容时自动运行该操作。没有它,仓库不会缩小。restic check 会验证仓库结构,--read-data-subset=10% 会重新读取并重新计算十分之一的 pack 文件哈希值,可以在无需读取全部文件的情况下发现目标端的损坏。另一种形式 --read-data-subset=1/10 会检查固定的十分之一,因此每周递增第一个数字,十周后即可覆盖整个仓库。
如果某次运行被强制终止,下一次运行会因 repository is already locked exclusively by PID 而停止。确认当前没有备份正在运行,然后使用 restic unlock 清除它。
对于对象存储,仓库字符串改为 s3:https://s3.example.net/web1,凭据放在 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 中。其他内容完全相同,因此 restic 可以连接到运行在同一 VPS 上的自托管 MinIO 对象存储。
形态 3:使用仅拉取密钥通过 SSH 运行 rsync
这种形态的安全特性在于方向性。备份 VPS 连接源端并读取数据。源端不保存任何密钥,也没有通往备份主机的路由,因此即使源端遭到入侵,也完全无法访问备份。
在备份 VPS 上生成密钥对,然后使用强制命令将公钥安装到源端。
command="rrsync -ro /srv",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA offsite-pull在 Debian 13 和 Ubuntu 24.04 上,rrsync随 rsync 软件包一起提供,位于 /usr/bin/rrsync。-ro仅允许读取,并隐含启用 -no-del,因此此密钥无法向源端写入数据,也无法删除源端的任何内容。restrict会关闭此处不需要的 SSH 功能,包括端口转发和伪终端,因此该密钥不能用于交互式登录。之后,路径都相对于指定的目录,因此远程路径 / 在源端表示 /srv。
拉取操作通过硬链接保留历史记录。新目录树中的未更改文件会链接到上一个目录树中的对应文件,因此只占用一个目录项,而无需再次复制文件。
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 结束后,目录名才会出现,因此中断的传输不会被误认为已完成的快照。使用一行命令清理旧目录,同时保留三十个。
ls -1d /srv/mirror/web1/2* | sort | head -n -30 | xargs -r rm -rf需要明确这种形态的代价。硬链接只能对完整文件去重,因此修改 4 GB 磁盘映像中的一个字节时,会复制全部 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 的令牌可以写入新快照并恢复自身创建的快照,但不能执行 prune,因为删除快照需要单独的 Datastore.Prune 权限。在 PBS 端执行保留策略,源端就不需要持有任何可以删除备份的凭据。
通过 SFTP 使用 restic 时没有这种权限分离,因为能够写入仓库的 SSH 密钥也能从仓库中删除数据。解决方法是使用 REST 后端。在备份 VPS 上使用 --append-only 运行 rest-server。该选项允许创建新备份,但禁止删除或修改已有备份。然后使用 RESTIC_REST_USERNAME 和 RESTIC_REST_PASSWORD,将客户端指向 rest:https://backup.example.net:8000/web1。此时,源端执行 restic forget --prune 会失败,这正是预期结果。因此,应在另一台机器上使用独立凭据执行保留策略。restic 手册还建议在仅追加仓库上使用 --keep-within,而不是基于数量的策略,因为攻击者如果向仓库写入大量无用快照,就可能将真正的快照挤出 --keep-last 时间窗口。
rsync 通过拉取备份以结构性方式解决同一问题,因为源端不持有目标端的凭据。
这三种架构都适用同一条规则:能够删除备份的凭据必须存放在备份目标之外的另一台机器上。
将恢复演练加入日程
从未执行过恢复的备份只是一个假设。每个季度安排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/,此外还应安排验证任务,在目标端重新读取数据块并报告校验和失败。
演练必须证明的不只是数据块完整。
- 从第三台机器执行恢复,而不是从源端恢复,因为源端正是您假设已经丢失的对象。这意味着仓库密码或 PBS 密钥必须能够在不依赖源端的情况下访问。
- 记录恢复耗时,然后与您声明的 RTO 对比。上面的图表给出了传输耗时下限。实际耗时还包括解密、写入磁盘,以及确定所需快照的时间。
- 恢复包含状态的数据,例如将数据库转储加载到临时实例中。能够解压 tar 文件并不能证明应用可以启动。
世界上最便宜的磁盘,在您成功从中恢复一次之前都毫无价值。
FAQ
VPS 提供商的快照算异地备份吗?
不算。提供商快照与被复制的服务器属于同一账户、使用同一个面板登录,并出现在同一张账单上。任何获得该登录凭据的人,都可以在一次会话中删除服务器及其所有快照。快照适合在高风险升级前快速回滚,但不属于第二个存储位置。异地副本应存放在不同账户下,最好位于不同提供商处,并使用源服务器未持有的凭据。
保留一个月的备份需要多少磁盘空间?
应根据最早快照的时间,而不是快照数量来估算。支持去重的工具只会存储每个唯一数据块一次,因此,仓库大小大致等于源数据大小,加上每天新增的唯一数据量乘以保留天数。对于 500 GB 数据、每天变化 5 GB 的情况,保留一周的每日备份约为 535 GB,保留完整一年的历史记录为 2,325 GB。在此基础上预留额外空间,因为磁盘写满会导致下一次备份失败;restic 的 prune 还需要可用空间重新打包 pack 文件,之后才能释放空间。
被入侵的服务器可以删除自己的异地备份吗?
可以,除非专门针对这种情况进行设计。对于普通 SSH 或 SFTP 仓库,能够写入数据的密钥也能够删除数据。应为源服务器提供无法删除数据的凭据:使用仅持有 DatastoreBackup 角色且不具备 Datastore.Prune 权限的 PBS API token,或者使用以 --append-only 启动的 rest-server 配合 restic;该模式会拒绝删除和修改现有备份。拉取式设计更进一步,因为源服务器完全不持有备份主机的凭据。应从非源端执行保留策略。
应在备份 VPS 上运行 Proxmox Backup Server 还是 restic?
应根据恢复单位选择工具。如果源端是 Proxmox VE,并且需要恢复完整虚拟机,应运行 PBS,因为它在磁盘映像级别执行备份,并可一步恢复虚拟机。如果源端是 Linux 主机,并且需要恢复文件和数据库转储,应运行 restic;它只需要目标端的 SSH 账户,并会在发送前加密数据。同时运行两者很常见:PBS 用于虚拟化管理程序,restic 用于未运行在该管理程序上的服务器。
从 VPS 备份恢复需要多长时间?
用数据量除以链路速度得到理论下限,再加上解密和写入所需的时间。通过 100 Mbit/s 链路传输 500 GB,按线路速率计算需要 11.1 小时;通过 1 Gbit/s 端口执行相同恢复需要 1.1 小时。由于每个文件都有额外开销,大量小文件的传输速度通常低于上述计算结果。应实际执行一次完整恢复并记录耗时,因为恢复计划唯一可以依赖的是这个实测值。