プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

【rsync】 サーバー間でのバックアップ

森ソフトのHPはさくらインターネットのレンタルサーバーで運用しています。いまさらですが、ファーストサーバーの事件を振り返り、バックアップを強化しました。

バックアップは、今までは思い出したように手作業で行っていたのですが、最近別記事に書いたようにEC2上にサーバー(SVN+Redmine)を立てて運用を始めたので、さくらのデータはEC2へバックアップしようと思います。なお、EC2上のデータ(SVNリポジトリ)を、さくらへバックアップすることも考えましたが、とりあえずこれはやめてローカルサーバーへとるようにする予定です。

こうしておけば、異なる事業者でデータを持つようになるので、データが失われる可能性はずいぶんと減らせると思います。

ここでは、これを実現するために行った作業をメモ書きにして残しておきます。

 

考え方

バックアップというと世代管理とか、差分バックアップとフルバックアップをどう組み合わせるか、などを考えないといけませんが、今回は簡易的な方法として、Webサイトのデータは最新の1世代のみを取っておくものとします。

あえて動作イメージを書くとこんな感じになります。

wwwデータ
さくらのサーバー ---(1)--> EC2のサーバー

今回は(1)の部分を自動化しました。

 

MySQLのバックアップ

まず、本WebサイトはJoomla!で構成しているので、apacheの公開ディレクトリの他に、MySQLのDBもバックアップしておく必要があります。今回作成したバックアップスクリプトはこんな感じです。

 

#!/usr/local/bin/bash
#
# MySQL DB dump script.
#   This script creates only newest zipped file that dumped
#   MySQL DB.
#   If you need any older files, you should keep older versions
#   at your own operations.
#
# Junichi MORI, 2013/2/1

# variables
HOST=xxxxxxxxx.db.sakura.ne.jp
USER=xxxxxxx
PASSWD=xxxxxxx
DBNAME=xxxxxxxxjoomla

DUMPDIR=/home/xxx/backup/db
#DUMPFILE=${DBNAME}.`date "+%Y%m%d"`.sql
DUMPFILE=${DBNAME}.sql
ZIPFILE=${DUMPFILE}.zip
ZIPBAKFILE=${ZIPFILE}.bak

# command
cd ${DUMPDIR}

if [ -f ${ZIPFILE} ]
then
    mv ${ZIPFILE} ${ZIPBAKFILE}
fi

mysqldump -h${HOST} -u${USER} -p${PASSWD} ${DBNAME} > ${DUMPFILE}
zip ${ZIPFILE} ${DUMPFILE}

if [ $? -ne 0 ]
then
    echo "error occured: zip file doesn't create."
    exit -1;
fi

# post process
rm -f ${DUMPFILE}
if [ -f ${ZIPBAKFILE} ]
then
    rm -f ${ZIPBAKFILE}
fi

コマンドラインから実行して問題無いようでしたら、cronに登録し(さくらのレンサバの場合はコントロールパネルから登録できます)、夜中に自動的に実行するようにしておきます。

 

 

さくらからEC2へのバックアップ

サーバー間のデータのやり取りは、rsync+sshで行います。

rsyncはコピー元とコピー先を指定して動作させますが、リモートサーバーをどちらに記述しても問題なく動作します。

いま、EC2はセキュリティグループの設定で、自宅環境からのSSH接続しか認めないようにしており、これを変更するのはちょっと嫌なので、EC2からさくらへsshでログインし、コピー元にさくら側を指定し、コピー先にec2側を指定してrsyncを実行するようにします。

 

rsyncをssh経由で実行するだけであれば、-e ssh オプションを追加すれば事足りますが、これだと常に対話でパスワード入力を求められるので、cronでの自動実行ができません。そこで下記のように公開鍵を使って自動応答できるようにします。

 

公開鍵によるsshログインの設定

cronでの利用を考えて、sshを公開鍵で認証するための設定を行います。まず、公開鍵と秘密鍵のペアを作ります。今回はEC2のサーバー側で作業をしました。

bitnami@ip-10-150-181-105:~$ ssh-keygen -t rsa -N '' -f ./.ssh/id_ssh_for_backup

この時秘密鍵はパスワードなしにしておきます。

 

次に、さくらのサーバーへ公開鍵を登録します。登録方法はいろいろあると思いますが、ssh-copy-idコマンドを使えば簡単に登録できます。なお、この時点ではパスワード認証でsshログインできることが必要です。

 

bitnami@ip-10-150-181-105:~$ ssh-copy-id -i ./.ssh/id_ssh_for_backup.pub xxx@xxxxxx
xxx@xxxxxx's password: 
Now try logging into the machine, with "ssh 'xxx@xxxxxx'", and check in:

  ~/.ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

bitnami@ip-10-150-181-105:~$ 

 

公開鍵、~/.ssh/authorized_keys は自分以外のユーザーが読み取れないようにパーミッションが600になっていることを確認しておいてください。

 

これで公開鍵で認証できるはずです。たとえば、

bitnami@ip-10-150-181-105:~$ ssh -i .ssh/id_ssh_for_backup xxx@xxxxxx

とすれば、パスワードを聞かれずにさくらのサーバーへログインできます。

 

rsyncによるバックアップ

sshログインができるようになったら、rsyncでバックアップができることを確認します。

bitnami@ip-10-150-181-105:~$ rsync -azvv --delete --dry-run -e 'ssh -i /home/bitnami/.ssh/id_ssh_for_backup'
 xxx@xxxxxx:/path/to/db/backup  xxx@xxxxxx:/path/to/www  /home/bitnami/backup

(コマンドラインは見やすいように適宜改行を入れています。以下も同様です。)

問題なく動作しているようなら、--dry-runオプションも外して実際にデータがコピーされることも確認しておきます。

 

ここまでで問題がないようなら、セキュリティのためにsshログイン時の制限を追加します。

sshでのログインを許可しているので、もし何かの原因で、秘密鍵が漏れてしまうと、誰でもリモートサーバーへログインして操作することができてしまいます。そこで、sshの公開鍵のファイルauthrized_keysに、command=""を追加して、sshログイン時に実行できるコマンドを制限しておき、被害を最小限にするようにします。

 

rsyncの場合、sshでログイン後、自動的にリモート側でrsyncコマンドが実行されます。先ほどのコマンドを実行時に、このリモートで実行されているrsyncコマンドが表示されています(-vvオプションが指定されているためです)。改めて示すと、

bitnami@ip-10-150-181-105:~$ rsync -azvv --delete --dry-run -e 'ssh -i /home/bitnami/.ssh/id_ssh_for_backup'
 xxx@xxxxxx:/path/to/db/backup xxx@xxxxxx:/path/to/www /home/bitnami/backup
opening connection using: ssh -i /home/bitnami/.ssh/id_ssh_for_backup -l xxx xxxxxx rsync --server --sender
 -vvnlogDtprze.iLsf . /path/to/db/backup /path/to/www
receiving incremental file list

のように表示されています。この時、rsync --server ・・・ より後ろがリモート側で実行されるコマンドなので、これを控えておきます。

 

次に、リモート側(さくら側)で、~/.ssh/authorized_keysファイルを開き、下記のようにcommand=を追加します。

command="rsync --server --sender -logDtprze.iLsf --delete . /path/to/db/backup /path/to/www",
from="xxx.xxx.
xxx.xxx" ssh-rsa xxxxxx・・・

commandに追加する際に、-vvオプションと-nオプション(--dry-runに対応)はなくしました。バックアップ時にはこの二つのオプションはつけずに実行するためです。今回は常に同じ接続元であるので、接続元制限(IPアドレスによる制限)も追加しています。

これで、authorized_keysファイルを保存すれば設定完了です。

 

ec2に戻って、

bitnami@ip-10-150-181-105:~$ rsync -az --delete -e 'ssh -i /home/bitnami/.ssh/id_ssh_for_backup'
 xxx@xxxxxx:/path/to/db/backup xxx@xxxxxx:/path/to/www /home/bitnami/backup

のようにコマンドを実行して、問題なくファイルのコピーが行われることを確認します。

 

ここまでの作業で問題が無いようでしたら、このコマンドをcronに登録すれば完了です。

 

参考

rsync-sshでパスワードなし認証(ポート指定)

rsync専用の秘密鍵を使ってサーバ間でrsyncする

sshで指定したコマンドしか実行できない公開鍵を作る

高機能なファイル同期ツール rsync の使い方