バックアップ・復旧・災害復旧
unmask を導入したホストを控えて、別のホストで戻すための運用手順です。
以下のパスはすべて既定値なので、実際の値は /etc/unmask/config.yml を確認してください。
何を控えるか(と、その理由)
| 対象 |
パス(既定) |
なぜ要るか |
| config.yml |
/etc/unmask/config.yml |
bv_secret と captcha_secret_base、DB 接続情報を持ちます。bv_secret を失う・変えると、発行済みの _bv cookie がすべて無効になり、いま訪れている人が一斉に再 challenge を受けます(停止はしませんが challenge が跳ねます)。DB の認証情報もここにあります。 |
| DB |
SQLite: /var/lib/unmask/unmask.sqlite(+ -wal / -shm) MariaDB/MySQL: db.mariadb.database の DB(既定は unmask。テーブルは unmask_*) |
管理ユーザー、ban、イベント(= stats)、毎時集計。 |
| アップロードしたロゴ |
/var/lib/unmask/branding/ |
設定でアップロードした challenge ページのロゴ(既定とサイト別)。戻さないと、復旧後はアップロードし直すまでロゴが出ません。 |
控えなくてよいもの(自動で再生成されます):
/var/lib/unmask/nginx/*.inc(unmask render-nginx が作り直す)、ban file の
/var/lib/unmask/nginx/banned.txt(daemon の起動時に DB の ban から書き直す)、
community-bans-*.map(feed から再取得)、配置済みの
ngx_http_unmask_module.so(再インストール / nginx 起動時に再配置)。
コンテナ install の場合: 上記はすべて volume の中にあります —
/etc/unmask(設定 + secret)、/var/lib/unmask(データベース)、自動 HTTPS を使うなら
/var/cache/nginx/unmask-acme(Let's Encrypt のアカウントと証明書)。
この volume をバックアップすれば表の項目は全部カバーされます。動いている SQLite をコピーすると壊れた状態を写すことがあるので、
コンテナを止めてから取るか、先に下の SQLite スナップショットをコンテナ内で取ってください。CLI の手順は
docker compose exec unmask unmask … で実行します。復元は volume を戻して
docker compose up -d するだけで、ホストの nginx は
存在しないので render / reload は不要です(コンテナ内の nginx が描画済み設定を自分で拾います)。
バックアップ
0.1.53 からはコマンド 1 つで取れます。unmask backup が
unmask-backup-<yyyymmdd-hhmmss>.tar.gz(時刻は UTC)を書き出し、中に config.yml、
ページデザインのタブでアップロードしたロゴ、SQLite なら DB の一貫したコピー(daemon を止めずに
VACUUM INTO で取ったもの)が入ります。置き場所は SQLite なら DB と同じディレクトリ、MariaDB/MySQL なら実行したディレクトリで、-out DIR で変えられます。
MariaDB/MySQL ではアーカイブに入るのは config とロゴだけなので、DB は下の 2b のとおり mysqldump で取ってください。
パッケージを更新する前に毎回取ってください。スキーマは先にしか進まないので、古い版に戻すには更新前の DB が要ります。
install -d -m 0700 /backup/unmask
unmask backup -out /backup/unmask
手作業で取る場合(0.1.53 より前の版もこちら):
# 1. config + アップロードしたロゴ(軽いのでこまめに)
install -d -m 0700 /backup/unmask
cp -a /etc/unmask/config.yml /backup/unmask/
cp -a /var/lib/unmask/branding /backup/unmask/ 2>/dev/null || true
# 2a. SQLite — daemon を止めずに一貫したスナップショット
sqlite3 /var/lib/unmask/unmask.sqlite ".backup '/backup/unmask/unmask.sqlite'"
# 2b. MariaDB/MySQL
mysqldump --single-transaction unmask > /backup/unmask/unmask.sql # db.mariadb.database の名前
--single-transaction(InnoDB)はロックせずに一貫したダンプを取ります。SQLite の
.backup は書き込み中でも安全で(read lock をかけてページ単位でコピーする)、稼働中の
SQLite ファイルを素の cp で取ると WAL が途切れた状態を拾うことがあります。
.backup は sqlite3 の版を問いません。0.1.52 以降の DB には SQLite 3.38 以上でないと
読めない索引があり、古い sqlite3 で SQL を流すと「malformed database schema」と出ますが
(DB は壊れていません)、.backup はページを読まずに写すので使えます。
復旧
unmask backup のアーカイブは、展開すると同じ 3 つに分かれます
(mkdir /tmp/unmask-restore && tar -xzf unmask-backup-….tar.gz -C /tmp/unmask-restore)。
あとは下の手順で戻してください。
- バックアップを取ったときと同じ unmask のバージョンを入れます(
unmask version)。
config.yml を先に戻します。これで bv_secret が保たれ、発行済みの _bv cookie がそのまま通り、訪問者を一斉に再 challenge せずに済みます。
- DB を戻します:
- SQLite: daemon を止め、残っている
unmask.sqlite-wal / -shm を消してからファイルを戻し、
chown unmask:unmask /var/lib/unmask/unmask.sqlite(daemon は unmask ユーザーで動くので、root 所有のままだと書き込めません)してから起動。
- MariaDB/MySQL:
mysql unmask < /backup/unmask/unmask.sql。
- アップロードしたロゴを
/var/lib/unmask/branding/ に戻します。
unmask render-nginx && nginx -t && systemctl reload nginx(SysVinit は service nginx reload、OpenRC は rc-service nginx reload)。
- unmask サービスを起動 / 再起動し、
unmask doctor と curl -sf http://127.0.0.1:9477/unmask/healthz で確認します。
DB ドライバの切り替え(SQLite ⇄ MariaDB/MySQL)
unmask にドライバ間の自動データ移行はありません。やり方は 2 通りです。
まっさらに切り替える(stats の履歴が惜しくないなら、これが楽)
config.yml の db.driver(と MariaDB/MySQL の接続情報)を新しいドライバに向け、
unmask migrate でそちらに schema を作り、再起動します。新しい DB は空から始まり、
過去のイベント / stats は残せず、管理ユーザーと ban は作り直し(または手動でインポート)になります。
stats が貯まる前の早い段階でやるのが楽です。admin の再設定ウィザード(設定済みなら
/unmask/admin/setup/)でも UI から同じことができます。
データを残す(手作業)
古いドライバをダンプし、SQL 方言の差(SQLite ↔ MariaDB/MySQL の型・クォート)を手で直して、
unmask migrate が作った schema に読み込みます。バージョン依存で、1 コマンドで済む経路は
用意していません。終わったら行数を突き合わせて確認してください。
アップグレードと確認
unmask migrate(daemon 起動時に走るほか、手動でも実行可能)は冪等で何度でも再実行できます。
これが、DDL がトランザクションにならない MariaDB/MySQL(ALTER / CREATE が都度 auto-commit され、ロールバックできない)でも安全な理由です。
スキーマの変更は番号付きのマイグレーションで、適用したものは schema_migrations に記録され、以後は飛ばされます。
土台は CREATE TABLE IF NOT EXISTS と「あるか確認してから適用」です。
途中で中断しても、unmask migrate を実行し直せば、まだ記録されていない最初のマイグレーションから続きます。
確認
unmask doctor # DB 疎通 + schema + config チェック
unmask version # 戻したバイナリのバージョン確認