
個人ブログや技術サイトを自宅サーバーで運用する際、最も怖いのが「ストレージ障害」「停電」「ランサムウェア」などの致命的なデータ損失です。
バックアップの鉄則に「3-2-1ルール」(3つのコピー、2つの異なるメディア、1つのオフサイト保管)がありますが、これを個人・自宅サーバー環境でコストをかけずに実現するのは意外と骨が折れます。
今回は、オープンソースのバックアップツール Restic を軸に、「宅内NAS(ローカル)」+「Cloudflare R2(格安クラウド)」 の二重体制をシェルスクリプト1本で自動化する構成を紹介します。
1. システム構成の全体像
- Webサーバー: Ubuntu(WordPress 複数サイト稼働、RAMディスク併用)
- リポジトリ①(オンサイト): 宅内NAS(TeraStation / CIFSマウント)
- メリット: 同一LAN内のためリストア・転送が爆速
- リポジトリ②(オフサイト): Cloudflare R2(S3互換オブジェクトストレージ)
- メリット: 自宅が被災・停電してもデータが残る、下り転送(Egress)料金が完全無料
- エンジン: Restic
- 暗号化、重複排除(Deduplication)、増分バックアップを標準搭載
2. なぜRestic × Cloudflare R2なのか?
一般的な tar + rsync や WordPressプラグイン(UpdraftPlus等)に比べ、この構成には圧倒的な強みがあります。
- 暗号化が標準: クラウド(R2)にデータを預ける際も、クライアント側(サーバー側)でAES-256暗号化されてから送信されるため、盗聴や漏洩のリスクが極めて低い。
- 重複排除(Deduplication)の恩恵: サイト全体のファイル群(数GB)を毎日バックアップしても、差分ブロックしか送信・保存されません。追加の通信量・保存容量は数MB〜数十MBに抑えられます。
- コストがほぼゼロ: Cloudflare R2はストレージ料金が格安(10GBまで無料枠あり)で、他のクラウド(AWS S3等)と違って「復元時に発生する下り転送量(Egress)」が一切かかりません。
3. 自動バックアップスクリプトの実装
複数サイト(本館・別館など)のDBダンプ、RAMディスクの圧縮退避、2箇所への同時転送、古い世代の自動ローテーション(7日分保持)を1つのシェルスクリプトで完結させています。
スクリプト本体(/root/scripts/wp-backup.sh)
Bash
#!/bin/bash
# ==========================================
# ⚙️ 共通設定(認証情報・リポジトリ)
# ==========================================
RESTIC_PASSWORD="YOUR_SECURE_PASSWORD"
export AWS_ACCESS_KEY_ID="YOUR_R2_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="YOUR_R2_SECRET_ACCESS_KEY"
export RESTIC_PASSWORD
# リポジトリの場所
NAS_REPO="/mnt/nas_backup"
R2_REPO="s3:https://<ACCOUNT_ID>.r2.cloudflarestorage.com/<BUCKET_NAME>"
# 一時作業ディレクトリ
TMP_BACKUP_DIR="/tmp/wp_backup_files"
# ==========================================
# 📂 サイトごとの個別設定
# 形式:「識別名 ディレクトリパス DB名 DBユーザー DBパス」
# ==========================================
SITES=(
"main_site /var/www/example.com main_db_name main_db_user main_db_pass"
"tech_site /var/www/sub.example.com sub_db_name sub_db_user sub_db_pass"
)
RAM_DISK_DIR="/mnt/ramdisk"
echo "=== [$(date '+%Y-%m-%d %H:%M:%S')] バックアップ処理開始 ==="
for SITE_INFO in "${SITES[@]}"; do
read -r SITE_NAME BACKUP_TARGET_DIR DB_NAME DB_USER DB_PASS <<< "${SITE_INFO}"
echo "▶️ 【${SITE_NAME}】処理中..."
rm -rf "${TMP_BACKUP_DIR}" && mkdir -p "${TMP_BACKUP_DIR}"
# 1. データベースのダンプ
mysqldump -u"${DB_USER}" -p"${DB_PASS}" "${DB_NAME}" > "${TMP_BACKUP_DIR}/${SITE_NAME}_db.sql"
# 2. RAMディスクデータのアーカイブ(利用している場合)
if [ -d "${RAM_DISK_DIR}" ]; then
tar -czf "${TMP_BACKUP_DIR}/${SITE_NAME}_ramdisk.tar.gz" -C "${RAM_DISK_DIR}" .
fi
# 3. 宅内NASへ送信(リポジトリ①)
restic -r "${NAS_REPO}" backup "${BACKUP_TARGET_DIR}" "${TMP_BACKUP_DIR}"
# 4. Cloudflare R2へ送信(リポジトリ②)
restic -r "${R2_REPO}" backup "${BACKUP_TARGET_DIR}" "${TMP_BACKUP_DIR}"
done
# ==========================================
# 🧹 古いバックアップのお掃除(7日分をキープ)
# ==========================================
echo "🧹 世代ローテーション実行中..."
restic -r "${NAS_REPO}" forget --keep-within 7d --prune
restic -r "${R2_REPO}" forget --keep-within 7d --prune
rm -rf "${TMP_BACKUP_DIR}"
echo "=== [$(date '+%Y-%m-%d %H:%M:%S')] すべてのバックアップが正常に完了しました ==="4. 自動化(cron)と確認用ショートカット
cronの設定
毎朝午前3時に自動実行されるよう crontab に登録します。
Bash
sudo crontab -ePlaintext
0 3 * * * /root/scripts/wp-backup.sh >> /var/log/wp-backup.log 2>&1スナップショット一覧を一発確認するエイリアス
NASとR2の両方のスナップショットをターミナルでサッと見られるよう、/usr/local/bin/restic-list などの確認スクリプトを用意しておくと便利です。
Bash
sudo restic-listPlaintext
=== 宅内NAS のバックアップ一覧 ===
repository a1b2c3d4 opened (version 2, compression level auto)
ID Time Host Paths
----------------------------------------------------------------------------------------
1a2b3c4d 2026-09-18 03:00:15 web-server /tmp/wp_backup_files, /var/www/example.com
5e6f7a8b 2026-09-18 03:00:28 web-server /tmp/wp_backup_files, /var/www/sub.example.com
=== Cloudflare R2 のバックアップ一覧 ===
(同様に7日分の世代が綺麗に並ぶ)まとめ:運用してみて分かったこと
- 帯域への負荷がほぼない: 初回こそ数分かかりますが、2回目以降は変更があった数MBのファイルしか送られないため、数秒〜十数秒で完了します。
- NAS換装・障害時も安心: どちらか片方のストレージが完全にクラッシュしても、もう一方に暗号化された全世代が生き残っているため、精神的な安心感が段違いです。
- 運用の手間ゼロ:
forget --keep-within 7d --pruneにより、ディスク容量が溢れる心配もありません。
自宅サーバーでブログを公開している方は、ぜひこの「ローカルNAS + R2」の二重構成を試してみてください。



コメント