ブログサーバーをリモートバックアップする:七牛クラウド低頻度ストレージ + Restic
ブログを立ち上げると、ページが表示されて、管理画面にログインできて、記事が普通に公開できれば、もう完了した気になってしまいがちです。
でも、よく考えてみると、実はそう簡単な話ではありません。
ブログ自体を再構築するのは難しくありません。難しいのは、記事、データベース、画像、設定ファイル、リバースプロキシ、Docker Compose、環境変数、cronジョブなど、時間をかけて少しずつ積み上げてきたものです。サーバーのハードディスクがいつか壊れたり、うっかりディレクトリを削除してしまったり、システムアップデートで問題が起きたりしたら、これらは「再デプロイ」だけでは戻ってこないかもしれません。
そこで、ブログサーバーのリモートバックアップを実行することにしました。
選んだのは七牛クラウドの低頻度ストレージで、バックアップツールはRestic、頻度は週1回です。特別に高度な構成ではありませんが、個人ブログには十分です。
この記事は主に自分の作業手順を記録したものです。将来サーバーに問題が発生したときに、この記事を見て復元できるようにするためです。
なぜリモートバックアップが必要か
「バックアップ」と聞くと、多くの人はまずサーバー内にローカルコピーを作ることを思い浮かべます。
例えば:
cp -r /www /backup/www
これももちろんバックアップですが、同じマシン上にあるという問題があります。
ファイルを誤って削除しただけなら、ローカルバックアップは役に立ちます。 しかし、ハードディスクが壊れたり、サーバーのシステムがクラッシュしたり、マシン全体にアクセスできなくなったりした場合、ローカルバックアップも一緒に失われます。
そこで、より堅牢な方法は次のようになると思います:
- サーバー上でブログを運用する。
- バックアップは別の場所に保存する。
- 普段は気にしない。
- 問題が発生したときに復元できる。
これが、今回オブジェクトストレージを選んだ理由です。
なぜ七牛クラウド低頻度ストレージを選んだか
七牛クラウドのオブジェクトストレージには、標準ストレージ、低頻度ストレージ、アーカイブストレージなど、さまざまなタイプがあります。
ブログのバックアップには、普段はほとんどダウンロードせず、問題が発生したときにのみ復元に使用するという特徴があります。
そのため、標準ストレージはもったいなく、アーカイブストレージは手間がかかります。低頻度ストレージはその中間で、「頻繁にはアクセスしないが、必要なときに取り出せる」データに適しています。
ただし、低頻度ストレージにも注意点があります。
たとえば最低保存期間が30日に設定されていることが多く、アップロード後すぐに削除すると、その最低保存期間に基づいて課金される可能性があります。
もう一つのポイントは、低頻度ストレージからの復元ダウンロードにはデータ取得料金が発生することです。つまり、普段は安く保管できますが、実際にダウンロードして復元する際には追加料金が発生します。
そこで、私の戦略はシンプルです:
- 週に1回バックアップする。
- 毎日削除しない。
- バックアップを1つだけ保持しない。
- 直近数ヶ月分のバックアップを保持すれば十分。
最終的に、直近12回の週次バックアップ、つまり約3ヶ月分を保持することにしました。
なぜ圧縮ファイルを直接アップロードしないのか
最初は最も簡単な方法を考えました:毎週圧縮ファイルを作成し、七牛クラウドにアップロードする。
例えば:
tar -czf blog-backup.tar.gz /www /etc/nginx
この方法は確かにシンプルですが、後々いくつかの問題が発生すると考えました。
第一に、毎回フルバックアップになります。 サイトのディレクトリが30GBある場合、毎週30GBを再パッケージして再アップロードする必要があります。その週に1記事だけしか変更がなくても、すべてを再アップロードしなければなりません。
第二に、バージョン管理が難しい。 時間が経つにつれて、多くの圧縮ファイルが蓄積されます。どれが正常で、どれがデータベースを含み、どれが復元済みなのか、自分でも忘れてしまいがちです。
第三に、暗号化を自分で処理する必要がある。 ブログにはデータベース、設定ファイル、秘密鍵、環境変数が含まれている可能性があります。単なる圧縮ファイルをそのままオブジェクトストレージに置くのは、あまり安心できません。
第四に、復元作業が煩雑になります。 実際に復元する際には、圧縮ファイルをダウンロードし、解凍し、パスを確認し、手動で上書きする必要があります。
その後、七牛KodoがS3互換インターフェースをサポートしており、ResticがS3に直接バックアップできることを知り、最終的にResticを選びました。
Resticとは
Resticはバックアップツールです。単にファイルをパッケージ化してアップロードするのではなく、バックアップをリポジトリとして管理します。
いくつかの利点があります:
- 増分バックアップをサポート。
- 重複排除をサポート。
- デフォルトで暗号化。
- 履歴スナップショットを表示可能。
- 指定した時点に復元可能。
- S3互換オブジェクトストレージに接続可能。
簡単に言うと、初回バックアップでは多くのデータをアップロードしますが、以降は変更された部分のみをアップロードします。
例えば、今週数記事を変更しただけの場合、Resticはブログ全体を再アップロードしません。変更を認識し、必要なコンテンツのみをアップロードします。
これは週次バックアップに適しています。
まずバックアップするものを確認する
バックアップの前に、最も重要なステップはコマンドを書くことではなく、何をバックアップする必要があるかを明確にすることです。
多くの人は最初にサーバーのルートディレクトリ全体をバックアップしようとします:
/
これは最も堅牢に見えますが、実際にはそうとは限りません。
システム全体には、キャッシュ、ログ、一時ファイル、Dockerイメージレイヤーなど、バックアップする必要のないものがたくさんあります。これらはサイズが大きく、復元時に役に立たないこともあります。
私が本当に気にしているのはこれらです:
/www
/var/www
/opt
/etc/nginx
/etc/systemd/system
サーバーによってパスは異なるため、そのままコピーすることはできません。
1Panelでブログをデプロイしている場合は、以下に注目する必要があります:
/opt/1panel
/opt/1panel/apps
/www
Docker Composeでブログをデプロイしている場合は、以下を重点的にバックアップします:
docker-compose.yml.env- マウントされたデータディレクトリ
- データベースのエクスポートファイル
ブログにデータベースがある場合は、必ずデータベースを個別にエクスポートしてください。 サイトファイルのみをバックアップし、データベースをバックアップしないと、復元後はプログラムだけで記事データがない可能性があります。
バックアップすべきでないもの
以下のディレクトリは、通常バックアップに含めないことをお勧めします:
/var/log
/tmp
/var/tmp
/var/lib/docker/overlay2
node_modules
.cache
logs
理由は簡単です。
ログは増え続け、ブログ復元時には通常必要ありません。
一時ディレクトリはバックアップする必要がありません。
node_modules は再インストールできます。
Dockerの overlay2 は大きく、直接コピーして復元するのには適していません。
キャッシュディレクトリをバックアップしても、スペースの無駄です。
バックアップは多ければ良いというものではありません。バックアップすべきものは必ずバックアップし、バックアップすべきでないものは含めないでください。
Resticのインストール
私のサーバーはUbuntuなので、aptでインストールします:
sudo apt update
sudo apt install -y restic
インストール後、バージョンを確認します:
restic version
バージョン番号が表示されれば、インストール完了です。
七牛クラウドの情報を準備する
次に、七牛クラウドの以下の情報を準備する必要があります:
- Access Key
- Secret Key
- バケット名
- リージョンID
Access KeyとSecret Keyは七牛クラウドの管理画面で確認できます。
バケット名は、作成したオブジェクトストレージスペースの名前です。
リージョンIDは、スペースがどのリージョンにあるかによって異なります。例えば、華東、華南、華北、シンガポールなどのリージョンには、それぞれ異なるリージョンIDがあります。
Resticが七牛KodoのS3エンドポイントに接続するための形式は次のようになります:
s3:s3.<Region-ID>.qiniucs.com/<bucket_name>
例えば、リージョンIDが次の場合:
cn-east-1
バケット名が次の場合:
my-blog-backup
リポジトリアドレスは次のようになります:
s3:s3.cn-east-1.qiniucs.com/my-blog-backup/blog-server
最後の blog-server は、このバケット内の異なるバックアップコンテンツを区別するために自分で追加したパスです。
将来的にNAS、写真、他のサーバーなどをバックアップする場合も、同じバケット内でディレクトリを分けることができます。
Restic設定ファイルの作成
毎回コマンドでAK、SK、リポジトリアドレス、パスワードを手動で入力したくないので、これらを別の設定ファイルにまとめます。
まずディレクトリを作成します:
sudo mkdir -p /etc/restic
次に設定ファイルを作成します:
sudo nano /etc/restic/blog.env
以下の内容を書き込みます:
ここは自分のものに変更する必要があります:
- あなたの七牛AccessKey
- あなたの七牛SecretKey
cn-east-1- あなたのバケット名
- 自分で設定する長いバックアップパスワード
RESTIC_PASSWORD は必ず保管してください。
このパスワードは七牛クラウドのパスワードではなく、Resticがバックアップリポジトリを暗号化するために使用するパスワードです。将来バックアップを復元する際にも必要になります。
このパスワードを紛失すると、七牛クラウド内のファイルが存在していても、復元できません。
保存後、設定ファイルのパーミッションを厳しくします:
sudo chmod 600 /etc/restic/blog.env
これにより、一般ユーザーが内部のキーを簡単に読み取れなくなります。
バックアップリポジトリの初期化
Resticを初めて使用する際は、リポジトリを初期化する必要があります。
実行します:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" init'
成功すると、次のようなメッセージが表示されます:
created restic repository ...
ここでエラーが発生した場合は、先に進まずに、以下の点を確認してください:
- Access Keyが間違っていないか。
- Secret Keyが間違っていないか。
- バケット名が間違っていないか。
- リージョンIDが間違っていないか。
- サーバーが七牛のS3エンドポイントにアクセスできるか。
このステップが成功したら、続行します。
まず小さなディレクトリでテストする
いきなりブログ全体をバックアップするのは避け、まず小さなディレクトリでテストして、アップロードと復元が問題なく行えることを確認します。
テスト用ディレクトリを作成します:
mkdir -p /tmp/qiniu-test
echo "hello backup" > /tmp/qiniu-test/test.txt
この小さなディレクトリをバックアップします:
スナップショットを確認します:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
先ほど作成したスナップショットが表示されれば、バックアップがアップロードされたことになります。
次に復元をテストします:
復元されたファイルを確認します:
cat /tmp/qiniu-restore/tmp/qiniu-test/test.txt
次のように表示されれば:
hello backup
バックアップと復元の両方が正常に機能しています。
このステップは一見無駄に見えるかもしれませんが、非常に重要だと思います。バックアップツールはアップロードできるだけでなく、復元できることを確認する必要があります。
本番用バックアップスクリプトの作成
テストが問題なければ、本番用のバックアップスクリプトを作成します。
スクリプトを作成します:
sudo nano /usr/local/bin/backup-blog-to-qiniu.sh
以下の内容を書き込みます:
保存後、スクリプトに実行権限を付与します:
sudo chmod +x /usr/local/bin/backup-blog-to-qiniu.sh
ここで、いくつか自分のサーバーに合わせて変更する必要がある点があります。
/var/www がない場合は削除してください。
/www がない場合も削除してください。
ブログデータが他のディレクトリにある場合は、対応するディレクトリを追加してください。
データベースがDocker内にある場合は、データベースエクスポートコマンドを自分のコンテナ名に変更してください。
パスをそのままコピーして終わりにしないでください。 バックアップスクリプトで最も重要なのは、自分のサーバーの実際の状況に合わせることです。
初回手動実行
スクリプトを作成したら、まず手動で一度実行します:
sudo /usr/local/bin/backup-blog-to-qiniu.sh
初回は時間がかかります。バックアップが必要なすべてのデータをアップロードする必要があるためです。
実行後、ログを確認します:
tail -n 100 /var/log/blog-qiniu-backup.log
次にスナップショットを確認します:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
新しいスナップショットが表示されれば、本番バックアップは成功です。
週次自動バックアップの設定
ここでは週に1回、例えば毎週月曜日の午前4時にバックアップを実行するように設定します。
rootのcronジョブを編集します:
rootのcrontabを編集します:
次の行を追加します:
0 4 * * 1 /usr/local/bin/backup-blog-to-qiniu.sh
この行の意味は:
毎週月曜日の午前4時に、バックアップスクリプトを実行します。
保存後、確認します:
sudo crontab -l
先ほど追加した行が表示されれば、cronジョブは正常に設定されています。
サーバーのタイムゾーンも確認できます:
timedatectl
サーバーのタイムゾーンが希望と異なる場合は、日本時間に変更することもできます:
sudo timedatectl set-timezone Asia/Seoul
バックアップの復元方法
バックアップは最初のステップに過ぎません。復元こそが重要です。
まず、利用可能なスナップショットを確認します:
sudo bash -c 'source /etc/restic/blog.env && restic -r "$RESTIC_REPOSITORY" -o s3.region="$QINIU_REGION" snapshots'
最新のバックアップを /restore/blog に復元します:
特定のスナップショットを復元する場合は、latest をスナップショットIDに置き換えます:
復元時に、本番ディレクトリを直接上書きすることはお勧めしません。
より安全な方法は、まず一時ディレクトリに復元することです。例えば:
/restore/blog
ファイルが完全で、データベースのダンプが存在し、設定に問題がないことを確認してから、上書きする方法を決定します。
MySQLのバックアップファイルがある場合、復元は次のように行います:
mysql -u root -p < mysql-all.sql
MySQLがDockerコンテナ内にある場合は、次のようになります:
docker exec -i mysqlコンテナ名 mysql -u root -pデータベースパスワード < mysql-all.sql
具体的なコマンドは、データベース環境によって異なります。
費用について
低頻度ストレージの費用は、主に「アップロードトラフィック」ではなく、以下の部分です:
- ストレージ容量料金。
- リクエスト料金。
- 復元時のデータ取得料金。
- 外部ネットワークへのダウンロード時の流出トラフィック料金。
週に1回バックアップし、普段は復元しない場合、費用は通常それほど高額にはなりません。
実際に費用が高くなるのは、以下のような場合です:
- Dockerディレクトリ全体をバックアップに含める。
- ログ、キャッシュ、一時ファイルをバックアップに含める。
- バックアップに大量の画像、動画、添付ファイルが含まれている。
- 低頻度ストレージ内のオブジェクトを頻繁に削除する。
- 低頻度ストレージから頻繁にダウンロードして復元する。
そのため、「週に1回バックアップし、1つだけ保持する」という方法は選びませんでした。 低頻度ストレージは頻繁な削除には適しておらず、直近12回の週次バックアップを保持する方が安定しています。
Resticの保持コマンドは次のとおりです:
restic forget --keep-weekly 12 --prune
これは、直近12回の週次バックアップを保持することを意味します。
将来的にブログデータがさらに大きくなった場合は、8週間、12週間、24週間など、データ量と予算に応じて戦略を調整できます。
最終的なバックアップ戦略
まとめると、私のバックアップ戦略は次のようになります:
- ブログファイルをバックアップする。
- Nginx設定をバックアップする。
- Docker Composeと環境変数をバックアップする。
- データベースは個別にエクスポートする。
- キャッシュ、ログ、node_modulesはバックアップしない。
- 毎週自動実行する。
- 直近12回の週次スナップショットを保持する。
- 定期的に手動で復元テストを実施する。
個人ブログにとって、この方法は複雑ではなく、費用もそれほど高くありません。
最も重要なのは、サーバーに実際に問題が発生したときに、全く手の施しようがないという状況を避けられることです。
以前は、バックアップは後回しにしがちな作業の一つでした。 しかし、サーバーというものは、実際に問題が発生するときは、通常事前に通知してくれません。
そこで、今回はきちんと対策を講じることにしました。
ブログはゆっくり書けばいいし、サーバーもゆっくり弄ればいいですが、データは一箇所だけに置かない方が良いでしょう。