自宅サーバー(openSUSE)のバックアップ方法(snapshots,rsync)

Home Server Backup Methods for openSUSE (Snapshots and Rsync)

はじめに

※自宅や小規模のビジネスでopenSUSEサーバーを利用している方向けの記事となっています。

openSUSEサーバーを自宅で稼働させています。自宅サーバーはデータセンターやクラウドとは異なり、いつ壊れるかわからないというデメリットがあるのですが、自分で様々カスタマイズ可能というメリットもあります。
気に入らないパーツを付け替えたり増設したり。OSの設定から、サービスの詳細な挙動、ネットワーク構成まで、自分のニーズに合わせて柔軟にカスタマイズすることができるのが楽しいところです。
このようなカスタマイズの自由度が高いからこそ、システムの安定性と重要なデータの保護がより重要になってきます。信頼性の高いバックアップが不可欠です。今回は他のIT環境での経験や知見を参考にしながら、自宅サーバーのバックアップ方法について詳しく記載していきたいと思います。

snapshots

openSUSEやUbuntuサーバーにはsnapshotsというデフォルトのバックアップ機能を採用しています。これは自分で設定した時間にバックアップを行ってくれるもので、瞬間的なものではありますが、完全な状態のものを一時的に保存してくれるというものになっています。
snapshotsがバックアップをとるタイミングですが、

  • OS等アップデート
  • 定期実行
  • 手動実行(コマンドに付随させる形)
    という風になっており、OSアップグレードやパッケージのアップデート・ダウンロード時にはsnapshotsが稼働してバックアップを手動で行ってくれるようになっています。
    私が自宅用サーバーにopenSUSEを選んだ理由としてはそういったバックアップが簡単に行えること・ロールバックが容易・GRUB上からsnapshotsの時刻を選んでロールバックを出来ることが挙げられます。
    自分も今までに、システムが壊れてLinuxが起動しなくなったときに助けてもらったことが多々あります。ほんとに優秀なバックアップツールです。

snapshotsのデメリット

snapshotは、一部ファイルのみをロールバックすることに特化しています。

Warning: Data Consistency
There is no mechanism to ensure data consistency when creating a snapshot. Whenever a file (for example, a database) is written at the same time as the snapshot is being created, it will result in a corrupted or partly written file. Restoring such a file will cause problems. Furthermore, some system files such as /etc/mtab must never be restored. Therefore it is strongly recommended to always closely review the list of changed files and their diffs. Only restore files that really belong to the action you want to revert.(https://doc.opensuse.org/documentation/leap/archive/15.0/reference/html/book.opensuse.reference/cha.snapper.htmlより引用)

これを要約すると、

  • スナップショット作成中にファイルが同時に書き込まれると、データが破損する可能性がある
  • 復元する際は変更されたファイルを慎重に確認し、必要なファイルのみを選択的に復元することが重要
  • 特定のシステムファイル(/etc/mtab)は復元してはいけない

以上のことから、デメリットとして挙げられるのがストレージが物理的に壊れた場合です。物理的な劣化(ディスクの寿命など)、セクター不良、ヘッドクラッシュでは完全な復旧が難しいことが多いです。
また、snapshotsのコピーを別ストレージに移しただけではだめで、重要なシステム設定や深いレベルのファイルが欠落する可能性があります。
snapshotsは通常、 同一のストレージデバイス上に保存されるため、機器全体の障害時には無効になる こともあるということです。

rsyncによる定期バックアップ

rsyncとは、Linuxに昔からあるバックアップで、システムの完全なファイルコピーを行うものです。弱点としてはsnapshotsのように 差分バックアップでないため、時間がかかる ことです。また、復旧にも作業がかかります。
完全にシステムを戻すことが可能ですが、snapshotのように時間を選んだだけでは起動せず、復旧にはある程度の知識と時間が必要になります。

バックアップの設計

snapshotsを常に稼働させつつ、別のストレージで定期的にrsync等のバックアップツールを利用することが重要です。
今回は基本的にどのディストリビューションにも標準でインストールされているrsyncを使った方法を載せます。
一日に一回完全バックアップさせるだけでも十分なので、バックアップスクリプトを作成することが必要だと思います。
※snapshotsの場合はパッケージをダウンロード・有効にすると稼働します。細かい時間の設定はetc/snapper/conf.dで設定が可能です。


実際に私が稼働させているスクリプトは以下のものです。rsyncをシステム以下に指定(rsync / path/backup)してもよかったのですが、大容量ファイルが省かれてしまう可能性があることや、必要のないファイルもバックアップしてしまうため、1つ1つ手入力で必要か・不要かを見極めてコピーさせる方が結果的に効率が良いと思います。

#!/bin/bash
BASE_BACKUP_DIR="/mnt/backup/full_system_backup"
BACKUP_DIR="${BASE_BACKUPDIR}/backup$(date +"%Y%m%d_%H%M%S")"
LOG_FILE="${BASE_BACKUP_DIR}/backuplog$(date +"%Y%m%d_%H%M%S").txt"
echo "バックアップ開始: $(date)" | tee -a "$LOG_FILE"
mkdir -p "$BACKUP_DIR"
echo "/homeをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /home "$BACKUP_DIR" --exclude={"/home/swapfile","/home//.cache/"} 2>&1 | tee -a "$LOG_FILE"
echo "/srvをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /srv "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/usrをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /usr "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/binをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /bin "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/sbinをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /sbin "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/libをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /lib "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/lib64をバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /lib64 "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/bootをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /boot "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/etcをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /etc "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/optをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /opt "$BACKUP_DIR" 2>&1 | tee -a "$LOG_FILE"
echo "/rootをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /root "$BACKUP_DIR" --exclude={"/root/.cache/"} 2>&1| tee -a "$LOG_FILE"
echo "/varをバックアップ中..." | tee -a "$LOG_FILE"
sudo rsync -avxHAXP --stats /var "$BACKUP_DIR" --exclude={'var/tmp/','var/cache/','var/log/journal/'} 2>&1 | tee -a "$LOG_FILE"

echo "パーティション情報のバックアップ中..." | tee -a "$LOG_FILE"
sudo fdisk -l > "${BACKUP_DIR}/partition_info.txt" 2>&1
sudo blkid >> "${BACKUP_DIR}/partition_info.txt" 2>&1

echo "パッケージリストを保存中..." | tee -a "$LOG_FILE"
sudo zypper pa > "${BACKUP_DIR}/installed_packages.txt" 2>&1

echo "ブートローダー設定を保存中..." | tee -a "$LOG_FILE"
sudo grub2-mkconfig -o "${BACKUP_DIR}/grub.cfg" 2>&1

echo "バックアップ完了: $(date)" | tee -a "$LOG_FILE"
echo "バックアップサイズ:" | tee -a "$LOG_FILE"
du -sh "$BACKUP_DIR" | tee -a "$LOG_FILE"

echo "古いバックアップの削除中..." | tee -a "$LOG_FILE"

# どちらか選択

# 日数制限
#find "$BASE_BACKUPDIR" -maxdepth 1 -type d -name "backup" -mtime +10 -exec rm -rf {} \; 2>&1 | tee -a "$LOG_FILE"


# バックアップの数を制限
MAX_BACKUPS=10
BACKUP_DIRS=($(find "$BASE_BACKUPDIR" -maxdepth 1 -type d -name "backup" -print0 | xargs -0 ls -dt))
if [ ${#BACKUP_DIRS[@]} -gt $MAX_BACKUPS ]; then
    BACKUPS_TO_REMOVE=$((${#BACKUP_DIRS[@]} - MAX_BACKUPS))
    for ((i=0; i<BACKUPS_TO_REMOVE; i++)); do
        echo "古いバックアップを削除: ${BACKUP_DIRS[${#BACKUP_DIRS[@]}-1-$i]}" | tee -a "$LOG_FILE"
        rm -rf "${BACKUP_DIRS[${#BACKUP_DIRS[@]}-1-$i]}" 2>&1 | tee -a "$LOG_FILE"
    done
else
    echo "バックアップ数が制限以下" | tee -a "$LOG_FILE"
fi
echo "古いバックアップの削除が完了" | tee -a "$LOG_FILE"

「どちらか選択」という部分で日数経過で古いバックアップを削除するか、規定数を超えたときに削除するか選べるようになっています(スクリプトは数で制限中)。
また、単純なバックアップ以外にも、

  1. 出力ログファイル
  2. インストールパッケージ一覧ファイル
  3. ブートローダー設定
  4. パーティション情報
    などを保存するようになっています。
    私の場合、利用率の低い深夜2時に一回これを回すようになっています。一回のバックアップの総容量が25GBぐらいなので、大体数分で終わります(古いPCなので多少遅いです)。
# VISUAL=emacs crontab -e
0 2 * * * /root/bin/backup_system_cron.sh > /dev/null 2>&1

実際に壊れた時の流れ

snapshotsが使える(物理的破損ではない場合)

GRUB上でsnapshotsを選択or以下の流れ

sudo btrfs subvolume list /
# 直近の安定したスナップショットを特定
sudo btrfs subvolume list / | grep 'stable'

# スナップショットにロールバック
sudo btrfs subvolume set-default <スナップショットのID> /
# システム再起動
sudo reboot

snapshotsが使えない(物理的破損の場合)

1.リカバリメディアの準備

  • システムのインストールUSBまたはライブDVDを用意
  • OSと同じディストリビューション(もしくはその系列)のインストールメディアを推奨

2.ブートと初期設定

  • リカバリメディアからコンピュータを起動
  • ライブ環境またはレスキューモードを選択
  • バックアップを保存しているHDDをマウント

3.パーティションの再作成

  • バックアップしたpartition_info.txtを参照
  • fdiskまたはpartedを使用して、元と同じパーティション構成を再現
  • パーティションのフォーマット(mkfsコマンドを使用)

4.バックアップからのリストア

  • バックアップディレクトリから各ディレクトリを元の場所にrsyncまたはcpでコピー
  • 具体的には以下を順番にリストア:
  sudo rsync -avxHAXP /path/to/backup/home /home
  sudo rsync -avxHAXP /path/to/backup/etc /etc
  # 他のディレクトリも同様に

5.ブートローダーの再インストール

  • 保存したgrub.cfgを参照
  • grub2-installでブートローダーを再設定
  sudo grub2-install /dev/sda  # ブートデバイスに合わせて変更
  sudo grub2-mkconfig -o /boot/grub2/grub.cfg

6.パッケージの再インストール

  • installed_packages.txtを使用してパッケージを復元
sudo zypper in $(cat /path/to/backup/installed_packages.txt)

まとめ

このようにsnapshotsとrsyncを組み合わせることで、火事にでもならない限りデータが消えてしまうことは無くなると思います。
※最近はこれに加えてクラウドバックアップをとる企業がほとんどです。
今回は互換性の高いrsyncでのやり方について紹介しましたが、これら以外にもバックアップツールは沢山ありますので、そちらの方も今後紹介出来たらと思います。
自宅サーバーや小規模ビジネスの管理者の方の参考になれば幸いです。

追記:バックアップセキュリティとプライバシーの強化

バックアップファイルの暗号化

バックアップデータを保護するためには暗号化が非常に重要です。openSUSEでは、以下の方法で暗号化を実装できます

1.gpgを使用した暗号化

#bin/bash/sh
BACKUP_DIR="/mnt/backup/full_system_backup"
BACKUP_FILE="${BACKUP_DIR}/backup$(date +"%Y%m%d_%H%M%S").tar.gz"
ENCRYPTED_FILE="${BACKUP_FILE}.gpg"

# バックアップ作成
tar -czf "$BACKUP_FILE" /path/to/backup/directories

# GPGで暗号化(対話形式でパスフレーズを設定)
gpg -c "$BACKUP_FILE"

# 元のバックアップファイルを削除
rm "$BACKUP_FILE"

2.cryptsetupを使用した完全ディスク暗号化:

# バックアップディスクの暗号化
sudo cryptsetup luksFormat /dev/sdX  
sudo cryptsetup luksOpen /dev/sdX backup_disk
sudo mkfs.ext4 /dev/mapper/backup_disk

権限設定と機密データの取り扱い

1.バックアップディレクトリの権限設定

# バックアップディレクトリの権限を厳密に設定
sudo chmod 700 /mnt/backup
sudo chown root:root /mnt/backup

2.機密データの除外と特別な取り扱い

# バックアップスクリプトに追加
# 機密ファイルの特別な処理
SENSITIVE_FILES=(
    "/home/*/.ssh/*"
    "/home/*/.gnupg/*"
    "/etc/shadow"
    "/root/.ssh/*"
)

# 機密ファイルを別途暗号化して保存
for file in "${SENSITIVE_FILES[@]}"; do
    find $file -type f | while read -r sensitive_file; do
        gpg -c "$sensitive_file"
    done
done

バックアップ失敗時の通知メカニズム

1.メール通知スクリプト

# バックアップスクリプトに追加
BACKUP_LOG_FILE="/mnt/backup/backuplog.txt"
ADMIN_EMAIL="admin@example.com"

backup_result=$(./backup_script.sh 2>&1)
backup_status=$?

# バックアップ失敗時の処理
if [ $backup_status -ne 0 ]; then
    echo "バックアップ失敗: $backup_result" | mail -s "バックアップ失敗通知" $ADMIN_EMAIL # 自身がよく使うメールツールに変更

    # システムログ
    logger -p user.error "バックアップ処理に失敗しました: $backup_result"
fi

2.Telegram等のサービスを使用した通知

#!/bin/bash
TELEGRAM_BOT_TOKEN="YOUR_TOKEN"
TELEGRAM_CHAT_ID="YOUR_ID"

send_telegram_message() {
    local message="$1"
    curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
         -d "chat_id=${TELEGRAM_CHAT_ID}" \
         -d "text=${message}"
}

# バックアップ失敗時に通知
if [ $backup_status -ne 0 ]; then
    send_telegram_message "バックアップ処理に失敗しました: $backup_result"
fi

注意点と推奨事項

1.機密性の高いデータの扱い

  • パスワード、鍵、認証情報は絶対に平文で保存しない
  • バックアップ前に機密ファイルを必ず暗号化
  • 暗号化キーは安全な場所に別途保管

2.アクセス制御

  • バックアップディレクトリへのアクセスを最小限の信頼できるユーザーのみに制限
  • 定期的に権限設定と暗号化の設定を見直す

3.多層的なバックアップ戦略

  • ローカルバックアップ
  • オフサイトバックアップ(クラウドまたはリモートストレージ)
  • 暗号化された外部ハードディスク

これらの追加設定により、バックアップのセキュリティと信頼性を大幅に向上させることができます。特に自宅サーバーや小規模ビジネスでは、データ保護は最優先事項となりますので今回の記事が誰かの参考になれば幸いです。

おわり