Immich auf einem VPS sichern und wiederherstellen
Erfahren Sie, was ein Immich-Backup enthalten muss, warum das Kopieren des Postgres-Datenverzeichnisses nicht genügt und wie eine leere Zeitleiste entsteht.
Was ein Immich-Backup enthalten muss
Ein Immich-Backup besteht aus drei Bestandteilen, die zum gleichen Zeitpunkt erfasst werden. Den Originaldateien unter UPLOAD_LOCATION. Einem SQL-Dump der Postgres-Datenbank. Den .env und docker-compose.yml, die den Stack beschreiben. Bei der Wiederherstellung wird dieser Dump in eine neue Datenbank eingespielt, während der Immich-Server gestoppt ist. Erst danach wird der restliche Stack gestartet. Wenn die Reihenfolge nicht stimmt, erhalten Sie ein funktionierendes Immich mit einer leeren Zeitleiste auf einer vollständig belegten Festplatte.
Diese Aufteilung ist wichtig, weil Immich seinen Zustand an zwei Stellen speichert, die nichts voneinander wissen. Postgres enthält jedes Album, jeden Gesichtscluster, jeden geteilten Link, jedes Benutzerkonto und jeden API-Schlüssel sowie den gespeicherten Pfad jedes Assets. Das Dateisystem enthält die Bilddaten. Stellen Sie die Dateien ohne die Datenbank wieder her, zeigt Immich keine Inhalte an. Stellen Sie die Datenbank ohne die Dateien wieder her, lässt sich jedes Asset nur als fehlerhaftes Bild öffnen.
Die folgenden Befehle beziehen sich auf Immich v3.1.0, die Anfang August 2026 aktuelle Version. Das Projekt veröffentlicht schnell neue Versionen, und die dokumentierte Backup-Prozedur wurde bereits mehrmals geändert. Prüfen Sie daher die tatsächlich ausgeführte Version, bevor Sie etwas kopieren. Wenn der Stack noch nicht läuft, beginnen Sie mit der Immich-Installationsanleitung und kehren Sie anschließend hierher zurück.
Verstehen, worauf Ihre Pfade zeigen
Zwei Variablen in .env bestimmen alles auf dieser Seite. UPLOAD_LOCATION ist das übergeordnete Verzeichnis, in das Immich alle Mediendateien schreibt. DB_DATA_LOCATION ist das Datenverzeichnis von Postgres.
Das standardmäßige example.env setzt UPLOAD_LOCATION=./library. Das ist ein verwirrender Standardwert, weil Immich darin anschließend einen Ordner namens library erstellt. Ihre Originale landen unter ./library/library. Verwenden Sie stattdessen einen absoluten Pfad. Dann hängt ein Backup-Skript nie davon ab, aus welchem Verzeichnis Sie es ausführen.
UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0In UPLOAD_LOCATION erstellt Immich mehrere Ordner. Drei davon enthalten Daten, die kein Auftrag wiederherstellen kann:
library: die Originale, entsprechend Ihrer Speichervorlage angeordnetupload: Originale, die noch nicht in die Struktur der Vorlage verschoben wurden, sowie laufende Uploadsprofile: Benutzerprofilbilder
Wenn library verloren geht, ist das Foto verloren. Immich speichert von einem Original nirgendwo eine zweite Kopie.
Warum das Kopieren des Postgres-Datenverzeichnisses kein Backup ist
DB_DATA_LOCATION sieht nach einem einfachen Ziel aus. Es ist ein Verzeichnis, rsync kopiert es, und der Kopiervorgang endet ohne Fehler. Trotzdem ist es aus zwei Gründen kein Backup. Beide können beim Wiederherstellen zu Fehlern führen.
Der erste Grund ist ein inkonsistenter Kopierstand. Postgres schreibt jede Änderung zuerst in das Write-Ahead-Log (WAL) und übernimmt sie später bei einem Checkpoint in die Tabellendateien. Zu jedem Zeitpunkt befinden sich die Dateien auf dem Datenträger daher in einem Zwischenzustand. Ein laufender Kopiervorgang, der vier Minuten dauert, liest die erste Datei um 02:00 und die letzte um 02:04. Diese beiden Dateien gehören nicht zur selben Transaktion. Wenn Sie Postgres mit dem Ergebnis starten, verweigert es entweder den Start mit PANIC: could not locate a valid checkpoint record oder startet und beendet sich beim ersten Lesen einer beschädigten Seite mit invalid page in block 1234 of relation base/16384/.... Aus dieser Kopie lässt sich keiner dieser Zustände wiederherstellen.
Der zweite Grund bleibt bestehen, selbst wenn Sie vorher alle Dienste anhalten. Ein Postgres-Datenverzeichnis ist an genau die Binärdateien gebunden, die es geschrieben haben. Immich pinnt sein Datenbank-Image über den Digest, derzeit ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0. Dabei handelt es sich um Postgres 14 mit zwei einkompilierten Erweiterungen für die Vektorsuche. Ein mit diesem Build geschriebenes Datenverzeichnis lässt sich nicht unter einer anderen Postgres-Hauptversion öffnen. Es lässt sich auch nicht unter einem Build mit anderen Erweiterungsversionen öffnen. Ihr Restore-Host muss das Image exakt reproduzieren. Ein SQL-Dump ist davon unabhängig: Er besteht aus Text, und jeder kompatible Server kann ihn wieder einspielen.
pg_dump umgeht das Problem des inkonsistenten Kopierstands vollständig. Es liest die gesamte Datenbank innerhalb eines einzigen MVCC-Snapshots (Multi-Version Concurrency Control). Dadurch sieht es die Datenbank exakt so, wie sie zu einem bestimmten Zeitpunkt war, während andere Schreibvorgänge parallel weiterlaufen. Deshalb müssen Sie Postgres für den Dump nicht anhalten.
Was Sie aus der Sicherung auslassen können
Diese Daten werden automatisch neu erzeugt. Sie können sie daher auslassen:
thumbs: Vorschaubilder und Miniaturbilderencoded-video: transkodierte VideosDB_DATA_LOCATION: aus dem Dump neu erstellt- das
model-cacheDocker-Volume: Machine-Learning-Modelle, die bei Bedarf erneut heruntergeladen werden
Das Auslassen ist ein Abwägen und kein kostenloser Vorteil. Das erneute Erzeugen von Miniaturbildern und Transkodierungen für eine große Bibliothek beansprucht auf einem kleinen VPS stundenlang CPU-Zeit. Währenddessen zeigt die Timeline durchgehend graue Platzhalter an. Sie starten die Vorgänge unter Administration > Jobs erneut. Setzen Sie dazu "Generate Thumbnails" und "Transcode Videos" auf die Ausführung für fehlende Assets. Wenn auf dem Sicherungsziel genügend Speicherplatz vorhanden ist, nehmen Sie diese Daten in die Sicherung auf und vermeiden Sie die Wartezeit. Wenn das Speicherlimit fast erreicht ist, lassen Sie sie aus und planen Sie die Neuerstellung ein. Größe einer Immich-Bibliothek beschreibt, wie stark diese Verzeichnisse im Verhältnis zu den Originalen wachsen.
Ein weiteres Verzeichnis sollten Sie kennen. UPLOAD_LOCATION/backups enthält die automatischen Datenbank-Dumps von Immich. Sie werden täglich um 02:00 Uhr erstellt. Die letzten 14 Dumps werden aufbewahrt. Die Einstellung dafür finden Sie unter Administration > Settings > Backup. Diese Dumps verursachen keinen zusätzlichen Aufwand und sind tatsächlich nützlich. Sie liegen jedoch auf demselben Datenträger wie die Bibliothek, die sie schützen sollen. Sie helfen daher bei einer fehlerhaften Migration, nicht aber bei einem ausgefallenen Server. Erstellen Sie trotzdem zusätzlich einen eigenen Dump. Ein manuell ausgelöster Dump wird zum selben Zeitpunkt wie der zugehörige Dateisnapshot erstellt.
Datenbank-Dump erstellen
docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres \
| gzip > /srv/immich/backup/immich.sql.gzErsetzen Sie immich und postgres durch Ihre DB_DATABASE_NAME und DB_USERNAME, falls Sie diese geändert haben. --clean --if-exists setzt vor jedes CREATE ein DROP ... IF EXISTS. Dadurch wird der Dump in eine Datenbank eingespielt, die bereits Objekte enthält, statt beim ersten Objekt abzubrechen.
Nun zu dem Detail, das Backup-Skripte unbemerkt unbrauchbar macht. Dieser Befehl ist eine Pipeline. Eine Shell meldet den Exit-Status des letzten Befehls in einer Pipeline. Wenn pg_dump wegen eines falschen Passworts oder eines nicht laufenden Containers fehlschlägt, erhält gzip einen leeren Datenstrom, schreibt eine formal gültige gzip-Datei und beendet sich mit 0. Ihr Skript protokolliert Erfolg, und Sie haben ein 20 Byte großes Backup. Setzen Sie pipefail an den Anfang jedes Backup-Skripts:
#!/usr/bin/env bash
set -euo pipefailPrüfen Sie anschließend das Ergebnis, statt dem Exit-Code zu vertrauen:
ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3Die erste Zeile eines intakten Dumps lautet -- PostgreSQL database dump. Eine Datei mit wenigen hundert Byte ist ein fehlgeschlagener Dump, unabhängig davon, was das Skript meldet.
Notieren Sie neben dem Dump, welcher Build ihn erstellt hat:
docker inspect --format '{{.Config.Image}}' immich_server > /srv/immich/backup/immich-version.txtVerlassen Sie sich dafür nicht auf .env. Die Standarddatei setzt IMMICH_VERSION=v3, ein veränderliches Tag, das jedem 3.x-Release folgt. Daher zeigt es nicht, welcher Build den Dump tatsächlich erstellt hat. Fixieren Sie zusätzlich das exakte Tag in .env.
Server anhalten und anschließend mit restic einen Snapshot erstellen
Dateien unter UPLOAD_LOCATION sind nicht unveränderlich, während Immich läuft. Der Server schreibt neue Uploads, und der Speicher-Template-Job verschiebt Dateien zwischen Verzeichnissen. Wenn ein Backup-Tool eine Datei liest, während sie teilweise geschrieben wird, speichert es diese Bytes so, als wären sie die vollständige Datei. Dabei wird kein Fehler gemeldet. Halten Sie den Server-Container für die Dauer des Vorgangs an:
docker stop immich_serverLassen Sie immich_postgres weiterlaufen, weil der Dump diesen Dienst benötigt. Die Weboberfläche und die mobile App sind offline, bis Sie den Server wieder starten. Bei einer privaten Instanz um 03:00 ist das normalerweise unproblematisch.
restic passt hier, weil es Daten dedupliziert und verschlüsselt, bevor sie den Server verlassen. Verweisen Sie auf ein Repository, das nicht auf diesem Server liegt:
export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic initObject Storage funktioniert auf dieselbe Weise. Es ist die bessere Lösung, wenn die Kopie vollständig außerhalb Ihrer eigenen Hardware liegen soll:
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 initDieser Endpunkt kann auf einen MinIO-Bucket, den Sie selbst betreiben auf einem zweiten Rechner oder auf einen beliebigen S3-kompatiblen Anbieter verweisen. Ein Repository auf derselben Festplatte wie die Bibliothek schützt Sie vor einem versehentlichen Löschen, aber vor keinem anderen Ausfall.
Erstellen Sie anschließend den Snapshot, der genau die relevanten Dateien erfasst:
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 liest bei jedem Lauf den gesamten Verzeichnisbaum, lädt aber nur Blöcke hoch, die es noch nicht kennt. Der erste Snapshot überträgt daher Ihre gesamte Bibliothek. Jeder weitere Snapshot überträgt nur die an diesem Tag neu hinzugekommenen Fotos.
Aufbewahrung und Schlüssel, die an einem anderen Ort liegen müssen
restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12forget entfernt Snapshots aus dem Index. --prune ist der Teil, der die Daten löscht, auf die diese Snapshots zuletzt verwiesen haben. Wenn Sie forget ohne --prune ausführen, sinken Ihre Speicherkosten nie.
Strukturprüfungen sind kostengünstig. Führen Sie daher einmal pro Woche eine aus:
restic checkDamit wird geprüft, ob die Repository-Metadaten konsistent sind. Ihre Daten werden dabei nicht gelesen. Lesen Sie einmal pro Monat ein Beispiel erneut ein und prüfen Sie es gegen die aufgezeichneten Hashes:
restic check --read-data-subset=5%Nur diese Prüfung erkennt stille Beschädigungen im Storage-Backend, weil dabei echte Blöcke heruntergeladen und ihre Prüfsummen neu berechnet werden. Ein vollständiges --read-data einer Fotosammlung bedeutet, das gesamte Repository herunterzuladen. Bei Object Storage mit nutzungsabhängiger Abrechnung kostet das tatsächlich Geld. Deshalb wird in der Praxis ein fortlaufend wechselnder Teilbestand verwendet.
Nun zum Punkt, den viele überspringen. Ein Passwort für ein restic-Repository kann nicht wiederhergestellt werden. Es gibt weder eine Zurücksetzung noch ein Support-Ticket. Wenn die einzige Kopie in /root/.restic-password auf dem Server liegt, den Sie gerade wiederherstellen möchten, sind Ihre Backups nur verschlüsseltes Rauschen. Dasselbe gilt für den Zugriffsschlüssel des Object Storage und für DB_PASSWORD aus .env. Bewahren Sie alle diese Informationen an einem Ort auf, der nicht davon abhängt, dass dieser Rechner läuft: ausgedruckt in einer Schublade oder in einem Passwortmanager auf anderer Hardware. Wenn auch dieser Manager selbst gehostet wird, gelten dafür dieselben Anforderungen. Vaultwarden zu sichern ist eine eigene Aufgabe.
Immich in der funktionierenden Reihenfolge wiederherstellen
Die Reihenfolge der Wiederherstellung entscheidet darüber, ob aus einem guten Backup eine leere Zeitleiste wird. Halten Sie diese Reihenfolge auf dem neuen Host ein.
Stellen Sie zuerst die Konfiguration wieder her. Daraus geht hervor, welche Version ausgeführt werden soll und auf welche Pfade verwiesen wird.
restic restore latest --target /restore \
--include /srv/immich/.env \
--include /srv/immich/docker-compose.yml \
--include /srv/immich/backupFixieren Sie die Version, bevor irgendetwas startet. Lesen Sie immich-version.txt, setzen Sie IMMICH_VERSION in .env auf genau diesen Tag und verwenden Sie die neueste Version vorerst nicht. Immich unterstützt kein Downgrade, auch nicht zwischen Patch-Releases. Wenn ein neuerer Server mit einem älteren Dump startet und dessen Migrationen ausführt, gibt es keinen Weg zurück.
Stellen Sie die Mediendateien wieder her.
restic restore latest --target /restore --include /srv/immich/dataVerschieben Sie anschließend library, upload und profile so, dass sie direkt innerhalb des Verzeichnisses liegen, auf das UPLOAD_LOCATION auf diesem Host verweist. Der Host-Pfad selbst darf sich ändern, weil die Compose-Datei dieses Verzeichnis an einen festen Pfad innerhalb des Containers bindet. Die Struktur innerhalb dieses Verzeichnisses darf sich nicht ändern.
Starten Sie die Datenbank allein. Lassen Sie DB_DATA_LOCATION leer, damit Postgres einen neuen Cluster initialisiert.
cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgrespg_isready gibt nach Abschluss der erstmaligen Einrichtung accepting connections aus. Das dauert einige Sekunden. docker compose create erstellt alle Container, ohne sie zu starten. Genau das ist der Zweck dieses Schritts: Der Immich-Server darf noch nicht ausgeführt werden. Ein Server, der mit einer leeren Datenbank startet, führt seine Migrationen aus, erstellt ein neues Schema und fordert Sie auf, ein neues Administratorkonto anzulegen. Anschließend spielen Sie den Dump unter einer laufenden Anwendung ein.
Spielen Sie den Dump wieder ein.
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=onZwei Bestandteile sind dabei entscheidend. sed ist erforderlich, weil pg_dump als Sicherheitsmaßnahme ein leeres search_path in die Ausgabe schreibt. Dadurch können nicht qualifizierte Namen im Dump nicht versehentlich auf ein unerwartetes Schema verweisen. Die Vektorsuchtypen von Immich befinden sich in public. Bei einem leeren Suchpfad erreicht die Wiederherstellung daher die erste Spalte, die mit einem Vektortyp deklariert ist, und psql bricht mit ERROR: type "vector" does not exist ab. Wenn Sie public wieder in den Suchpfad aufnehmen, wird das Problem behoben.
--single-transaction --set ON_ERROR_STOP=on führt die gesamte Wiederherstellung in einer Transaktion aus und bricht beim ersten Fehler ab. Sie erhalten entweder eine vollständige Datenbank oder eine unveränderte Datenbank. Ohne diese Option hinterlässt ein Fehler in der Mitte eine Datenbank, die startet, Ihre Anmeldung akzeptiert und eine unbekannte Anzahl von Alben nicht enthält. Das bemerken Sie möglicherweise erst Wochen später.
Starten Sie jetzt alles.
docker compose up -d
docker compose ps
docker logs -f immich_serverWarten Sie auf eine Startmeldung wie Immich Server is listening on. Öffnen Sie anschließend Port 2283 und melden Sie sich mit Ihren bisherigen Zugangsdaten an, da die Benutzerkonten mit dem Dump wiederhergestellt wurden. Wenn die Anmeldeseite stattdessen das Anlegen des ersten Administratorkontos anbietet, wurde die Datenbank nicht wiederhergestellt. Stoppen Sie den Vorgang und lesen Sie die psql-Ausgabe erneut.
Beachten Sie einen wichtigen Punkt bei der offiziellen Anleitung zur Wiederherstellung, die mit docker compose down -v beginnt. -v entfernt benannte Volumes. In der standardmäßigen Compose-Datei sind UPLOAD_LOCATION und DB_DATA_LOCATION Bind-Mounts und bleiben daher erhalten. Wenn Sie einen der beiden Pfade in ein benanntes Volume geändert haben, löscht dieser Befehl Ihre Fotos. Lesen Sie die Compose-Datei, bevor Sie den Befehl ausführen.
Warum die Zeitleiste nach einer Wiederherstellung leer ist
Die Zeitleiste wird aus Datenbankzeilen erzeugt. Immich durchsucht upload/ beim Start nie, um Fotos erneut zu erkennen, weil eine Datei ohne Datenbankzeile keinen Besitzer, kein Datum und kein Album hat. Die häufigste fehlerhafte Wiederherstellung besteht daher darin, dass die Dateien vorhanden sind, die Datenbank aber fehlt. Immich startet, legt ein leeres Schema an und stellt Ihnen eine funktionierende Instanz bereit, die keine Inhalte enthält, während die Festplatte mit Ihren Fotos gefüllt ist. Es ist nichts verloren. Sichtbar ist jedoch ebenfalls nichts. Die Lösung besteht darin, den Dump bei gestopptem Server genau wie oben erneut einzuspielen.
Die zweite Variante ist unauffälliger. Die Datenbank wird wiederhergestellt, die Zeitleiste füllt sich mit Einträgen, und jedes Asset kann nicht geöffnet werden. Das bedeutet, dass die Zeilen auf Dateien verweisen, die der Container nicht sehen kann. Ursache ist meist, dass library, upload und profile nach einem restic restore --target /restore eine Ebene zu tief liegen, weil niemand es an die richtige Stelle verschoben hat. Prüfen Sie dies innerhalb des Containers, statt zu raten:
docker exec immich_server ls /dataDie mitgelieferte Compose-Datei bind-mountet UPLOAD_LOCATION nach /data. Die Auflistung sollte daher library, upload und profile anzeigen. Wenn ein leeres Verzeichnis oder ein fremder Ordner srv angezeigt wird, verweist Ihr Bind-Mount auf die falsche Ebene. Die Zeilen sind dann korrekt.
Versionsübereinstimmung zwischen Backup und Wiederherstellung
Immich veröffentlicht häufig neue Versionen, und das Schema wird dabei angepasst. Ein Dump enthält daher das Schema des Servers, der ihn erstellt hat.
Die Wiederherstellung eines älteren Dumps auf einem neueren Server funktioniert normalerweise, weil der Server beim Start ausstehende Migrationen ausführt und das Schema schrittweise aktualisiert. Dieser Pfad wird entlang der Versionsfolge getestet. Probleme treten auf, wenn mehrere Hauptversionen in einem Schritt übersprungen werden. Das Projekt beschränkt inkompatible Änderungen auf Hauptversionen und dokumentiert sie im Changelog.
Die Wiederherstellung eines neueren Dumps auf einem älteren Server funktioniert überhaupt nicht. Der Dump enthält Tabellen und Spalten, die der ältere Code nicht kennt. Immich erklärt außerdem, dass ein Downgrade selbst zwischen Patch-Versionen nicht unterstützt wird. Es gibt keinen Rollback-Befehl, den Sie dafür verwenden können.
Eine sichere Wiederherstellung ist daher unspektakulär. Führen Sie exakt die Version aus, die den Dump erstellt hat, spielen Sie ihn ein, melden Sie sich an und prüfen Sie, ob die Timeline vollständig ist. Aktualisieren Sie erst danach. Führen Sie das Upgrade jeweils um eine Version durch, passen Sie IMMICH_VERSION an und führen Sie anschließend docker compose pull && docker compose up -d aus. Wenn Sie Dumps eine Woche lang aufbewahren, hilft das ebenfalls: Falls der neueste Dump während eines fehlgeschlagenen Upgrades erstellt wurde, befindet sich der Dump vom Vortag noch im Repository.
Backup jeden Monat überprüfen
Ein Backup, das Sie noch nie wiederhergestellt haben, ist nur eine Vermutung. Stellen Sie es einmal im Monat in einer Wegwerf-Instanz wieder her und sehen Sie sich ein Foto an. Die Prüfung dauert etwa zwanzig Minuten. Nur dadurch wird der Rest dieser Seite zu einem Wiederherstellungsplan.
restic snapshots
restic stats latestsnapshots sollte den Lauf der vergangenen Nacht auflisten. stats latest sollte eine Größe nahe der Größe Ihrer Bibliothek ausgeben, nicht nur wenige Megabytes.
Stellen Sie das Backup in einem temporären Verzeichnis wieder her, idealerweise auf einem Ersatzhost:
restic restore latest --target /tmp/immich-drillKopieren Sie docker-compose.yml und .env aus dem wiederhergestellten Bestand heraus. Ändern Sie anschließend drei Dinge in der Kopie. Verweisen Sie mit UPLOAD_LOCATION und DB_DATA_LOCATION auf Verzeichnisse unter /tmp/immich-drill. Veröffentlichen Sie den Webport an einer anderen Stelle, also 12283:2283 statt 2283:2283. Löschen Sie die Zeilen container_name:, weil die mitgelieferte Compose-Datei Namen wie immich_server fest vorgibt. Dadurch kollidiert ein zweiter Stack auf demselben Host mit dem ersten, und Docker verweigert dessen Erstellung.
Führen Sie die oben beschriebene Wiederherstellungssequenz aus: nur die Datenbank, den Dump einspielen und anschließend docker compose up -d. Führen Sie nun die vier Prüfungen durch, die den Erfolg belegen.
- Melden Sie sich mit dem Passwort an, das Sie vor der Prüfung verwendet haben. Funktionierende Konten zeigen, dass der Dump wiederhergestellt wurde.
- Öffnen Sie die Zeitleiste und blättern Sie zum ältesten Monat. Assets über den gesamten Datumsbereich zeigen, dass alle Datensätze zurückgekommen sind, nicht nur die aktuellen.
- Öffnen Sie ein Foto in voller Größe und laden Sie das Original herunter.
- Vergleichen Sie es mit derselben Datei in Ihrer aktiven Bibliothek mit
sha256sum. Übereinstimmende Hashes zeigen, dass die Bytes den vollständigen Weg durch restic überstanden haben.
Räumen Sie die Prüfung anschließend mit docker compose down -v im Prüfverzeichnis auf und löschen Sie /tmp/immich-drill. Notieren Sie das Datum an einer Stelle, an der Sie es sehen, denn der Nutzen dieser Prüfung liegt vollständig darin, sie im nächsten Monat erneut durchzuführen. Wenn Sie noch entscheiden, für welchen Fotoserver Sie sich festlegen möchten, beschreibt der Vergleich von PhotoPrism und Immich, worin sich beide genau in diesem Punkt unterscheiden.
FAQ
Muss ich Immich für die Sicherung stoppen?
Stoppen Sie immich_server und lassen Sie immich_postgres weiterlaufen. Die Datenbank benötigt keine Pause, weil pg_dump innerhalb eines einzelnen MVCC-Snapshots liest und unabhängig von anderen Schreibvorgängen einen konsistenten Zeitpunkt sieht. Der Grund für das Stoppen sind die Dateien: Der Server schreibt neue Uploads, und der Storage-Template-Job verschiebt Dateien zwischen Verzeichnissen. Ein Sicherungstool kann daher eine Datei während eines Schreibvorgangs lesen und ohne Fehlermeldung eine abgeschnittene Kopie speichern. docker stop immich_server vor dem Snapshot und docker start immich_server danach beseitigt diese Race Condition.
Kann ich das Postgres-Datenverzeichnis kopieren, statt pg_dump auszuführen?
Nein. Eine laufende Kopie eines aktiven Datenverzeichnisses liest verschiedene Dateien zu unterschiedlichen Zeitpunkten. Das Ergebnis entspricht daher keinem konsistenten Zustand. Postgres weist die Kopie beim Start mit PANIC: could not locate a valid checkpoint record zurück oder schlägt später wegen einer beschädigten Seite fehl. Selbst eine Kopie, die bei vollständig gestoppten Diensten erstellt wurde, ist an den exakten Datenbank-Build gebunden: Immich verwendet ein Postgres-14-Image mit bestimmten Versionen der Vektorsuche-Erweiterungen, und das Verzeichnis lässt sich mit keiner anderen Variante öffnen. Ein SQL-Dump ist Klartext und kann in jeden kompatiblen Server eingespielt werden.
Warum ist meine Immich-Timeline nach einer Wiederherstellung leer?
Weil die Timeline aus Datenbankzeilen erzeugt wird und Sie die Dateien ohne die Datenbank wiederhergestellt haben. Immich durchsucht upload/ nie erneut, um Fotos zu erkennen. Dateien ohne zugehörige Zeilen bleiben daher unsichtbar. Die Fotos selbst sind unverändert. Stoppen Sie den Server, spielen Sie den Dump in ein frisch initialisiertes Postgres ein und starten Sie anschließend den Stack. Wenn die Timeline dagegen vollständig ist, sich aber kein Foto öffnen lässt, liegt das umgekehrte Problem vor: library, upload und profile befinden sich nicht direkt in dem Verzeichnis, das in den Container eingebunden ist. Prüfen Sie dies mit docker exec immich_server ls /data.
Welche Immich-Verzeichnisse kann ich bei einer Sicherung auslassen?
thumbs und encoded-video werden aus den Originalen neu erzeugt, und DB_DATA_LOCATION wird aus dem Dump wiederhergestellt. Keines dieser Verzeichnisse muss daher in der Sicherung enthalten sein. Das Auslassen spart vor der Wiederherstellung Speicherplatz, erfordert danach aber zusätzliche Zeit, da die Vorschauen und Transcodierungen für eine große Bibliothek mehrere Stunden CPU-Zeit benötigen. Starten Sie den Vorgang unter Administration > Jobs für fehlende Assets. Niemals auslassen dürfen Sie library, upload und profile. Sie enthalten die jeweils einzige Kopie jedes Originals.
Kann ich einen Immich-Dump in einer neueren Version wiederherstellen?
In der Regel ja, weil der Server beim Start ausstehende Migrationen ausführt und das Schema schrittweise aktualisiert. Die umgekehrte Richtung schlägt fehl: Immich unterstützt kein Downgrade, auch nicht zwischen Patch-Releases. Ein Dump aus einer neueren Version kann daher nicht in einen älteren Server geladen werden. Stellen Sie den Dump mit IMMICH_VERSION auf die Version fest, die den Dump erstellt hat, prüfen Sie, ob die Timeline vollständig ist, und führen Sie erst danach das Upgrade durch. Vermerken Sie die Version mit docker inspect --format '{{.Config.Image}}' immich_server neben jedem Dump, weil IMMICH_VERSION=v3 standardmäßig ein schwebender Tag ist und keine verwertbare Information liefert.