バックアップとリストア
バックアップすべき 3 つのもの、それを 3 つとも行うスクリプト、そして必要になる前に一度やっておくべきリストア訓練。
Busabase インスタンスはディスク上では 3 つのものです。どれか 1 つでも欠けたバックアップは、バックアップではありません。
| 中身 | 失うと | |
|---|---|---|
| データベース | 構造的なものすべて: ワークスペース、レコード、ドキュメント、メンバー、権限、履歴 | すべて |
| オブジェクトストレージ | 添付ファイルの実体 | レコードは残るが添付リンクがすべて壊れる |
| 設定 | .env、seaweed-s3.json | 手元にあるデータベースを開けない |
3 つ目が見落とされがちです。.env には Postgres のパスワードとセッション署名鍵が、ストレージ設定には S3 の認証情報が入っています。これらなしでデータだけ戻しても、手元に残るのは開くことのできないデータベースです。
バックアップ
Compose バンドルには 3 つすべてを行う backup.sh が含まれます:
./backup.sh /var/backups/busabaseタイムスタンプ付きディレクトリに database.sql.gz、storage.tar.gz、設定ファイルのコピーを書き出します。想定している使い方は日次の cron です:
0 3 * * * /opt/busabase-selfhosted/backup.sh /var/backups/busabaseバックアップにはデータベースのパスワードとセッション署名鍵が含まれます。本番とまったく同じ厳しさで扱ってください — スクリプトは出力に 600 を設定します。それを緩めないでください。
オールインワンのバックアップ
すべてが 1 つのボリュームにあるので、ボリュームをバックアップします:
docker run --rm -v busabase-data:/data:ro -v "$PWD":/out \
alpine tar czf /out/busabase-data.tar.gz -C /data .これには生成されたシークレットの唯一のコピーである /data/.credentials も含まれます。
リストア
稼働中のものに上書きするのではなく、新しいデプロイへリストアしてください。そのバックアップが壊れていた場合でも、元が残ります。
# 1. 新しいデプロイを起動し、リストア中に書き込みが入らないよう app を止める
docker compose up -d postgres seaweedfs
docker compose stop app
# 2. データベース
gunzip -c database.sql.gz | docker compose exec -T postgres psql -U busabase -d busabase
# 3. オブジェクトストレージ
docker run --rm -v busabase-premium_seaweedfs_data:/data -v "$PWD":/in \
alpine tar xzf /in/storage.tar.gz -C /data
# 4. 設定を戻して起動
cp .env seaweed-s3.json /opt/busabase-selfhosted/
docker compose up -dリストア先のアドレスが元と違う場合(ホストが違う、あるいはポートだけ違う場合も)、起動前にリストアした .env の APP_URL を新しいアドレスに書き換えてください。セッション cookie はこの値を基準に発行されるため、古い値のままだとログインは成功したように見えて即座にログイン画面へ戻され、ログには何も出ません。今回のリリース向けのリストア訓練で実際に踏みました。
必要になる前に訓練しておく
一度もリストアしたことのないバックアップは仮説にすぎません。予備のホストで一度通しでやって、後から 3 点を確認してください:
- ログインできる —
BETTER_AUTH_SECRETが引き継がれた証拠。 - レコード件数が元と一致する — データベースが完全に戻った証拠。
- 添付ファイルを開く — オブジェクトストレージとその認証情報の両方が揃った証拠。
失敗するのは 3 番です。そして「ざっと見て問題なさそう」では絶対に見つかりません — 誰かがファイルをクリックするその瞬間まで、すべてのページは正しく表示されるからです。