Une galerie photo : Immich


L’application Immich est d’une qualité assez exceptionnelle. Toutefois, étant en développement actif, elle fait l’objet de temps en temps d’évolutions structurantes ou « breaking changes ». Je modifie cet article en fonction de ces évolutions structurantes. Ainsi, l’article a évolué le 20 avril 2024 afin de prendre en compte la modification des modalités Docker d’hébergement de la base de données, passée d’un volume à un répertoire lié (bind mount).


Aujourd’hui je vous propose d’installer une magnifique galerie photo. Immich dispose de nombreuses fonctionnalités parmi lesquelles j’apprécie particulièrement :

  • la récupération directe des photos sur les téléphones mobiles via une application dédiée,
  • la reconnaissance faciale,
  • le positionnement des photos sur une carte selon la géolocalisation de la prise de vue,
  • la possibilité de paramétrer le classement des photos dans le répertoire,
  • la capacité à intégrer en masse des milliers de photos déjà collectées par ailleurs,

L’application a été développée pour « mimer » le fonctionnement de Google Photos. Elle connaît un franc succès auprès de la communauté des auto-hébergeurs.

Installer Immich

Avant d’installer Immich, je vous conseille d’installer sur votre Pi, si ce n’est pas encore fait, un système de refroidissement passif (radiateur) et/ou actif (ventilateur) car votre Raspberry Pi va être soumis à une activité intensive lorsqu’il va prendre en charge de nouvelles photos et qu’il devra les faire passer à la moulinette de son intelligence artificielle. Les systèmes de refroidissement pour Raspberry Pi sont généralement accessibles pour quelques euros.

Bien qu’Immich soit un ensemble applicatif assez complexe, son installation via Docker compose est assez simple. Attention toutefois, Immich est en cours de développement intensif au moment où je rédige ces lignes. Il est donc possible, voire probable, qu’assez rapidement, certains éléments soient obsolètes. J’essaierai de maintenir ce tutoriel afin qu’il reflète toujours l’état de l’application, mais je ne garantis pas d’être systématiquement à jour.

Nous allons sur notre Raspberry Pi et créons un répertoire immich, puis nous allons dans ce répertoire :

sudo mkdir immich
cd immich

Comme à chaque fois que nous installons une nouvelle application via Docker compose, nous créons un fichier docker-compose.yml :

sudo nano docker-compose.yml

Néanmoins, cette fois-ci, nous allons créer, dans un seul fichier docker-compose.yml, plusieurs conteneurs, qui vont travailler ensemble. Je reprends le fichier tel qu’il est disponible sur Github au moment de la rédaction du tutoriel, avec les messages qu’il inclut en commentaires.

#
# WARNING: Make sure to use the docker-compose.yml of the current release:
#
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
#
# The compose file on main may not be compatible with the latest release.
#

name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    command: ['start.sh', 'immich']
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - 3001:3001
    depends_on:
      - redis
      - database
    restart: always

  immich-microservices:
    container_name: immich_microservices
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/hardware-transcoding
    #   file: hwaccel.transcoding.yml
    #   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
    command: ['start.sh', 'microservices']
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    depends_on:
      - redis
      - database
    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    # For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag.
    # Example tag: ${IMMICH_VERSION:-release}-cuda
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    # extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
    #   file: hwaccel.ml.yml
    #   service: cpu # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always

  redis:
    container_name: immich_redis
    image: registry.hub.docker.com/library/redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
    restart: always

  database:
    container_name: immich_postgres
    image: registry.hub.docker.com/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    restart: always

volumes:
  model-cache:

Vous voyez ici que nous avons cinq applications :

  • Immich-server, qui a pour fonction de présenter les photos,
  • Immich-microservices, qui gère la bibliothèque,
  • Immich-machine-learning, qui assure la reconnaissance faciale et l’ensemble des fonctions d’intelligence artificielle de l’application serveur,
  • Redis et Database, qui gèrent la base de données des photos confiées au serveur Immich.

Vous remarquerez également la présence de commandes dans le fichier. Il s’agit de commandes qui sont lancées à l’initialisation de chaque conteneur. Ici, elles servent notamment à spécialiser les deux conteneurs immich-server et immich-microservices dans les services qui sont attendus de chacun d’eux. En effet, vous aurez pu remarquer que l’image sur laquelle ils s’appuient tous les deux est unique.

Ces applications partagent en outre un volume :

  • model-cache, qui est un espace de stockage des données pour l’intelligence artificielle.

Je vous conseille d’ajouter à ce fichier les lignes suivantes, qui vont permettre de réaliser quotidiennement une sauvegarde de la base de données :

services:
...
  backup:
    container_name: immich_db_dumper
    image: prodrigestivill/postgres-backup-local
    env_file:
      - .env
    environment:
      POSTGRES_HOST: database
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      SCHEDULE: "@daily"
      BACKUP_DIR: /db_dumps
    volumes:
      - ./db_dumps:/db_dumps
    depends_on:
      - database

Cela génère un sixième conteneur, exclusivement dédié à la sauvegarde. Vous aurez compris que pour changer la fréquence de la sauvegarde, il suffit de modifier la valeur de la variable SCHEDULE et de la remplacer par « @hourly » pour une sauvegarde toutes les heurs, ou par « @weekly » pour une sauvegarde hebdomadaire.

Cette fois-ci, nous n’allons pas créer notre conteneur immédiatement après avoir édité le fichier docker-compose.yml, mais nous allons créer un fichier .env. Ce fichier va contenir les variables d’environnement de nos applications Immich. Il s’agit d’informations que vous voulons partager entre différents conteneurs d’Immich, et que nous regroupons ainsi dans un fichier accessible par chacun d’entre eux.

sudo nano .env

Là aussi, je vous propose de reprendre le fichier déposé sur Github :

# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=./library

# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release

# Connection secret for postgres. You should change it to a random password
DB_PASSWORD=postgres

# The values below this line do not need to be changed
###################################################################################
DB_HOSTNAME=immich_postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
DB_DATA_LOCATION=./postgres

REDIS_HOSTNAME=immich_redis

Ce fichier ne comporte que les variables d’environnement indispensables pour faire fonctionner notre configuration Docker compose. Le premier commentaire indique que de nombreuses autres variables peuvent être utilisées. Revenons à notre fichier .env.

Vous pourrez choisir où seront stockées vos photos dans l’arborescence de votre système de fichiers en saisissant cette adresse en face de la variable UPLOAD_LOCATION. Vous pouvez choisir un chemin relatif, basé sur le répertoire immich que nous avons créé, en commençant son chemin par ./ (le point représentant le répertoire « actuel »), ou bien un chemin absolu en commençant par /, qui représente la racine du système de fichiers. Ce choix est important car il vous permet éventuellement de dédier un disque à vos photos, mais aussi car il peut avoir un impact sur votre stratégie de sauvegarde.

Vous devrez également définir un mot de passe pour votre base de données. Inutile ici d’en faire des tonnes : si quelqu’un a accès à votre serveur, il a accès à vos photos, qui sont bien plus importantes à vos yeux que la base de données.

Je vous invite à ajouter la variable supplémentaire suivante à ce fichier (à ajuster à votre propre position géographique évidemment) :

TZ="Europe/Paris"

Les autres variables peuvent être laissées en l’état.

Pour les lecteurs qui utilisent un matériel autre qu’un Raspberry Pi, ils pourraient bénéficier de l’accélération matérielle, pour l’intelligence artificielle et pour la transcodification des vidéos. Il leur faudra pour cela éditer les fichiers hwaccel.ml.yml et hwaccel.transcoding.yml. Sur notre Raspberry Pi, nous n’en bénéficions pas (à ce jour), donc je vais passer sur ces éléments. Sachez simplement que leur absence ne gêne pas l’utilisation d’Immich, même si les fonctions d’intelligence artificielle en sont ralenties.

Intégrer notre service Immich

Ensuite, il est nécessaire, comme pour notre service Vaultwarden, d’intégrer Immich dans l’environnement de notre serveur, en particulier avec Swag et Crowdsec. Pour cela, nous procéderons sensiblement comme indiqué pour Vaultwarden, avec une variante. La variante va consister, compte tenu du fait qu’Immich n’a pas nativement de fichier journal, à orienter Crowdsec vers le journal de Docker.

Pour cela, nous nous plaçons sur le répertoire de Crowdsec et nous arrêtons le conteneur :

cd ~/crowdsec
sudo docker compose stop

Nous indiquons au conteneur de lire les données échangées par Docker. Pour cela, nous modifions le fichier docker-compose.yml :

sudo nano docker-compose.yml

Et nous ajoutons dans la partie volume :

service:
  immich:
...
  volumes:
...
      - /var/run/docker.sock:/var/run/docker.sock:ro

Puis nous enregistrons le fichier le le refermons. Cela permet à Crowdsec d’accéder aux informations de journal de Crowdsec, en lecture seulement (les dernière lettres :ro signifient read-only), de manière à ce que le conteneur ne puisse pas émettre des ordres à destination de Docker, ce qui poserait des problèmes de sécurité.

Puis nous ouvrons le fichier crowdsec/acquis.yaml :

sudo nano crowdsec/acquis.yaml

Et nous saisissons à la fin du fichier les lignes suivantes :

---
source: docker
container_name:
 - immich_server
labels:
  type: immich

Nous sauvegardons et sortons. Cela indique à Crowdsec qu’il doit chercher les informations du conteneur immich-server dans Docker.

Nous pouvons relancer le conteneur :

sudo docker compose up -d

Nous allons maintenant mettre en oeuvre dans Crowdsec le moteur d’analyse du journal. Pour cela, nous entrons dans le conteneur de Crowdsec :

sudo docker exec -ti crowdsec /bin/sh

Et nous ajoutons la collection immich :

cscli collections install gauth-fr/immich
exit

Nous devons maintenant paramétrer Swag exactement comme nous l’avons fait pour Vaultwarden. Nous allons ouvrir son accès via notre proxy inverse :

cd ~/swag

Nous allons donc ouvrir le fichier config/nginx/proxy-confs/immich.subdomain.conf.sample.

sudo nano config/nginx/proxy-confs/immich.subdomain.conf.sample

Si nous avons choisi le filtrage géographique dans Swag, nous n’oublions pas d’apporter les deux lignes de modification à notre fichier pour protéger Immich.

Puis nous tapons CTRL+O. Cela ouvre en bas de l’écran une boîte de dialogue afin de spécifier le nouveau nom que nous souhaitons donner au fichier. Nous enlevons le .sample de la fin du nom pour aboutir à config/nginx/proxy-confs/immich.subdomain.conf.

Nous allons maintenant indiquer à Swag de prendre en compte le sous-domaine immich. Nous arrêtons le conteneur Swag :

sudo docker compose down

Nous ouvrons le fichier docker-compose.yml :

sudo nano docker-compose.yml

Et nous allons le modifier pour ajouter le sous-domaine immich :

---
services:
  swag:
    image: lscr.io/linuxserver/swag:latest
    container_name: swag
    environment:
      - PUID=1000
      - PGID=1000
      - TZ="Europe/Paris"
      - URL=yourdomain.url
      - VALIDATION=http
      - SUBDOMAINS=www,vaultwarden,immich
      - CERTPROVIDER= #optionnel
    volumes:
      - ./config:/config
    ports:
      - 443:443
      - 80:80 #optionnel
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

Enfin, nous créons auprès de notre registraire une entrée A de zone DNS comme nous l’avons fait pour Vaultwarden (se référer à cet article).

L’initialisation d’Immich

Pour initialiser Immich, nous nous rendons sur notre navigateur internet préféré et nous tapons l’adresse de notre serveur : https://immich.domaine.tld.

L’écran d’initialisation nous est présenté :

Nous allons donc saisir les informations demandées. N’oubliez pas que vous disposez d’un gestionnaire de mots de passe avec Vaultwarden : il vous permettra de générer puis d’enregistrer votre mot de passe.

Le premier utilisateur est systématiquement l’administrateur du serveur de photos. Nous pouvons ensuite créer de nouveaux utilisateurs. Il est à noter que les photos déposées par chaque utilisateur seront privées sauf à ce qu’il décide de les partager avec un ou plusieurs autres utilisateurs.

D’autres paramètres peuvent être personnalisés, parmi lesquels la priorité des différents travaux en cas de conflit, ou l’arborescence du stockage des photos. Pour ma part, les paramètres par défaut me convenaient parfaitement.

Il est ensuite intéressant de télécharger l’application Android (également disponible via F-Droid ou en téléchargement direct sur Github) ou iOS. Elles assureront notamment le téléchargement des photos de votre téléphone vers le serveur. Attention : si vous souhaitez supprimer des photos du stockage de votre téléphone tout en les laissant sur le serveur, ne les supprimez pas via l’application mais via le gestionnaire de fichiers. Sans quoi elles seront supprimées aussi du serveur.

Pour nous connecter via l’application, nous insérerons l’adresse de notre serveur : immich.domaine.tld puis nous entrerons nos identifiants. Ensuite, nous pourrons choisir de sauvegarder sur notre nouveau serveur l’ensemble des photos disponibles sur notre téléphone, ou seulement celles présentes sur certains répertoires, par exemple le répertoire DCIM, qui stocke classiquement les photos que nous avons prises.

L’intégration de nouvelles photos

Immich propose un outil d’intégration de nouvelles photos en bloc, via l’interface en ligne de commande, pour la situation dans laquelle vous disposez déjà de photos sur un autre support de stockage. Il nous faut avant tout récupérer une clé d’API, qui nous sera nécessaire pour nous authentifier. Nous allons sur l’interface web d’Immich, cliquons sur notre icône de profil en haut à droite, puis sur le menu « Account settings ». Un nouvel écran apparaît et nous cliquons sur « New API key ». Nous copons cette clé. Je vous recommande, une fois générée, de la conserver dans votre coffre-fort Vaultwarden.

Nous allons ensuite lancer l’interface de ligne de commande immich via la constitution temporaire d’un nouveau conteneur dédié, après avoir copié nos photos sur un répertoire sur le Raspberry Pi. Nous nous rendons dans ce répertoire et lançons :

sudo docker run -it -v "$(pwd)":/import:ro -e IMMICH_INSTANCE_URL=https://notre-instance-immich/api -e IMMICH_API_KEY=<notre-clé-immich> ghcr.io/immich-app/immich-cli:latest

N’omettez pas la mention »:ro » qui ouvre ce répertoire en lecture seule et vous garantit ainsi que les originaux ne seront pas modifiés.

Nous nous retrouvons à l’intérieur de notre conteneur, comme nous l’avons déjà fait précédemment. Et nous tapons l’ordre de chargement :

immich upload --recursive .

Différentes instructions plus spécifiques sont disponibles ici.

Attention : une fois la commande upload lancée, le chargement des photos et leur analyse peuvent prendre de longues heures. Sur un Raspberry Pi 4 8GB, ils m’ont pris 48h pour 17 000 photos.


Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *