Jak wykonać kopię zapasową i przywrócić Immich na VPS
Dowiedz się, jak poprawnie zabezpieczyć Immich. Kopia musi zawierać pliki z UPLOAD_LOCATION, zrzut Postgres oraz pliki konfiguracyjne. Uniknij błędu pustej osi czasu.
Co musi zawierać kopia zapasowa Immich
Kopia zapasowa Immich to trzy elementy zarejestrowane w tym samym momencie. Pliki źródłowe w UPLOAD_LOCATION. Zrzut SQL bazy danych Postgres. Pliki .env oraz docker-compose.yml, które opisują stos. Przywracanie polega na wgraniu tego zrzutu do czystej bazy danych przy zatrzymanym serwerze Immich i uruchomieniu reszty stosu dopiero po zakończeniu tej operacji. Błędna kolejność prowadzi do sytuacji, w której Immich działa, ale wyświetla pustą oś czasu mimo pełnego dysku.
Podział ten jest istotny, ponieważ Immich przechowuje swój stan w dwóch miejscach, które nie mają o sobie nawzajem informacji. Postgres przechowuje każdy album, każdy klaster twarzy, każdy udostępniony link, każde konto użytkownika i klucz API oraz zapisaną ścieżkę każdego zasobu. System plików przechowuje piksele. Przywrócenie plików bez bazy danych sprawia, że Immich nic nie wyświetla. Przywrócenie bazy danych bez plików sprawia, że każdy zasób otwiera się jako uszkodzony obraz.
Polecenia w tym dokumencie zostały przygotowane dla Immich v3.1.0, wersji aktualnej na początku sierpnia 2026 roku. Według stanu na 2026-10-21 aktualnym wydaniem jest v3.3.4, opublikowane 2026-10-20, a jego plik compose, obraz bazy danych oraz udokumentowane kroki tworzenia i przywracania kopii zapasowej są zgodne z tymi opisanymi na tej stronie. Projekt rozwija się szybko, a udokumentowana procedura tworzenia kopii zapasowych zmieniała się już kilkukrotnie, dlatego przed skopiowaniem czegokolwiek należy sprawdzić wersję, która jest faktycznie uruchomiona. Jeśli stos nie został jeszcze uruchomiony, należy zacząć od przewodnika instalacji Immich, a następnie wrócić do tego miejsca.
Zrozumienie wskazań ścieżek
Dwie zmienne w .env decydują o wszystkim na tej stronie. UPLOAD_LOCATION to katalog nadrzędny, w którym Immich zapisuje wszystkie multimedia. DB_DATA_LOCATION to katalog danych Postgres.
Domyślna konfiguracja example.env ustawia UPLOAD_LOCATION=./library, co jest mylącym ustawieniem domyślnym, ponieważ Immich tworzy wewnątrz niego folder o nazwie library. Oryginalne pliki trafiają do ./library/library. Należy ustawić ścieżkę bezwzględną, aby skrypt kopii zapasowej nigdy nie zależał od katalogu, z którego został uruchomiony.
UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0Wewnątrz UPLOAD_LOCATION Immich tworzy kilka folderów. Trzy z nich przechowują dane, których żadne zadanie nie jest w stanie odtworzyć:
library: oryginalne pliki, rozmieszczone zgodnie z szablonem przechowywaniaupload: oryginalne pliki jeszcze nieprzeniesione do układu szablonu oraz przesyłane daneprofile: zdjęcia profilowe użytkowników
Utrata library oznacza bezpowrotną utratę zdjęcia. Immich nie przechowuje nigdzie drugiej kopii oryginału.
Dlaczego kopiowanie katalogu danych Postgres nie jest kopią zapasową
DB_DATA_LOCATION wygląda na łatwy cel. Jest to katalog, rsync skopiuje go, a operacja zakończy się bez błędu. Jeśli kopiowanie następuje podczas pracy Postgres, kopia nie jest kopią zapasową. Jeśli kopiowanie następuje po zatrzymaniu Postgres, jest to kopia zapasowa, ale bardzo krucha. Oto dwa powody, które można zweryfikować poprzez niepowodzenie przywracania.
Pierwszym powodem jest niespójność danych (tearing). Postgres zapisuje każdą zmianę najpierw do dziennika transakcji (WAL), a następnie stosuje ją do plików tabel podczas punktu kontrolnego (checkpoint). W każdej chwili pliki na dysku są w trakcie zmian, a trwająca cztery minuty kopia odczytuje pierwszy plik o 02:00, a ostatni o 02:04. Te dwa pliki nie należą do tej samej transakcji. Po uruchomieniu Postgres na tak przygotowanych danych, serwer albo odmawia startu z błędem PANIC: could not locate a valid checkpoint record, albo uruchamia się i ulega awarii przy pierwszej próbie odczytu uszkodzonej strony z błędem invalid page in block 1234 of relation base/16384/.... Żaden z tych przypadków nie pozwala na odzyskanie danych z takiej kopii.
Drugi powód dotyczy kopii wykonanej przy zatrzymanym serwerze. Dokumentacja PostgreSQL uznaje pełną kopię katalogu danych po poprawnym zamknięciu za prawidłową kopię zapasową, jednak katalog ten otwiera się tylko przy użyciu plików binarnych współdzielących ten sam format przechowywania. Immich przypina obraz bazy danych za pomocą skrótu (digest), obecnie ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0. Jest to Postgres 14 z wbudowanymi rozszerzeniami do wyszukiwania wektorowego: VectorChord, pgvector oraz pgvecto.rs. Kolejne wydanie poprawkowe Postgres 14 może otworzyć katalog bez zmian, ale inna główna wersja Postgres już nie. Rozszerzenia, od których zależą tabele, również muszą być obecne w kompatybilnych wersjach. Host przywracający musi uruchomić kompatybilny obraz. Zrzut SQL (SQL dump) nie ma tego problemu: jest to tekst, który każdy kompatybilny serwer może przetworzyć.
pg_dump całkowicie eliminuje problem niespójności danych. Odczytuje całą bazę danych w ramach pojedynczej migawki MVCC (multi-version concurrency control), dzięki czemu widzi bazę danych dokładnie w takim stanie, w jakim znajdowała się w jednej chwili, podczas gdy inne operacje zapisu trwają w tle. Dlatego nie trzeba zatrzymywać Postgres, aby wykonać zrzut.
Co można pominąć w kopii zapasowej
Elementy te generują się ponownie, więc można je pominąć:
thumbs: podglądy i miniatury obrazówencoded-video: transkodowane wideoDB_DATA_LOCATION: odtwarzane z zrzutu bazy danych- wolumen Docker
model-cache: modele uczenia maszynowego, pobierane ponownie na żądanie
Pominięcie ich to kompromis, a nie darmowy zysk. Ponowne generowanie miniatur i transkodowanie dla dużej biblioteki to godziny pracy procesora na małym VPS, a oś czasu przez cały ten czas wyświetla szare symbole zastępcze. Można je uruchomić ponownie z poziomu Administration > Jobs, ustawiając "Generate Thumbnails" oraz "Transcode Videos" na przetwarzanie brakujących zasobów. Jeśli miejsce docelowe kopii zapasowej na to pozwala, należy je uwzględnić, aby uniknąć oczekiwania. Jeśli zbliżasz się do limitu pamięci, pomiń je i zaplanuj proces odtwarzania. Sizing an Immich library opisuje, jak duże stają się te foldery w stosunku do plików oryginalnych.
Warto wiedzieć o jeszcze jednym folderze. UPLOAD_LOCATION/backups przechowuje automatyczne zrzuty bazy danych Immich, zapisywane codziennie o 02:00, przy czym przechowywanych jest 14 ostatnich kopii, co można skonfigurować w Administration > Settings > Database Dump Settings. Nie kosztują one nic i są naprawdę przydatne. Znajdują się one jednak na tym samym dysku, co biblioteka, którą chronią, więc pomagają w przypadku błędnej migracji, a nie awarii serwera. Mimo to należy wykonywać własne zrzuty, ponieważ zrzut wywołany ręcznie powstaje w tym samym momencie, co migawka plików, która jest z nim powiązana.
Wykonanie zrzutu bazy danych
docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres \
| gzip > /srv/immich/backup/immich.sql.gzZastąp immich oraz postgres swoimi wartościami DB_DATABASE_NAME i DB_USERNAME, jeśli zostały zmienione. Flaga --clean --if-exists dodaje DROP ... IF EXISTS przed każdym poleceniem CREATE, dzięki czemu zrzut można zaimportować do bazy danych zawierającej już obiekty, zamiast przerywać proces przy pierwszym konflikcie.
Oto szczegół, który często powoduje ciche awarie skryptów kopii zapasowych. Polecenie to jest potokiem, a powłoka zgłasza kod wyjścia ostatniego polecenia w potoku. Jeśli pg_dump zawiedzie z powodu błędnego hasła lub niedziałającego kontenera, gzip otrzyma pusty strumień, utworzy poprawny plik gzip i zakończy działanie z kodem 0. Skrypt zarejestruje sukces, a użytkownik otrzyma 20-bajtową kopię zapasową. Umieść pipefail na początku każdego skryptu kopii zapasowej:
#!/usr/bin/env bash
set -euo pipefailNastępnie zweryfikuj wynik zamiast polegać na kodzie wyjścia:
ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3Pierwsza linia poprawnego zrzutu zawiera -- PostgreSQL database dump. Plik o rozmiarze kilkuset bajtów oznacza nieudany zrzut, niezależnie od komunikatu skryptu.
Zapisz wersję wydania, która utworzyła zrzut, obok pliku kopii, odpytując działający serwer:
curl -fsS http://localhost:2283/api/server/version > /srv/immich/backup/immich-version.txtTen punkt końcowy nie wymaga logowania i zwraca numer wersji w formacie major, minor i patch, więc 3, 1 oraz 0 oznaczają v3.1.0. Nie należy polegać na .env w tym celu, ani na docker inspect --format '{{.Config.Image}}' immich_server, który zwraca jedynie referencję obrazu z konfiguracji. Domyślny plik ustawia IMMICH_VERSION=v3, czyli zmienny tag podążający za każdym wydaniem 3.x, więc zapis kończący się na :v3 nie informuje o tym, która kompilacja faktycznie utworzyła zrzut. Przypnij dokładny tag również w .env.
Wstrzymanie serwera i wykonanie migawki za pomocą restic
Pliki w UPLOAD_LOCATION nie są niezmienne, gdy Immich jest uruchomiony. Serwer zapisuje nowe przesyłane pliki, a zadanie szablonu pamięci masowej przenosi je między katalogami. Jeśli narzędzie do tworzenia kopii zapasowych odczyta plik w trakcie zapisu, zapisze te bajty tak, jakby stanowiły cały plik, a żaden mechanizm nie zgłosi błędu. Zatrzymaj kontener serwera na czas trwania operacji:
docker stop immich_serverPozostaw immich_postgres uruchomione, ponieważ zrzut bazy danych wymaga jego działania. Interfejs WWW oraz aplikacja mobilna będą niedostępne do momentu ponownego uruchomienia serwera, co w przypadku instancji domowej o godzinie 03:00 zazwyczaj nie stanowi problemu.
restic sprawdza się tutaj, ponieważ wykonuje deduplikację i szyfrowanie, zanim jakiekolwiek dane opuszczą serwer. Wskaż repozytorium, które nie znajduje się na tym serwerze:
export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic initPamięć obiektowa działa w ten sam sposób i jest lepszym rozwiązaniem, jeśli chcesz całkowicie przenieść kopię poza własny sprzęt:
export RESTIC_REPOSITORY=s3:https://s3.example.com/immich-backup
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
restic initTen punkt końcowy może być własnym bucketem MinIO na drugiej maszynie lub dowolnym dostawcą zgodnym z S3. Repozytorium znajdujące się na tym samym dysku co biblioteka chroni jedynie przed przypadkowym usunięciem danych.
Następnie wykonaj migawkę, wskazując dokładnie to, co istotne:
restic backup \
/srv/immich/backup/immich.sql.gz \
/srv/immich/backup/immich-version.txt \
/srv/immich/data/library \
/srv/immich/data/upload \
/srv/immich/data/profile \
/srv/immich/.env \
/srv/immich/docker-compose.yml
docker start immich_serverrestic odczytuje całe drzewo plików przy każdym uruchomieniu, ale przesyła tylko te bloki, których wcześniej nie widział. Dzięki temu pierwsza migawka przenosi całą bibliotekę, a każda kolejna tylko zdjęcia dodane w danym dniu.
Retencja oraz klucze, które muszą znajdować się w innym miejscu
restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12forget usuwa migawki z indeksu. --prune to część procesu, która usuwa dane, do których te migawki były ostatnim odwołaniem. Uruchomienie forget bez --prune sprawi, że rachunki za przechowywanie danych nigdy nie spadną.
Weryfikacja struktury jest mało kosztowna, dlatego należy ją przeprowadzać raz w tygodniu:
restic checkPotwierdza to spójność metadanych repozytorium. Nie powoduje to odczytu właściwych danych. Raz w miesiącu należy ponownie odczytać próbkę danych i porównać ją z zapisanymi sumami kontrolnymi:
restic check --read-data-subset=5%Jest to jedyna kontrola, która wykrywa cichą korupcję danych w backendzie pamięci masowej, ponieważ pobiera ona rzeczywiste bloki i ponownie oblicza ich sumy kontrolne. Pełne polecenie --read-data dla biblioteki zdjęć oznacza pobranie całego repozytorium, co w przypadku płatnej pamięci obiektowej generuje realne koszty, dlatego w praktyce uruchamia się sprawdzanie wybranego podzbioru danych.
Teraz część, którą użytkownicy często pomijają. Hasło do repozytorium restic jest nie do odzyskania. Nie istnieje funkcja resetowania ani wsparcie techniczne w tym zakresie. Jeśli jedyna kopia hasła znajduje się w /root/.restic-password na serwerze, który próbujesz przywrócić, Twoje kopie zapasowe są jedynie zaszyfrowanym szumem. To samo dotyczy klucza dostępu do pamięci obiektowej oraz DB_PASSWORD z .env. Przechowuj je wszystkie w miejscu niezależnym od działania tej maszyny: wydrukowane w szufladzie lub w menedżerze haseł działającym na innym sprzęcie. Jeśli ten menedżer jest również hostowany samodzielnie, wymaga on takiego samego traktowania, a tworzenie kopii zapasowej Vaultwarden jest osobnym zadaniem.
Przywracanie Immich w poprawnej kolejności
Kolejność przywracania decyduje o tym, czy kopia zapasowa będzie użyteczna, czy powstanie pusta oś czasu. Na nowym hoście należy zachować poniższą sekwencję.
Najpierw przywróć konfigurację. Określa ona wersję oprogramowania oraz ścieżki dostępu.
restic restore latest --target /restore \
--include /srv/immich/.env \
--include /srv/immich/docker-compose.yml \
--include /srv/immich/backupZablokuj wersję przed uruchomieniem czegokolwiek. Przeczytaj immich-version.txt, ustaw IMMICH_VERSION w pliku .env na konkretną wersję (v3.1.0 dla wersji głównej 3, podrzędnej 1, poprawki 0) i na razie nie używaj najnowszego wydania. Immich nie wspiera downgrade'u, nawet pomiędzy poprawkami. Jeśli nowszy serwer uruchomi się na starszym zrzucie bazy i wykona migracje, powrót do poprzedniego stanu będzie niemożliwy.
Przywróć pliki multimedialne.
restic restore latest --target /restore --include /srv/immich/dataPrzenieś library, upload oraz profile tak, aby znajdowały się bezpośrednio wewnątrz katalogu wskazywanego przez UPLOAD_LOCATION na nowym hoście. Ścieżka na hoście może ulec zmianie, ponieważ plik compose mapuje ten katalog na stałą ścieżkę wewnątrz kontenera. Struktura wewnątrz tego katalogu musi pozostać niezmieniona.
Uruchom samodzielnie bazę danych. Pozostaw DB_DATA_LOCATION puste, aby Postgres zainicjował świeży klaster.
cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgrespg_isready wyświetli accepting connections po zakończeniu wstępnej konfiguracji, co zajmuje kilka sekund. docker compose create buduje wszystkie kontenery bez ich uruchamiania i o to właśnie chodzi w tym kroku: serwer Immich nie może jeszcze działać. Serwer, który uruchomi się na pustej bazie, wykona migracje, utworzy nowy schemat i poprosi o założenie konta administratora, co uniemożliwi poprawne wgranie zrzutu bazy pod działającą aplikację.
Wgraj zrzut bazy danych.
gunzip --stdout /restore/srv/immich/backup/immich.sql.gz \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| docker exec -i immich_postgres psql --dbname=immich --username=postgres \
--single-transaction --set ON_ERROR_STOP=onDwa elementy tego polecenia wykonują kluczową pracę. sed jest konieczne, ponieważ pg_dump zapisuje puste search_path w swoim wyjściu jako zabezpieczenie, aby niekwalifikowane nazwy w zrzucie nie odwoływały się do nieoczekiwanego schematu. Typy wyszukiwania wektorowego Immich znajdują się w public, więc przy pustej ścieżce wyszukiwania proces przywracania napotyka kolumnę z typem wektorowym i psql przerywa działanie z błędem ERROR: type "vector" does not exist. Przywrócenie public na ścieżkę rozwiązuje ten problem.
--single-transaction --set ON_ERROR_STOP=on obejmuje cały proces przywracania jedną transakcją, która przerywa działanie przy pierwszym błędzie. Dzięki temu otrzymasz albo kompletną bazę danych, albo nienaruszoną. Bez tego parametru błąd w połowie procesu pozostawi bazę, która się uruchomi i pozwoli zalogować, ale będzie brakować nieokreślonej liczby albumów, co zostanie wykryte dopiero po tygodniach.
Teraz uruchom wszystko.
docker compose up -d
docker compose ps
docker logs -f immich_serverPoczekaj na komunikat startowy, taki jak Immich Server is listening on, a następnie otwórz port 2283 i zaloguj się przy użyciu starych danych, ponieważ konta użytkowników zostały przywrócone wraz ze zrzutem bazy. Jeśli strona logowania proponuje utworzenie pierwszego konta administratora, oznacza to, że baza danych nie została przywrócona. Zatrzymaj proces i ponownie przeanalizuj wyjście psql.
Ostrzeżenie dotyczące oficjalnej instrukcji przywracania z linii komend, która zaczyna się od docker compose down -v. Polecenie -v usuwa wolumeny nazwane. W standardowym pliku compose UPLOAD_LOCATION oraz DB_DATA_LOCATION są dowiązaniami (bind mounts), więc przetrwają tę operację. Jeśli jednak zmieniłeś którykolwiek z nich na wolumen nazwany, to polecenie usunie Twoje zdjęcia. Przed wykonaniem polecenia sprawdź swój plik compose.
Dlaczego oś czasu jest pusta po przywróceniu danych
Oś czasu jest generowana na podstawie wierszy w bazie danych. Immich nigdy nie przeszukuje upload/ podczas uruchamiania w celu ponownego wykrycia zdjęć, ponieważ plik bez przypisanego wiersza nie posiada właściciela, daty ani albumu. Najczęstszym błędem przy przywracaniu jest posiadanie plików przy braku bazy danych. Immich uruchamia się, tworzy pusty schemat i udostępnia działającą instancję, która jest pusta, mimo że dysk jest pełny zdjęć. Nic nie zostało utracone. Nic jednak nie jest widoczne. Rozwiązaniem jest ponowne wczytanie zrzutu bazy danych przy zatrzymanym serwerze, dokładnie w sposób opisany powyżej.
Drugi scenariusz jest mniej oczywisty. Baza danych zostaje przywrócona, oś czasu wypełnia się wpisami, ale każdy zasób nie otwiera się. Oznacza to, że wiersze wskazują na pliki, których kontener nie widzi. Zazwyczaj dzieje się tak, ponieważ library, upload oraz profile znajdują się o jeden poziom za głęboko po restic restore --target /restore, którego nikt nie przeniósł we właściwe miejsce. Zamiast zgadywać, należy sprawdzić zawartość z wnętrza kontenera:
docker exec immich_server ls /dataStandardowy plik compose montuje UPLOAD_LOCATION w /data, więc powyższa lista powinna zawierać library, upload oraz profile. Jeśli wyświetlany jest pusty katalog lub pojedynczy folder srv, oznacza to, że bind mount wskazuje na niewłaściwy poziom, a wiersze w bazie danych są poprawne.
Zgodność wersji kopii zapasowej i przywracania
Projekt Immich publikuje nowe wersje często, a schemat bazy danych zmienia się wraz z nimi. Zrzut bazy danych zawiera schemat wersji serwera, na którym został wykonany.
Przywracanie starszego zrzutu na nowszy serwer zazwyczaj przebiega pomyślnie, ponieważ serwer podczas uruchamiania stosuje oczekujące migracje i aktualizuje schemat. Ta ścieżka jest testowana w ramach sekwencji wydań. Problemy pojawiają się przy przeskakiwaniu kilku głównych wersji jednocześnie. Projekt wprowadza zmiany powodujące niekompatybilność (breaking changes) w głównych wydaniach i dokumentuje je w pliku changelog.
Przywracanie nowszego zrzutu na starszy serwer nie działa. Zrzut zawiera tabele i kolumny, których starszy kod nie obsługuje. Immich nie wspiera procedury obniżania wersji (downgrade), nawet pomiędzy wydaniami typu patch. Nie istnieje polecenie wycofania zmian (rollback).
Bezpieczne przywracanie danych jest procesem powtarzalnym. Należy uruchomić dokładnie tę wersję oprogramowania, która wygenerowała zrzut, zaimportować dane, zalogować się i potwierdzić kompletność osi czasu. Dopiero po tym kroku można wykonać aktualizację. Należy aktualizować oprogramowanie o jedno wydanie na raz, zmieniając wartość IMMICH_VERSION i uruchamiając docker compose pull && docker compose up -d po każdej zmianie. Pomocne jest przechowywanie kopii zapasowych z ostatniego tygodnia: jeśli okaże się, że najnowszy zrzut został wykonany w trakcie nieudanej aktualizacji, w repozytorium dostępna będzie kopia z poprzedniego dnia.
Weryfikacja kopii zapasowej co miesiąc
Kopia zapasowa, której nigdy nie przywrócono, jest jedynie przypuszczeniem. Raz w miesiącu przywróć ją na tymczasowej instancji i sprawdź poprawność zdjęcia. Procedura ta zajmuje około dwudziestu minut i jest jedynym elementem, który zmienia resztę tej strony w plan odzyskiwania danych.
restic snapshots
restic stats latestsnapshots powinno wyświetlić listę ostatniego uruchomienia z poprzedniej nocy. stats latest powinno wskazywać rozmiar zbliżony do rozmiaru biblioteki, a nie zaledwie kilka megabajtów.
Przywróć dane do katalogu tymczasowego, najlepiej na dodatkowym hoście:
restic restore latest --target /tmp/immich-drillSkopiuj docker-compose.yml oraz .env z przywróconego zestawu, a następnie zmień trzy elementy w kopii. Skieruj UPLOAD_LOCATION oraz DB_DATA_LOCATION na katalogi wewnątrz /tmp/immich-drill. Opublikuj port WWW pod innym adresem, 12283:2283 zamiast 2283:2283. Usuń linie container_name:, ponieważ domyślny plik compose ma na sztywno wpisane nazwy, takie jak immich_server, co powoduje konflikt drugiego stosu z pierwszym na tym samym hoście i uniemożliwia Docker utworzenie kontenerów.
Uruchom procedurę przywracania opisaną powyżej: tylko baza danych, wczytanie zrzutu, a następnie docker compose up -d. Teraz wykonaj cztery testy potwierdzające poprawność.
- Zaloguj się przy użyciu hasła stosowanego przed testem. Działające konta oznaczają, że zrzut został poprawnie przywrócony.
- Otwórz oś czasu i przewiń do najstarszego miesiąca. Zasoby w całym zakresie dat oznaczają, że wszystkie wiersze zostały przywrócone, a nie tylko te najnowsze.
- Otwórz jedno zdjęcie w pełnym rozmiarze i pobierz oryginał.
- Porównaj go z tym samym plikiem w aktywnej bibliotece za pomocą
sha256sum. Zgodne sumy kontrolne oznaczają, że dane przetrwały pełny cykl zapisu i odczytu przez restic.
Następnie usuń środowisko testowe za pomocą docker compose down -v w katalogu testowym i usuń /tmp/immich-drill. Zapisz datę w widocznym miejscu, ponieważ wartość tych działań zależy wyłącznie od ich powtórzenia w przyszłym miesiącu. Jeśli nadal wybierasz serwer zdjęć, porównanie PhotoPrism i Immich opisuje różnice między tymi rozwiązaniami właśnie w tym aspekcie.
FAQ
Czy muszę zatrzymać Immich, aby wykonać kopię zapasową?
Zatrzymaj immich_server i pozostaw immich_postgres w stanie uruchomionym. Baza danych nie wymaga wstrzymania, ponieważ pg_dump odczytuje dane w ramach jednego migawki MVCC i widzi spójny stan w danym momencie, niezależnie od innych operacji zapisu. Powodem zatrzymania są pliki: serwer zapisuje nowe przesyłane dane, a zadanie szablonu przechowywania przenosi pliki między katalogami, więc narzędzie do kopii zapasowych może odczytać plik w trakcie zapisu i utworzyć uszkodzoną kopię bez zgłoszenia błędu. docker stop immich_server przed wykonaniem migawki oraz docker start immich_server po niej eliminuje ten konflikt.
Czy mogę skopiować folder danych Postgres zamiast uruchamiać pg_dump?
Nie, gdy Postgres jest uruchomiony. Kopiowanie na żywo katalogu danych powoduje odczyt różnych plików w różnych momentach, co sprawia, że wynik nie jest spójnym stanem, a Postgres odrzuci go przy starcie z błędem PANIC: could not locate a valid checkpoint record lub ulegnie awarii później z powodu uszkodzonej strony. Pełna kopia wykonana przy zatrzymanym Postgresie jest poprawną kopią zapasową, ale zadziała tylko w tej samej wersji głównej Postgresa z kompatybilnymi rozszerzeniami. Immich korzysta z obrazu Postgres 14 zawierającego VectorChord, pgvector oraz pgvecto.rs, a katalog nie otworzy się w innej wersji głównej. Zrzut SQL jest zwykłym tekstem i można go odtworzyć na dowolnym kompatybilnym serwerze, dlatego jest to zalecana metoda przechowywania kopii.
Dlaczego moja oś czasu w Immich jest pusta po przywróceniu danych?
Ponieważ oś czasu jest budowana na podstawie wierszy w bazie danych, a przywrócono pliki bez bazy danych. Immich nigdy nie skanuje upload/ w celu ponownego wykrycia zdjęć, więc pliki bez odpowiadających im wierszy pozostają niewidoczne. Same zdjęcia pozostają nienaruszone. Zatrzymaj serwer, wczytaj zrzut do świeżo zainicjowanego Postgresa, a następnie uruchom stos. Jeśli natomiast oś czasu jest pełna, ale żadne zdjęcie się nie otwiera, problem jest odwrotny: library, upload oraz profile nie znajdują się bezpośrednio w katalogu podpiętym do kontenera. Sprawdź to za pomocą docker exec immich_server ls /data.
Które foldery Immich można pominąć w kopii zapasowej?
thumbs oraz encoded-video generują się ponownie z oryginałów, a DB_DATA_LOCATION odbudowuje się ze zrzutu, więc żaden z nich nie musi znajdować się w zestawie kopii zapasowej. Pominięcie ich oszczędza miejsce przed przywróceniem, ale wymaga czasu po nim, ponieważ odbudowa podglądów i transkodowanie dla dużej biblioteki to godziny pracy procesora, uruchamiane z poziomu Administration > Jobs dla brakujących zasobów. Nigdy nie można pominąć library, upload oraz profile, które zawierają jedyną kopię każdego oryginału.
Czy mogę przywrócić zrzut Immich do nowszej wersji?
Zazwyczaj tak, ponieważ serwer stosuje oczekujące migracje przy starcie i aktualizuje schemat. Odwrotna operacja nie zadziała: Immich nie wspiera obniżania wersji, nawet między wydaniami poprawkowymi, więc zrzutu z nowszego wydania nie można załadować do starszego serwera. Przywracaj dane za pomocą IMMICH_VERSION przypiętego do wydania, w którym wykonano zrzut, potwierdź kompletność osi czasu, a dopiero potem wykonaj aktualizację. Zapisuj wersję wydania przy każdym zrzucie za pomocą curl -fsS http://localhost:2283/api/server/version, ponieważ docker inspect wyświetla tylko skonfigurowaną referencję obrazu, a domyślny IMMICH_VERSION=v3 jest zmiennym tagiem, który nie dostarcza żadnych informacji.