Перейти до вмісту

Резервне копіювання, експорт і імпорт

Усе, що 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 перелічує лише знімки інсталяції, зокрема й неповні.

Поле Тип Значення
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 у кожній відповіді — це шлях на хості сервера.

Від найновіших, відсортовано за назвою каталогу (а це часова мітка, тож порядок зберігається навіть для знімка, чий маніфест не вдалося прочитати).

{
"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. Це навмисно: «відновити цей робочий простір із цього знімка» — це і є операція імпорту, тож ці двоє не можуть розійтися в різному поводженні з тим самим файлом.

Перш ніж щось замінюється, файл-кандидат відкривається лише для читання через недовговічне сире з’єднання 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. Лише останній каталог має заплановане зберігання; видалення знімка інсталяції потребує явної дії власника інсталяції.