深夜2時のVPSクラッシュと痛恨の教訓
1年以上前のこと、45GBのPostgreSQLを運用していたVPSが突然停止しました。ホスティング業者の物理ストレージアレイの障害が原因でした。ECサイトの全データベースと120GBを超えるアップロード画像ファイルが、わずか数分ですべて消滅してしまったのです。
それまでの私は完全に油断していました。ファイルを圧縮して同じVPS上の/home/backupパーティションに保存するcronjobを設定していただけでした。さらにホスティング業者の週次自動スナップショットをお守り代わりにしていたのです。しかし、物理サーバー全体のコントローラーが破損したことで、本番データもバックアップも跡形もなく消え去ってしまいました。
「本番サーバーと同じカゴにバックアップを入れるな」。この苦い経験から、現在運用している20台のUbuntu VPSすべてにおいて、私が最初に行う作業は必ず外部へデータを退避させるオフサイト転送パイプラインの構築になりました。
一般的な同期ツールが途中で破綻しやすい理由
理想的なソリューションに行き着く前、さまざまな方法を試しましたが、いずれも厄介な問題に直面しました。
- Google DriveやOneDriveにはLinux向けの公式CLIが存在しない: SSH経由のGUIがないヘッドレスVPS環境でアカウント認証を通すのは一苦労です。
- サードパーティ製ツールが大量のRAMを消費する: PythonやNode.jsベースのスクリプトは、実行時に150MB〜300MBものメモリを消費しがちです。1GB RAMの格安VPSプランでは、OSのOOM Killerが発動してデータベースプロセスを強制終了させてしまうリスクがあります。
- REST APIを直接叩く自作スクリプトはメンテナンスが困難: curlを使う場合、OAuth2トークンの更新ロジック、5GB超のファイルに対するチャンクアップロード処理、ネットワーク切断時のリトライ制御などをすべて自前で実装しなければなりません。
比較検討した代替案
検討対象に上がった3つの定番アプローチは以下の通りです。
- SSH経由で専用バックアップVPSへRsync: 安定性と速度は抜群です。しかし、ファイル保管のためだけに毎月5〜10ドルを払ってサブサーバーを維持する必要があります。また、VPSのディスク増設費用はオブジェクトストレージと比べて大幅に割高です。
- AWS CLI / s3cmd: AWS S3、Cloudflare R2、Wasabiなどと連携させるには非常に快適です。ただし、Google Drive Workspaceや1TBのOneDrive Familyといった既存のクラウドアカウントの空き容量を活用できないのが大きな難点です。
- BorgBackup: 圧縮率や重複排除機能はトップクラスです。一方で、インフラ専門職でないエンジニアにとって、個人向けクラウドストレージをリモートバックエンドとして構成するハードルはかなり高めです。
Rclone: システム管理者にとって軽量な救世主
こうした課題をすべて解消してくれたのがRcloneでした。Go言語で書かれており、単一のバイナリファイルとして完結しています。実行時のメモリ消費量はわずか20MB〜35MB程度です。40種類以上のクラウドサービスに対応しており、トークンの自動更新からファイル分割アップロードまでをすべて標準で処理してくれます。
ステップ1: UbuntuへのRcloneの推奨インストール手順
apt install rcloneでのインストールは避けてください。Ubuntuの公式リポジトリは1〜2年前の古いバージョンが登録されていることが多く、GoogleやMicrosoftのAPI仕様変更時にエラーが発生しやすくなります。公式のインストールスクリプトを利用しましょう。
sudo -v && curl https://rclone.org/install.sh | sudo bash
# バージョン確認
rclone version
ステップ2: Google Drive、AWS S3、OneDriveのリモート設定
対話型設定画面を起動します。
rclone config
1. Google Driveの設定
nを入力して新規作成し、名前にgdriveと入力後、Google Driveに該当する番号を選択します。ターミナルにUse web browser to automatically authenticateと表示されたら、VPSにはブラウザがないためnを選択します。
すると、Rcloneが認証用コマンドを出力します。ご自身のPC(ローカル環境)のターミナルを開き、そのコマンドを実行します。
# ブラウザが利用可能なローカルPCで実行
rclone authorize "drive" "client_id" "client_secret"
自動的にWebブラウザが起動するので、アカウントの権限を承認します。承認が完了すると、ローカルPCのターミナルにアクセストークンを含むJSON文字列が出力されます。この文字列をすべてコピーし、VPS側のターミナルに貼り付ければ完了です。
2. AWS S3(またはCloudflare R2 / MinIO)の設定
S3はAccess Keyを直接使用できるため、よりシンプルです。リモート名をs3_backupとし、Amazon S3 Compliant Storage Providerを選択してパラメータを入力します。
provider> AWS
env_auth> false
access_key_id> AKIAIOSFODNN7EXAMPLE
secret_access_key> wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region> ap-southeast-1
location_constraint> ap-southeast-1
acl> private
3. OneDriveの設定
手順はGoogle Driveとほぼ同様です。リモート名をonedriveとし、ローカルPC上でrclone authorize "onedrive"を実行して取得したトークンを貼り付けます。
ステップ3: 接続テストの実施
いきなり自動化スクリプトを書くのではなく、まずは正常に疎通できているか接続テストを行います。
# Google Driveのディレクトリ一覧を表示
rclone lsd gdrive:
# S3のバケット一覧を表示
rclone lsd s3_backup:
# 小さなファイルで転送テスト
rclone copy /etc/hosts gdrive:Server_Backups/Test/
非常に重要な注意点: Rcloneには混同しやすいコマンドとしてcopyとsyncがあります。copyコマンドは新規ファイルや変更されたファイルのみを転送し、クラウド上の既存ファイルはそのまま保持します。一方、syncコマンドは一方向のミラー同期を行います。つまり、VPS上で誤ってファイルを削除した場合、次回の実行時にクラウド側のファイルも完全に削除されてしまいます。バックアップ目的であれば、必ずcopyを使用してください。
ステップ4: 自動圧縮・転送スクリプトの作成
/opt/scripts/backup.shを作成します。
#!/usr/bin/env bash
set -euo pipefail
# 変数設定
DATE=$(date +%Y-%m-%d_%H%M%S)
BACKUP_DIR="/var/backups/daily"
WEB_DIR="/var/www"
DB_NAME="my_production_db"
DB_USER="db_backup_user"
DB_PASS="MatKhauSieuKho123!"
LOG_FILE="/var/log/rclone_backup.log"
mkdir -p "$BACKUP_DIR"
# 1. gzipを使用して安全にデータベースをダンプ
echo "[$(date)] データベースをダンプ中..." >> "$LOG_FILE"
mysqldump -u"$DB_USER" -p"$DB_PASS" --single-transaction --quick "$DB_NAME" | gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"
# 2. ソースコードの圧縮
echo "[$(date)] ソースコードを圧縮中..." >> "$LOG_FILE"
tar -czf "$BACKUP_DIR/web_${DATE}.tar.gz" -C "$WEB_DIR" .
# 3. Google Driveへファイルをアップロード
echo "[$(date)] Google Driveへのアップロードを開始..." >> "$LOG_FILE"
rclone copy "$BACKUP_DIR" gdrive:Server_Backups/Daily/ \
--bwlimit 10M \
--transfers 2 \
--log-file "$LOG_FILE" \
--log-level NOTICE
# 冗長化のためS3へ予備バックアップを転送
rclone copy "$BACKUP_DIR" s3_backup:my-backup-bucket/Daily/ \
--bwlimit 10M \
--transfers 2
# 4. ディスク容量確保のため3日以上経過したローカルバックアップを削除
find "$BACKUP_DIR" -type f -name "*.gz" -mtime +3 -delete
echo "[$(date)] バックアップが正常に完了しました!" >> "$LOG_FILE"
実行権限を付与します。
sudo chmod +x /opt/scripts/backup.sh
ステップ5: Crontabによる自動実行の設定
rootのcron設定を開きます。
sudo crontab -e
毎日深夜2時30分にバックアップを実行するよう、以下の行を追加します。
30 2 * * * /opt/scripts/backup.sh > /dev/null 2>&1
本番環境運用における実践的なTips
--bwlimit 10Mの設定を忘れずに: 20GB〜30GBクラスの圧縮ファイルを帯域無制限で転送すると、VPSのネットワーク帯域を使い果たしてしまいます。その結果、バックアップ中にWebサイトへのアクセスが遅延・切断される原因になります。10MB/s〜15MB/s程度に制限しておくのが理想的です。- Google DriveのHTTP 403エラーを回避する: Googleは1アカウントあたり1日750GBのアップロード制限を設けており、API呼び出し頻度にも制限があります。24時間のAPI一時ブロックを防ぐためにも、
--transfers 2 --checkers 4のように並列度を抑えて運用するのが賢明です。 crypt機能でデータを暗号化する: パブリッククラウド上に機密情報を保管することに懸念がある場合は、元のremoteの上にcryptタイプのリモートを被せて作成しましょう。VPSのメモリ上でAES-256暗号化を施してから転送するため、クラウド事業者側からは暗号化された無意味なバイナリデータにしか見えなくなります。
