SSD Nodes Learn 🎉 VPS dès $4.99/mois
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-07

Comment sauvegarder et restaurer Immich sur un VPS

Découvrez les 3 éléments indispensables d’une sauvegarde Immich v3.1.0 et pourquoi copier le dossier Postgres produit une timeline vide après restauration.

Ce qu’une sauvegarde Immich doit contenir

Une sauvegarde Immich comprend trois éléments capturés au même moment. Les originaux sous UPLOAD_LOCATION. Un dump SQL de la base de données Postgres. Les fichiers .env et docker-compose.yml qui décrivent la stack. La restauration consiste à réinjecter ce dump dans une base de données neuve, pendant que le serveur Immich est arrêté, puis à démarrer le reste de la stack. Si vous inversez l’ordre, vous obtenez un Immich fonctionnel qui affiche une timeline vide sur un disque pourtant plein.

Cette séparation est importante, car Immich conserve son état à deux endroits qui ne communiquent pas entre eux. Postgres contient chaque album, chaque groupe de visages, chaque lien partagé, chaque compte utilisateur et chaque clé API, ainsi que le chemin enregistré de chaque asset. Le système de fichiers contient les pixels. Si vous restaurez les fichiers sans la base de données, Immich n’affiche rien. Si vous restaurez la base de données sans les fichiers, chaque asset s’ouvre comme une image inaccessible.

Les commandes de cette procédure ciblent Immich v3.1.0, la release disponible début août 2026. Le projet évolue rapidement et la procédure de sauvegarde documentée a changé plusieurs fois. Vérifiez donc la version réellement utilisée avant de copier quoi que ce soit. Si la stack n’est pas encore démarrée, commencez par le guide d’installation d’Immich, puis revenez ici.

Identifiez la cible de vos chemins

Deux variables de .env déterminent tout ce qui se trouve sur cette page. UPLOAD_LOCATION est le répertoire parent dans lequel Immich écrit tous les médias. DB_DATA_LOCATION est le répertoire de données de Postgres.

Le example.env fourni par défaut définit UPLOAD_LOCATION=./library. Cette valeur par défaut prête à confusion, car Immich crée ensuite un dossier nommé library à l’intérieur de ce répertoire. Vos originaux se retrouvent dans ./library/library. Définissez plutôt un chemin absolu, afin qu’un script de sauvegarde ne dépende jamais du répertoire depuis lequel vous l’avez exécuté.

UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0

Dans UPLOAD_LOCATION, Immich crée plusieurs dossiers. Trois d’entre eux contiennent des données qu’aucun job ne peut reconstruire :

  • library : les originaux, organisés selon votre modèle de stockage
  • upload : les originaux qui n’ont pas encore été déplacés selon la structure du modèle, ainsi que les téléversements en cours
  • profile : les photos de profil des utilisateurs

Si vous perdez library, la photo est perdue. Immich ne conserve aucune autre copie d’un original.

Pourquoi copier le répertoire de données Postgres ne constitue pas une sauvegarde

DB_DATA_LOCATION semble être une cible facile. C’est un répertoire, rsync permet de le copier, et la copie se termine sans erreur. Il ne s’agit pourtant pas d’une sauvegarde, pour deux raisons qui peuvent provoquer un échec.

La première est l’incohérence de la copie. Postgres écrit d’abord chaque modification dans le write-ahead log (WAL), puis l’applique aux fichiers de tables lors d’un checkpoint. À un instant donné, les fichiers présents sur le disque sont donc dans un état intermédiaire. Une copie progressive qui dure quatre minutes lit le premier fichier à 02:00 et le dernier à 02:04. Ces deux fichiers ne correspondent pas à la même transaction. Lorsque vous démarrez Postgres avec le résultat, il refuse soit de démarrer et affiche PANIC: could not locate a valid checkpoint record, soit il démarre puis s’arrête dès la première lecture d’une page endommagée avec invalid page in block 1234 of relation base/16384/.... Cette copie ne permet de récupérer aucun de ces cas.

La deuxième raison reste valable même si vous arrêtez d’abord tous les services. Un répertoire de données Postgres dépend exactement des binaires qui l’ont écrit. Immich épingle l’image de sa base de données par digest, actuellement ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0. Il s’agit de Postgres 14 avec deux extensions de recherche vectorielle compilées. Un répertoire de données écrit par cette build ne s’ouvrira pas avec une autre version majeure de Postgres. Il ne s’ouvrira pas non plus avec une build contenant d’autres versions des extensions. L’hôte de restauration doit reproduire exactement l’image utilisée. Un dump SQL n’a pas cette contrainte : c’est du texte, et n’importe quel serveur compatible peut le rejouer.

pg_dump évite directement le problème d’incohérence. Il lit toute la base de données dans un seul snapshot MVCC (multi-version concurrency control). Il voit ainsi la base exactement telle qu’elle était à un instant donné, tandis que les autres écritures se poursuivent. C’est pourquoi vous n’avez pas besoin d’arrêter Postgres pour effectuer le dump.

Ce que vous pouvez exclure de la sauvegarde

Ces éléments peuvent être régénérés. Vous pouvez donc les exclure :

  • thumbs : images d’aperçu et miniatures
  • encoded-video : vidéos transcodées
  • DB_DATA_LOCATION : fichiers reconstruits à partir du dump
  • le volume Docker model-cache : modèles de machine learning, retéléchargés à la demande

Les exclure implique un compromis. La reconstruction des miniatures et des transcodages d’une grande bibliothèque peut utiliser plusieurs heures de CPU sur un petit VPS. Pendant ce temps, la timeline affiche des emplacements réservés gris. Vous pouvez relancer ces tâches depuis Administration > Jobs, en configurant « Generate Thumbnails » et « Transcode Videos » pour qu’elles s’exécutent sur les éléments manquants. Si votre cible de sauvegarde dispose de suffisamment d’espace, incluez-les et évitez cette attente. Si vous approchez de la limite de stockage, excluez-les et prévoyez leur reconstruction. Dimensionner une bibliothèque Immich explique comment la taille de ces répertoires évolue par rapport aux originaux.

Un autre répertoire mérite votre attention. UPLOAD_LOCATION/backups contient les dumps automatiques de la base de données créés par Immich. Ils sont générés chaque jour à 02:00, et les 14 derniers sont conservés. Ce comportement se configure dans Administration > Settings > Backup. Ils ne consomment aucune ressource supplémentaire significative et sont réellement utiles. Ils se trouvent toutefois sur le même disque que la bibliothèque qu’ils protègent. Ils vous aident donc en cas de migration défectueuse, mais pas en cas de panne du serveur. Effectuez tout de même votre propre dump, car celui que vous déclenchez vous-même est créé au même moment que le snapshot des fichiers correspondant.

Effectuer le dump de la base de données

docker exec -t immich_postgres pg_dump --clean --if-exists \
  --dbname=immich --username=postgres \
  | gzip > /srv/immich/backup/immich.sql.gz

Remplacez immich et postgres par vos valeurs DB_DATABASE_NAME et DB_USERNAME si vous les avez modifiées. --clean --if-exists place un DROP ... IF EXISTS devant chaque CREATE. Le dump peut ainsi être restauré dans une base qui contient déjà des objets, au lieu de s’arrêter au premier objet rencontré.

Voici le détail qui fait échouer silencieusement les scripts de sauvegarde. Cette commande utilise un pipeline, et un shell renvoie le code de sortie de la dernière commande du pipeline. Si pg_dump échoue, à cause d’un mot de passe incorrect ou d’un conteneur qui n’est pas en cours d’exécution, gzip reçoit un flux vide, écrit un fichier gzip parfaitement valide et se termine avec le code 0. Votre script journalise une réussite et vous vous retrouvez avec une sauvegarde de 20 octets. Placez pipefail au début de chaque script de sauvegarde :

#!/usr/bin/env bash
set -euo pipefail

Vérifiez ensuite le résultat au lieu de faire confiance au code de sortie :

ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3

La première ligne d’un dump valide est -- PostgreSQL database dump. Un fichier de quelques centaines d’octets correspond à un dump échoué, quel que soit le résultat indiqué par le script.

Notez le build qui a généré le dump, à côté de celui-ci :

docker inspect --format '{{.Config.Image}}' immich_server > /srv/immich/backup/immich-version.txt

Ne vous fiez pas à .env pour cela. Le fichier fourni définit IMMICH_VERSION=v3, un tag flottant qui suit chaque version 3.x. Il ne vous indique donc pas quel build a réellement généré le dump. Épinglez également le tag exact dans .env.

Mettre le serveur à l’arrêt, puis créer un snapshot avec restic

Les fichiers sous UPLOAD_LOCATION ne sont pas immuables pendant l’exécution d’Immich. Le serveur écrit les nouveaux uploads, et la tâche du template de stockage déplace les fichiers entre les répertoires. Si un outil de sauvegarde lit un fichier pendant son écriture, il enregistre ces octets comme s’il s’agissait du fichier complet, sans signaler d’erreur. Arrêtez le conteneur du serveur pendant toute la durée de l’opération :

docker stop immich_server

Laissez immich_postgres en fonctionnement, car le dump en a besoin. L’interface web et l’application mobile restent indisponibles jusqu’au redémarrage du serveur. Sur une instance familiale, une exécution à 03:00 convient généralement.

restic convient ici, car il déduplique et chiffre les données avant qu’elles ne quittent le serveur. Configurez-le pour utiliser un repository qui ne se trouve pas sur ce serveur :

export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init

Le stockage objet fonctionne de la même manière. C’est la meilleure solution si vous voulez que la copie se trouve entièrement sur un autre matériel :

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 init

Cet endpoint peut être un bucket MinIO que vous gérez vous-même sur une deuxième machine, ou n’importe quel fournisseur compatible S3. Un repository situé sur le même disque que la bibliothèque vous protège contre une suppression accidentelle, mais contre rien d’autre.

Créez ensuite le snapshot en listant précisément ce qui doit être sauvegardé :

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_server

restic parcourt toute l’arborescence à chaque exécution, mais n’envoie que les blocs qu’il n’a pas déjà vus. Le premier snapshot transfère donc toute votre bibliothèque. Les snapshots suivants transfèrent uniquement les nouvelles photos de la journée.

Rétention et clés à conserver ailleurs

restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12

forget supprime les snapshots de l’index. --prune est la partie qui supprime les données dont ces snapshots étaient la dernière référence. Exécutez forget sans --prune et votre facture de stockage ne baisse jamais.

Les vérifications de structure sont peu coûteuses. Exécutez-en une chaque semaine :

restic check

Cette commande vérifie que les métadonnées du repository sont cohérentes. Elle ne lit pas vos données. Une fois par mois, relisez un échantillon et comparez-le aux hashes enregistrés :

restic check --read-data-subset=5%

C’est la seule vérification qui détecte une corruption silencieuse sur le backend de stockage, car elle télécharge de vrais blocs et recalcule leurs checksums. Un --read-data complet sur une photothèque nécessite de télécharger l’intégralité du repository. Sur un object storage facturé à l’usage, cela coûte réellement de l’argent. Un sous-ensemble traité par rotation est donc la version réellement utilisée.

Voici la partie souvent négligée. Le mot de passe d’un repository restic n’est pas récupérable. Il n’existe aucune réinitialisation et aucun ticket de support ne peut résoudre le problème. Si la seule copie se trouve dans /root/.restic-password sur le serveur que vous essayez de restaurer, vos sauvegardes ne sont qu’un contenu chiffré inutilisable. Il en va de même pour la clé d’accès à l’object storage et pour DB_PASSWORD de .env. Conservez-les tous dans un emplacement qui ne dépend pas du fonctionnement de cette machine : imprimés et rangés dans un tiroir, ou dans un gestionnaire de mots de passe exécuté sur un autre matériel. Si ce gestionnaire est lui aussi auto-hébergé, il doit être traité de la même manière, et sauvegarder Vaultwarden est une tâche à part.

Restaurer Immich dans l’ordre correct

L’ordre de restauration permet de transformer de bonnes sauvegardes en chronologies vides. Suivez cette séquence sur le nouvel hôte.

Restaurez d’abord la configuration. Elle indique quelle version exécuter et où pointent les chemins.

restic restore latest --target /restore \
  --include /srv/immich/.env \
  --include /srv/immich/docker-compose.yml \
  --include /srv/immich/backup

Figez la version avant tout démarrage. Lisez immich-version.txt, définissez IMMICH_VERSION dans .env avec ce tag exact et laissez la version la plus récente de côté pour le moment. Immich ne prend pas en charge les rétrogradations, même entre versions de correctif. Si un serveur plus récent démarre avec un dump plus ancien et exécute ses migrations, il est impossible de revenir en arrière.

Restaurez les fichiers multimédias.

restic restore latest --target /restore --include /srv/immich/data

Déplacez ensuite library, upload et profile afin qu’ils se trouvent directement dans le répertoire vers lequel pointe UPLOAD_LOCATION sur cet hôte. Le chemin sur l’hôte peut changer, car le fichier compose lie ce répertoire à un chemin fixe dans le conteneur. L’arborescence à l’intérieur de ce répertoire ne doit pas changer.

Démarrez la base de données seule. Laissez DB_DATA_LOCATION vide afin que Postgres initialise un cluster vierge.

cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgres

pg_isready affiche accepting connections une fois l’initialisation terminée, ce qui prend quelques secondes. docker compose create construit tous les conteneurs sans les démarrer. C’est précisément l’objectif de cette étape : le serveur Immich ne doit pas encore s’exécuter. Un serveur qui démarre avec une base vide exécute ses migrations, crée un schéma vierge et vous demande de créer un nouveau compte administrateur. Vous restaurez alors un dump sous une application en cours d’exécution.

Réinjectez le dump.

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=on

Deux éléments jouent ici un rôle important. Le sed est nécessaire parce que pg_dump écrit un search_path vide dans sa sortie par mesure de sécurité. Les noms non qualifiés du dump ne peuvent ainsi pas être résolus vers un schéma inattendu. Les types de recherche vectorielle d’Immich résident dans public. Avec un chemin de recherche vide, la restauration atteint la première colonne déclarée avec un type vectoriel, puis psql s’arrête avec ERROR: type "vector" does not exist. Remettre public dans le chemin corrige le problème.

--single-transaction --set ON_ERROR_STOP=on englobe toute la restauration dans une seule transaction qui s’arrête à la première erreur. Vous obtenez soit une base complète, soit une base inchangée. Sans cette option, une erreur à mi-parcours laisse une base qui démarre, accepte votre connexion et à laquelle il manque un nombre indéterminé d’albums. Vous pouvez ne le découvrir que plusieurs semaines plus tard.

Démarrez maintenant tous les services.

docker compose up -d
docker compose ps
docker logs -f immich_server

Attendez une ligne de démarrage telle que Immich Server is listening on, puis ouvrez le port 2283 et connectez-vous avec vos anciens identifiants, car les comptes utilisateurs ont été restaurés avec le dump. Si la page de connexion propose plutôt de créer le premier compte administrateur, la base de données n’a pas été restaurée. Arrêtez-vous et relisez la sortie de psql.

Une mise en garde concernant les instructions officielles de restauration, qui commencent par docker compose down -v. La commande -v supprime les volumes nommés. Dans le fichier compose standard, UPLOAD_LOCATION et DB_DATA_LOCATION sont des bind mounts ; ils sont donc conservés. Si vous avez remplacé l’un d’eux par un volume nommé, cette commande supprime vos photos. Lisez votre fichier compose avant de l’exécuter.

Pourquoi la timeline est vide après une restauration

La timeline est générée à partir des lignes de la base de données. Immich ne parcourt jamais upload/ au démarrage pour redécouvrir les photos, car un fichier sans ligne n’a ni propriétaire, ni date, ni album. Le cas de restauration incorrect le plus fréquent est donc le suivant : les fichiers sont restaurés, mais pas la base de données. Immich démarre, crée un schéma vide et vous fournit une instance fonctionnelle qui ne contient rien, alors que le disque est rempli de vos photos. Rien n’est perdu. Mais rien n’est visible non plus. Pour corriger le problème, rejouez le dump avec le serveur arrêté, exactement comme indiqué plus haut.

La deuxième variante est plus discrète. La base de données est restaurée, la timeline se remplit d’entrées, mais chaque asset ne peut pas être ouvert. Cela signifie que les lignes pointent vers des fichiers que le conteneur ne peut pas voir, généralement parce que library, upload et profile sont un niveau trop profond après un restic restore --target /restore que personne n’a déplacé au bon endroit. Vérifiez depuis l’intérieur du conteneur au lieu de procéder par déduction :

docker exec immich_server ls /data

Le fichier compose fourni par défaut monte UPLOAD_LOCATION sur /data. La commande doit donc afficher library, upload et profile. Si elle affiche un répertoire vide ou un dossier srv isolé, votre bind mount pointe vers le mauvais niveau et les lignes sont correctes.

Correspondance des versions entre sauvegarde et restauration

Immich publie fréquemment de nouvelles versions, et le schéma évolue avec elles. Un dump contient donc le schéma du serveur qui l’a créé.

La restauration d’un dump plus ancien sur un serveur plus récent fonctionne généralement, car le serveur applique ses migrations en attente au démarrage et fait évoluer le schéma. Ce parcours est testé tout au long de la séquence des versions. Les problèmes apparaissent surtout lorsqu’on saute plusieurs versions majeures en une seule étape. Le projet réserve les changements incompatibles aux versions majeures et les documente dans son changelog.

La restauration d’un dump plus récent sur un serveur plus ancien ne fonctionne pas. Le dump contient des tables et des colonnes que l’ancien code ne connaît pas. Immich indique également que la rétrogradation n’est pas prise en charge, même entre des versions correctives. Il n’existe aucune commande de rollback à utiliser.

La méthode de restauration sûre est donc simple. Exécutez exactement la version qui a créé le dump, restaurez-le, connectez-vous et vérifiez que la timeline est complète. Effectuez ensuite la mise à niveau. Procédez une version à la fois, en mettant à jour IMMICH_VERSION et en exécutant docker compose pull && docker compose up -d après chaque mise à niveau. Conserver une semaine de dumps est également utile ici : si le plus récent a été créé pendant une mise à niveau échouée, celui de la veille se trouve encore dans le dépôt.

Vérifiez la sauvegarde chaque mois

Une sauvegarde que vous n’avez jamais restaurée reste une hypothèse. Une fois par mois, restaurez-la dans une instance temporaire et affichez une photo. L’exercice prend environ vingt minutes. C’est le seul moyen de transformer le reste de cette page en véritable plan de reprise.

restic snapshots
restic stats latest

snapshots doit afficher l’exécution de la nuit dernière. stats latest doit indiquer une taille proche de celle de votre photothèque, et non quelques mégaoctets.

Restaurez la sauvegarde dans un répertoire de travail, idéalement sur un hôte de secours :

restic restore latest --target /tmp/immich-drill

Copiez docker-compose.yml et .env hors de l’ensemble restauré, puis modifiez trois éléments dans ces copies. Faites pointer UPLOAD_LOCATION et DB_DATA_LOCATION vers des répertoires situés sous /tmp/immich-drill. Publiez le port web ailleurs, avec 12283:2283 au lieu de 2283:2283. Supprimez les lignes container_name:, car le fichier compose fourni en standard contient en dur des noms comme immich_server. Une seconde stack sur le même hôte entrerait ainsi en conflit avec la première et Docker refuserait de la créer.

Exécutez la séquence de restauration indiquée plus haut : la base de données uniquement, rejouez le dump, puis docker compose up -d. Effectuez ensuite les quatre vérifications suivantes.

  1. Connectez-vous avec le mot de passe utilisé avant l’exercice. Si les comptes fonctionnent, le dump a bien été restauré.
  2. Ouvrez la timeline et faites défiler jusqu’au mois le plus ancien. La présence d’assets sur toute la période indique que toutes les lignes ont été restaurées, et pas seulement les plus récentes.
  3. Ouvrez une photo en taille réelle et téléchargez l’original.
  4. Comparez-le au même fichier dans votre photothèque active avec sha256sum. Des hash identiques prouvent que les octets ont survécu à l’aller-retour via restic.

Supprimez ensuite l’environnement de test avec docker compose down -v dans le répertoire de l’exercice, puis supprimez /tmp/immich-drill. Notez la date à un endroit où vous la verrez, car l’intérêt de cette procédure repose entièrement sur sa répétition le mois suivant. Si vous hésitez encore sur le serveur photo à retenir, la comparaison entre PhotoPrism et Immich explique leurs différences précisément sur ce point.

FAQ

Dois-je arrêter Immich pour effectuer la sauvegarde ?

Arrêtez immich_server et laissez immich_postgres fonctionner. La base de données n’a pas besoin d’être suspendue, car pg_dump lit dans un snapshot MVCC unique et voit un instant cohérent, quelles que soient les autres opérations d’écriture. Les fichiers sont la raison pour laquelle il faut arrêter le service : le serveur écrit les nouveaux téléversements et la tâche de template de stockage déplace les fichiers entre les répertoires. Un outil de sauvegarde peut donc lire un fichier pendant son écriture et enregistrer une copie tronquée sans signaler d’erreur. docker stop immich_server avant le snapshot et docker start immich_server après celui-ci supprime cette condition de concurrence.

Puis-je copier le dossier de données Postgres au lieu d’exécuter pg_dump ?

Non. La copie progressive d’un répertoire de données actif lit différents fichiers à des instants différents. Le résultat ne correspond donc pas à un état cohérent, et Postgres la refuse au démarrage avec PANIC: could not locate a valid checkpoint record ou échoue plus tard sur une page endommagée. Même une copie effectuée lorsque tout est arrêté dépend exactement du build de la base de données : Immich utilise une image Postgres 14 avec des versions précises de l’extension de recherche vectorielle, et le répertoire ne s’ouvrira avec rien d’autre. Un dump SQL est du texte brut et peut être rejoué sur tout serveur compatible.

Pourquoi ma timeline Immich est-elle vide après une restauration ?

Parce que la timeline est construite à partir des lignes de la base de données et que vous avez restauré les fichiers sans la base de données. Immich n’analyse jamais upload/ pour retrouver les photos. Les fichiers sans ligne correspondante restent donc invisibles. Les photos elles-mêmes n’ont pas été modifiées. Arrêtez le serveur, rejouez le dump dans une instance Postgres fraîchement initialisée, puis démarrez la stack. Si, au contraire, la timeline est complète mais que chaque photo échoue à l’ouverture, le problème est inversé : library, upload et profile ne se trouvent pas directement dans le répertoire monté dans le conteneur. Vérifiez-le avec docker exec immich_server ls /data.

Quels dossiers Immich puis-je exclure d’une sauvegarde ?

thumbs et encoded-video sont régénérés à partir des originaux, et DB_DATA_LOCATION est reconstruit à partir du dump. Aucun de ces dossiers n’a donc besoin de figurer dans le jeu de sauvegarde. Les exclure consomme du temps après une restauration plutôt que de l’espace avant celle-ci, car la reconstruction des previews et des transcodages d’une grande bibliothèque demande plusieurs heures de CPU. Elle s’exécute depuis Administration > Jobs pour les assets manquants. Vous ne pouvez jamais exclure library, upload et profile, qui contiennent l’unique copie de chaque original.

Puis-je restaurer un dump Immich dans une version plus récente ?

En général, oui, car le serveur applique ses migrations en attente au démarrage et fait évoluer le schéma. L’opération inverse échoue : Immich ne prend pas en charge le downgrade, même entre des patch releases. Un dump provenant d’une release plus récente ne peut donc pas être chargé dans un serveur plus ancien. Effectuez la restauration avec IMMICH_VERSION épinglé sur la release qui a écrit le dump, vérifiez que la timeline est complète, puis procédez à la mise à niveau. Notez la version à côté de chaque dump avec docker inspect --format '{{.Config.Image}}' immich_server, car la valeur par défaut IMMICH_VERSION=v3 est un tag flottant qui ne vous apprend rien.