SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor

VPSをオフサイトバックアップ先にする方法

プロバイダーのスナップショットはオフサイトではありません。VPSでProxmox Backup Server、restic、rsyncを使う構成と、90日保存の料金を比較します。

オフサイトバックアップ先の実態

オフサイトバックアップ先とは、データのコピーを保持し、元の環境とは独立して障害が発生する別のマシンです。多くの読者にとって、別のプロバイダーの VPS が最も安価な選択肢です。現実的な構成は、VPS 上で Proxmox Backup Server を実行する方法、SSH または S3 経由でアクセスする restic リポジトリ、バックアップホストが取得する rsync ミラーの 3 つです。どれが適するかは、何を復元するか、どれだけ早く復旧する必要があるかで決まります。コピーを削除できる人を誰にするかが、その他の構成を左右します。

オフサイトとは、異なる障害ドメインに置くという意味です。つまり、異なるプロバイダーを使用し、サーバーを運用するアカウントとログイン情報を共有しないアカウントを使います。同じプロバイダーの別リージョンに 2 台目のサーバーを置けば、一方の建物で発生した火災には耐えられます。しかし、1 つのアカウントで両方のコピーを管理しているため、コントロールパネルのログイン情報が侵害された場合には耐えられません。

プロバイダーのスナップショットは、2 つ目のコピーではありません。スナップショットは同じパネルパスワードの管理下にあるため、そのパスワードを取得した攻撃者は、1 回のセッションでサーバーとスナップショットを削除できます。また、スナップショットサービスは通常のディスクより大幅に高い料金を、1 GB あたり月額で請求します。そのため、90 日間保存すると高額になります。どちらかに依存する前に、VPS のスナップショットとバックアップの違いを確認してください。

自分に合う 3 つの方式

  • Proxmox Backup Server (PBS): ソースは Proxmox VE(仮想環境)で、復元する対象は仮想マシン全体です。ディスクイメージ単位でバックアップし、verify ジョブではターゲット上のデータを再読み込みして検証します。
  • restic リポジトリ: ソースは 1 台以上の Linux ホストで、復元する対象はディレクトリまたはデータベースダンプです。クライアント側で暗号化し、SSH と S3 に加えて、独自の REST プロトコルを使用します。
  • バックアップホストが取得する rsync over SSH: ターゲット上に通常のファイルとして保存し、lscat で読み取れるようにしたい場合に適しています。復元時にクライアントソフトウェアは必要ありません。

判断できない場合は、restic を使用してください。マシンの外部へデータを送る前に暗号化し、ターゲット側には SSH アカウントとディスク以外は必要ありません。VPS で restic バックアップを設定するではクライアント側の設定を詳しく説明し、restic と BorgBackup の比較では、すでに Borg を運用している場合の選択基準を説明します。

対象容量の見積もり: 1 か月分の保持にかかる費用

数値が想定より小さくなる理由は重複排除です。restic と PBS は、どちらもファイルを可変長のチャンクに分割し、各チャンクをハッシュ化します。一意のチャンクは 1 回だけ保存されます。500 GB のデータセットを 2 回目にバックアップしても、さらに 500 GB が追加されるわけではありません。変更されたチャンクだけが追加されます。

そのため、リポジトリのサイズはスナップショット数ではなく、最も古いスナップショットの経過期間に応じて増えます。データが 500 GB あり、毎日 5 GB の新しい一意データが発生するとします。リポジトリには 500 GB のベースデータに加えて、保持ポリシーで維持する最も古いスナップショットまでの日数分として、おおよそ 1 日あたり 5 GB が追加されます。

ChartRepository size for 500 GB of data at 5 GB of new unique data per day
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
  }
]

ドルの列では、リポジトリの料金を 1 TB あたり月 10 US dollars として計算しています。これは計算例のための仮定であり、プロバイダーの見積もりではありません。実際に検討しているプランの TB あたりの料金に置き換えてください。1 週間分の日次バックアップでは、約 535 GB を保持します。1 年分の履歴をすべて保持すると 2,325 GB になり、料金は月額 $23.25 です。1 週間分の料金は $5.35 です。履歴の保持費用は安価です。料金の大部分を占めるのはベースコピーです。

重複排除は、圧縮または暗号化された状態で生成されるデータには効果がありません。gzip 圧縮されたデータベースダンプは実行のたびに内容が完全に変わるため、各ダンプが新しいチャンクとして保存されます。その結果、リポジトリは毎晩、ダンプ 1 回分ずつ増加します。ダンプは非圧縮で書き出し、バックアップツールに圧縮させてください。restic は 0.14 以降、圧縮リポジトリをサポートしています。バージョン 0.19 では fastestbetter の zstd モードが追加されました。写真や動画のライブラリも同じ理由で重複排除の効果が低いため、上の行ではなく実際の増加率に基づいて容量を見積もってください。

ここで購入しているのは CPU ではなく、ほとんど使用しないディスク容量です。この用途では、通常の VPS よりストレージ VPS が適しています

帯域幅とリストア時間で計画が決まる

安価なのはディスクです。コストがかかるのは、最初のアップロードと、最終的なリストアです。500 GB は 4 trillion bits なので、リンク速度で割れば、完全なリストアにかかる時間の下限がわかります。

ChartElapsed hours to pull 500 GB back, at line rate
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 時間かかります。数百キロバイト未満のファイルではファイルごとのオーバーヘッドが支配的になるため、小さなファイルが多数ある場合は、この計算より遅くなります。

ここから 2 つのことがわかります。許容できる停止時間である復旧時間目標(RTO)が 4 時間なら、100 Mbit/s のリンク経由で 500 GB をリストアする時点で、すでに目標を達成できません。ディスクが安くても解決にはなりません。また、多くの VPS プランでは外向きの転送量が計測されるため、完全なリストアを 1 回行うだけで、バックアップホストの月間転送量の 0.5 TB を消費します。データが必要になる前に、転送量の上限と、超過した場合のプロバイダーの対応を確認してください。

最初のバックアップではデータセット全体を転送するため、これまでで最も時間のかかる実行になります。金曜日に開始し、送信元のアップリンクを飽和させないように速度を制限してください。restic は --limit-upload KiB/秒、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.gpg
sudo apt update && sudo apt install -y proxmox-backup-server
sudo proxmox-backup-manager datastore create offsite /mnt/datastore/offsite

データストアには専用のファイルシステムまたは専用のボリュームを割り当てます。データストアが満杯になるとバックアップが停止します。root ファイルシステムを共有するデータストアが満杯になると、サーバー全体が停止します。

次に、ソースが使用するアカウントを作成し、パスワードではなくトークンを割り当てます。

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'

トークンシークレットは 1 回だけ表示され、後から読み出せません。表示されたら保存してください。トークンと同じくらいロールも重要です。DatastoreBackup は自身のバックアップを作成および復元できますが、Datastore.Prune 権限は持ちません。そのため、このトークンで、すでに書き込んだスナップショットを削除することはできません。

PBS の保持処理には 2 つの段階があり、後半は省略されがちです。prune はスナップショットを削除します。Garbage collection は、残っているスナップショットが参照していないチャンクを削除します。空き容量が増えるのは prune の実行後ではなく、garbage collection の実行後です。

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 を削除します。Garbage collection は 2 段階で実行されます。まず、現在も参照されているすべてのチャンクのアクセス時刻を更新します。次に、実行開始時刻の 24 時間 5 分前より古いアクセス時刻を持つチャンクを削除します。この猶予期間は、実行中のバックアップが書き込んでいるチャンクを途中で削除しないためにあります。データストアで prune を毎日、garbage collection を毎週実行するようスケジュールします。さらに 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 上で、デフォルトの pull 方向で実行します。VPS はホームのデータストアへ接続します。そのため、ホーム側のサーバーにオフサイトコピーへアクセスできる認証情報を保持する必要がありません。

方式 2: SSH または S3 経由の restic リポジトリ

Debian と Ubuntu はどちらも restic をパッケージ化していますが、upstream より遅れています。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 version

restic 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

このパスワードは、このサーバーでもバックアップ先でもない場所に保存します。パスワードを失うと、リポジトリは読み取れなくなり、復旧手段は一切ありません。これがクライアント側暗号化の前提です。

保持期間の設定は 1 つのコマンドで行います。後半の処理がディスク領域を解放する部分です。

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 ファイルの 10 分の 1 を再読み込みして再ハッシュします。これにより、すべてを読み取るコストをかけずにバックアップ先の破損を検出できます。もう一方の形式である --read-data-subset=1/10 は、固定した 10 分の 1 を検査します。そのため、最初の番号を毎週増やすと、10 週間でリポジトリ全体を検査できます。

実行が強制終了された場合、次回の実行は repository is already locked exclusively by PID で停止します。バックアップが実行中でないことを確認してから、restic unlock でこれを解除します。

オブジェクトストレージでは、リポジトリ文字列を s3:https://s3.example.net/web1 に変更し、認証情報を AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY に指定します。それ以外はすべて同じです。これにより、restic は同じ VPS 上で実行する自己ホスト型の MinIO オブジェクトストアと通信できます。

方式 3: pull-only key による rsync over SSH

この方式のセキュリティ上の特性は、接続方向にあります。バックアップ VPS がソースに接続して読み取ります。ソースには鍵もバックアップホストへの経路もないため、ソースが侵害されてもバックアップへ到達することはできません。

バックアップ VPS で鍵ペアを生成し、強制コマンドを設定して公開鍵をソースに配置します。

command="rrsync -ro /srv",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA offsite-pull

rrsync は Debian 13 と Ubuntu 24.04 では、/usr/bin/rrsync にある rsync パッケージに含まれています。-ro は読み取りだけを許可し、-no-del も暗黙的に有効にするため、この鍵でソースへ書き込んだり、ソース上のファイルを削除したりすることはできません。restrict は、ポート転送や pty など、ここでは不要な SSH 機能を無効にします。そのため、この鍵を対話型ログインに使用することはできません。以降のパスは指定したディレクトリからの相対パスになります。したがって、リモートパス / はソース上の /srv を意味します。

pull ではハードリンクを使って履歴を保持します。新しいツリー内の変更されていないファイルは前のツリーへのハードリンクになるため、2 個目のコピーではなくディレクトリエントリ分の容量だけを消費します。

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"

最後に rename を実行することで、日付付きディレクトリの信頼性を確保できます。名前は rsync が 0 で終了した後にだけ現れるため、転送が中断されても完了済みのスナップショットには見えません。1 行で古いツリーを期限切れにし、30 個を残します。

ls -1d /srv/mirror/web1/2* | sort | head -n -30 | xargs -r rm -rf

この方式のコストも正しく理解してください。ハードリンクで重複排除できるのはファイル全体だけです。そのため、4 GB のディスクイメージ内の 1 バイトを変更すると、4 GB 全体がコピーされます。一方、restic と PBS では変更された数個のチャンクだけが保存されます。また、ターゲットにはファイルが平文で保存されます。そのため、バックアップ VPS の root 権限を持つユーザーはファイルを読み取れます。

クライアント側で暗号化し、対象側には平文を見せない

バックアップ用VPSは、完全には管理できないマシンとして扱います。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のミラーには同等の仕組みがありません。ファイルはファイルとして保存先に配置されます。データが機密情報である場合は、保存先が読み取れることを受け入れるか、他の2つの方式のいずれかを使用します。

侵害されたソースによるバックアップ自体の消去を防ぐ

攻撃者はソースを侵害すると、次にバックアップを探します。バックアップをアップロードする認証情報は、そのマシン上に存在するためです。その認証情報で削除もできるなら、攻撃者はそれを使います。

PBS では、これをロールで防ぎます。DatastoreBackupだけを持つトークンは、新しいスナップショットを作成し、自身のスナップショットを復元できます。ただし、スナップショットの削除には別の Datastore.Prune 権限が必要なため、prune は実行できません。保持期間の処理を PBS 側で実行すれば、ソース上に削除権限を持つ認証情報を置かずに済みます。

SFTP 経由の restic には、このような権限分離がありません。リポジトリへの書き込みに使う SSH key で、リポジトリ内のデータも削除できるためです。解決策は REST backend です。バックアップ用 VPS で rest-server を --append-only とともに実行します。これにより、新しいバックアップの作成は許可しつつ、既存のバックアップの削除と変更を防止できます。クライアントは RESTIC_REST_USERNAMERESTIC_REST_PASSWORD を使って rest:https://backup.example.net:8000/web1 を指定します。ソースからの restic forget --prune は失敗しますが、これは意図した動作です。そのため、保持期間の処理は、専用の認証情報を持つ別のマシンから実行します。restic のマニュアルでも、追記専用リポジトリでは個数ベースのポリシーではなく --keep-within を推奨しています。攻撃者が不要なスナップショットを大量に作成すると、個数ベースの --keep-last の範囲から本物のスナップショットが押し出されるためです。

rsync では、ソースがターゲット用の認証情報を保持しない pull 方式にすることで、同じ問題を構造的に解決できます。

3 つの方式すべてに共通するルールは 1 つです。バックアップを削除できる認証情報は、バックアップ対象とは別のマシンに置きます。

復元訓練を予定表に登録する

一度も復元したことのないバックアップは、仮説にすぎません。四半期ごとに1時間を確保し、テストしてください。

restic snapshots
restic restore latest --target /var/tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /var/tmp/restore-test/etc/nginx

diff -r が何も出力しない場合、復元したツリーが稼働中のツリーと一致しています。PBS では同じ訓練が proxmox-backup-client restore host/web1/2026-08-13T02:30:00Z root.pxar /var/tmp/restore-test/ となり、対象上のチャンクを再読み取りしてチェックサムエラーを報告する、スケジュール済みの検証ジョブも実行します。

この訓練では、データが壊れていないことだけでなく、次の点も確認する必要があります。

  • ソースではなく、3 台目のマシンから復元します。ソースは、まさに失われたと想定している対象だからです。そのため、リポジトリのパスワードまたは PBS key は、ソースがなくても取得できなければなりません。
  • 復元にかかった時間を計測して記録し、提示した RTO と比較します。上のグラフは転送に必要な最短時間を示しています。実際の時間には、復号とディスクへの書き込みに加え、どの snapshot が必要かを特定する時間も含まれます。
  • データベースダンプを scratch instance に読み込むなど、状態を持つデータを復元します。展開できる tar file だけでは、アプリケーションが起動することの証明になりません。

世界で最も安価なディスクでも、そこから一度復元するまでは価値がありません。

FAQ

VPS プロバイダーのスナップショットはオフサイトバックアップですか?

いいえ。プロバイダーのスナップショットは、コピー元のサーバーと同じアカウント内にあり、同じ管理パネルのログイン情報で管理され、同じ請求に含まれます。そのログイン情報を取得した攻撃者は、1 回のセッションでサーバーとそのすべてのスナップショットを削除できます。スナップショットは、リスクの高いアップグレード前に迅速にロールバックする用途には便利ですが、別の場所にあるコピーではありません。オフサイトコピーは、別のアカウント、できれば別のプロバイダーの配下に置き、コピー元のマシンにはその認証情報を保持させません。

1 か月分のバックアップを保持するには、どれだけのディスク容量が必要ですか?

スナップショットの数ではなく、最も古いスナップショットの経過期間を基準に容量を見積もります。重複排除に対応したツールは、各一意のチャンクを 1 回だけ保存します。そのため、リポジトリの容量はおおむね、コピー元のデータ量に、1 日あたりの新しい一意のデータ量へ保持日数を掛けたものを加えた値になります。データ量が 500 GB で、1 日に 5 GB 変化する場合、日次バックアップを 1 週間保持すると約 535 GB、履歴を 1 年分保持すると 2,325 GB です。これに加えて余裕を確保してください。ディスクが満杯になると次のバックアップに失敗します。また、restic の prune は、容量を解放する前に pack ファイルを再構成するための空き容量を必要とします。

侵害されたサーバーは、自身のオフサイトバックアップを削除できますか?

はい。対策を設計していない場合は削除できます。通常の SSH または SFTP リポジトリでは、書き込みに使う鍵で削除も実行できます。コピー元にはデータを削除できない認証情報を付与してください。たとえば、DatastoreBackup ロールだけを持ち、Datastore.Prune 権限を持たない PBS API トークンを使う方法があります。または、--append-only を指定して起動した rest-server に対して restic を使用する方法もあります。この構成では、既存のバックアップの削除と変更が拒否されます。プル方式なら、さらに強固にできます。コピー元がバックアップホストの認証情報を一切保持しないためです。保持期間の処理は、コピー元ではない側で実行してください。

バックアップ用 VPS では Proxmox Backup Server と restic のどちらを実行すべきですか?

復元する単位に合わせてツールを選びます。コピー元が Proxmox VE で、仮想マシン全体を復元したい場合は PBS を実行します。PBS はディスクイメージ単位でバックアップし、1 回の操作で VM を復元できるためです。コピー元が Linux ホストで、ファイルやデータベースダンプを復元したい場合は restic を実行します。restic は保存先の SSH アカウントだけを必要とし、送信前にデータを暗号化します。両方を実行する構成も一般的です。ハイパーバイザーには PBS を使い、その上で稼働していないサーバーには restic を使います。

VPS バックアップからの復元にはどのくらい時間がかかりますか?

データ量をリンク速度で割って最短時間を求め、復号と書き込みにかかる時間を加えます。100 Mbit/s のリンクで 500 GB を復元する場合、回線速度どおりなら 11.1 時間です。同じ復元を 1 Gbit/s のポートで行う場合は 1.1 時間です。小さなファイルが多数ある場合は、ファイルごとのオーバーヘッドがあるため、この計算より遅くなります。実際の復元を 1 回計測し、その測定値を使用してください。復旧計画が信頼できるのは、その実測値だけです。

#backups#restic#proxmox-backup-server#storage-vps#3-2-1