バックアップ、エクスポート、インポート
Control Center がコピー、受け渡し、採用できるものすべてと、各アーティファクトの正確な形を まとめます。実際にバックアップを取得する方法は バックアップと復元を、永続化が このように分割されている理由は ワークスペースと分離を参照してください。
アーティファクト
「アーティファクト」というセクションデータベースのコピーを伴うアーティファクトは 3 つあり、スコープと削除ポリシーがそれぞれ異なります。
| アーティファクト | 書き込み元 | 形 | 対象 |
|---|---|---|---|
| インストール全体のスナップショット | server.backupNow |
タイムスタンプ付きのディレクトリ | インストール上のすべてのデータベース |
| ワークスペースのバックアップ | Workspace backup パイプライン |
.db を 1 つ含むタイムスタンプ付きディレクトリ |
1 つのワークスペースのデータベース |
| ワークスペースのエクスポート | workspace.export |
単一の .db ファイル |
1 つのワークスペースのデータベース |
いずれも SQLite の VACUUM INTO で書き込まれるため、稼働中の WAL データベースに対しても
安全です。読み取りトランザクションを取得し、断片化を解消したトランザクション整合性のある
コピーを生成し、サーバーを停止する必要は一切ありません。
スナップショットのレイアウト
「スナップショットのレイアウト」というセクション<dataDir>/backups/2026-07-28T09-12-33-000Z/ manifest.json global.db <workspaceId>/workspace.db one directory per workspaceこのレイアウトは稼働中のデータディレクトリを正確に反映しているため、インストールの復元は
変換ではなくコピーを書き戻すだけの操作になります。ディレクトリ名は UTC タイムスタンプの
: と . を - に置き換えたもので、Windows でもファイルシステム上安全であり、プレーンな
文字列として時系列順に並びます。
スケジュールされたワークスペースのバックアップは、別途
<dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db に置かれます。
これらにはマニフェストも global.db も含まれず、インストール全体のスナップショットでは
ありません。週次パイプラインの保持ステップが削除するのは、設定された期間(既定では 30 日)
より古い、そのワークスペース自身のバックアップだけです。手動で作成したインストール全体の
スナップショットがこのステップでローテーションされることはありません。
server.listBackups が一覧に出すのはインストール全体のスナップショットだけで、不完全な
ものも含まれます。
manifest.json
「manifest.json」というセクション| フィールド | 型 | 意味 |
|---|---|---|
version |
int | マニフェストのフォーマットバージョン。現在は 1 |
created_at |
ISO-8601 UTC | スナップショットを取得した時刻 |
global.file |
string | 常に global.db |
global.schema_version |
int | 取得時点の GlobalDatabase スキーマバージョン |
global.bytes |
int | 書き込まれた global.db のサイズ |
workspace_schema_version |
int | すべてのワークスペースファイルで共通の WorkspaceDatabase スキーマバージョン |
workspaces[] |
array | 取得したワークスペースごとに 1 エントリ |
workspaces[].workspace_id |
string | このファイルが保持するワークスペース |
workspaces[].file |
string | スナップショットルートからの相対パス、<workspaceId>/workspace.db |
workspaces[].bytes |
int | そのファイルのサイズ |
skipped_workspaces[] |
array of string | バックアップが取得できなかったワークスペース |
ワークスペースがスキップされるのは、登録されているものの一度も書き込まれていない場合
(ファイルがまだ存在しない)、またはその VACUUM INTO が失敗した場合です。どちらの場合も
スナップショットは完了し、マニフェストに何が欠けているかが記録されます。
server.listBackups はスナップショットごとに complete フラグを報告します。マニフェストが
存在しないか解析できない場合、global.db が欠けている場合、またはマニフェストが
ディスク上にないワークスペースファイルを指している場合に false になります。
不完全なスナップショットも引き続き一覧に表示されます。運用者に見えないスナップショットは、
持っていると信じてしまうスナップショットだからです。マニフェストが読めない場合、一覧は
レイアウトそのものにフォールバックし、見つかった <workspaceId>/workspace.db ファイルを
報告します。スナップショット全体としてはインストールを復元できませんが、これらは
workspace.import を通じて個別に採用できます。
バックアップに含まれないもの
「バックアップに含まれないもの」というセクションどちらのアーティファクトもデータベースのみです。ワークスペースのディレクトリには データベース以外のものもあり、それらは一切持ち出されません。
| パス | スナップショットに含まれる? | ワークスペースのエクスポートに含まれる? |
|---|---|---|
global.db |
はい | いいえ |
<workspaceId>/workspace.db |
はい | はい(それ自体がそのファイル) |
<workspaceId>/blobs/ |
いいえ | いいえ |
<workspaceId>/skills/ |
いいえ | いいえ |
<workspaceId>/agents/ |
いいえ | いいえ |
<workspaceId>/chat_credentials/ |
いいえ | いいえ |
<workspaceId>/spaces/<spaceId>/ |
いいえ | いいえ |
<workspaceId>/pr_clones/ |
いいえ | いいえ |
secrets.json |
いいえ | いいえ |
models/ |
いいえ | いいえ |
meetings/<meetingId>/ |
いいえ | いいえ |
rigs/ |
いいえ | いいえ |
その一部は捨ててよいものです。spaces/ はリポジトリから再プロビジョニングされる
コピーオンライトのワークツリー、pr_clones/ はキャッシュ、models/ は
再ダウンロードされるもの、rigs/ はマシンの状態です。そうでないものもあります。
blobs/ はデータベースの行が参照する貼り付け画像を保持し、skills/ と agents/ は
エージェントが実行時に使うファイルを保持し、secrets.json はインストール上のすべての
ペアリングキー、プロバイダーの認証情報、SSO 設定を保持します。残りをカバーする方法は
バックアップと復元を
参照してください。
インストールのバックアップ RPC とワークスペースのエクスポート/インポートは fullClient
専用です。ペアリングされたスマートフォンからは実行できません。バックアップポートが
構成されていないサーバー(デモサーバーなど)では、これらはすべて、拒否されるのではなく
構造的に存在しません。
| 操作 | 種別 | スコープ | 最小ロール | 引数 | 戻り値 |
|---|---|---|---|---|---|
server.backupNow |
変更 | インストール | インストールのオーナー | なし | {ok, path} |
server.listBackups |
読み取り | インストール | インストールのオーナー | なし | {backups: [...]} |
server.deleteBackup |
変更 | インストール | インストールのオーナー | name |
{ok} |
workspace.export |
読み取り | ワークスペース | admin |
なし | {ok, path} |
workspace.import |
変更 | ワークスペース | owner |
source_path |
{ok, workspace_id} |
workspace.delete |
変更 | インストール* | owner |
id |
レジストリの行に削除済みの印を付ける |
workspace.deleteがスコープを持たないのは、印を付ける行がグローバルレジストリに あるためです。そのハンドラーは、呼び出し元が指定されたワークスペースのメンバーかどうかを 確認し、ownerを要求します。
すべてのレスポンスの path は、サーバーホスト上のパスです。
server.listBackups のレスポンス
「server.listBackups のレスポンス」というセクション新しい順に、ディレクトリ名(タイムスタンプ)で並びます。そのため、マニフェストを 読み取れなかったスナップショットでも順序は保たれます。
{ "backups": [ { "path": "/…/backups/2026-07-28T09-12-33-000Z", "name": "2026-07-28T09-12-33-000Z", "created_at": "2026-07-28T09:12:33.000Z", "bytes": 481203712, "complete": true, "workspaces": [ { "workspace_id": "w_9f2c…", "path": "/…/backups/2026-07-28T09-12-33-000Z/w_9f2c…/workspace.db", "bytes": 190840832 } ], "skipped_workspace_ids": [] } ]}マニフェストを読み取れなかった場合、created_at は省略されます。トップレベルの bytes は、
マニフェスト自身の合計ではなく、ディレクトリ全体のディスク上の実際のサイズです。
スナップショットを整理する運用者が知りたいのは、バックアップが書き込むつもりだった量では
なく、そのディレクトリが占める容量だからです。
各 workspaces[].path は、workspace.import が source_path として受け取る値そのものです。
これは意図的で、「このスナップショットからこのワークスペースを復元する」ことはインポート
操作そのものなので、両者が同じファイルを別々に扱う方向へずれていくことはありません。
workspace.import の検証
「workspace.import の検証」というセクション何かを置き換える前に、候補のファイルを短命な生の SQLite 接続で読み取り専用として開き、
その workspace_meta 行を読み取ります。
| 条件 | 結果 |
|---|---|
読み取り可能な SQLite データベースではない、または workspace_meta がない |
拒否。何も変更されません |
| 記録されたワークスペース ID ≠ 対象 | 許可され、ログに記録されます。これがワークスペースを複製したり、新しい ID で復元したりする方法です |
| 記録されたインストール ID ≠ このインストール | 許可され、ログに記録されます。そのペアリング済みデバイスとユーザー ID はそのインストールに属しており、ここでは解決されません |
| 無効なワークスペース ID、またはファイルが存在しない | 拒否 |
受け入れると、対象ワークスペースのデータベースは、ファイルを上書きコピーする前に閉じられ、
マネージャーから外されます(開いている drift 接続がファイルとその -wal を保持している
ためです)。その後で再度開かれ、beforeOpen が FTS と同期トリガーを再インストールし、
FTS インデックスが再構築されます。インポートしたファイルのコンテンツテーブルにはデータが
入っていますが、そのインデックスは古い可能性があります。
転送ルート
「転送ルート」というセクション上記のすべての操作はサーバー側のパスで語られるため、サーバーが自分のマシンである場合に
のみ完全な答えになります。次の 3 つは、メディアプロキシと Blob ストアが使うのと同じ
PSK 署名付きの経路で、実際のバイトを運びます。呼び出し元はデバイスの事前共有鍵で
ターゲット文字列に署名し、その署名を s として渡します。
| ルート | メソッド | クエリ | 署名対象 | 必要な権限 |
|---|---|---|---|---|
/backup/workspace |
GET | w, d, s |
backup-workspace:<workspaceId> |
ワークスペースの管理者 |
/backup/snapshot |
GET | n, d, s |
backup-snapshot:<name> |
インストールのオーナー |
/backup/restore |
POST | w, d, s |
backup-restore:<workspaceId> |
ワークスペースのオーナー |
w はワークスペース ID、n はスナップショットのディレクトリ名、d は呼び出し元の
デバイス ID、s は署名です。n はバックアップのルートに連結されるのではなく、
バックアップの一覧に対して解決されるため、一覧に表示されないディレクトリをルートに
指定することはできません。
| ステータス | 原因 |
|---|---|
400 |
必須のクエリパラメータが欠けているか、アップロードのボディが空です |
403 |
不明または失効したデバイス、不正な署名、または呼び出し元にロールがありません |
404 |
このホストにバックアップポートがない、または指定されたスナップショット/ワークスペースファイルが存在しません |
405 |
/backup/restore が POST 以外で呼び出されました |
413 |
アップロードのボディが 8 GiB を超えています(宣言された content-length でも、実際に読み取ったバイト数でも) |
500 |
エクスポートまたはアーカイブがサーバー側で失敗しました |
どちらのダウンロードも Cache-Control: no-store と Accept-Ranges: none を返します。
各リクエストは新しいコピーを作成し、ストリーミングが終わるとそれを削除します。そのため、
キャッシュされたり再開されたりしたレスポンスは、2 つの異なるエクスポートのバイトを
つなぎ合わせ、有効に見えて実際には有効でない 1 つのファイルを作ってしまいます。
/backup/snapshot は <name>.zip を返します。エントリはスナップショットルートからの
相対パスなので、展開すると manifest.json + global.db + <workspaceId>/workspace.db が
そのまま再現されます。エントリはソート順に書き込まれるため、同じスナップショットの
2 つのアーカイブは同一のアーカイブになります。
/backup/restore はボディをバッファリングせず、そのままステージングファイルへ
ストリーミングし、読み取り前と読み取り中にサイズを制限し、拒否を含むあらゆる終了経路で
ステージングファイルを削除します。
パスと制限
「パスと制限」というセクション| 項目 | 値 |
|---|---|
| スナップショット | <dataDir>/backups/<timestamp>/ |
| スケジュールされたワークスペースのバックアップ | <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db |
| ワークスペースのエクスポート | <dataDir>/backups/exports/<workspaceId>-<timestamp>.db |
| 転送のステージング | <dataDir>/backups/transfer/ — 作業台であり、そこに書き込むルートによって掃除されます |
| スナップショットのアーカイブ名 | <snapshot directory name>.zip |
| アップロードの上限 | POST /backup/restore あたり 8 GiB |
| 保持 | インストール全体のスナップショットは手動削除。ワークスペースのバックアップは週次パイプラインで、既定は 30 日 |
exports/、transfer/、workspace-backups/ の各ディレクトリはインストール全体の
スナップショットではなく、server.listBackups から除外されます。スケジュールされた保持が
あるのは最後のディレクトリだけです。インストール全体のスナップショットを削除するには、
インストールのオーナーが明示的に操作する必要があります。
関連項目
「関連項目」というセクション- バックアップと復元 — これらの操作が属する手順
- ワークスペースと分離 — 1 つのワークスペースが 1 つのファイルである理由
cc_serverCLI — これらのパスが置かれるデータディレクトリ- ルートマップ — UI がどこにあるか
- アーキテクチャ — パスが従うクライアント/サーバー分割