Przejdź do głównej zawartości

Kopia zapasowa, eksport i import

Wszystko, co Control Center potrafi skopiować, przekazać lub przejąć, oraz dokładny kształt każdego artefaktu. Aby faktycznie wykonać kopię zapasową, zobacz Kopia zapasowa i przywracanie; wyjaśnienie, dlaczego trwałość jest podzielona w ten sposób, znajdziesz w Obszary robocze i izolacja.

Istnieją trzy artefakty kopiowania bazy danych, o różnych zakresach i zasadach usuwania.

Artefakt Zapisywany przez Kształt Obejmuje
Migawka instalacji server.backupNow Katalog ze znacznikiem czasu Każda baza danych w instalacji
Kopia zapasowa obszaru roboczego potok Workspace backup Katalog ze znacznikiem czasu z jednym plikiem .db Baza danych jednego obszaru roboczego
Eksport obszaru roboczego workspace.export Pojedynczy plik .db Baza danych jednego obszaru roboczego

Wszystkie są zapisywane za pomocą SQLite VACUUM INTO, co jest bezpieczne wobec działającej bazy danych w trybie WAL: operacja bierze transakcję odczytu, tworzy zdefragmentowaną i spójną transakcyjnie kopię i nigdy nie wymaga zatrzymywania serwera.

<dataDir>/backups/2026-07-28T09-12-33-000Z/
manifest.json
global.db
<workspaceId>/workspace.db one directory per workspace

Układ dokładnie odwzorowuje działający katalog danych i właśnie dlatego przywrócenie instalacji jest skopiowaniem go z powrotem, a nie tłumaczeniem. Nazwa katalogu to znacznik czasu UTC z : i . zastąpionymi przez -, dzięki czemu jest bezpieczna dla systemu plików w Windows i sortuje się chronologicznie jako zwykły ciąg znaków.

Zaplanowane kopie zapasowe obszarów roboczych leżą osobno w <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db. Nie zawierają manifestu ani global.db i nie są migawkami instalacji. Krok retencji cotygodniowego potoku usuwa wyłącznie kopie jego własnego obszaru roboczego starsze niż skonfigurowany wiek (domyślnie 30 dni); ręcznie utworzone migawki instalacji nigdy nie są przez ten krok rotowane. server.listBackups wymienia tylko migawki instalacji, w tym niekompletne.

Pole Typ Znaczenie
version int Wersja formatu manifestu. Obecnie 1
created_at ISO-8601 UTC Kiedy wykonano migawkę
global.file string Zawsze global.db
global.schema_version int Wersja schematu GlobalDatabase w momencie wykonania migawki
global.bytes int Rozmiar zapisanego pliku global.db
workspace_schema_version int Wersja schematu WorkspaceDatabase wspólna dla każdego pliku obszaru roboczego
workspaces[] array Jeden wpis na każdy przechwycony obszar roboczy
workspaces[].workspace_id string Obszar roboczy przechowywany w tym pliku
workspaces[].file string Ścieżka względem katalogu głównego migawki, <workspaceId>/workspace.db
workspaces[].bytes int Rozmiar tego pliku
skipped_workspaces[] array of string Obszary robocze, których kopia nie zdołała przechwycić

Obszar roboczy zostaje pominięty, gdy jest zarejestrowany, ale nigdy nie był zapisywany (więc nie istnieje jeszcze żaden plik), albo gdy jego VACUUM INTO się nie powiodło. Tak czy inaczej migawka i tak się kończy, a manifest wymienia, czego brakuje.

server.listBackups zwraca flagę complete dla każdej migawki. Jest fałszywa, gdy manifestu nie ma lub nie da się go sparsować, gdy brakuje global.db albo gdy manifest wymienia plik obszaru roboczego, którego nie ma na dysku.

Niekompletna migawka nadal trafia na listę, bo migawka, której operator nie widzi, to migawka, o której operator myśli, że ją ma. Gdy manifestu nie da się odczytać, lista opiera się na samym układzie katalogów i zgłasza te pliki <workspaceId>/workspace.db, które znajdzie — każdy z nich można nadal adoptować pojedynczo przez workspace.import, choć migawka jako całość nie potrafi przywrócić instalacji.

Oba artefakty to wyłącznie bazy danych. Katalog obszaru roboczego przechowuje więcej niż jego bazę danych, a nic z reszty nie podróżuje:

Ścieżka W migawce? W eksporcie obszaru roboczego?
global.db Tak Nie
<workspaceId>/workspace.db Tak Tak (to jest ten plik)
<workspaceId>/blobs/ Nie Nie
<workspaceId>/skills/ Nie Nie
<workspaceId>/agents/ Nie Nie
<workspaceId>/chat_credentials/ Nie Nie
<workspaceId>/spaces/<spaceId>/ Nie Nie
<workspaceId>/pr_clones/ Nie Nie
secrets.json Nie Nie
models/ Nie Nie
meetings/<meetingId>/ Nie Nie
rigs/ Nie Nie

Część z tego jest jednorazowa — spaces/ przechowuje drzewa robocze z kopiowaniem przy zapisie, które są odtwarzane z repozytoriów, pr_clones/ to cache, models/ pobiera się ponownie, a rigs/ to stan maszyny. Część jednak nie: blobs/ przechowuje wklejone obrazy, na które wskazują wiersze w bazie danych, skills/ i agents/ przechowują pliki, z którymi działa agent, a secrets.json przechowuje każdy klucz parowania, poświadczenie dostawcy i ustawienie SSO w instalacji. Jak objąć resztę, opisano w Kopia zapasowa i przywracanie.

RPC kopii zapasowej instalacji oraz eksport i import obszaru roboczego są dostępne tylko dla fullClient: sparowany telefon nie może ich wywołać. Wszystkie są całkowicie nieobecne — nie odrzucane, lecz strukturalnie nieistniejące — na serwerze bez podłączonego portu kopii zapasowych, takim jak serwer demonstracyjny.

Operacja Rodzaj Zakres Minimalna rola Argumenty Zwraca
server.backupNow zapis Instalacja właściciel instalacji brak {ok, path}
server.listBackups odczyt Instalacja właściciel instalacji brak {backups: [...]}
server.deleteBackup zapis Instalacja właściciel instalacji name {ok}
workspace.export odczyt Obszar roboczy admin brak {ok, path}
workspace.import zapis Obszar roboczy owner source_path {ok, workspace_id}
workspace.delete zapis Instalacja* owner id wiersz rejestru oznaczony jako usunięty
  • workspace.delete nie ma zakresu, bo wiersz, który oznacza, mieszka w globalnym rejestrze; jej handler sprawdza członkostwo wywołującego w nazwanym obszarze roboczym i wymaga roli owner.

path w każdej odpowiedzi to ścieżka na hoście serwera.

Od najnowszej, sortowane według nazwy katalogu (która jest znacznikiem czasu, więc kolejność zachowuje się nawet dla migawki, której manifestu nie udało się odczytać).

{
"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 jest pomijane, gdy manifestu nie udało się odczytać. bytes na najwyższym poziomie to rzeczywisty rozmiar całego katalogu na dysku, a nie suma z samego manifestu — pytanie, które zadaje operator porządkujący migawki, brzmi, ile kosztuje katalog, a nie ile kopia zamierzała zapisać.

Każde workspaces[].path to dokładnie to, co workspace.import przyjmuje jako source_path. To celowe: „przywróć ten obszar roboczy z tej migawki” jest operacją importu, więc oba nie mogą się rozjechać w różne traktowanie tego samego pliku.

Zanim cokolwiek zostanie zastąpione, plik-kandydat jest otwierany tylko do odczytu przez krótkotrwałe surowe połączenie SQLite i odczytywany jest jego wiersz workspace_meta.

Warunek Wynik
Nieczytelna baza danych SQLite albo brak workspace_meta Odmowa. Nic nie zostaje tknięte
Zapisany identyfikator obszaru roboczego ≠ docelowy Dozwolone, rejestrowane w logu. W ten sposób obszar roboczy jest duplikowany lub przywracany pod nowym identyfikatorem
Zapisany identyfikator instalacji ≠ ta instalacja Dozwolone, rejestrowane w logu. Jego sparowane urządzenia i identyfikatory użytkowników należą do tamtej instalacji i nie zostaną tu rozwiązane
Nieprawidłowy identyfikator obszaru roboczego albo plik nie istnieje Odmowa

Po zaakceptowaniu baza danych docelowego obszaru roboczego jest zamykana i usuwana z menedżera, zanim plik zostanie na nią skopiowany (otwarte połączenie driftu trzyma plik i jego -wal), a następnie otwierana ponownie, tak aby beforeOpen ponownie zainstalował wyzwalacze FTS i synchronizacji, i indeksy FTS są odbudowywane — tabele treści zaimportowanego pliku są wypełnione, ale jego indeks może być nieaktualny.

Każda z powyższych operacji mówi ścieżkami po stronie serwera, co jest pełną odpowiedzią tylko wtedy, gdy serwerem jest Twoja własna maszyna. Te trzy trasy przenoszą bajty, tym samym torem podpisywanym kluczem PSK, którego używają proxy multimediów i magazyn blobów. Wywołujący podpisuje ciąg docelowy kluczem wstępnie współdzielonym swojego urządzenia i przekazuje podpis jako s.

Trasa Metoda Zapytanie Podpisany cel Wymaga
/backup/workspace GET w, d, s backup-workspace:<workspaceId> administrator obszaru roboczego
/backup/snapshot GET n, d, s backup-snapshot:<name> właściciel instalacji
/backup/restore POST w, d, s backup-restore:<workspaceId> właściciel obszaru roboczego

w to identyfikator obszaru roboczego, n — nazwa katalogu migawki, d — identyfikator wywołującego urządzenia, a s — podpis. n jest rozwiązywane względem listy kopii zapasowych, a nie dołączane do katalogu głównego kopii, więc trasy nie da się wycelować w katalog, którego lista by nie pokazała.

Status Przyczyna
400 Brakuje wymaganego parametru zapytania albo treść wysyłki jest pusta
403 Nieznane lub unieważnione urządzenie, nieprawidłowy podpis albo wywołującemu brakuje roli
404 Brak portu kopii zapasowych na tym hoście albo wskazana migawka/plik obszaru roboczego nie istnieje
405 /backup/restore wywołane czymkolwiek innym niż POST
413 Treść wysyłki przekracza 8 GiB — według zadeklarowanej długości treści albo według faktycznie odczytanych bajtów
500 Eksport albo archiwizacja nie powiodły się po stronie serwera

Oba pobierania odpowiadają Cache-Control: no-store z Accept-Ranges: none. Każde żądanie tworzy świeżą kopię i usuwa ją po przesłaniu, więc zapamiętana w cache albo wznowiona odpowiedź skleiłaby bajty z dwóch różnych eksportów w jeden plik, który wygląda na poprawny, a nim nie jest.

/backup/snapshot zwraca <name>.zip, a wpisy są względne wobec katalogu głównego migawki, więc rozpakowanie odtwarza manifest.json + global.db + <workspaceId>/workspace.db. Wpisy są zapisywane w kolejności posortowanej, więc dwa archiwa tej samej migawki to to samo archiwum.

/backup/restore strumieniuje treść prosto do pliku tymczasowego, zamiast ją buforować, ogranicza ją przed odczytem i w jego trakcie oraz usuwa odłożony plik na każdej drodze wyjścia, także przy odmowie.

Element Wartość
Migawki <dataDir>/backups/<timestamp>/
Zaplanowane kopie zapasowe obszarów roboczych <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
Eksporty obszarów roboczych <dataDir>/backups/exports/<workspaceId>-<timestamp>.db
Obszar tymczasowy transferu <dataDir>/backups/transfer/ — miejsce robocze, czyszczone przez trasę, która do niego pisze
Nazwa archiwum migawki <snapshot directory name>.zip
Limit wysyłki 8 GiB na POST /backup/restore
Retencja Migawki instalacji: ręczne usuwanie. Kopie zapasowe obszarów roboczych: cotygodniowy potok, domyślnie 30 dni

Katalogi exports/, transfer/ i workspace-backups/ nie są migawkami instalacji i są wyłączone z server.listBackups. Tylko ostatni katalog ma zaplanowaną retencję; usunięcie migawki instalacji wymaga wyraźnego działania właściciela instalacji.