VPSのバックアップを自動化する方法|cronとrsyncで安心のデータ保護環境を構築する手順・設定例・注意点を徹底解説【2026年版】
VPSを運用していて、最も怖いのが「データの消失」です。サーバーの障害、操作ミス、セキュリティ侵害など、データが失われるリスクは常に存在します。しかし、手動でバックアップを取る作業は面倒で、つい後回しにしてしまいがちではないでしょうか。
- なぜVPSのバックアップ自動化が重要なのか
- rsyncの基本と仕組みを理解する
- cronの基本とスケジュール設定
- 実践:バックアップスクリプトの作成と設定
この記事では、Linux標準のツールであるcronとrsyncを組み合わせて、VPSのバックアップを自動化する具体的な手順を解説します。コマンドの意味から実際の設定例、運用上の注意点まで、初心者の方でも理解できるように丁寧に説明していきます。バックアップの仕組みを一度構築してしまえば、あとは自動で動き続けるため、日々の運用負荷を大幅に下げることができます。
なぜVPSのバックアップ自動化が重要なのか
レンタルサーバー(共用サーバー)と異なり、VPSは基本的に自分自身でサーバー管理を行う必要があります。つまり、バックアップも自己責任です。多くのVPSプロバイダーはオプションで自動バックアップ機能を提供していますが、以下のような理由から、自前でのバックアップ環境構築を検討する価値があります。
プロバイダー提供のバックアップだけでは不十分な理由
- 復元の柔軟性が低い:プロバイダーのバックアップはサーバー全体のスナップショットが多く、特定のファイルだけを復元したい場合に不便
- バックアップ頻度が限られる:多くの場合、日次や週次など頻度が固定されており、リアルタイムに近いバックアップが取れない
- 追加料金がかかる:有料オプションとして提供されるケースが多い
- 保存世代数が少ない:直近1〜3世代のみ保持というプランも多い
一方、cronとrsyncを使った自前のバックアップであれば、バックアップ対象・頻度・保存先・保持世代数をすべて自由にコントロールできます。
バックアップが必要になる具体的なシーン
- WordPressのアップデート時にデータベースやファイルが破損した
rm -rfコマンドの誤操作でディレクトリを丸ごと削除してしまった- 不正アクセスによりファイルが改ざんされ、クリーンな状態に戻したい
- サーバー移行の際に、移行元のデータを確実に保持しておきたい
- 設定ファイルの変更前の状態に素早くロールバックしたい
これらは決して珍しいケースではなく、VPS運用をしていれば誰でも遭遇する可能性があります。「転ばぬ先の杖」として、バックアップの自動化は最優先で取り組むべき設定の一つです。
rsyncの基本と仕組みを理解する
rsyncは、ファイルやディレクトリの同期・コピーを効率的に行うLinuxコマンドです。単純なコピー(cpコマンド)と異なり、差分転送に対応しているため、変更があったファイルだけを転送します。これにより、2回目以降のバックアップが非常に高速になります。
rsyncの主要オプション解説
rsyncには多くのオプションがありますが、バックアップで特によく使うものを整理します。
| オプション | 意味 | 用途・備考 |
|---|---|---|
-a |
アーカイブモード | パーミッション・所有者・タイムスタンプなどを保持してコピー。-rlptgoDと同等 |
-v |
詳細表示 | 転送されたファイル名を表示。ログ取得時に便利 |
-z |
圧縮転送 | リモートへの転送時にデータを圧縮。ローカルコピーでは不要 |
--delete |
削除同期 | 転送元で削除されたファイルを転送先でも削除。完全なミラーリングに必要だが、誤操作のリスクもある |
--exclude |
除外指定 | バックアップ不要なファイルやディレクトリを除外 |
-e "ssh -p ポート番号" |
SSH接続指定 | リモートサーバーへのバックアップ時に使用 |
--log-file |
ログ出力 | 実行結果をファイルに記録。トラブルシューティングに役立つ |
rsyncの基本的な使い方
まずはローカル内でのバックアップの基本形です。
# ローカルディレクトリのバックアップ(基本形)
rsync -av /var/www/html/ /backup/www/
# 特定のファイルを除外してバックアップ
rsync -av --exclude='*.log' --exclude='cache/' /var/www/html/ /backup/www/
# リモートサーバーへバックアップ(SSH経由)
rsync -avz -e "ssh -p 22" /var/www/html/ user@backup-server:/backup/www/
重要な注意点として、rsyncではコピー元のパスの末尾にスラッシュ(/)を付けるかどうかで動作が変わります。/var/www/html/とすると「html内のファイル」が対象になり、/var/www/html(スラッシュなし)とすると「htmlディレクトリ自体」がコピーされます。バックアップスクリプトを書く際は、この違いを意識してください。
cronの基本とスケジュール設定
cronは、Linux/Unixシステムに標準搭載されているジョブスケジューラです。指定した日時に指定したコマンドを自動実行できます。バックアップスクリプトをcronに登録することで、完全な自動化が実現します。
crontabの書式
cronのスケジュールは5つのフィールドで表現されます。
分 時 日 月 曜日 コマンド
* * * * * 実行したいコマンド
│ │ │ │ │
│ │ │ │ └─ 曜日 (0-7, 0と7は日曜日)
│ │ │ └──── 月 (1-12)
│ │ └─────── 日 (1-31)
│ └────────── 時 (0-23)
└───────────── 分 (0-59)
よく使うスケジュール設定例
| 設定値 | 実行タイミング | 用途の例 |
|---|---|---|
0 3 * * * |
毎日 午前3時 | 日次バックアップ(深夜のアクセスが少ない時間帯) |
0 3 * * 0 |
毎週日曜 午前3時 | 週次フルバックアップ |
0 */6 * * * |
6時間ごと | 更新頻度の高いサイトの定期バックアップ |
30 2 1 * * |
毎月1日 午前2時30分 | 月次バックアップ |
0 4 * * 1-5 |
平日 午前4時 | 営業日のみバックアップ |
crontabの編集方法
# 現在のcrontabを確認
crontab -l
# crontabを編集(エディタが開く)
crontab -e
# 特定ユーザーのcrontabを編集(root権限が必要)
sudo crontab -u username -e
なお、cronで実行されるコマンドは、ログインシェルとは異なる環境変数で動作します。そのため、スクリプト内でコマンドのフルパス(例:/usr/bin/rsync)を使うか、スクリプトの冒頭でPATHを明示的に設定することをおすすめします。
実践:バックアップスクリプトの作成と設定
ここからは、実際にバックアップの自動化を構築する手順を、ユースケース別に解説します。
ユースケース1:VPS内のローカルバックアップ
最もシンプルな構成として、同一VPS内の別ディレクトリにバックアップを取る方法です。ディスク障害には対応できませんが、誤操作によるファイル削除などからの復旧には有効です。
ステップ1:バックアップ用ディレクトリの作成
sudo mkdir -p /backup/daily
sudo mkdir -p /var/log/backup
ステップ2:バックアップスクリプトの作成
以下のスクリプトを/usr/local/bin/backup-local.shとして保存します。
#!/bin/bash
# --------------------------------------------------
# VPS ローカルバックアップスクリプト
# 対象: Webサイトデータ + データベース
# --------------------------------------------------
# 設定
BACKUP_SRC="/var/www/html/"
BACKUP_DEST="/backup/daily/"
LOG_FILE="/var/log/backup/backup_$(date +%Y%m%d_%H%M%S).log"
DATE=$(date +%Y%m%d_%H%M%S)
# MySQL/MariaDBのデータベースバックアップ(WordPressなどを運用している場合)
DB_USER="your_db_user"
DB_PASS="your_db_password"
DB_NAME="your_db_name"
DB_BACKUP_DIR="/backup/daily/database/"
# ログ出力関数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "===== バックアップ開始 ====="
# データベースのバックアップ
mkdir -p "$DB_BACKUP_DIR"
if mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "${DB_BACKUP_DIR}${DB_NAME}_${DATE}.sql" 2>> "$LOG_FILE"; then
log "データベースバックアップ: 成功"
# 7日以上前のDBバックアップを削除
find "$DB_BACKUP_DIR" -name "*.sql" -mtime +7 -delete
log "古いDBバックアップの削除: 完了"
else
log "データベースバックアップ: 失敗"
fi
# ファイルのバックアップ(rsync)
if rsync -av --exclude='cache/' --exclude='*.log' --exclude='tmp/' \
"$BACKUP_SRC" "$BACKUP_DEST" >> "$LOG_FILE" 2>&1; then
log "ファイルバックアップ: 成功"
else
log "ファイルバックアップ: 失敗"
fi
# 30日以上前のログファイルを削除
find /var/log/backup/ -name "*.log" -mtime +30 -delete
log "===== バックアップ完了 ====="
ステップ3:スクリプトに実行権限を付与
sudo chmod +x /usr/local/bin/backup-local.sh
ステップ4:cronに登録
# rootユーザーのcrontabを編集
sudo crontab -e
# 以下の行を追加(毎日午前3時に実行)
0 3 * * * /usr/local/bin/backup-local.sh
注意:スクリプト内にデータベースのパスワードを平文で記載していますが、これはセキュリティ上のリスクがあります。本番環境では、MySQLの設定ファイル(~/.my.cnf)にパスワードを記載し、パーミッションを600に設定する方法を推奨します。
# ~/.my.cnf の例
[mysqldump]
user=your_db_user
password=your_db_password
# パーミッションを設定
chmod 600 ~/.my.cnf
この設定をすれば、スクリプト内で-uや-pオプションを指定せずにmysqldumpを実行できます。
ユースケース2:リモートサーバーへのバックアップ(推奨)
より安全なバックアップのために、別のサーバーへrsyncでデータを転送する方法です。VPS自体が障害で利用不能になってもデータを復旧できます。
事前準備:SSHの公開鍵認証を設定
cronから自動実行するためには、パスワードなしでSSH接続できるように公開鍵認証を設定する必要があります。
# バックアップ元のVPSで鍵ペアを生成(パスフレーズなし)
ssh-keygen -t ed25519 -f ~/.ssh/id_backup -N ""
# 公開鍵をバックアップ先サーバーに登録
ssh-copy-id -i ~/.ssh/id_backup.pub user@backup-server
# 接続テスト
ssh -i ~/.ssh/id_backup user@backup-server "echo OK"
リモートバックアップスクリプトの例(/usr/local/bin/backup-remote.sh)
#!/bin/bash
# --------------------------------------------------
# VPS リモートバックアップスクリプト
# --------------------------------------------------
# 設定
REMOTE_USER="backupuser"
REMOTE_HOST="backup-server.example.com"
REMOTE_PORT="22"
SSH_KEY="/root/.ssh/id_backup"
BACKUP_SRC="/var/www/html/"
REMOTE_DEST="${REMOTE_USER}@${REMOTE_HOST}:/backup/vps01/"
LOG_FILE="/var/log/backup/remote_$(date +%Y%m%d).log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "===== リモートバックアップ開始 ====="
# rsyncでリモートバックアップ
rsync -avz --delete \
--exclude='cache/' \
--exclude='*.log' \
--exclude='tmp/' \
-e "ssh -i ${SSH_KEY} -p ${REMOTE_PORT} -o StrictHostKeyChecking=yes" \
"$BACKUP_SRC" "$REMOTE_DEST" >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
log "リモートバックアップ: 成功"
else
log "リモートバックアップ: 失敗(終了コード: $?)"
# 失敗時にメール通知(mailコマンドが使える場合)
# echo "バックアップ失敗" | mail -s "[ALERT] VPSバックアップ失敗" [email protected]
fi
log "===== リモートバックアップ完了 ====="
このスクリプトでは--deleteオプションを使用しています。これにより、バックアップ元で削除されたファイルはバックアップ先でも削除されます。筆者の見解では、ミラーリングとしては正しい動作ですが、誤操作で重要ファイルを削除した場合にバックアップ先からも消えてしまうリスクがあります。世代管理(後述)と組み合わせて運用することを強くおすすめします。
バックアップの世代管理とローテーション
「最新の状態だけ」をバックアップしていると、ファイルの破損や改ざんに気づかないまま上書きしてしまう危険があります。過去の複数世代を保持しておくことで、任意の時点の状態に戻せるようになります。
rsyncの--link-destオプションを使った世代管理
rsyncの--link-destオプションを使うと、前回のバックアップから変更がないファイルはハードリンクで参照されるため、ディスク容量を抑えつつ複数世代を保持できます。
#!/bin/bash
# --------------------------------------------------
# 世代管理付きバックアップスクリプト
# --------------------------------------------------
BACKUP_BASE="/backup/generations"
BACKUP_SRC="/var/www/html/"
DATE=$(date +%Y%m%d_%H%M%S)
LATEST_LINK="${BACKUP_BASE}/latest"
BACKUP_DEST="${BACKUP_BASE}/${DATE}"
KEEP_GENERATIONS=7 # 保持する世代数
LOG_FILE="/var/log/backup/gen_${DATE}.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
mkdir -p "$BACKUP_BASE"
log "===== 世代管理バックアップ開始 ====="
# --link-dest で前回バックアップとの差分のみ実体コピー
if [ -d "$LATEST_LINK" ]; then
rsync -av --link-dest="$LATEST_LINK" \
--exclude='cache/' --exclude='*.log' \
"$BACKUP_SRC" "$BACKUP_DEST" >> "$LOG_FILE" 2>&1
else
rsync -av \
--exclude='cache/' --exclude='*.log' \
"$BACKUP_SRC" "$BACKUP_DEST" >> "$LOG_FILE" 2>&1
fi
if [ $? -eq 0 ]; then
# latestシンボリックリンクを更新
rm -f "$LATEST_LINK"
ln -s "$BACKUP_DEST" "$LATEST_LINK"
log "バックアップ成功: $BACKUP_DEST"
else
log "バックアップ失敗"
exit 1
fi
# 古い世代を削除(KEEP_GENERATIONS より古いものを削除)
cd "$BACKUP_BASE" || exit 1
ls -dt */ 2>/dev/null | grep -v 'latest' | tail -n +$((KEEP_GENERATIONS + 1)) | while read -r old_dir; do
rm -rf "${BACKUP_BASE}/${old_dir}"
log "古い世代を削除: ${old_dir}"
done
log "===== 世代管理バックアップ完了 ====="
バックアップ方式の比較
| 方式 | ディスク使用量 | 復旧の容易さ | 世代管理 | 適したケース |
|---|---|---|---|---|
| rsync 単純ミラー | 少ない(1世代分) | 簡単 | 不可 | 容量が限られている場合 |
| rsync + –link-dest | 中程度(差分のみ実体) | 簡単 | 可能 | 複数世代を効率的に保持したい場合 |
| tar.gz アーカイブ | 多い(毎回フルコピー) | 解凍が必要 | 可能 | 持ち運びやすいアーカイブが欲しい場合 |
| VPSスナップショット | プロバイダー依存 | 非常に簡単 | プラン依存 | サーバー全体の状態を保存したい場合 |
筆者の見解では、一般的なWebサイトやアプリケーションの運用であれば、--link-destを使った世代管理が最もバランスの良い選択肢です。ディスク容量を抑えながら複数世代を保持でき、復元時もファイルコピーだけで済みます。
運用時の注意点とトラブルシューティング
バックアップの自動化は「設定して終わり」ではありません。正常に動作し続けているかの確認や、トラブル発生時の対応を事前に考えておく必要があります。
1. バックアップが本当に動いているか確認する
cronジョブは失敗しても画面に表示されないため、気づかないまま何週間もバックアップが取れていなかったというケースがあります。以下の方法で定期的に確認しましょう。
# cronのログを確認(ディストリビューションにより場所が異なる)
sudo grep CRON /var/log/syslog # Ubuntu/Debian系
sudo grep CRON /var/log/cron # CentOS/RHEL系
# バックアップログの確認
ls -la /var/log/backup/
tail -20 /var/log/backup/backup_$(date +%Y%m%d)*.log
# バックアップ先のファイル更新日時を確認
ls -la /backup/daily/
2. ディスク容量の監視
バックアップが積み重なるとディスクが逼迫します。古い世代の削除処理が正しく動いているか、定期的にdf -hで確認してください。ディスク使用率が90%を超えたら警告を出す仕組みも有効です。
3. –deleteオプションのリスク
前述のとおり、--deleteオプションは転送元で削除されたファイルをバックアップ先でも削除します。世代管理なしで--deleteを使うと、誤操作からの復旧が困難になります。このオプションを使う場合は、必ず世代管理と組み合わせるか、--backupオプションで削除されたファイルを別ディレクトリに退避する設定を検討してください。
4. cronのPATH問題
cronは最小限の環境変数で動作するため、通常のシェルでは使えるコマンドがcronからは見つからないことがあります。スクリプトの先頭に以下を追加すると安全です。
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
5. ファイルのパーミッションに注意
cronをどのユーザーで実行するかによって、アクセスできるファイルが異なります。Webサーバーのファイル(www-data所有など)をバックアップする場合、rootユーザーのcrontabで実行するか、適切な権限を付与する必要があります。
6. 復元テストを定期的に行う
バックアップは取っているだけでは意味がありません。復元できて初めてバックアップと言えます。月に一度はテスト環境で復元手順を確認し、バックアップデータが正常であることを検証しましょう。
よくある質問(FAQ)
Q1. rsyncとscpはどう違うのですか?
scpはファイルの単純なコピーを行うコマンドで、毎回すべてのファイルを転送します。一方、rsyncは差分転送に対応しており、変更のあったファイルだけを転送するため、2回目以降の転送が高速です。バックアップ用途では、転送時間とネットワーク帯域の節約の観点から、rsyncのほうが適しています。
Q2. バックアップの頻度はどのくらいが適切ですか?
サイトの更新頻度とデータの重要度によります。更新が日に数回程度のブログであれば日次バックアップで十分なケースが多いです。ECサイトやユーザーが投稿するサービスなど、頻繁にデータが変わる場合は、6時間ごとや、データベースだけは1時間ごとにバックアップを取るなど、対象によって頻度を変える運用が現実的です。
Q3. VPSの容量が少なく、ローカルにバックアップを置く余裕がありません
その場合はリモートバックアップ一択です。バックアップ専用の安価なストレージサービスやオブジェクトストレージ(Amazon S3、Wasabi、Backblaze B2など)を利用する方法もあります。rsyncは直接オブジェクトストレージには対応していないため、その場合はrcloneというツールの利用を検討してください(確認が必要:rcloneの料金体系や細かい設定は各サービスの公式ドキュメントを参照してください)。
Q4. cronの代わりにsystemd timerを使うべきですか?
systemd timerはcronの代替として使えるスケジューラで、ログ管理や依存関係の定義などcronにない機能があります。ただし、設定がcronより複雑で、学習コストがやや高いです。シンプルなバックアップの定期実行であれば、cronで十分です。より高度なジョブ管理が必要な場合や、すでにsystemdベースの運用に慣れている場合はsystemd timerも良い選択肢です。
Q5. パスフレーズなしのSSH鍵を作るのはセキュリティ上問題ないですか?
自動化のためにパスフレーズなしのSSH鍵を使うのは一般的な運用ですが、鍵が漏洩した場合にそのままアクセスされるリスクがあります。以下の対策を講じてください。
- バックアップ専用の鍵ペアを作成し、用途を限定する
- バックアップ先サーバーの
~/.ssh/authorized_keysで、その鍵に対して実行可能なコマンドを制限する(command=オプション) - 鍵ファイルのパーミッションを
600にし、rootのみ読み取り可能にする - バックアップ先サーバーでは、そのユーザーに最小限の権限だけを与える
まとめ
VPSのバックアップ自動化は、cronとrsyncという標準的なLinuxツールの組み合わせで実現できます。この記事のポイントを整理します。
- rsyncは差分転送により効率的なバックアップが可能。
-aオプションでパーミッションなどの属性も保持できる - cronでスケジュール登録すれば、毎日決まった時間に自動実行される
- ローカルバックアップだけでなく、リモートサーバーへのバックアップを組み合わせることで、より安全なデータ保護が実現できる
--link-destを使った世代管理で、ディスク効率を保ちながら複数時点のデータを保持できる- バックアップは取るだけでなく、定期的な復元テストとログの確認が不可欠
--deleteオプションの利用やSSH鍵の管理など、セキュリティと運用上の注意点を理解した上で設定すること
バックアップの仕組みは、問題が起きる前に構築しておくことに意味があります。「あのとき設定しておけば」と後悔する前に、ぜひこの記事を参考にして自動バックアップ環境を整えてください。
VPSのバックアップ環境を構築するなら、安定したサーバー選びも重要です。以下からVPSサービスの詳細をチェックしてみてください。

