1. 実際に直面した現場の課題:ディスク容量枯渇の惨劇と従来のrsyncの限界
インフラエンジニア(sysadmin)になりたての頃、私は今でも忘れられない苦い失敗を経験しました。MySQLと顧客の画像ファイルが保存されたuploadsディレクトリを運用するサーバー群のデータ容量が、急速に320GBを超えて膨れ上がっていたのです。安全を期すため、私はtar.gzでアーカイブを作成し、毎日午前2時にrsyncでバックアップサーバーへ転送するシェルスクリプトを組みました。
ところが2週間後、アラート通知が鳴り止まなくなりました。バックアップサーバーの2TB HDDが使用率100%(Disk Full)に達してしまったのです。さらに追い討ちをかけるように、本番サーバーがランサムウェアの攻撃を受けました。追加専用(append-only)のスナップショット保護機構を設けていなかったため、バックアップサーバー上にそのまま配置されていた.tar.gzファイルも被害に遭いました。肥大化した圧縮ファイルのせいで内部1Gbpsネットワーク帯域が完全に飽和し、データ復旧には18時間以上を要することになりました。
2. 原因分析:なぜ従来のバックアップ手法は破綻するのか?
インシデントを徹底的に振り返った結果、システム破綻を引き起こした3つの致命的な弱点が見えてきました。
- 重複排除(Deduplication)の欠如によるディスク容量の浪費:ソースコードやデータベースダンプの日常的な変更量は全体のわずか3〜5%程度です。しかし
tar.gzは毎回100%の全容量を圧縮・保存します。10世代のバックアップを保持するだけで、単純に10倍のストレージ容量を消費してしまいます。 - セキュリティの脆弱性:転送経路も保存先のファイルも平文(プレーンテキスト)のままでした。万が一バックアップサーバーが侵害されれば、顧客のデータベース情報がすべて盗まれるリスクがありました。
- 巨大ファイル処理時におけるRsyncの高負荷:50〜80GB規模のSQLダンプファイルの一部が書き換わっただけでも、rsyncはブロックチェックサムのスキャンに数時間を費やし、転送元サーバーのCPU使用率が100%に張り付いてしまいました。
3. Linuxにおける主要なバックアップ方式の比較
この課題を解決するため、インフラエンジニアは通常次の3つのアプローチを検討します。
- アプローチ1:BtrfsやZFSのスナップショットをSSH経由で送信する。ブロック層で直接転送されるため極めて高速です。ただし、転送元と転送先の双方が同じBtrfs/ZFSファイルシステムでフォーマットされている必要があり、安価なVPSやクラウドストレージを利用する場合には導入ハードルが高くなります。
- アプローチ2:ResticまたはDuplicityを採用する。ResticはS3やMinIOなど多彩なバックエンドをネイティブサポートしています。しかし、物理サーバー上でリポジトリが数百万個のチャンク規模に巨大化すると、Resticは大量のRAMを消費します(prune実行時にメモリ消費が4〜8GBに達することも珍しくありません)。
- アプローチ3:BorgBackup(Borg)を導入する。C言語とPythonで開発された、重複排除に特化した高機能ツールです。ファイルを細かなチャンクに分割してハッシュ化し、クライアント側で暗号化を施した上でSSH転送します。保存先に既存のチャンクが存在する場合は即座にスキップされます。
4. 最適解:Fedora Server上にBorgBackupを構築しSSH経由で自動化する
Fedora Serverにおいて、BorgBackupは最も堅牢かつ有力な選択肢です。省メモリ設計で動作が安定しており、パッケージリポジトリから常に最新のアップストリーム版を入手できます。
ステップ1:両サーバーへのBorgBackupのインストール
Borgは転送元(Fedora Server)と転送先(バックアップストレージサーバー)の双方に導入する必要があります。FedoraではDNFを使ってインストールします。
sudo dnf install -y borgbackup
バックアップサーバー(Ubuntu、Debian、またはCentOS/Fedora)側でも、対応するパッケージマネージャーでインストールします。
# バックアップサーバーがUbuntu/Debianの場合
sudo apt update && sudo apt install -y borgbackup
ステップ2:バックアップ専用SSHキーの設定
パスワード入力なしでバッチ処理を無人実行できるよう、Fedora Server側で専用のSSH鍵ペアを作成します。
# rootユーザー用のパスフレーズなしed25519鍵を生成
sudo ssh-keygen -t ed25519 -f /root/.ssh/id_borg_ed25519 -N ""
# 公開鍵をバックアップサーバーへ転送
sudo ssh-copy-id -i /root/.ssh/id_borg_ed25519.pub [email protected]
以下のコマンドを実行して接続テストを行います。
sudo ssh -i /root/.ssh/id_borg_ed25519 [email protected] "echo 'SSH接続に成功しました!'"
ステップ3:暗号化リポジトリの初期化(Borg Init)
ハッシュ計算が極めて高速で、AES-256によって強固に保護されるrepokey-blake2暗号化モードの利用を強く推奨します。Fedora Serverから初期化コマンドを実行します。
export BORG_RSH="ssh -i /root/.ssh/id_borg_ed25519"
export BORG_PASSPHRASE="MatKhauCucKyBaoMatCuaBan123@#"
# 転送先の /data/backups/fedora-app にリポジトリを初期化
borg init --encryption=repokey-blake2 [email protected]:/data/backups/fedora-app
極めて重要:暗号化キーは必ず別ファイルとしてエクスポートし、BitwardenなどのパスワードマネージャーやオフラインのUSBメモリに安全に退避してください。キーを紛失するとバックアップデータは二度と復元できなくなります。
borg key export [email protected]:/data/backups/fedora-app /root/borg-key-backup.txt
ステップ4:バックアップ&世代整理(Prune)スクリプトの作成
/usr/local/bin/borg-backup.shにシェルスクリプトを作成します。
sudo nano /usr/local/bin/borg-backup.sh
スクリプト内では高速性を重視してlz4圧縮アルゴリズムを採用し、直近7日、4週、6ヶ月の世代を保持するリテンションポリシーを適用します。
#!/usr/bin/env bash
set -euo pipefail
# 環境変数の設定
export BORG_REPO="[email protected]:/data/backups/fedora-app"
export BORG_PASSPHRASE="MatKhauCucKyBaoMatCuaBan123@#"
export BORG_RSH="ssh -i /root/.ssh/id_borg_ed25519 -o BatchMode=yes"
ARCHIVE_NAME="::fedora-backup-$(date +'%Y-%m-%d_%H%M%S')"
echo "[$(date)] BorgBackup処理を開始します..."
# 不要なキャッシュを除外して重要ディレクトリをバックアップ
borg create \
--verbose \
--stats \
--compression lz4 \
--exclude-caches \
"$BORG_REPO$ARCHIVE_NAME" \
/etc \
/var/www \
/home
echo "[$(date)] 保持ポリシーに基づいて古いスナップショットを整理中..."
# 保持世代数: 7日分、4週間分、6ヶ月分
borg prune \
--list \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
"$BORG_REPO"
echo "[$(date)] バックアップが正常に完了しました!"
パスフレーズが含まれるため、rootユーザーのみが読み取り・実行できるようパーミッションを厳格に制限します。
sudo chmod 700 /usr/local/bin/borg-backup.sh
ステップ5:Crontabに代わるSystemd Timerによる定期実行
Systemdタイマーを利用することで、journalctlを通じた高精度なログ追跡が可能になり、前回のジョブが未完了のまま次回ジョブが重複起動するトラブルも防止できます。
/etc/systemd/system/borg-backup.serviceにServiceユニットを作成します。
[Unit]
Description=BorgBackup Automated Job
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/borg-backup.sh
StandardOutput=journal
StandardError=journal
続いて、毎日午前2時に起動するTimerユニットを/etc/systemd/system/borg-backup.timerに作成します。
[Unit]
Description=Run BorgBackup Daily at 02:00 AM
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
設定をリロードしてタイマーを有効化・起動します。
sudo systemctl daemon-reload
sudo systemctl enable --now borg-backup.timer
# 次回実行スケジュールの確認
sudo systemctl list-timers borg-backup.timer
ステップ6:スナップショットの確認とリストア訓練
実際にリストア訓練を実施して初めて、バックアップ環境は完成したと言えます。リポジトリに保存されたスナップショット一覧を確認するには次を実行します。
export BORG_RSH="ssh -i /root/.ssh/id_borg_ed25519"
export BORG_PASSPHRASE="MatKhauCucKyBaoMatCuaBan123@#"
borg list [email protected]:/data/backups/fedora-app
データの整合性を確認するため、任意のスナップショットから/etcディレクトリのみをテスト抽出してみます。
mkdir -p /mnt/recovery && cd /mnt/recovery
# /etc のみを抽出(注: 先頭のスラッシュは除外する)
borg extract [email protected]:/data/backups/fedora-app::fedora-backup-2026-10-20_020000 etc
私の運用環境での実績値として、元データ320GBに対する30日分の継続バックアップが、バックアップサーバー上ではわずか48GBのディスク消費量に収まりました。Borgを導入することで、ストレージコストを最大85%削減しつつ、ハードウェア障害やマルウェアの脅威にも冷静かつ確実に対処できるようになります。

