Immich, la photothèque des pros

Présentation d'Immich

Des années que je cherchais un outil correct pour gérer mes photos. Je ne demandais pas la lune, mais:

  • un outil OpenSource
  • qui soit accessible depuis une interface Web
  • qui gère un nombre important de photos / vidéos
  • qui puisse être disponible sur smartphone, notamment iPhone

Je n'ai jamais trouvé chaussure à mon pied, et je me contentais de gérer mes photos transférées sur mon Synology pour archivage. Tout ça c'était avant Immich!

Immich est puissant, solide, facile d'accès. What else?

L'idée d'Immich c'est de reprendre l'excellent travail des équipes de Google, en mettant en place un outil gratuit et libre de droits. Mais la popularité de l'outil a fait qu'ils ont été bien plus loin qu'un fork de Google Photos.

On le verra dans le paragraphe d'après, mais le choix de Docker est ici assumé et très pratique, notament pour les nombreuses mises à jour de l'outil.

La base de données postgresql est bien taillée pour l'utilisation de nombreuses photos et les tags associés, et l'interface web est bien foutue.

Donc une fois installé, il n'y a aucune difficulté à prendre en main l'outil pour y ajouter ses premières photos, rajouter des utilisateurs, partager des albums...

Une communauté mo-ti-vée

Pour celles et ceux qui ne connaissent pas Docker, les débuts peuvent être laborieux. Mais heureusement une communauté très développée accompagne les nouveaux Immichiens (je viens de l'inventer, oui c'est moche) pour paufiner leur installation et surtout y ajouter leurs nombreuses photos.

Car comme moi de nombreuses personnes ont longtemps erré sur les entrailles du net avant de découvrir la lumière, et c'est en milliers (dizaines de milliers?) de photos qu'on compte les souvenirs à ajouter.

Tout cela ne se fait pas en un claquement de doigts, et surtout avec les photos... nous sommes frileux!

Avant d'écrire cet article, j'ai donc bien poncé l'outil:

  • une dizaine de différentes versions (dont deux majeures) le tout sur deux petites années
  • un apport dans un 1er temps des photos stockées sur deux iPhones (environ 400 photos)...
  • ...puis la synchro complète avec mon NAS (environ 10000 photos) via l'outil en ligne de commande (j'y reviens plus bas)
  • un accès en local, vpn et ouvert sur le net

Alors oui allez y, Immich c'est de la bonne.

Que du positif donc?

Non, rien n'est parfait et Immich n'est pas une exception.

D'abord le design vraiment trop proche de Google Photos, ok c'est un fork mais là c'est presque abusé. Une petite touche perso aurait été agréable, même si dans l'absolu ce n'est pas un problème en soit.

D'autre part Immich c'est un projet qui va vite, trop vite. D'ailleurs c'est indiqué sur la page d'accueil:

The project is under very active development. Expect bugs and changes. Do not use it as the only way to store your photos and videos!

Je n'ai pour ma part jamais eu de pertes ou de trucs bizarres, mais par contre il faut se forcer à mettre régulièrement à jour l'application, que ça soit coté serveur comme le client. Sinon gare à la MAJ en PLS après un an de fainéantise! Rien n'est jamais perdu, la base de données ne sera pas impactée mais il faudra forcément se taper la lecture des changements survenus entre-temps pour comprendre pourquoi l'outil refuse de se relancer après de trop longs mois sans mise à jour.

Vous voilà prévenu.

Déploiement

Le choix Docker

Passons au déploiement de l'outil, la doc est très bien faite pour ça: https://immich.app/docs/overview/quick-start

notons que j'utilise Immich de la plus simple des façons, à savoir je déploie les conteneurs formant un service 3-tiers au sein de Docker

Grosso-modo le déploiement s'effectue en 3 phases, aidé par Docker Compose qui permet de gérer toutes les étapes du cycle de vie du service.

  • Le téléchargement du fichier docker-Compose
  • Le téléchargement du fichier des variables d'environnement qu'on modifiera dans la foulée
  • Une fois le tout récupéré, on lance la magie du conteneur:

docker compose up -d

ça prendra du temps, il faut récupérer la première fois l'ensemble des conteneurs.

Ensuite toujours indiqué dans la documentation, la première connexion permettra de créer un identifiant admin, pour ensuite pouvoir gérer l'application.

ça se passe pas bien?

Lors d'un déploiment récent j'ai bêtement demandé à Immich de se déployer sur un port déjà utilisé par le système.

Les logs Docker n'étant pas accessibles directement depuis l'OS source, voici quelques astuces pour facilement interroger les conteneurs:

lister les images et conteneurs Docker:

Un docker images vous permettra dans un premier temps de lister les images téléchargées:

root@debian-routeur:~# docker images
REPOSITORY                                       TAG       IMAGE ID       CREATED         SIZE
ghcr.io/immich-app/immich-server                 release   c9d539d7fc8c   10 days ago     2.13GB
ghcr.io/immich-app/immich-machine-learning       release   91ebf545ffaf   2 weeks ago     1.04GB
ghcr.io/immich-app/immich-cli                    2.2.29    d57414ad1475   6 months ago    301MB
ghcr.io/immich-app/immich-cli                    latest    d57414ad1475   6 months ago    301MB
redis                                            <none>    ec1b0a84ddf9   8 months ago    30MB
registry.hub.docker.com/library/redis            <none>    b6c412dc2987   18 months ago   30.3MB
ghcr.io/immich-app/immich-web                    release   c171b5641006   18 months ago   279MB
ghcr.io/immich-app/immich-proxy                  release   996c87bf4e83   18 months ago   41.4MB
redis                                            <none>    b9cad9a5aff9   23 months ago   27.4MB
postgres                                         <none>    2e0bc99c553f   23 months ago   235MB
typesense/typesense                              <none>    de9eadc78acf   2 years ago     799MB

Puis un docker ps vous permettra de voir les conteneurs actifs sur votre machine:

root@debian-routeur:~# docker ps
CONTAINER ID   IMAGE                                                        COMMAND                  CREATED         STATUS                  PORTS                                                                                                                    NAMES
78575181b00c   ghcr.io/immich-app/immich-machine-learning:release           "tini -- python -m i…"   8 days ago      Up 14 hours (healthy)                                                                                                                            immich_machine_learning
dd4a57fabe1c   ghcr.io/immich-app/immich-server:release                     "tini -- /bin/bash s…"   8 days ago      Up 14 hours (healthy)   0.0.0.0:2283->2283/tcp, [::]:2283->2283/tcp                                                                              immich_server
74be3c89af13   registry.hub.docker.com/tensorchord/pgvecto-rs:pg14-v0.2.0   "docker-entrypoint.s…"   7 months ago    Up 14 hours             5432/tcp                                                                                                                 immich_postgres
67fb2014f812   registry.hub.docker.com/library/redis:6.2-alpine             "docker-entrypoint.s…"   7 months ago    Up 14 hours             6379/tcp                                                                                                                 immich_redis

Vous noterez au passage qu'on voit également les ports utilisés par les conteneurs avec leur redirection.

Interroger les logs d'un conteneur spécifique

Prenons l'exemple du conteneur immich-server en cours sur ma machine:

root@debian-routeur:~# docker logs immich_server |more
Initializing Immich v1.133.1
Detected CPU Cores: 4
Starting api worker
Starting microservices worker
[Nest] 7  - 05/26/2025, 5:40:24 AM     LOG [Microservice
s:EventRepository] Initialized websocket server
[Nest] 17  - 05/26/2025, 5:40:24 AM     LOG [Api:EventRe
pository] Initialized websocket server
[Nest] 17  - 05/26/2025, 5:40:27 AM     LOG [Api:Databas
eRepository] Running migrations, this may take a while
[Nest] 17  - 05/26/2025, 5:41:25 AM     LOG [Api:Logging
Repository] Database has up to date TypeORM migrations, skipping ini
tial Kysely migration
[Nest] 17  - 05/26/2025, 5:41:33 AM     LOG [Api:Databas
eRepository] Migration "1744910873969-InitialMigration" succeeded

[Nest] 17  - 05/26/2025, 5:41:33 AM     LOG [Api:Databas
eRepository] Migration "1744991379464-AddNotificationsTable" succeed
ed
[Nest] 17  - 05/26/2025, 5:41:33 AM     LOG [Api:Databas
eRepository] Migration "1745244781846-AddUserAvatarColorColumn" succ
eeded
[Nest] 17  - 05/26/2025, 5:41:33 AM     LOG [Api:Databas
eRepository] Migration "1745902563899-AddAssetVisibilityColumn" succ
eeded
[Nest] 17  - 05/26/2025, 5:41:33 AM     LOG [Api:Databas
eRepository] Migration "1746636476623-DropExtraIndexes" succeeded

On peut donc simplement cibler un conteneur, et voir les logs en cours, ça peut grandement aider si ce dernier ne démarre pas correctement.

Une page regroupe quelques commande utiles, c'est par ici

Comment récupérer ses anciennes photos?

Quand on démarre avec Immich, bah c'est tout vide.

Il y a bien la possibilité d'uploader des fichiers mais c'est franchement limité si vous avez une photothèque conséquente. J'ai tenté au départ de transférer mes photos par ce biais, mais entre un navigateur qui freeze ou des photos manquants j'ai très vite cherché un autre moyen.

L'autre option donc -pour les friands de la ligne de commande- c'est d'utiliser Immich CLI qui n'est autre qu'un conteneur mis à disposition pour lancer une interface depuis un terminal. Cette image peut être installée sur le serveur, ou depuis le client sur lequel se trouvent les photos.

  • Il faut dans un premier temps générer une clé API sur l'utilisateur visé. Pour cela c'est simple, rendez vous depuis l'interface web:

> Paramètres du compte > Clés d'API > Nouvelle clé API

  • Une fois l'API obtenue, il faudra cibler l'instance immich comme indiqué dans la doc dédiée.

Il est bien sûr possible de traiter des dossiers en récursif, de tester sans appliquer réellement (dry-run) ou encore de créer des albums à la volée. C'est très puissant et très pratique.

J'ai tenté tout d'abord de cibler l'upload de photos sur un mois (quelques dizaines de photos) puis sur une année (environ un millier) et ça passe crème. N'hésitez pas à relancer la commande deux fois si vous avez un grand nombre de photos, vous verrez alors qu'Immich n'importe rien de plus, au moins ça vous rassurera sur la pérénité du transfert.

Et comment sauvegarder ses photos une fois celles ci sous Immich?

J'ai fait le le choix de m'appuyer sur Immich désormais pour la gestion de mes photos, notament les metadata générées lors du transfert. C'est donc mon point d'entrée.

J'ai souhaité ensuite synchroniser les photos stockées localement (il est néanmoins tout à fait possible de stocker les photos sur un accès distant type NAS ou autre) vers un répertoire de mon NAS, pour cela on s'appuie sur une tâche cron classique.

Comme indiqué ici les photos ** ne sont pas stockées en BDD **. Seuls 3 répertoires doivent être sauvegardés pour garantir de remonter un Immich tout neuf.

J'ai donc créé un cron.daily du genre:

#!/bin/bash

rsync -avi /root/immich/library /media/externe/immich/ --delete --log-file=/var/log/rsync
rsync -avi /root/immich/upload /media/externe/immich/ --delete --log-file=/var/log/rsync
rsync -avi /root/immich/profile /media/externe/immich/ --delete --log-file=/var/log/rsync

Sécurisation avec crowdsec

L'intérêt d'Immich c'est de pouvoir rapatrier à la volée les photos prisent depuis son smartphone préféré, via Internet ou le réseau local.

J'ai utilisé pendant plus d'une année un VPN pour y accéder, empêchant de facto les vils hackers de tenter d'accéder à mes préciseuses photos.

Mais une expatriation dans un super pays a eu raison de moi! Me voilà obligé de partager certaines de mes photos auprès de mes proches via un lien dédié, par Internet donc. Se pose alors la question de comment mettre en ligne le site, et surtout comment le sécuriser.

Apache et sous-domaine

Immich est par défaut accessible sur le port 2283, ça fait le boulot en local mais vraiment pas sexy sur Internet. Un grand classic donc, avec Apache le bien nommé:

  • une redirection http > https
  • un VHost qui porte le nom d'un sous domaine
  • un certificat Let's Encrypt qui sécurise la connexion TLS

Exemple de conf:

<VirtualHost *:80>
  ServerName immich.domaine.net
  ServerAlias immich.domaine.net
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =immich.domaine.net [OR]
  RewriteCond %{SERVER_NAME} =domaine.net
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
  ServerName immich.domaine.net
  ServerAlias immich.domaine.net
  ServerAdmin johann@domaine.net
   ProxyRequests Off
   # set timeout in seconds
   ProxyPass / http://127.0.0.1:2283/ timeout=600 upgrade=websocket
   ProxyPassReverse / http://127.0.0.1:2283/
   ProxyPreserveHost On
  Protocols h2 http/1.1
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/immich.domaine.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/immich.domaine.net/privkey.pem
</VirtualHost>

On engage un videur

Avec l'accès à la mire de connexion sur Internet, on ouvre la porte au robot parser et autres bruteforce. Pour blacklister les malveillants, on va utiliser crowdsec.

Je vous invite à consulter un précédent article sur crowdsec pour découvrir ce formidable outil: https://docs.scourzic.net/2023-01-08_Securisation-de-son-micro-site/

J'y croyais moyen en regardant s'il y avait une bonne âme qui ait créé un logs parsers pour Immich, mais bingo! https://app.crowdsec.net/hub/author/gauth-fr/collections/immich merci l'ami gauth-fr ...cependant mon euphorie a été de courte durée, je n'ai jamais réussi à correctement paramétrer le ban (qui ne déclenche rien). Vous aurez peut être plus de chance que moi.

J'ai fini par installer un nouveau bouncer: https://doc.crowdsec.net/u/bouncers/apache_bouncer/ qui va s'appuyer sur de nombreux scénarios pour présenter une erreur 403 à n'importe quelle ip que sera bannie.

Ca fonctionne bien, bien que ça soit moins sexy que le précédent qui présentait d'abord un captcha et ensuite une belle page de ban.

J'ai donc rajouté à ma configuration Apache présentée ci dessus:

CrowdsecLocation /one/
<Location /one/>
Crowdsec off
RewriteEngine On
RewriteRule .* - [R=403,L]
# Require all denied
ErrorDocument 403 "non!"
</Location>

Et ça marche nickel! Je tente de me logguer plusieurs fois avec un mauvais identifiant / mot de passe sous Immich:

J'ai bien une action sous crowdsec:

│   ID  │        value       │                   reason                   │ country │                  as                 │ decisions │                created_at               │
├───────┼────────────────────┼────────────────────────────────────────────┼─────────┼─────────────────────────────────────┼───────────┼─────────────────────────────────────────┤
│ 25371 │ Ip:2X.X.X.X    │ LePresidente/http-generic-401-bf           │ AU      │ 7545 TPG Telecom Limited            │ ban:1     │ 2025-06-04 05:04:50.718347 +0000 UTC  

Et une belle 403 environ une minute après.

Conclusion

Un nouvel article qui vous a présenté une super photothèque, libre de droits et qui devrait gagner en célébrité.

Je n'ai même pas pris la peine de faire le tour du propriétaire tellement l'application est parlante. On y stock ses photos, on navigue d'année en année avec une fluidité record. Pour l'ajout des photos, si vous avez un grand nombre d'images n'hésitez pas à passer par leur outil CLI qui vous évitera quelques galères.

Je vais très probablement faire un don, au bout de deux années je suis convaincu. Chose rigolote, ils proposent d'acheter une licence qui débloquera...quedalle.

C'est une manière comme une autre de demander de supporter le développement du logiciel, et vu l'utilisation que j'ai d'Immich au quotidien ce n'est pas cher payé.

A présent, à vous d'essayer!