unmask

docs

JA4 の取得方法、LB / CDN 設定、対応 distro、FAQ。

バックアップ・復旧・災害復旧

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)。 あとは下の手順で戻してください。

  1. バックアップを取ったときと同じ unmask のバージョンを入れます(unmask version)。
  2. config.yml を先に戻します。これで bv_secret が保たれ、発行済みの _bv cookie がそのまま通り、訪問者を一斉に再 challenge せずに済みます。
  3. 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。
  4. アップロードしたロゴを /var/lib/unmask/branding/ に戻します。
  5. unmask render-nginx && nginx -t && systemctl reload nginx(SysVinit は service nginx reload、OpenRC は rc-service nginx reload)。
  6. 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         # 戻したバイナリのバージョン確認