Skip to main content

260828-Tofs à compresse sur SASNEXTE

Compression des photos du NAS SASNEXTE — étude de faisabilité

2026-08-28. Suite de la procédure Photos-Caesium (page 284), appliquée cette fois au stock photo du NAS. Copie de référence : Jux-scripts/Photos-Caesium/doc_bookstack_285.md.

En bref

C'est faisable, et le NAS est le bon endroit pour le faire — pas le PC à travers le VPN.

Débit mesuré sur le NAS (Celeron J4025, 2 cœurs) 1,55 Mo/s
Gain mesuré sur 300 photos réelles -59,5 %
Stock JPEG concerné 16 422 fichiers, 37,59 Go
Durée estimée du rattrapage complet ~6,7 heures
Espace récupérable ~22,4 Go
EXIF, GPS, dates, dimensions préservés, vérifié sur les fichiers du NAS

Une réserve bloquante avant tout déploiement : la majorité de ces photos n'a pas de copie hors du NAS. Voir « Points de vigilance ».


1. Rétablissement de l'accès SSH

Le NAS était joignable en SMB par le tunnel WireGuard (page 245) mais pas en SSH.

Cause réelle : le service SSH était désactivé et le port 22 fermé par les règles de sécurité DSM posées par Julien. Leur neutralisation a tout débloqué immédiatement.

Ce qui m'a égaré, et qu'il faut noter pour ne pas s'y reprendre : le port 22 répondait par une bannière SSH-2.0-OpenSSH_8.2, annonçait publickey,password et évaluait les identifiants avant de les rejeter par « Permission denied ». J'en ai conclu à tort que le service tournait et que le problème venait de l'autorisation — j'ai successivement soupçonné le groupe administrators, puis la vérification en deux étapes. Les deux hypothèses étaient fausses. Une bannière SSH qui répond ne prouve pas que l'accès soit ouvert sur ce NAS.

Diagnostics utiles conservés au passage :

Test Résultat Enseignement
smbclient -L //10.0.0.2 -N NT_STATUS_LOGON_FAILURE pas d'accès anonyme, le NAS est correctement fermé
smbclient //10.0.0.2/NEXTE -U sas_nexte listing obtenu le mot de passe documenté est valide
ssh -o PreferredAuthentications=none publickey,password méthodes proposées, sans risquer d'échec comptabilisé

Encodage du mot de passe : le § final ne survit pas au passage par Git Bash vers plink. Le contourner en construisant le mot de passe côté cible en octets explicites :

printf 'xAPIJU5108\xc2\xa7' > /tmp/pw
sshpass -f /tmp/pw ssh -o NumberOfPasswordPrompts=1 sas_nexte@10.0.0.2

-o NumberOfPasswordPrompts=1 est important : sans lui, un échec compte pour trois tentatives auprès du blocage automatique de DSM.

Le compte

uid=1026(SAS_NEXTE) gid=100(users) groups=100(users),101(administrators),1023(http)

Le compte Unix s'appelle SAS_NEXTE en majuscules, alors qu'on s'y connecte en sas_nexte. DSM est insensible à la casse à l'ouverture de session, mais le dossier personnel et le propriétaire des fichiers portent la forme majuscule. C'est à surveiller dans tout script.

Authentification par clé — non aboutie

Une paire ed25519 a été générée sur le PC (D:\SSH\nas_sasnexte, hors de l'arbre Syncthing, empreinte SHA256:4yK8Mxz5e9jmxSdIh6PT/Murip0pIpoFlA0MzDanB98) et la clé publique déposée par SMB dans \\10.0.0.2\home\.ssh\authorized_keys. Le fichier est bien arrivé, intact, 105 octets — mais l'authentification reste refusée.

Cause probable : le StrictModes d'OpenSSH, qui rejette un ~/.ssh ou un dossier personnel accessibles en écriture au groupe ou à tous, ce que Synology crée par défaut. Non résolu à ce jour ; on travaille au mot de passe en attendant. Correctif à tenter, en root :

H=$(getent passwd sas_nexte | cut -d: -f6)
chown -R SAS_NEXTE "$H/.ssh"; chmod 700 "$H/.ssh"; chmod 600 "$H/.ssh/authorized_keys"

Deux pièges DSM à connaître

  1. scp échoue — dest open: No such file or directory. DSM n'expose pas de sous-système SFTP, dont dépend scp moderne. Transférer par un tube SSH :
    ssh nas 'cat > /chemin/cible' < fichier_local
    
  2. /tmp est monté noexec (tmpfs … rw,nosuid,nodev,noexec). Un binaire copié là est bien marqué exécutable mais refuse de démarrer avec « Permission denied ». Les exécutables doivent vivre sur /volume1, qui est en btrfs sans noexec.

2. La machine

Modèle Synology DS220+
Processeur Intel Celeron J4025 @ 2,00 GHz — 2 cœurs, pas d'HyperThreading
Mémoire 5,8 Go (2 Go d'origine + extension)
Volume btrfs, 5,3 To, 1,4 To libres (75 % occupé)
Binaire déposé /volume1/homes/SAS_NEXTE/bin/caesiumclt — v1.4.0, build x86_64-unknown-linux-musl

Le binaire musl est statique et sans aucune dépendance : il s'exécute nativement sur DSM sans rien installer, sans Docker, sans Entware.


3. Le stock réel de /volume1/photo

Mesuré en excluant les dossiers techniques. Total du dossier : 79 Go (du), dont 78,8 Go retrouvés fichier par fichier — les deux mesures concordent.

Contenu Fichiers Poids Traité par Caesium ?
JPEG 16 422 37,59 Go oui — la cible
MP4 + MOV 413 21,11 Go non
PNG 624 2,95 Go oui, en sans-perte
HEIC 691 0,79 Go non pris en charge
TIFF, PSD, divers ~157 0,76 Go TIFF oui, PSD non
Contenu réel 18 307 63,20 Go
@eaDir — vignettes Synology 94 791 15,36 Go à ne jamais toucher

Attention au recensement naïf : un find … -iname '*.jpg' sans exclure @eaDir compte 71 802 fichiers au lieu de 16 422, parce qu'il ramasse les vignettes générées par Synology. Un échantillon constitué ainsi fausse gravement la taille moyenne — c'est l'erreur commise en première approche ici.

La corbeille s'est vidée pendant l'étude, à 07:19 : /volume1/photo est passé de 91 Go à 79 Go. Cela explique deux écarts de mesure qui semblaient d'abord contradictoires.


4. Banc d'essai

Méthode : 300 JPEG prélevés dans tout l'arbre (un fichier sur 200, pour ne pas biaiser vers un dossier ou une époque), copiés dans un dossier de travail, compressés vers un autre. Aucun original n'a été modifié. Dossier de test supprimé après mesure.

caesiumclt -q 80 -e --keep-dates --min-savings 1% --threads 0 --json -o SORTIE ENTREE
Échantillon 299 fichiers exploitables, 201,4 Mo
Résultat 81,6 Mo
Gain -59,5 % (13 fichiers sans gain suffisant, originaux conservés)
Durée 130 s sur 2 threads
Débit 1,55 Mo/s

À titre de comparaison, le même profil q80 sur le Ryzen 5 2600X du PC (12 threads) donne 11,4 Mo/s — soit un facteur 7,4, cohérent avec l'écart de cœurs et d'IPC.


5. Vérification des métadonnées

C'était la question décisive : compresser 16 000 photos de famille ne doit pas coûter une date ni une position.

EXIF, dates, dimensions — 6 photos tirées du stock

avant après gain bloc EXIF DateTimeOriginal dimensions
p1 305 586 o 184 102 o -40 % identique 2013:11:24 12:02:25 1606×1886
p2 — — — gain insuffisant, original conservé
p3 1 129 457 o 417 739 o -64 % identique 2006:05:23 11:31:57 1944×2592
p4 394 396 o 347 306 o -12 % identique 2008:01:01 00:02:15 1600×1200
p5 1 953 775 o 391 469 o -80 % identique 2012:01:01 16:05:02 3264×2448
p6 3 559 252 o 1 283 096 o -64 % identique 2012:06:17 14:43:37 3264×2448

Bloc EXIF identique à l'octet près, date de prise de vue inchangée, dimensions inchangées, date du fichier préservée par --keep-dates.

GPS — sur des photos qui en portent réellement

Les six photos ci-dessus, prises entre 2006 et 2013 par des appareils photo, ne contenaient aucune coordonnée. Un second test a donc cherché des fichiers réellement géolocalisés :

Fichier GPS avant GPS après
PhotoLab445379.jpg 43.161944, 5.916944 43.161944, 5.916944
2013 Marseille/Gaetan.jpg 43.3025, 5.364722 43.3025, 5.364722
2013 Marseille/20130915_122108_Tunnel du Vieux-Port.jpg 43.294444, 5.365556 43.294444, 5.365556
2013 Marseille/20130915_114356_Tunnel du Vieux-Port.jpg 43.294444, 5.365556 43.294444, 5.365556

Coordonnées préservées au chiffre près. Les positions correspondent bien au Vieux-Port de Marseille et à la région de La Ciotat.

⚠ Tout cela dépend de l'option -e, qui n'est PAS le comportement par défaut de Caesium. Sans elle, l'EXIF entier est supprimé — dates et GPS avec. Ne jamais la retirer des options communes. Ne pas utiliser --strip-icc non plus, qui l'annule pour les profils colorimétriques.


6. NAS ou PC à travers le VPN ?

Le tunnel WireGuard est en étoile : chaque octet entre le PC et le NAS fait PC → VPS OVH → NAS, deux sauts WAN, sans liaison directe. Débit mesuré en lecture : 4,01 Mo/s (32 Mbit/s).

Sur le NAS Depuis le PC via le tunnel
Facteur limitant CPU (1,55 Mo/s) réseau (4 Mo/s, lecture et réécriture)
Durée pour 37,6 Go ~6,7 h ~3,7 h
Bande passante consommée aucune 53 Go à travers le VPS
PC allumé requis non oui, en continu
Lien de Toulon intact saturé pendant toute la durée

Le PC est plus rapide en temps de mur, mais il monopolise le lien du site de Toulon pendant quatre heures et impose de laisser la machine allumée. Le NAS travaille la nuit, ne coûte rien et personne ne l'attend. C'est le bon choix pour le rattrapage du stock ; le PC resterait pertinent pour un lot ponctuel de quelques gigaoctets.


7. Points de vigilance

1. La sauvegarde — point bloquant. Le script sync_kdrive_complete.sh du NAS ne synchronise que /volume1/photo/2026 vers kDrive, et en rclone sync --delete-during, c'est-à-dire un miroir. Les 37,6 Go de JPEG couvrant 1967 à 2025 n'ont donc aucune copie hors du NAS par cette voie, et une compression sur place propagerait les versions compressées en écrasant le miroir pour 2026. Vérifier ce qui existe par ailleurs (Hyper Backup, ActiveBackupforBusiness) avant toute réécriture de masse.

2. La compression sur place est irréversible. Le profil q80 est un ré-encodage : on ne revient pas en arrière. Deux parades, à combiner : écrire d'abord dans une arborescence parallèle et ne basculer qu'après contrôle (37,6 Go de plus sur 1,4 To libres, c'est indolore), et commencer par un seul dossier pour juger la qualité à l'œil.

3. Ne jamais toucher aux @eaDir. 15,36 Go de vignettes et d'index Synology. Les compresser casserait Synology Photos, qui les régénérerait aussitôt.

4. --keep-dates protège l'indexation. En préservant la date de modification, on évite de déclencher une réindexation complète de Synology Photos sur 16 000 fichiers — ce qui occuperait le NAS bien plus longtemps que la compression elle-même.

5. HEIC et vidéos restent hors de portée. 691 HEIC et 21 Go de vidéos ne sont pas concernés. Pour les vidéos, le levier serait un ré-encodage H.265, un tout autre chantier, très au-delà des capacités d'un J4025.


8. Reste à faire

  • Établir l'état réel des sauvegardes de /volume1/photo — préalable à tout déploiement
  • Faire aboutir l'authentification par clé (chmod sur ~/.ssh en root) pour cesser de passer le mot de passe
  • Adapter compress_photos.py (page 284) au NAS : chemins, écriture en arborescence parallèle, exclusion de @eaDir et #recycle, journal dans /volume1/homes/SAS_NEXTE/logs/
  • Le déclencher par le planificateur de tâches de DSM, la nuit, avec une limite de durée
  • Décider du sort des 624 PNG (2,95 Go) : le sans-perte y rend environ -28 % sans aucune altération

9. Immich et la chronologie — la question decisive (2026-08-28)

Crainte soulevee par Julien : « Immich ne lit que la date de modification du fichier pour composer l'historique. Avec cette compression, tout mon historique photo va devenir illisible. »

Elle est fondee pour une partie du stock. Verifie sur la bibliotheque reelle (18 156 elements, Immich v2.7.5, /home/debian/photo monte en lecture seule sur /mnt/media/photo — bibliotheque externe) :

Cas observe fileModifiedAt Chronologie (localDateTime) Ce qui fait foi IMG_20260718_181515.jpg — avec DateTimeOriginal EXIF 2026-07-21 22:01 2026-07-18 18:15 l'EXIF, le mtime est ignore IMG_20260705.jpg, images WhatsApp — sans date EXIF 2026-07-21 22:00 2026-07-21 22:00 le mtime du fichier

Autrement dit : quand la photo porte une vraie date de prise de vue, Immich s'en sert et se moque du fichier. Quand elle n'en a pas — images WhatsApp, captures d'ecran, scans — Immich se rabat sur la date de modification du fichier. Ces photos-la sont exactement celles que la crainte visait.

Ce qui a ete change en consequence

--keep-dates de Caesium preserve bien le mtime (verifie). Mais faire reposer l'historique photo d'une famille sur une option d'un outil tiers etait trop fragile. Le script ne dependant plus de cette option :

    il releve st_mtime, st_atime, st_uid, st_gid et les permissions de l'original avant traitement ; il les reimpose lui-meme sur le fichier produit (os.utime, os.chown, os.chmod) ; il relit ensuite le fichier et leve une exception si le mtime a bouge, ne serait-ce que d'une seconde.

    Ce n'est plus une promesse mais une assertion verifiee fichier par fichier, aussi bien en remplacement sur place qu'en arborescence parallele.

    Preuve

    Dossier temoin /volume1/photo/1968-1994 - photos famille dont Noumea/1990, 26 photos, mode parallele :

    26 fichiers compares, 0 ecart(s)
    originaux inchanges (taille et date) : oui
    VERDICT : aucune date ni aucun proprietaire alteres
    

    ⚠ La tache DSM doit imperativement tourner en ROOT

    Le controle ci-dessus a immediatement servi. Lance en tant que SAS_NEXTE, le meme test signale 26 ecarts de proprietaire : les photos appartiennent a admin:users, l'appel os.chown echoue faute de privileges, et les fichiers produits basculent sur SAS_NEXTE. Sur 16 422 fichiers, cela casserait l'acces SMB et Synology Photos.

    Relance en root (sudo), la meme verification donne 0 ecart.

    A retenir : dans le planificateur de taches de DSM, choisir l'utilisateur root, jamais SAS_NEXTE.

    Etat de la chronologie avant intervention

    Sur 18 156 elements indexes, 2 seulement sont dates de l'an 4501 (4501-01-01) — des scans totalement depourvus de metadonnees, pour lesquels Immich n'a trouve aucune date exploitable. C'est preexistant, marginal, et sans rapport avec la compression.

    Acces Immich depuis Claude

    Il n'y a pas de MCP Immich dans cette session : mcp_immich.py fait partie des serveurs perdus avec le profil Windows eliob et jamais reecrits (voir la liste « reste a ecrire » dans CLAUDE.md). L'API REST suffit :

    d = json.dumps({'email': 'bertrand.dadone@gmail.com', 'password': '...'}).encode()
    r = urllib.request.Request('https://immich.juxjux.ovh/api/auth/login', data=d,
                               headers={'Content-Type': 'application/json'})
    jeton = json.loads(urllib.request.urlopen(r).read())['accessToken']
    

    Endpoints utiles : POST /api/search/metadata (avec withExif: true pour obtenir dateTimeOriginal), GET /api/timeline/buckets?size=MONTH (comptage par mois — le seul moyen fiable d'obtenir des totaux, total dans la recherche ne renvoyant que le compte de la page), GET /api/assets/statistics.

    10. Le script de production

    Jux-scripts/Photos-Caesium/compress_photos_nas.py — stdlib seule, deploye sur le NAS dans /volume1/homes/SAS_NEXTE/scripts/.

    python3 compress_photos_nas.py [--source CHEMIN] [--parallele CHEMIN]
                                   [--profil q80|q90|sans-perte] [--minutes N]
                                   [--simulation] [--reprendre]
    

    Choix de conception :

      Appel de caesiumclt sans -R, dossier par dossier. Verifie sur le NAS : sans -R, il ne descend pas dans les sous-dossiers. C'est ce qui garantit qu'aucun @eaDir n'est jamais touche, sans avoir besoin d'une option d'exclusion que Caesium ne propose pas. Liste de fichiers explicite, limitee aux .jpg/.jpeg. Passer un dossier ferait traiter aussi les PNG et TIFF avec un profil lossy, ce qui les degraderait. Ecriture en dossier temporaire, puis validation, puis remplacement. Un fichier produit n'ecrase l'original que s'il existe, commence bien par FF D8, et est plus petit. Jamais d'original ecrase par un fichier partiel. Metadonnees reimposees et verifiees (section 9). Reprise : les dossiers traites sont memorises dans ~/.photos_caesium_etat.json, --reprendre saute ceux qui sont faits. Budget de temps (--minutes, 360 par defaut) : arret propre en fin de nuit, reprise le lendemain. Journal dans /volume1/homes/SAS_NEXTE/logs/photos_caesium_AAAAMMJJ.log.

      Mesure sur les vieux scans familiaux (466 fichiers, 22 dossiers) : -28,6 % seulement, a 0,82 Mo/s. Bien loin des -59,5 % du tirage aleatoire — ces scans anciens sont de petits fichiers deja compresses, et le surcout par fichier domine. Le gain reel sera donc tres inegal selon les albums : fort sur les photos recentes de telephone, faible sur les numerisations anciennes.

      Voir aussi

      • Page 284 — la procédure Photos-Caesium sur le PC, dont celle-ci reprend le moteur et les réglages
      • Page 245 — le tunnel WireGuard qui donne accès au NAS
      • Page 238 — le NAS SASNEXTE et sa synchronisation vers kDrive