LabLinux

BookStackのバックアップを公式CLIで取る【復元まで試して分かった4つの落とし穴】

スポンサーラベル
BookStackの公式CLIによるバックアップ。ZIPにはdb.sqlとuploads3種とthemesと.envが入るが、.envはDocker版ではテンプレートのまま Lab

当サイトはアフィリエイト広告を利用しています。

社内wikiとしてBookStackを立てたあと、必ず来るのがバックアップです。データベースだけ取っていても、画像を貼り付けて使っていたなら、それは復元できません。

BookStackには公式の bookstack-system-cli があり、1コマンドでデータベースとアップロードファイルを1つのZIPにまとめられます。ただし実際に環境を破棄して戻してみると、そのままでは困る点が4つありました。

BookStackの公式CLIによるバックアップ。ZIPにはdb.sqlとuploads3種とthemesと.envが入るが、.envはDocker版ではテンプレートのまま

この記事では、バックアップの取り方に加えて復元テストの手順と、その過程で踏んだ4点をまとめます。最後に、CLIを使わず設定ディレクトリごとコピーする方式とも実測で比較します。BookStackの構築手順はBookStackをAlmaLinux 9.4にインストールする手順を参照してください。

検証環境: BookStack v26.05.5(linuxserver/bookstack v26.05.5-ls284)/bookstack-system-cli 0.4.0/MariaDB 11.8.8/Docker Compose。検証はDocker版で行いました。 AlmaLinuxへ手動インストールした場合との差異は、該当箇所で明記します。

1. 結論:公式CLIで取れる。ただしZIPだけでは戻らない

BookStackのインストールディレクトリに bookstack-system-cli が同梱されています。

# バックアップ。ZIP を1つ作るだけ
./bookstack-system-cli backup /path/to/backup.zip

# 復元。ZIP を指定する
./bookstack-system-cli restore /path/to/backup.zip

これだけです。ただし先に知っておくべきことが4つあります。

  • ZIPに入る .env が、設定の復元に使えないことがある
  • 復元は .env をマージする。差異があると対話で止まる
  • -n(非対話)を付けると復元されない
  • 復元後、アップロード先の所有者が root になり書き込めなくなる

順に見ていきます。なお実行すると冒頭に WARNING: This CLI is in beta testing. と出ます。APIが変わる可能性がある旨が明示されているので、本番の運用に組み込むならバージョンを固定してください。

2. ZIPに何が入るのか

まず中身を開いて確かめます。

./bookstack-system-cli backup /config/backup.zip
unzip -l /config/backup.zip

実際の出力です。

  Length      Date    Time    Name
---------  ---------- -----   ----
     2009  09-25-2026 02:10   .env
   393659  09-14-2026 22:58   bookstack-system-cli
    53256  09-25-2026 02:19   db.sql
       14  09-25-2026 02:18   public/uploads/test-a.txt
       13  09-25-2026 02:18   storage/uploads/images/gallery/test-b.txt
       12  09-25-2026 02:18   storage/uploads/files/test-c.txt
       13  09-25-2026 02:18   themes/test-d.txt

アップロード先が3箇所に分かれているのが要点です。

パス中身
public/uploads/ロゴなど公開用の画像
storage/uploads/images/ページに貼り付けた画像
storage/uploads/files/ページに添付したファイル
themes/カスタムテーマ

手作業でバックアップを組むなら、この3箇所を全部指定しないと画像だけ戻らないことになります。--no-database --no-uploads --no-themes で個別に除外できるので、裏を返せば既定ではこの3種類とデータベースが入ります。

なお、これらが空のときは黙って0件になります。「ZIPが小さいから失敗した」とは限りません。 筆者は最初、まだ画像を1枚も貼っていない状態で取って「uploadsが入らない」と誤解しました。ファイルを置いて取り直したら正しく入っていました。

3. 落とし穴①:ZIP内の .env が設定の復元に使えないことがある

ZIPには .env が入ります。ところが Docker版(linuxserver イメージ)では、この .env がテンプレートのままでした。

unzip -p backup.zip .env | grep -E '^(APP_KEY|APP_URL|DB_HOST|DB_USERNAME)'
APP_KEY=SomeRandomString
APP_URL=https://example.com
DB_HOST=localhost
DB_USERNAME=database_username

全部プレースホルダです。 一方、アプリが実際に使っている値はコンテナの環境変数側にあります。

APP_URL=http://localhost:6875
DB_USERNAME=bookstack
APP_KEY=base64:i99REr……

つまり Docker で運用している場合、ZIPだけ持っていても設定は復元できません。 docker-compose.yml(または .env ファイル)を別途、同じ場所に保管する必要があります。バックアップ対象は「ZIP」ではなく「ZIP+compose定義」と考えてください。

AlmaLinuxへ手動インストールした場合は逆になります。 設定は BookStack ディレクトリ直下の .env に実値で入るため、ZIPから設定ごと戻せます。その代わり、ZIPの中に本物の APP_KEY とデータベースのパスワードが入ります。 保管場所の権限と、バックアップの転送経路に注意してください。

APP_KEY は Laravel がセッションなどの暗号化に使う鍵です。失っても記事本文が消えるわけではありませんが、揃えておくに越したことはありません。

4. 落とし穴②:復元は .env を「マージ」する

復元すると、こう表示されます。

Restoring and merging .env file...
Found different APP_URL values, which would you like to use?
  [0] http://localhost:6875
  [1] https://example.com

上書きではなくマージで、値が食い違う項目は対話で選ばせます。 別のホストへ移設するときは、ここでURLの選択を誤らないようにしてください。

なお復元後、Docker版では .env にプレースホルダが残ったままになります。それでもアプリが動くのは、環境変数のほうが優先されるためです。「.env が壊れているのに動いている」状態になるので、後から中身を見て混乱しないよう覚えておいてください。

5. 落とし穴③:-n を付けると復元されない

自動化しようとして -n(非対話)を付けると、こうなります。

Contents found in the backup ZIP:
✔ .env Config File
✔ Themes Folder
✔ Public File Uploads
✔ Private File Uploads
✔ Database Dump
The checked elements will be restored into [/app/www].
Existing content will be overwritten.
Stopping restore operation.

確認が取れないので、実行せずに終了します。 エラーにはなりません。終了コードだけ見ていると「成功した」と誤読しかねない出方です。

無人で流すなら確認に応答を渡します。ただし前章のとおり APP_URL が食い違うとさらに選択肢を聞かれるので、定期実行に組み込むのはバックアップ側だけにして、復元は人が実行するのが現実的です。

# 確認に応答して復元する
echo yes | ./bookstack-system-cli restore /config/backup.zip

6. 落とし穴④:復元後、所有者が root になる

復元が終わると、CLI自身がこう言います。

You may need to fix file/folder permissions so that the webserver has
the required read/write access to the necessary directories & files.

実際に確認すると、こうなっていました。

ls -ld /config/www/uploads /config/www/themes /config/www/images
drwxr-xr-x 1 root root  4096 /config/www/uploads
drwxr-xr-x 1 root root  4096 /config/www/themes
drwxr-xr-x 1 abc  users 4096 /config/www/images

uploads と themes が root:root に変わっています。 アプリを動かすユーザーで書き込めるか試すと、こうなります。

su abc -s /bin/sh -c 'touch /config/www/uploads/writetest.txt'
# touch: cannot touch '...': Permission denied

復元した直後は、読めるが書けない状態です。 画面を開くと記事は表示されるので正常に見えますが、新しく画像を貼り付けようとした時点で失敗します。復元後は所有者を戻してください。

# Docker(linuxserver)の場合。PUID/PGID に合わせる
chown -R abc:users /config/www/uploads /config/www/themes

# AlmaLinux に手動インストールした場合は Web サーバーのユーザーに合わせる
chown -R nginx:nginx /var/www/bookstack/public/uploads \
                     /var/www/bookstack/storage/uploads \
                     /var/www/bookstack/themes

7. 復元テストの手順

バックアップは、戻せることを確認して初めてバックアップです。実際に行った手順を残します。要点は「目印を入れてから壊す」ことです。

① 目印を入れる

データベースとファイルの両方に、復元後すぐ確認できる印を置きます。

# データベース側:設定テーブルに目印を1行入れる
mariadb -u bookstack -p bookstackapp -e \
  "INSERT INTO settings (setting_key, value, created_at, updated_at)
   VALUES ('restore_marker','MARKER-2026-09-25',NOW(),NOW());"

# ファイル側:3箇所すべてに目印ファイルを置く
echo A > public/uploads/test-a.txt
echo B > storage/uploads/images/test-b.txt
echo C > storage/uploads/files/test-c.txt

② バックアップを取り、退避する

./bookstack-system-cli backup /tmp/backup.zip

ZIPは必ず、これから消す領域の外へ移してください。 設定ディレクトリの中に置いたまま環境を破棄すると、バックアップごと消えます。

③ 環境を完全に壊す

docker compose down
rm -rf ./app_config ./db_config      # 設定とデータの実体を消す

④ まっさらな状態で立て直し、空であることを確認する

ここを飛ばすと、元のデータが残っていただけなのか、復元が効いたのかが区別できません。

mariadb -u bookstack -p bookstackapp -e \
  "SELECT COUNT(*) FROM settings WHERE setting_key='restore_marker';"   # → 0

⑤ 復元し、目印が戻ることを確認する

echo yes | ./bookstack-system-cli restore /tmp/backup.zip

実際の結果です。

setting_key      value
restore_marker   MARKER-2026-09-25

/config/www/uploads/test-a.txt          UPLOAD-TEST-A
/config/www/images/gallery/test-b.txt   IMAGE-TEST-B
/config/www/files/test-c.txt            FILE-TEST-C
/config/www/themes/test-d.txt           THEME-TEST-D

データベースの1行と、3箇所のファイルがすべて戻りました。最後に画面が開くこと(HTTP 200)と、所有者を直したうえで書き込めることまで確認して完了です。

なお復元時、CLIはデータベースのマイグレーションを自動で実行します。ヘルプにも「同じかそれ以降のバージョンへ復元すること」と書かれているので、古いバージョンへ戻すのは想定されていません。バックアップを取ったバージョンは記録しておいてください。

8. フォルダ丸ごとという選択肢

Docker Composeで動かしているなら、CLIを使わず設定ディレクトリごとコピーする手もあります。同じ環境で両方試したので、実測値で比較します。

公式CLI(ZIP)フォルダ丸ごと
サイズ0.36 MB159.3 MB
設定の復元不可(.env がテンプレート)可(compose・nginx設定・鍵まで)
復元操作対話プロンプトあり戻して up -d だけ
復元後の所有者root:root・書き込み不可変化なし・書き込み可
別バージョンへの移植可(mysqldump なので)不可に近い
停止の要否不要コールドなら必要(実測 10.6秒)

どちらも復元に成功し、データベースの1行とアップロードファイルが戻ることを確認しています。

8.1 サイズ差の正体はデータではない

159MBの内訳を見ると、ほぼ全部がInnoDBの固定領域でした。

ib_logfile0   96.0 MB
ibdata1       12.0 MB
ibtmp1        12.0 MB
undo001/2/3   10.0 MB × 3

実データはほとんど入っていません。 記事が増えてもこの150MBは最初から乗っているので、440倍という比率は初期状態特有のものです。運用が進めば差は縮まります。

8.2 フォルダ方式なら落とし穴①と④が起きない

この記事で挙げた4つのうち、2つはフォルダ方式で回避できます。

  • 落とし穴①(.env がテンプレートで設定が戻らない)— docker-compose.yml が同じ場所にあるので、バックアップ対象を分けて考える必要がありません
  • 落とし穴④(uploads と themes が root になる)— 所有者がそのまま保たれ、書き込みも通りました

8.3 代わりに失うもの

移植性がありません。 rawデータファイルはMariaDBのバージョンに紐づくため、別バージョンや別ディストリへ移すなら mysqldump、つまり公式CLIのZIPが必要です。

もうひとつ、稼働したままコピーする方式(ホットコピー)の安全性は確認できていません。 無負荷の状態で試した限りは復元できましたが、1回成功したことは安全の証明になりません。書き込みの最中にコピーすれば、InnoDBのファイルが中途半端な状態で取られる可能性が残ります。無停止が要件なら、フォルダコピーではなく mariadb-dump を使ってください。

8.4 どちらの方式でも、復元後のDBは元と同一にはならない

検証中に気づいた点です。復元して起動したあとのデータベースには、コピー時には存在しなかったテーブルが6つ増えていました。BookStackが起動のたびにマイグレーションを実行するためです。

筆者は最初これを「稼働中コピーがファイルを取りこぼした」と誤解しましたが、停止して取ったコピーにも同じ6つが無かったので、原因はマイグレーションでした。ファイル単位で元と突き合わせても一致しません。 確認するのは中身(目印が戻っているか)にしてください。

8.5 使い分け

  • 日常の定期バックアップ — 停止できるならコールドでフォルダ丸ごと。10秒の停止で、設定ごと確実に戻せます
  • バージョンアップ前・移設前 — 公式CLIのZIP。移植性があるのはこちらだけです
  • 両方取るのが理想 — サイズの桁が違うので、併用のコストはほぼありません

なお所有者が保たれた結果は、Windows上のバインドマウントで検証したものです。Linuxホストで同じことをする場合は、所有者とパーミッションを保つために tar -p か rsync -a を使ってください(こちらは未検証です)。

9. まとめ

BookStackのバックアップと復元について、実測をもとに整理しました。

  • 公式CLIで1コマンド。 データベース・アップロード3箇所・テーマが1つのZIPにまとまる
  • Dockerで運用しているならZIPだけでは足りない。 .env がテンプレートなので、compose定義も一緒に保管する
  • 手動インストールならZIPに実値が入る。 保管場所の権限に注意する
  • -n では復元されない。 エラーも出ないので終了コードだけ見ない
  • 復元後は uploads と themes の所有者が root になる。 読めるが書けない状態になる
  • 目印を入れてから壊して戻す。 空を確認する手順を飛ばさない
  • Docker運用ならフォルダ丸ごとという選択肢がある。 設定ごと戻せて権限も崩れないが、サイズは440倍で移植性が無い。同一ホストへ戻すならフォルダ、移設するならZIP

バックアップを取る設定まではすぐ終わります。戻す側を一度通しておくかどうかで、いざという時の差が出ます。 検証環境を1つ立てて、この手順を一度流しておくことをおすすめします。

サーバーをこれから用意する場合の選び方は、BookStackを社内サーバー無しで始めるにまとめています。

社内ツールを動かすサーバーの選び方

BookStack や Redmine のような社内ツールは、PHP とデータベースを自分で用意して動かします。そのためSSH で操作できる VPS が必要で、共用のレンタルサーバーでは構築できません。メモリはデータベースと同居する分を見て、2GB以上を目安にしてください。

まず試すだけなら、VPS を1台借りて動かしてみるのが手軽です。候補は次の2社です。

お名前.com レンタルサーバー(GMOインターネット)……VPSプランがあります。独自ドメインも同じ事業者でまとめたい場合はこちらです。

ConoHa VPS……Linux のほかに ConoHa for Windows Server も選べます。Windows で検証したい場合はこちらです。

契約前に、使いたい OS のテンプレートが用意されているかと、料金体系・解約条件を確認してください。

コメント

タイトルとURLをコピーしました