Резервне копіювання, експорт і імпорт
Усе, що Control Center може скопіювати, передати чи прийняти, і точний вигляд кожного артефакту. Щоб насправді зробити резервну копію, дивіться Резервне копіювання та відновлення; про те, чому збереження даних поділено саме так, — у Робочих просторах та ізоляції.
Артефакти
Розділ із назвою «Артефакти»Є три артефакти-копії бази даних, із різними областями дії та політиками видалення.
| Артефакт | Що його створює | Форма | Охоплює |
|---|---|---|---|
| Знімок інсталяції | server.backupNow |
Каталог із часовою міткою | Кожну базу даних в інсталяції |
| Резервна копія робочого простору | конвеєр Workspace backup |
Каталог із часовою міткою та одним .db |
Базу даних одного робочого простору |
| Експорт робочого простору | workspace.export |
Один файл .db |
Базу даних одного робочого простору |
Усі вони записуються через 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 | Один запис на кожен захоплений робочий простір |
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 або коли
маніфест називає файл робочого простору, якого немає на диску.
Неповний знімок усе одно показується, бо знімок, якого оператор не бачить, — це знімок,
який він вважає наявним. Коли маніфест не читається, список відкочується до самої
структури й повідомляє ті файли <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 |
Відмовлено. Нічого не торкається |
| Записаний ідентифікатор робочого простору ≠ цільовий | Дозволено, записано в журнал. Так робочий простір дублюють або відновлюють під новим ідентифікатором |
| Записаний ідентифікатор інсталяції ≠ цій інсталяції | Дозволено, записано в журнал. Його спаровані пристрої та ідентифікатори користувачів належать тій інсталяції й не розв’яжуться тут |
| Неприпустимий ідентифікатор робочого простору, або файлу не існує | Відмовлено |
Після прийняття база даних цільового робочого простору закривається й прибирається з
менеджера, перш ніж файл копіюють поверх неї (відкрите з’єднання drift тримає файл і
його -wal), потім відкривається знову, щоб beforeOpen перевстановив тригери FTS і
синхронізації, а індекси FTS перебудовуються: таблиці вмісту імпортованого файлу
заповнені, але його індекс може бути застарілим.
Маршрути передавання
Розділ із назвою «Маршрути передавання»Кожна з наведених операцій говорить серверними шляхами, а це повна відповідь лише тоді,
коли сервер — ваша власна машина. Ці три переносять самі байти тим самим каналом із
підписом PSK, який використовують медіапроксі та сховище blob. Викликач підписує цільовий
рядок попередньо спільним ключем свого пристрою й передає підпис як 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 — ідентифікатор робочого простору, n — назва каталогу знімка, d — ідентифікатор
пристрою-викликача, s — підпис. n розв’язується за списком резервних копій, а не
долучається до кореня backups, тож маршрут не можна націлити на каталог, якого список
не показав би.
| Статус | Причина |
|---|---|
400 |
Бракує обов’язкового параметра запиту, або тіло вивантаження порожнє |
403 |
Невідомий або відкликаний пристрій, поганий підпис, або викликачеві бракує ролі |
404 |
На цьому хості немає порту резервного копіювання, або названого знімка/файлу робочого простору не існує |
405 |
/backup/restore викликано чимось іншим, ніж POST |
413 |
Тіло вивантаження перевищує 8 GiB — за заявленою довжиною вмісту або за фактично прочитаними байтами |
500 |
Експорт або архівування не вдалося на боці сервера |
Обидва завантаження відповідають Cache-Control: no-store із Accept-Ranges: none.
Кожен запит викарбовує свіжу копію й видаляє її після потокового передавання, тож
закешована чи продовжена відповідь зшила б байти двох різних експортів в один файл, який
виглядає справним, але ним не є.
/backup/snapshot повертає <name>.zip, де записи відносні до кореня знімка, тож
розпакування відтворює manifest.json + global.db + <workspaceId>/workspace.db.
Записи записуються у відсортованому порядку, тож два архіви одного знімка — це той самий
архів.
/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 |
| Стеля вивантаження | 8 GiB на POST /backup/restore |
| Зберігання | Знімки інсталяції: видалення вручну. Резервні копії робочого простору: тижневий конвеєр, типово 30 днів |
Каталоги exports/, transfer/ і workspace-backups/ не є знімками інсталяції й
виключені з server.listBackups. Лише останній каталог має заплановане зберігання;
видалення знімка інсталяції потребує явної дії власника інсталяції.
Дивіться також
Розділ із назвою «Дивіться також»- Резервне копіювання та відновлення — рецепти, до яких належать ці операції
- Робочі простори та ізоляція — чому один робочий простір — це один файл
- CLI
cc_server— каталог даних, у якому лежать ці шляхи - Карта маршрутів — де живе інтерфейс
- Архітектура — поділ клієнт/сервер, якого дотримуються ці шляхи