Backup Runbook · 正本: davar-ai/docs/BACKUP.md · 正本照合: 2026-09-02

Davar 環境 バックアップ運用

会員サイト(Member Web)と Davar AI を、別ホストへ丸ごと復元できる状態で日次保全する仕組みと、その運用手順です。復元そのものの手順はDR 復元手順を参照してください。

取り扱い注意:このページに秘密値そのものは掲載していません。ただしバックアップ内の secrets/ は平文であり、その保管場所を記載しています。保存先2ホストへのアクセス権は本番と同等に管理してください。
全体像 守る対象 2箇所の対称性 経路とスケジュール 取得対象 DR手順書の配布 監視 手動実行 ハマり所 移行の経緯 残課題

Davar 環境 バックアップ運用

全体像

日次バックアップは 米国 LA の lax(主)と東京の tky(副)の cloud VM 2 箇所に、最新 1 本ずつを保持します。内容は完全に対称で、どちらからでも同じ手順で復元できます。運用者の Mac・外付け SSD・iCloud には一切依存しません(2026-07-31 に移行。理由は移行の経緯)。

項目設定
実行元lax の cron。08:00 EDT(= 05:00 PT)
保存先laxtky/opt/davar-backup/
保持両ホストとも最新 1 本のみ
1 本のサイズ約 7.8 GB
鮮度監視48 時間を超えると日次レポートメールが警告
最終検証2026-07-31(rc=0・両ホストで整合性確認済み)

方式は pull 型です。保存先である lax が取りに行くので、取得元が侵害されてもバックアップ側を消せません

守る対象

Davar の実体は 2 つのホストに分かれています。どちらが失われても会員向けサービスが止まるため、両方を 1 つのバックアップに揃えて取ります。

ホスト役割失うと何が起きるか
rh10Davar AI。Open WebUI・RAG(bge-m3 + reranker)・LiteLLM・ollama質問応答が停止。学習済み Knowledge・モデル定義・システムプロンプト・利用者が消える
d.cblh.usMember Web。WordPress + Traefik + MariaDB会員サイトが停止。投稿・質問履歴・FAQ・アップロード済みメディア・テーマが消える

コードは GitHub にあるため対象外です。バックアップが担うのは データと秘密情報、つまり GitHub から再生成できないものだけです。

2箇所の対称性

両ホストは同一パス・同一構成です。以下は 2026-07-31 の実測値です。

lax

主 · RHEL 9.8 · 米国 LA · 実行 + 保存
zip
8,274,937,854 B
zip 内エントリ
11,263
非圧縮合計
8,423,729,246 B
staging
11,221 files
sha256 検証
OK
unzip -t
OK

tky

副 · Ubuntu 24.04 · 東京 · 保存のみ
zip
8,274,936,666 B
zip 内エントリ
11,263
非圧縮合計
8,423,729,246 B
staging
11,221 files
sha256 検証
OK
unzip -t
OK

zip のサイズが 1,188 バイト違うのは正常です。各ホストが独立に圧縮するため、zip のバイト列と .sha256 はホスト間で一致しません。一致するのは格納内容(エントリ数と非圧縮合計)です。整合性検証は必ず取得元と同じホストの .sha256 で行ってください。

ディスク上の構成(両ホスト共通)

/opt/davar-backup/
├── archive/
│   ├── d.cblh.us-backup_YYYYMMDD.zip          最新 1 本のみ
│   ├── d.cblh.us-backup_YYYYMMDD.zip.sha256
│   └── DR-RESTORE.md                          復元手順書
├── staging/                                   展開済みツリー(zip 化元)
│   └── corpus/  owui/  wp/  secrets/  DR-RESTORE.md
├── backup_davar_lax.sh                        lax のみ
├── DR-RESTORE.md                              lax のみ(配布マスター)
└── logs/                                      lax のみ・14 日保持

staging/ は zip を作る元ですが、それ自体が完全なバックアップでもあります。急ぐときは unzip せずこのツリーをそのまま復元に使えます。

東京へ zip を送らない理由

約 8 GB の zip を毎日日米間で転送するのは無駄なので、差分の staging ツリーだけを送り、tky 自身が同じ zip を作ります。初回は 7.9 GB(実測 約 0.5 GB/分)、以降は差分のみで済みます。

秘密情報は平文です。secrets/ には rh10.env、WordPress の wp-config.php、DB ダンプ、メール中継の資格情報が平文で入ります(個別暗号化はしない方針)。ディレクトリ 700 / ファイル 600 / zip 600 で保護しています。

経路とスケジュール

経路状態方法
lax → d.cblh.us到達直接 SSH。sudo はパスワード不要
lax → rh10到達二段ジャンプ必須 ssh -J d.cblh.us,opn1 rh10
lax → opn1(直接)不通タイムアウト。これが二段ジャンプの理由
lax → tky到達直接 SSH。ファイアウォール変更は不要だった
Mac → tky不通網の制限。必要なら ssh -J lax tky
# lax の crontab
0 8 * * * /usr/bin/flock -n /opt/davar-backup/.lock /opt/davar-backup/backup_davar_lax.sh

08:00 EDT(= 05:00 PT)。Davar AI の収集ジョブ(02:00 PT)と OS 自動パッチの再起動(04:15 PT)より後に置き、再起動途中のデータを掴まないようにしています。flock で多重起動を防ぎます。

取得対象

区分中身目安
corpus/収集コーパス・curated Knowledge・memory・台帳(学習データの源泉)89 MB
owui/webui.db — モデル定義・システムプロンプト・Knowledge 定義とファイル本文・RAG 設定・利用者68 MB
wp/アップロード済みメディア・テーマ・質問と FAQ の JSON7.8 GB
secrets/.envwp-config.php・WP DB 全表ダンプ・インフラ設定・メール中継資格12 MB

取得しないもの(復元時に作り直せる)

対象外復元方法
ベクタ DB・キャッシュ(約 4 GB)webui.db がファイル本文を持つので reindex で再構築(埋め込みは無料)
ollama のモデル(約 7.7 GB)ollama pull
コンテナイメージdocker pull

非対象を切ったことで 1 本あたり約 12 GB を節約しています。wp/ が全体の 99% を占めるのは、会員サイトのメディアが 7.6 GB あるためです。

DR手順書の配布

「バックアップはあるが手順書が無い」状態を作らないため、復元手順書 DR-RESTORE.mdzip の中を含む 10 箇所に配布し、毎回同期しています。

場所意図
GitHub リポジトリ docs/RESTORE.md正本
lax の配布マスターここから各所へ配る元
lax / tky の archive/zip と同じ場所に手順書がある
lax / tky の staging/ツリーを直接使う場合用
lax / tky の zip 内バックアップ 1 本だけで手順が揃う
rh10 / d.cblh.us の本番ホストSSH できる状態ならその場で読める
正本を直したらマスターも直すこと。配布スクリプトは GitHub を見ません。docs/RESTORE.md を更新したら scp docs/RESTORE.md lax:/opt/davar-backup/DR-RESTORE.md を実行してください。忘れると各所へ古い手順書を配り続けます。

監視

バックアップが静かに止まる事故を二度起こさないため、成功したときだけ rh10成功マーカーを書きます。日次レポートメールがその鮮度を見て、48 時間を超えるか、マーカーが無ければ冒頭に赤い警告を出します。

# 最終成功時刻と保存先(dest=lax+tky が正常)
ssh rh10 'cat /opt/davar-ai/data/web/last_backup_ok.json'

# 直近の実行ログ
ssh lax 'tail -30 /opt/davar-backup/logs/backup-$(date +%Y%m%d).log'

# 両ホストの保持状況(それぞれ 1 本だけあること)
ssh lax 'ls -l /opt/davar-backup/archive/'
ssh lax 'ssh tky "ls -l /opt/davar-backup/archive/"'

# 整合性(取得元と同じホストの .sha256 で)
ssh lax 'cd /opt/davar-backup/archive && sha256sum -c *.sha256 && unzip -t *.zip | tail -1'

成功マーカーは「動いたこと」しか保証しません。中身が正しいことは別に確かめる必要があり、それが上の sha256sum -cunzip -t です。

手動実行・一時停止

# 手動実行(cron と同じ経路。flock で二重起動を防ぐ)
ssh lax '/usr/bin/flock -n /opt/davar-backup/.lock /opt/davar-backup/backup_davar_lax.sh'

# 東京へのミラーを飛ばして lax だけ取る
ssh lax 'DAVAR_SKIP_TKY=1 /opt/davar-backup/backup_davar_lax.sh'

# 一時停止(cron 行をコメントアウト)
ssh lax 'crontab -l | sed "s#^0 8 \* \* \*#\#&#" | crontab -'

所要時間の目安は、差分実行で数分〜十数分です。zip の生成が最も重く、7.8 GB を書き出すのに各ホストで十数分かかります。初回のみメディア 7.6 GB の転送が加わります。

ハマり所

いずれも実際に踏んで判明したものです。同じ場所で止まらないために残します。

lax から rh10 へは踏み台を 2 段重ねる

lax の SSH 設定には rh10 用の踏み台が書いてありますが、lax からその踏み台自身に届かないため機能しません。会員サイトのホストが踏み台と同じネットワークにいるので、それを 1 段目にします。

ssh -J d.cblh.us,opn1 rh10   # OK
ssh -J d.cblh.us      rh10   # NG: そこから先が届かない
rsync -e "ssh -J d.cblh.us,opn1" ...   # rsync にも同じ指定が必要

「Mac から届かない」をファイアウォールの不備と決めつけない

東京のホストは SSH の接続元が特定の網に制限されています。Mac から届かないのはその制限であって、経路の不備ではありません。laxtky は元から疎通しており、設定変更は不要でした。当事者間で実測してから変更を検討してください。

メディアはコンテナ経由でコピーしない

7.6 GB を一旦コンテナから /tmp へ複製すると、会員サイトのディスクを一時的に食い、所要時間も大幅に伸びます。WordPress のデータは named volume なので、ホスト側のパスから直接 rsync します(読み取りに sudo を使う)。

wp-cli はコンテナ再作成で消える

WordPress 操作に使う wp-cli は volume の外にあるため、コンテナを作り直すと消えます。スクリプトは使う前に存在を確認して自動復元します。このガードを外さないでください。

2 箇所の zip は .sha256 で突き合わせられない

独立に圧縮するとバイト列が一致しません。対称性を確かめるときはエントリ数と非圧縮合計で比較します。

移行の経緯

以前は運用者の Mac が毎朝 5 時に取得し、外付け SSD に保存、書けなければ iCloud に退避する構成でした。2026 年 7 月に破綻し、cloud VM へ移しました。原因は独立した 3 つが重なったもので、どれもエラー通知を出しませんでした

要因何が起きたか
容量会員サイトのメディアが 7.6 GB 増え、1 本が 199 MB から 7.7 GB へ約 37 倍に膨張。iCloud が容量不足になり、7/27 と 7/30 が書き込み失敗
外付け SSD接続されていても、自動実行の文脈からは OS の保護機能で書き込みを拒否され続けていた
世代管理「各月の最新だけ残す」処理が 7/28 以降まったく動かず、古い世代が残って容量をさらに圧迫。失敗ではなく無言だったため気づけなかった

設計判断は 3 つです。保存先を運用者端末に依存させない世代管理を最新 1 本に単純化する(状態が目で見て分かる)、保存先を地理的に離れた 2 箇所にする

教訓:鮮度マーカーによる監視は 2026-07-24 に導入済みで、これが唯一の検知手段でした。逆に言えば、それが無ければ約 1 か月バックアップが無い状態に気づけませんでした(実際に 6/25〜7/23 の全滅を経験しています)。成功したときだけ印を残し、その鮮度を見る方式は残します。

残課題