Le livre de Claude

Pages de scripts et d'études de Claude Code sur le PC Elio+Jux

0_Claude et le Jux_VPS

0_Claude et le Jux_VPS

A_liens entre Claude et le KDRIVE


kDrive API REST — Infomaniak

Paramètre Valeur
Drive ID 591617
Token Bearer cnAZannhRpecgAfsQM7QiO4Vqh37g6Ht_hm4f0E6eDihMRaP2ZckKCmW959T5ST2Nv3qhGlqs0ltpNAb
Base URL https://api.infomaniak.com/3/drive/591617

Endpoints fonctionnels

Méthode Endpoint Usage
GET /files/{dir_id}/files Lister le contenu d'un dossier
GET /files/{file_id} Métadonnées d'un fichier
POST /upload?directory_id={id}&file_name={name}&conflict=replace&total_size={bytes} Uploader un fichier. ⚠ conflict=replace n'est pas accepté par kDrive — l'API répond 422 en silence et l'upload est perdu. C'est ce qui avait cassé toutes les sauvegardes du 2026-06-12 au 2026-06-19. conflict=version crée une nouvelle version.


Recovery automatique FUSE — monitor-rclone.sh (2026-06-24)

Le script /home/debian/monitor-rclone.sh (cron */5 * * * *) surveille les 5 mounts rclone et effectue une recovery complète si l'un d'eux est mort.

Fonctionnement

Pour chaque mount (/music, /komga, /livres, /audiobookshelf/audiobooks, /photo) :

timeout 10 ls — si inaccessible : sudo systemctl restart (kdrive-music, kdrive-komga, kdrive-livres, rclone-audiobooks, rclone-photo) Attente 5s + vérification que le mount répond Restart des containers Docker associés : /music → navidrome-navidrome-1 /komga → komga /livres → Kavita /audiobookshelf/audiobooks → audiobookshelf /photo → Immich-SERVER Immich-MICROSERVICES

Le script est silencieux quand tout va bien — il ne logue que les pannes et recoveries. Log : /home/debian/logs/rclone-monitor.log

Avant cette refactorisation, le script lançait un rclone mount direct (en parallèle des services systemd) et ne redémarrait pas les containers — le FUSE était remonté mais Navidrome gardait l'ancienne référence corrompue.

Suppression de fichiers — non fonctionnelle (testé 2026-06-09)

Tous les endpoints suivants retournent {"result":"error","error":{"code":"method_not_found"}} :

La doc officielle (developer.infomaniak.com) n'est pas accessible publiquement. L'endpoint de suppression reste inconnu.

Stratégie de rétention — rotation par jour de la semaine

Puisque la suppression via API ne fonctionne pas, le script de backup utilise une rotation par jour de la semaine (date +%u → 1=lundi … 7=dimanche) avec conflict=version. Résultat : exactement 7 fichiers max par service, les anciens sont écrasés automatiquement chaque semaine.

Script : /opt/backups/vps_backup.sh — cron : 0 2 * * *

Dossiers kDrive (TOOJUX/jux_vps)

Service Dossier ID Exemple de fichier
BookStack 1427916 bookstack_db_day1.7z
Immich 1427919 immich_db_day1.7z
Joplin 1427920 joplin_db_day1.7z (~630 Mo)
Mealie 1427921 mealie_db_day1.7z
Readeck 1427922 readeck_db_day1.7z
Baïkal 1467771 baikal_day1.7z (contacts + agendas + config)
Documents (dossier Syncthing) 1485489 documents_day1.7z (~489 Mo) — ajouté le 2026-08-30
Documents — mensuel 1486390 documents_month01.7z à month12.7z — année glissante

Télécharger un fichier depuis kDrive — il faut suivre la redirection (2026-08-30)

Point découvert en testant la restauration d'une sauvegarde. L'endpoint de téléchargement est en API v2, pas v3, et il répond 302 vers un hôte séparé (*.download.kdrive.infomaniakusercontent.com) :

curl -sL -H "Authorization: Bearer $TOKEN" -o archive.7z \
  "https://api.infomaniak.com/2/drive/591617/files/{file_id}/download"

Sauvegarde du dossier Syncthing ~/Documents (2026-08-30)

Septième service ajouté à /opt/backups/vps_backup.sh. Le détail du pourquoi est sur la page 23_Syncthing ; ici, le côté kDrive :

Dossier kDrive1485489 (backups/documents)
Fichier (quotidien)documents_day{1-7}.7z, rotation hebdomadaire comme les autres
Fichier (mensuel)documents_month{01-12}.7z dans le sous-dossier mensuel (1486390)
Taille489 Mo par nuit (1 760 entrées)
Durée34 s au total (26 s de compression, 6 s d'upload)
Niveau 7z-mx=1 et non -mx=5

Pourquoi -mx=1 : 73 % du volume est le coffre Cryptomator « Vault 2603 » (fichiers .c9r), déjà chiffré donc incompressible. Mesuré : -mx=1 rend 2,9 % en 44 s. Monter le niveau coûterait des minutes de CPU pour un gain nul.

Pourquoi une archive et pas un rclone sync : le remote kdrive: est un WebDAV vendor = other — rclone backend features kdrive: renvoie Hashes: [] et une Precision de 100 ans, autrement dit ni empreinte ni date de modification exploitables. rclone n'y compare que les tailles et raterait toute modification à taille constante — typiquement un bloc de coffre Cryptomator réécrit. L'archive monolithique supprime cette dépendance.

Restauration vérifiée de bout en bout le 2026-08-30 : archive re-téléchargée depuis kDrive, 7z t → Everything is Ok, tar extrait (1 760 entrées, masterkey.cryptomator présent), et un fichier témoin comparé à la source — identique à l'octet près.

Profondeur de rétention — copie mensuelle sur un an (2026-08-30)

La rotation par jour de la semaine ne donne que 7 jours de recul : une suppression repérée au bout de huit jours était perdue. Une seconde copie a donc été ajoutée, sur le même principe de nom qui revient — puisque la suppression via l'API kDrive ne fonctionne pas (voir plus haut), on ne purge pas, on écrase un nom déjà pris.

Coût réel : 12 × 489 Mo ≈ 5,9 Go — et non 1,5 Go comme estimé de tête au moment de la décision. kDrive avait 2,0 To libres à cette date, la question ne se pose donc pas.

Le tar est produit par une fonction commune documents_tar(), appelée par les deux copies. Le 1er du mois l'archive est donc construite deux fois (~33 s de plus) : c'est le prix de l'indépendance des deux séries — un échec du quotidien n'empêche pas le mensuel.

0_Claude et le Jux_VPS

B_les procédures de Claude

1/ la sauvegarde quotidienne de la base de données Joplin sur Kdrive (sans images)   

5/ 260611 - Komga-PDF 

6/ 260614 - Joplin-Compression

0_Claude et le Jux_VPS

C_ installation de Claude Code dans le VPS juxjux

Installation de Claude Code dans le VPS juxjux

Objectif

Pouvoir intervenir sur les containers du VPS (redémarrage, diagnostic, logs, fix rapide) depuis un mobile Android en mobilité, via SSH + tmux + Claude Code CLI directement installé sur le VPS.

Prérequis constatés (2026-07-21)

Installation de Claude Code CLI

Installation en local user (pas de sudo npm install -g) pour éviter de faire tourner le CLI en root et éviter les conflits de permissions npm globales :

mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
npm install -g @anthropic-ai/claude-code

Ajout du PATH dans ~/.bashrc :

echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc

Version installée : 2.1.197

Authentification

Choix retenu : login OAuth avec le compte claude.ai (Julien, plan Claude Pro) — pas de clé API Anthropic séparée, donc pas de facturation à l'usage additionnelle.

Procédure suivie (le VPS est headless, pas de navigateur local) :

  1. Lancer claude dans une session tmux dédiée (tmux new-session -d -s claude) pour que la session survive à une déconnexion SSH
  2. Choisir "Claude account with subscription" au login
  3. Le CLI affiche une URL https://claude.com/cai/oauth/authorize?... — impossible à ouvrir depuis le VPS, donc récupérée via tmux capture-pane et ouverte manuellement sur un navigateur (PC ou mobile)
  4. Après connexion sur claude.ai, un code xxxx#yyyy est retourné — collé dans le prompt Paste code here if prompted > via tmux send-keys
  5. Confirmation : Logged in as julien.bertrand@live.fr

Les credentials sont persistés dans ~/.claude/.credentials.json (permissions 600, debian:debian) — la connexion reste valide pour les sessions futures, pas besoin de se ré-authentifier à chaque lancement.

Usage depuis Android (Termux)

  1. Installer Termux depuis F-Droid (pas le Play Store, version obsolète)
  2. Se connecter en SSH au VPS :
    ssh debian@51.77.141.54
    
  3. Rattacher ou créer la session tmux :
    tmux attach -t claude   # si la session existe déjà
    tmux new -s claude      # sinon
    
  4. Lancer claude (ou il tourne déjà si la session persiste)
  5. Détacher sans tuer la session : Ctrl+b puis d — permet de couper la connexion mobile sans interrompre Claude Code

Sécurité

Répertoire de lancement recommandé

Le VPS a déjà en local le CLAUDE.md partagé, synchronisé via Syncthing :

~/Documents/Jux_univers/Claude-pcelio+jux/CLAUDE.md

C'est le même fichier que celui utilisé sur le PC Windows (D:\Syncthing\Jux_univers\Claude-pcelio+jux\CLAUDE.md) et sur Ubuntu. Il fait partie du dossier Syncthing afltj-njyuy ("Tablette VPS Syncthing"), local path ~/Documents.

Lancer claude depuis ce dossier plutôt que /home/debian : le CLI charge automatiquement ce CLAUDE.md et récupère tout le contexte partagé (MCPs, infra, conventions) sans rien reconfigurer.

cd ~/Documents/Jux_univers/Claude-pcelio+jux/
claude

Piège constaté — Syncthing VPS silencieusement déconnecté (2026-07-21)

En vérifiant le CLAUDE.md sur le VPS, le fichier était resté figé au 24 juin alors que la version de référence (PC Windows) avait été mise à jour bien plus récemment (ex. section Inkscape du 21/07).

Diagnostic via le MCP Syncthing :

Autrement dit : Syncthing sur le VPS ne remonte aucune erreur quand il est déconnecté de tout le monde — il affiche juste l'état "idle" du dernier sync connu, ce qui peut faire croire à tort que tout est synchronisé.

Résolution : dès que Syncthing a été relancé côté PC Windows, la connexion TCP vers le VPS (device I4M5WXU) s'est rétablie en quelques secondes, et le CLAUDE.md s'est mis à jour immédiatement (nouveau hash, date du jour).

Point de vigilance pour la suite : si le CLAUDE.md sur le VPS semble périmé, ne pas se fier à get_folder_status seul (peut afficher "idle" à tort) — vérifier get_connections pour confirmer que le VPS a bien une connexion active vers au moins un appareil source avant de creuser plus loin.

Points d'attention pour la suite

0_Claude et le Jux_VPS

00_Recapitulatif

260802 - Allegement JVM Komga + StirlingPDF (applique le 2026-08-02 a 22h)

Application des optimisations memoire validees le 2026-08-01, apres verification du backup quotidien (BILAN 5/5 OK). Les deux stacks ont ete redeployees depuis /home/debian/{komga,stirling}-compose-new.yml, les composes precedents sauvegardes en .bak-260802.

ServiceAvantApresResultat
Komga (stack 7) -Xmx4g -Xms2g -XX:MaxRAMPercentage=70.0
limits 4500M / reservations 3000M
707 Mio residents
-Xmx1g
limits 1500M / reservations 256M
415 Mio (-292 Mio, -41 %)
StirlingPDF (stack 89) JVM sans limite
722 Mio residents
-Xmx512m
limits 2g
785 Mio — pas de reduction, mais consommation desormais bornee

Bilan hote : swap 3,7 Go -> 2,2 Go (-1,5 Go), memoire disponible 4,4 -> 4,6 Gi. L'essentiel du gain vient de Komga : c'est le -Xms2g qui pre-allouait 2 Go de heap au demarrage.

Pourquoi StirlingPDF ne baisse pas : le process java conserve 799 Mio de RSS malgre -Xmx512m (512 Mio de heap + non-heap : metaspace, code cache, piles de threads), auxquels s'ajoutent LibreOffice (soffice.bin, ~98 Mio), unoserver et Xvfb que Stirling lance pour les conversions. Le benefice obtenu n'est pas une baisse mais un plafond : la consommation ne peut plus deborder.

Limite portee de 1 Go a 2 Go avant application. Le plan initial prevoyait 1 Go. Or l'OCR fait tourner ocrmypdf et tesseract comme processus Python hors JVM : -Xmx ne les borne pas, seul le plafond cgroup du container s'applique. Pic mesure a 894-969 Mio pour une seule page A4 300 dpi — un plafond de 1 Go aurait provoque un OOM kill des le premier OCR. La version 1 Go est conservee en /home/debian/stirling-compose-new.yml.orig1g mais ne doit pas etre utilisee.

Verifications apres deploiement : Komga repond 200 et son API /api/v1/libraries renvoie bien les bibliotheques ; StirlingPDF valide ses deux fonctions critiques, compress-pdf (utilise par les workflows komga-pdf et nas_geo_compress) et l'OCR (page A4 300 dpi, pic 969 Mio, aucun OOM kill, aucun redemarrage).

Piege de deploiement : les projets compose s'appellent 7 et 89 (les IDs de stack Portainer), pas komga / stirlingpdf. La commande correcte est sudo docker compose -p 7 -f /var/lib/docker/volumes/portainer_data/_data/compose/7/docker-compose.yml up -d.

Rollback : restaurer le .bak-260802 de la stack concernee et redeployer de la meme facon.


Vue d ensemble - VPS Jux + Claude Code

34 containers en production sur le VPS. 25 pages de documentation, une par service. 13 services disposent d un MCP actif dans Claude Code. Mis a jour le 2026-05-30.

Page URL MCP Claude Code Statut integration
01_Portainer https://portainer.juxjux.ovh mcp__portainer__* MCP actif
02_Bookstack https://bookstack.juxjux.ovh bookstack-mcp-server (npm) MCP actif
03_Homarr https://homarr.juxjux.ovh mcp__homarr__* MCP actif
04_Audiobookshelf https://audiobookshelf.juxjux.ovh mcp__audiobookshelf__* MCP actif
05_BentoPDF - - API directe
06_Cadvisor - - via Prometheus
07_Calibre-web - - OPDS
08_Dozzle - - via Portainer MCP
09_FileBrowser https://files.juxjux.ovh mcp__filebrowser__* MCP actif
10_FreshRSS https://freshrss.juxjux.ovh mcp__freshrss__* MCP actif
11_Gitea - - API REST directe
12_Grafana https://grafana.juxjux.ovh - API REST directe
13_Immich https://immich.juxjux.ovh mcp__immich__* MCP actif (5 containers)
14_Jellyfin https://jellyfin.juxjux.ovh mcp__jellyfin__* MCP actif
15_Joplin - - sync server uniquement
16_Kavita https://kavita.juxjux.ovh mcp__kavita__* MCP actif
17_Komga https://komga.juxjux.ovh mcp__komga__* MCP actif
18_Mealie https://mealie.juxjux.ovh mcp__mealie__* MCP actif
19_Navidrome https://navidrome.juxjux.ovh mcp__navidrome__* MCP actif
20_NodeExporter - - via Prometheus
21_Prometheus - - API REST / PromQL
22_Readeck https://readeck.juxjux.ovh mcp__readeck__* MCP actif
23_Syncthing https://syncthing.juxjux.ovh mcp__syncthing__* MCP actif
24_Yourls - - API REST directe
25_StirlingPDF https://spdf.juxjux.ovh - API directe
A_liens entre Claude et le KDRIVE kdrive.infomaniak.com @infomaniak/mcp-server-kdrive + API REST MCP actif (kdrive_search) + API directe

Scripts de maintenance

fill_bookstack_pages.py Remplit les pages avec les infos containers (image, ports, volumes) C:\Users\eliob\.claude\fill_bookstack_pages.py
fill_bookstack_mcp.py Ajoute la section integration Claude Code / MCP a chaque page C:\Users\eliob\.claude\fill_bookstack_mcp.py

Configuration MCP

Scripts dans C:\Users\eliob\.claude\, enregistres dans C:\Users\eliob\.mcp.json. Projet Claude Code principal : C:\Users\eliob. Endpoint Portainer Docker local : ID 3.

260611-REX VPS par Claude

Releve du 2026-06-11 via Prometheus (PromQL sur localhost:9090) + Portainer MCP.

Etat global

RAM 8.4 / 11.41 GB (73.6%)
Swap 3.99 / 4.0 GB (quasi plein)
CPU 5.2%

Top consommateurs RAM (RSS)

Container RAM RSS
komga 1059 MB
Immich-SERVER 1011 MB
Immich-MICROSERVICES 520 MB
stirling-pdf 442 MB
homarr2026 355 MB
jellyfin 272 MB
prometheus 259 MB
jdownloader 220 MB
Kavita 196 MB
joplin 179 MB
calibre-web-eyrolles 132 MB
mealie 129 MB
grafana 125 MB
cadvisor 91 MB
navidrome 86 MB

Swap sature : komga + Immich representent ~2.5 GB a eux deux. StirlingPDF (442 MB) reste charge entre les appels.

 

260801-REX VPS par Claude

Releve du 2026-08-01 via docker stats + /proc en SSH (PC eliob).

Etat global

RAM 8.2 / 11.41 GB (71.7%)
Swap 4.0 / 4.0 GB (sature a 100%)
CPU 28% (compression 7z du backup en cours)

Top consommateurs RAM (RSS)

Container RAM RSS
Immich-SERVER 1147 MB
komga 791 MB
Immich-MICROSERVICES 618 MB
stirling-pdf 566 MB
jellyfin 380 MB
homarr2026 313 MB
Immich-DB 310 MB
prometheus 282 MB
joplin 241 MB
Kavita 240 MB
cadvisor 195 MB
grafana 164 MB
joplin-db 158 MB
yourls-db 157 MB
audiobookshelf 140 MB

Swap sature : komga (760 MB) + StirlingPDF (406 MB) en tete des processus swappes, Immich ~330 MB. Des limites memoire ont ete posees depuis juin sur les gros containers (komga 4.4G, Immich 2G, Kavita 4G, joplin 2G). Decouvertes du jour : GNOME/gdm3 tourne a vide sur tty1 depuis le 8 juillet (98 paquets installes, ~150 MB RAM, aucun acces distant configure) ; sauvegardes Immich vides depuis l'origine (pg_dump sans -d immich, archives de 4 Ko) — corrigees le 2026-08-01, dump reel 307 MB.

Actions realisees le 2026-08-01 (soir)

Action Detail Gain
Fix backup Immich -d immich ajoute dans /opt/backups/vps_backup.sh + run manuel complet 5/5 OK (archive 87 MB sur kDrive, premiere sauvegarde Immich valide) donnees enfin sauvegardees
Fusion Immich 5 containers → 3 : SERVER unique (API + workers, NODE_OPTIONS=--max-old-space-size=768), MICROSERVICES et LEARNING supprimes (recherche semantique et visages non utilises). Ancien compose : compose/29/docker-compose.yml.bak-260801 ~900 MB RAM
Arret cAdvisor docker update --restart=no cadvisor + stop. Plus de metriques par container dans Prometheus/Grafana (node-exporter conserve le host) ~200 MB RAM + 4-8% CPU
GDM/GNOME desactive puis purge gdm3 + gnome-shell + Xorg tournaient a vide sur tty1 depuis le 2026-07-08. systemctl disable --now gdm puis purge apt de 263 paquets (bureau complet + LibreOffice, jeux...). Verifie avant : ens3 gere par systemd-networkd, NetworkManager non critique. Verifie apres : 30 containers up, nginx/docker/ssh/wg actifs, sites en 200 ~150 MB RAM + 3,5 GB disque

Resultat global du 2026-08-01 : swap 4,0/4,0 GB (sature depuis juin) → 2,6/4,0 GB ; disque 62% → 59% ; ~1,3 GB de RAM liberes. Immich verifie fonctionnel par Julien.

Plan du 2026-08-02 a 19h (tache planifiee Claude Code)

Apres verification du backup nocturne (BILAN 5/5 OK), appliquer les deux fixes JVM prepares et valides (fichiers en attente dans /home/debian/) :

Service Avant Apres Gain attendu
Komga (stack 7) -Xmx4g -Xms2g (2 GB pre-alloues, ~760 MB en swap), limites 4500M/3000M -Xmx1g sans Xms, limites 1500M/256M ~400-500 MB RAM + ~700 MB swap
StirlingPDF (stack 89) JVM sans plafond (566-643 MB residents + ~406 MB swap) JAVA_TOOL_OPTIONS=-Xmx512m, limite 1g ~300-400 MB RAM

Verifications prevues : komga.juxjux.ovh en 200, test compress-pdf sur spdf.juxjux.ovh (fonction critique des workflows komga-pdf et geo_loud), docker stats, free -h (swap attendu sous ~2 GB). Rollback : restaurer les .bak-260802. Nota : BentoPDF n'existe plus sur le VPS (container supprime) — il ne peut de toute facon pas remplacer StirlingPDF (pas d'API serveur, traitement 100% navigateur).

0_Claude et le Jux_VPS

01_Portainer

portainer

Docker container management made simple, with the world’s most popular GUI-based container management platform.

Imageportainer/portainer-ce:latest
EtatUp 9 hours
Reseaubridge
URLhttps://portainer.juxjux.ovh

Ports

HoteContainerIP
94439443/tcp0.0.0.0
94439443/tcp::
80008000/tcp0.0.0.0
80008000/tcp::
90009000/tcp0.0.0.0
90009000/tcp::

Volumes

Source (hote)DestinationTypeMode
/var/lib/docker/volumes/portainer_data/_data/datavolumerw
/var/run/docker.sock/var/run/docker.sockbindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__portainer__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_portainer.py | Projet Claude Code : C:\Users\eliob | Auth : JWT via POST /api/auth, endpoint Docker local ID 3

Outils disponibles

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

02_Bookstack

bookstack

[Bookstack](https://github.com/BookStackApp/BookStack) is a free and open source Wiki designed for creating beautiful documentation. Featuring a simple, but powerful WYSIWYG editor it allows for teams to create detailed and useful documentation with ease. Powered by SQL and including a Markdown editor for those who prefer it, BookStack is geared towards making documentation more of a pleasure than a chore. For more information on BookStack visit their website and check it out: https://www.bookstackapp.com

Imagelscr.io/linuxserver/bookstack:latest
Versionv26.03.3-ls256
EtatUp 9 hours
Compose projectbookstack
Reseaubookstack_default
URLhttps://bookstack.juxjux.ovh
Sourcehttps://github.com/linuxserver/docker-bookstack

Ports

HoteContainerIP
687580/tcp0.0.0.0
687580/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/bookstack/app/configbindrw

bookstack_db

[Mariadb](https://mariadb.org/) is one of the most popular database servers. Made by the original developers of MySQL.

Imagelscr.io/linuxserver/mariadb:latest
Version11.4.9-r0-ls212
EtatUp 9 hours
Compose projectbookstack
Reseaubookstack_default
URLhttps://bookstack.juxjux.ovh
Sourcehttps://github.com/linuxserver/docker-mariadb

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/bookstack/db/configbindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)bookstack MCP (npm bookstack-mcp-server)
Configurationnpm via npx -y bookstack-mcp-server | Projet Claude Code : C:\Users\eliob | Auth : Token ID + Secret en variables d'environnement (.claude.json)

Outils disponibles

Ce que nous pouvons faire ensemble


Sauvegarde de la base de données

Sauvegarde automatique quotidienne de la base MariaDB bookstackapp vers kDrive Infomaniak. Mise en place le 2026-06-01.

Paramètres

Script/opt/backups/bookstack_backup.sh
CronTous les jours à 2h du matin (0 2 * * *)
Base sauvegardéebookstackapp — container bookstack_db (MariaDB)
Taille base (disque)~203 Mo
Format archive.7z (compression niveau 5) — ~564 Ko
DestinationkDrive Infomaniak — TOOJUX/jux_vps/bookstack (dossier ID 1427916)
Rétention7 jours glissants (purge automatique des anciens fichiers)
Log/opt/backups/backup.log
Nommage fichierbookstack_db_YYYY-MM-DD.7z

Fonctionnement du script

  1. Exécute mysqldump depuis le container bookstack_db vers /tmp/
  2. Compresse en .7z avec 7z (déjà installé sur le VPS)
  3. Upload sur kDrive via l'API REST Infomaniak (POST /3/drive/{id}/upload) avec le paramètre total_size
  4. Supprime le fichier temporaire local
  5. Purge les fichiers kDrive nommés bookstack_db_* de plus de 7 jours

Consulter les logs

ssh debian@51.77.141.54 "tail -50 /opt/backups/backup.log"

Relancer manuellement

ssh debian@51.77.141.54 "bash /opt/backups/bookstack_backup.sh"
0_Claude et le Jux_VPS

03_Homarr

homarr2026

A modern and easy to use dashboard. 30+ integrations. 10K+ icons built in. Authentication out of the box. No YAML, drag and drop configuration.

Imageghcr.io/homarr-labs/homarr:latest
Versionmain
EtatUp 9 hours
Compose projecthomarr
Reseauhomarr_homarr_network
URLhttps://homarr.juxjux.ovh
Sourcehttps://github.com/homarr-labs/homarr

Ports

HoteContainerIP
75753000/tcp0.0.0.0
75753000/tcp::

Volumes

Source (hote)DestinationTypeMode
/etc/localtime/etc/localtimebindro
/var/run/docker.sock/var/run/docker.sockbindro
/home/debian/docker/homarr2026/icons/app/public/iconsbindrw
/home/debian/docker/homarr2026/appdata/appdatabindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__homarr__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_homarr.py | Projet Claude Code : C:\Users\eliob | Auth : cookie NextAuth session (authjs.session-token)

Outils disponibles

Ce que nous pouvons faire ensemble


Mise a jour disponible (verifie le 2026-07-19)

Version installee0.53
Derniere version1.71.0 (2026-07-17)
EcartTraverse la refonte majeure 1.0 (reecriture complete, ete 2024) + ~70 releases mineures jusqu'a juillet 2026

Attention : migration majeure, pas un simple bump

Le projet a ete entierement reecrit en version 1.0 et le depot a change de proprietaire : ghcr.io/ajnart/homarr -> ghcr.io/homarr-labs/homarr. Le stack VPS (homarr2026) utilise deja l'image homarr-labs avec le tag latest et un volume /appdata, donc une partie de la migration structurelle semble deja faite -- a verifier avant de bumper vers un tag fige.

Principaux breaking changes (0.x -> 1.0)

Nouveautes notables depuis la 1.0 (jusqu'a 1.71.0)

Etapes de migration recommandees

  1. Sauvegarder /home/debian/docker/homarr2026/appdata avant toute action
  2. Exporter la config du dashboard depuis l'UI (fonction export/backup SQLite)
  3. Verifier les variables d'environnement du compose homarr2026 contre la liste des breaking changes ci-dessus (notamment SECRET_ENCRYPTION_KEY, DOCKER_HOSTNAMES/DOCKER_PORTS)
  4. Redeployer le stack, puis retester chaque integration (Jellyfin, Sonarr, etc.) -- test de connexion obligatoire en 1.x
  5. Reimporter la sauvegarde SQLite si necessaire

Sources : github.com/homarr-labs/homarr/releases, homarr.dev/blog - Homarr 1.0

0_Claude et le Jux_VPS

04_Audiobookshelf

audiobookshelf

Self-hosted audiobook and podcast server

Imageghcr.io/advplyr/audiobookshelf:latest
Version2.35.0
EtatUp (healthy)
Compose projectaudiobookshelf
Reseauaudiobookshelf_audiobookshelf_network
URLhttps://audiobookshelf.juxjux.ovh
Sourcehttps://github.com/advplyr/audiobookshelf

Ports

HoteContainerIP
1337880/tcp127.0.0.1

Volumes

Source (hote)DestinationTypeMode
/home/debian/audiobookshelf/config/configbindrw
/home/debian/audiobookshelf/metadata/metadatabindrw
/home/debian/audiobookshelf/podcasts/podcastsbindrw
/home/debian/audiobookshelf/audiobooks/audiobooksbindrw, :shared

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__audiobookshelf__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_audiobookshelf.py | Auth : JWT Bearer via POST /login

Outils disponibles

Ce que nous pouvons faire ensemble


Scan quotidien automatique — 2026-06-24

Un cron tourne chaque nuit à 04h00 UTC pour scanner toutes les bibliothèques Audiobookshelf et détecter les nouveaux contenus ou les renommages de dossiers.

Script

/home/debian/abs_scan.sh — log : /var/log/abs_scan.log

0 4 * * * bash /home/debian/abs_scan.sh

Fonctionnement

  1. Authentification via POST /login pour obtenir un token JWT frais
  2. Récupération de toutes les bibliothèques via GET /api/libraries
  3. Déclenchement d'un scan pour chaque bibliothèque via POST /api/libraries/{id}/scan

Bibliothèques scannées : 36 (audiobooks + podcasts). Durée estimée : quelques minutes.

Exemple de log :

2026-06-24 04:00 SCAN OK 36/36 libs

REX — 2026-06-24 : audiobook illisible après renommage de dossier

Contexte

Audiobookshelf ne pouvait plus lire Les routes de la soie (Peter Frankopan). Erreur dans les logs :

Error: ENOENT: no such file or directory, stat '/audiobooks/Histoire/2 - Moyen Age/Peter Frankopan - Les routes de la soie/27_CH_08_LA_ROUTE_DU_CIEL.mp3'

Cause

Le dossier avait été renommé sur kDrive/NAS de Peter Frankopan - Les routes de la soie en Peter Frankopan-les routes de la soie (tiret sans espaces, minuscule). Audiobookshelf conservait l'ancien chemin dans sa base.

Solution

Le scan quotidien abs_scan.sh détecte ce type de désynchronisation et met à jour les chemins. Pour forcer immédiatement : lancer un scan manuel depuis l'interface Audiobookshelf ou exécuter bash /home/debian/abs_scan.sh.

0_Claude et le Jux_VPS

05_BentoPDF

bentopdf

Unprivileged NGINX Dockerfiles

Imagebentopdfteam/bentopdf-simple:latest
Version1.28.0-alpine-slim
EtatUp 9 hours
Compose projectbentopdf
Reseaubentopdf_default
URLhttps://bento.juxjux.ovh
Sourcehttps://github.com/alam00000/bentopdf

Ports

HoteContainerIP
80898080/tcp0.0.0.0
80898080/tcp::

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueAPI REST interne, pas de MCP configuré. Accessible via PowerShell/Python httpx.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

06_Cadvisor

cadvisor

Imagegcr.io/cadvisor/cadvisor:latest
EtatUp 9 hours (healthy)
Compose projectgemini_grafana
Reseaugemini_grafana_monitor_net

Volumes

Source (hote)DestinationTypeMode
/var/run/var/runbindrw
//rootbindro
/sys/sysbindro
/var/lib/docker/var/lib/dockerbindro

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueEndpoint Prometheus /metrics exposé à Prometheus (port 8080). Pas de MCP. Données lisibles via Prometheus MCP ou requêtes PromQL directes.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

07_Calibre-web

calibre-web-eyrolles

[Calibre-web](https://github.com/janeczku/calibre-web) is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing Calibre database. It is also possible to integrate google drive and edit metadata and your calibre library through the app itself. This software is a fork of library and licensed under the GPL v3 License.

Imagelscr.io/linuxserver/calibre-web:latest
Version0.6.26-ls383
EtatUp 9 hours (healthy)
Compose projectcalibreweb_automated
Reseaucalibre_network
Sourcehttps://github.com/linuxserver/docker-calibre-web

Ports

HoteContainerIP
82148083/tcp0.0.0.0
82148083/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/livres/Eyrolles/booksbindrw
/home/debian/docker/calibre-web-automated/config/configbindrw

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueInterface OPDS disponible pour parcourir la bibliothèque. API REST limitée. Pas de MCP configuré.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

08_Dozzle

dozzle

Realtime log viewer for containers. Supports Docker, Swarm and K8s.

Imageamir20/dozzle:latest
Versionv8.14.9
EtatUp 9 hours
Compose projectdozzle
Reseaunginx_npm-network
URLhttps://dozzle.juxjux.ovh
Sourcehttps://github.com/amir20/dozzle

Ports

HoteContainerIP
90918080/tcp0.0.0.0
90918080/tcp::

Volumes

Source (hote)DestinationTypeMode
/var/run/docker.sock/var/run/docker.sockbindrw

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueInterface de visualisation de logs uniquement. Pas d'API publique exploitable. Les logs sont mieux accessibles via mcp__portainer__get_container_logs.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

09_FileBrowser

File-Browser

Imagefilebrowser/filebrowser:latest
Version2.63.3
EtatUp 9 hours (healthy)
Compose projectfilebrowser
Reseaufilebrowser_default
URLhttps://files.juxjux.ovh
Sourcehttps://github.com/filebrowser/filebrowser

Ports

HoteContainerIP
814780/tcp0.0.0.0
814780/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/filebrowser/database/databasebindrw
/home/debian/srvbindrw
/home/debian/docker/filebrowser/config/configbindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__filebrowser__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_filebrowser.py | Auth : JWT via POST /api/login (admin)

Outils disponibles

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

10_FreshRSS

freshrss

A free, self-hostable news aggregator…

Imagefreshrss/freshrss:latest
Version1.28.1
EtatUp 26 minutes
Compose projectfreshrss
Reseaufreshrss_default
URLhttps://freshrss.juxjux.ovh
Sourcehttps://github.com/FreshRSS/FreshRSS

Ports

HoteContainerIP
808180/tcp0.0.0.0
808180/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/freshrss/data/var/www/FreshRSS/databindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__freshrss__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_freshrss.py | Auth : GReader API avec mot de passe API dédié (≠ mot de passe web)

Outils disponibles

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

11_Gitea

gitea

Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD

Imagegitea/gitea:latest
Version1.25.4
EtatUp 9 hours (healthy)
Compose projectgitea
Reseaugitea_default
URLhttps://gitea.juxjux.ovh
Sourcehttps://github.com/go-gitea/gitea

Ports

HoteContainerIP
22222222/tcp0.0.0.0
22222222/tcp::
30053000/tcp0.0.0.0
30053000/tcp::

Volumes

Source (hote)DestinationTypeMode
/var/lib/gitea_data/databindrw
/etc/localtime/etc/localtimebindro
/etc/timezone/etc/timezonebindro

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueAPI REST Gitea complète disponible sur /api/v1. Auth : token Bearer ou Basic Auth. Pas de MCP configuré — appels directs via PowerShell/Python.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

12_Grafana

grafana

Image grafana/grafana:latest
Etat Up 5 days (healthy)
Compose project gemini_grafana (stack ID 63)
Réseau gemini_grafana_monitor_net
URL https://grafana.juxjux.ovh
Source https://github.com/grafana/grafana

Ports

Hote Container IP
3000 3000/tcp 0.0.0.0
3000 3000/tcp ::

Volumes

Source (hote) Destination Type Mode
/opt/monitoring/grafana_data /var/lib/grafana bind rw

Intégration Claude Code — API directe

Statut MCP Pas de MCP — API directe possible
Note technique API REST Grafana sur /api. Auth : clé API ou Basic Admin. Pas de MCP configuré — appels directs possibles.

Ce que nous pouvons faire ensemble


Compte rendu — 2026-06-11

Vérification via Portainer MCP (endpoint 3) + Prometheus PromQL (localhost:9090).

Métriques VPS globales

Métrique Valeur
RAM 8.4 / 11.41 GB 73.6%
Swap 3.99 / 4.0 GB quasi plein
CPU 5.2% —

Stack gemini_grafana — 4 containers, tous running (5 jours)

Container Image Etat Healthcheck Port exposé
grafana grafana/grafana:latest running healthy 3000
prometheus prom/prometheus:latest running — 9090
node-exporter prom/node-exporter:latest running — 9100
cadvisor gcr.io/cadvisor/cadvisor:latest running healthy 8080 (interne)

Notes

0_Claude et le Jux_VPS

13_Immich

Immich-SERVER

High performance self-hosted photo and video management solution.

Imageghcr.io/immich-app/immich-server:release
Versionv2.7.5
EtatUp (healthy)
Compose projectimmich
Reseauimmich_immich-network
URLhttps://immich.juxjux.ovh
Sourcehttps://github.com/immich-app/immich

Ports

HoteContainerIP
82122283/tcp0.0.0.0
82122283/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/immich/upload/databindrw
/etc/localtime/etc/localtimebindro
/home/debian/docker/immich/upload/encoded-video/mnt/media/encoded-videobindrw
/home/debian/photo/mnt/media/photobindro,shared

Immich-MICROSERVICES

High performance self-hosted photo and video management solution.

Imageghcr.io/immich-app/immich-server:release
Versionv2.7.5
EtatUp (healthy)
Compose projectimmich
Reseauimmich_immich-network
URLhttps://immich.juxjux.ovh
Sourcehttps://github.com/immich-app/immich

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/immich/upload/databindrw
/etc/localtime/etc/localtimebindro
/home/debian/docker/immich/upload/encoded-video/mnt/media/encoded-videobindrw
/home/debian/photo/mnt/media/photobindro,shared

Immich-LEARNING

High performance self-hosted photo and video management solution.

Imageghcr.io/immich-app/immich-machine-learning:release
Versionv2.7.5
EtatUp (healthy)
Compose projectimmich
Reseauimmich_immich-network
URLhttps://immich.juxjux.ovh
Sourcehttps://github.com/immich-app/immich

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/immich/cache/cachebindrw

Immich-REDIS

Imageredis:6.2-alpine
EtatUp (healthy)
Compose projectimmich
Reseauimmich_immich-network
URLhttps://immich.juxjux.ovh

Volumes

Source (hote)DestinationTypeMode
 /datavolumerw

Immich-DB

Base images for Immich containers

Imageghcr.io/immich-app/postgres:16-vectorchord0.3.0-pgvectors0.2.0
Version16-vectorchord0.3.0-pgvector0.8.1-pgvectors0.2.0
EtatUp (healthy)
Compose projectimmich
Reseauimmich_immich-network
URLhttps://immich.juxjux.ovh
Sourcehttps://github.com/immich-app/base-images

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/immich/db/var/lib/postgresql/databindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__immich__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_immich.py | Auth : JWT via POST /api/auth/login

Outils disponibles

Ce que nous pouvons faire ensemble


Sauvegarde de la base de données

Sauvegarde automatique quotidienne de la base PostgreSQL Immich-DB vers kDrive Infomaniak. Mise en place le 2026-06-01.

Paramètres

Script/opt/backups/vps_backup.sh
CronTous les jours à 2h du matin (0 2 * * *)
Container DBImmich-DB (PostgreSQL 16)
Commandepg_dump -U postgres
Taille base (disque)~7.5 Mo (métadonnées uniquement — photos sur volume séparé)
Format archive.7z (compression niveau 5)
DestinationkDrive Infomaniak — TOOJUX/jux_vps/immich (dossier ID 1427919)
Rétention7 jours glissants
Nommage fichierimmich_db_YYYY-MM-DD.7z

Note importante

Cette sauvegarde couvre uniquement les métadonnées (albums, faces, tags, utilisateurs). Les fichiers photos/vidéos sont stockés dans /home/debian/docker/immich/upload et /home/debian/photo — ils ne sont pas inclus dans ce backup.


REX — 2026-06-21 — FUSE cassé après restart rclone-photo

Symptôme

Immich connecté mais aucune photo visible. Logs Immich-SERVER :

WARN [Microservices:LibraryService] Skipping invalid import path: /mnt/media/photo. Reason: Error: ENOTCONN: socket is not connected, stat '/mnt/media/photo'

Cause

Le service rclone-photo.service a redémarré le 2026-06-18 (suite à l'incident sécurité du 2026-06-09 — fix --rc-addr 127.0.0.1). Les containers Immich-SERVER et Immich-MICROSERVICES, démarrés avant ce restart, conservent un file descriptor FUSE invalide. La propagation :shared aide pour les nouveaux montages mais ne restaure pas un fd FUSE mort.

Fix immédiat

docker restart Immich-SERVER Immich-MICROSERVICES
# puis déclencher un scan de bibliothèque :
curl -s -X POST "https://immich.juxjux.ovh/api/libraries/89bfcdc1-1604-47a1-90a3-975d2f6c4639/scan" \
  -H "Authorization: Bearer TOKEN"
# TOKEN obtenu via POST /api/auth/login (bertrand.dadone@gmail.com / 27101809)

Fix structurel — ExecStartPost dans rclone-photo.service (2026-06-21)

Ajout d'un ExecStartPost dans /etc/systemd/system/rclone-photo.service : à chaque redémarrage de rclone-photo, les containers Immich sont automatiquement relancés si et seulement s'ils tournent déjà (pas de blocage au boot).

ExecStartPost=/bin/bash -c 'sleep 3; docker ps --filter name=Immich-SERVER --filter status=running -q | grep -q . && docker restart Immich-SERVER Immich-MICROSERVICES || true'

Rechargement : sudo systemctl daemon-reload (pas de restart du service nécessaire — prendra effet au prochain redémarrage de rclone-photo).

Library ID Immich

89bfcdc1-1604-47a1-90a3-975d2f6c4639


Inventaire par Claude le 251001


2026-08-28 — Photos en double et chronologie cassee : diagnostic et reparation

Symptome : apres la resynchronisation d'un dossier renomme cote NAS, les photos de l'ete 2026 apparaissaient en double dans Immich et ne se rangeaient plus a leur date de prise de vue.

Deux causes distinctes se superposaient, et les confondre fait perdre du temps.

1. Les doublons — deja resolus par Immich lui-meme

Le dossier 2026_Eté UK ayant ete renomme en 2026_Eté UK et Italia, 308 assets pointaient sur un chemin disparu. Immich les avait deja marques hors ligne et mis a la corbeille tout seul : ils ne polluaient donc plus la chronologie. Ils ont ete purges definitivement par API.

POST /api/search/metadata   {"isOffline": true}     -> recensement
DELETE /api/assets          {"ids": [...], "force": true}

Aucun fichier reel n'est touche (ils n'existent plus sur le disque) et ces assets n'appartenaient a aucun album — verifie avant la purge.

2. Les dates — 275 photos n'avaient plus AUCUN bloc EXIF

Non pas « un EXIF sans date » : plus une seule metadonnee. Mesure sur les 351 fichiers du dossier :

NombreTaille moyennePeriode
Sans aucun EXIF275493 Ko02/07 au 21/07
EXIF complet + GPS761103 Ko17/07 au 17/08

Cause : la passe de compression Caesium du 2026-07-14, lancee sans l'option -e — le piege decouvert et documente seulement le 27/08 (page 284). Les fichiers traites ont perdu date et GPS. Le GPS est definitivement perdu ; seule la date etait reconstituable, parce que les appareils Android nomment leurs prises IMG_AAAAMMJJ_HHMMSS au declenchement.

Pourquoi le probleme n'est apparu que maintenant

Prive de DateTimeOriginal, Immich retombe sur la date de modification du fichier. Or le WebDAV kDrive ne preserve pas les mtime : chaque reupload redate les fichiers au jour de la synchronisation, et les photos partent se ranger a cette date. Tant qu'aucune resynchronisation n'avait lieu, le defaut dormait — la compression de juillet ne s'est vue qu'en aout.

⚠ Corriger la date dans Immich ne tient pas

Teste puis abandonne : PUT /api/assets/{id} avec dateTimeOriginal a tenu quelques secondes, puis la valeur a ete ecrasee par la re-extraction des metadonnees du fichier. Sur une bibliotheque externe, le fichier fait autorite.

Il n'existe aucun reglage Immich pour « n'utiliser que la date de prise de vue » : sans EXIF, le logiciel n'a pas d'autre source. Exiger ce comportement revient a exiger que les fichiers portent leur date. La reparation doit donc se faire dans le fichier.

Reparation appliquee

Jux-scripts/Photos-Caesium/dater_photos_nas.py (stdlib seule, deploye sur le NAS) reconstruit la date depuis le nom et l'inscrit dans un segment APP1 de 138 octets insere apres le marqueur SOI.

python3 dater_photos_nas.py "/volume1/photo/2026/2026_Eté UK et Italia"        # simulation
python3 dater_photos_nas.py "/volume1/photo/2026/2026_Eté UK et Italia" --go   # ecriture

Garde-fous : ne touche que les JPEG totalement depourvus d'EXIF ; n'invente jamais de date (sans motif reconnu, le fichier est laisse tel quel) ; refuse les dates impossibles ; ecriture atomique avec relecture de controle avant remplacement ; mtime, proprietaire et permissions releves puis reimposes et verifies.

Resultat : 275 fichiers dates en 224 s, 0 echec. Donnees image identiques a l'octet pres (+138 octets de metadonnees), mtime preserve. Apres resynchronisation et POST /api/libraries/{id}/scan, Immich a relu l'EXIF en moins de 40 s : les 351 photos se repartissent du 02/07 au 17/08, et plus une seule n'est datee du jour de la synchro.

Audit du reste du stock — pas de reparation de masse

auditer_exif_nas.py sur les 16 262 JPEG du NAS : 1 001 sans date de prise de vue, mais aucun autre degat Caesium.

Reperes API (aucun MCP Immich dans la session)

POST /api/auth/login                 -> accessToken (Bearer)
POST /api/search/metadata            isOffline, originalFileName, takenAfter/takenBefore,
                                     withExif ; pagination par le champ nextPage
GET  /api/assets/statistics
GET  /api/libraries + /api/libraries/{id}/statistics
POST /api/libraries/{id}/scan

Bibliotheque externe : 89bfcdc1-1604-47a1-90a3-975d2f6c4639, chemin d'import /mnt/media/photo.

0_Claude et le Jux_VPS

14_Jellyfin

jellyfin

The Free Software Media System

Imagejellyfin/jellyfin:latest
Version10.10.7
EtatUp 9 hours (healthy)
Compose projectjellyfin
Reseauhost
URLhttps://jellyfin.juxjux.ovh
Sourcehttps://github.com/jellyfin/jellyfin-packaging

Volumes

Source (hote)DestinationTypeMode
/mnt/nas_videos/movies/data/moviesbindrw
/mnt/nas_videos/palettes/data/palettesbindrw
/home/debian/jellyfin/config/configbindrw
/mnt/nas_videos/cinema_europe/data/cinema_europebindrw
/mnt/nas_videos/cinema_UK/data/cinema_ukbindrw
/mnt/nas_videos/spectacles/data/spectaclesbindrw
/cachevolumerw
/mnt/nas_videos/animes/data/animesbindrw
/mnt/nas_videos/cinema_asie/data/cinema_asiebindrw
/mnt/nas_videos/cinema_realisateurs/data/cinema_realisateursbindrw
/mnt/nas_videos/fantastique_et_SF/data/fantastique_et_SFbindrw
/mnt/nas_videos/historiques/data/historiquesbindrw
/mnt/nas_videos/series/data/seriesbindrw
/mnt/nas_videos/cinema_italie/data/cinema_italiebindrw
/mnt/nas_videos/culture_cuisine/data/culture_cuisinebindrw
/mnt/nas_videos/documentaires/data/documentairesbindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__jellyfin__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_jellyfin.py | Auth : JWT MediaBrowser Token via POST /Users/AuthenticateByName

Outils disponibles

Ce que nous pouvons faire ensemble


260830 - Lecture des flux vidéos Jellyfin à partir de kDrive

Statut : FAIT le 2026-08-30. Jellyfin ne lit plus le NAS. Il lit kDrive par un montage rclone FUSE. Le NAS conserve l'intégralité des 694 Go — l'étape 6 (suppression) reste en attente, après période d'observation.

Résultat mesuré

AvantAprès
Source de /mnt/nas_videosCIFS //10.0.0.2/videorclone kDrive Videos_NAS
Débit lu depuis le container5,0 Mo/s65,6 Mo/s
Propagation des 15 bindsabsenteshared sur les 15
EnableRealtimeMonitoractif sur 15 bibliosdésactivé partout
monitor-rclone.sh5 montages6, avec restart de jellyfin
Films catalogués343629 (+286, fusion cuisine)

Le goulot était le tunnel WireGuard depuis Toulon (40 Mbit/s, incompatible avec deux flux simultanés), pas kDrive. La bascule améliore la lecture au lieu de la dégrader.

Le montage

Service /etc/systemd/system/kdrive-video.service, activé au démarrage, calqué sur kdrive-music.service :

ExecStart=/usr/bin/rclone --config=/home/debian/.config/rclone/rclone.conf mount \
  --rc --rc-addr 127.0.0.1:5578 --rc-user=rcadmin --rc-pass=RcVideo2026! --rc-enable-metrics \
  "kdrive:Julien Bertrand (0)/Videos_NAS" /mnt/nas_videos \
  --allow-other --dir-cache-time 72h --poll-interval 15s \
  --vfs-cache-mode minimal --buffer-size 256M \
  --uid 1000 --gid 1000 --umask 002 --allow-non-empty

La carte des binds

Le montage porte sur Videos_NAS entier, pas seulement sur son sous-dossier video, parce que deux bibliothèques ont été fusionnées avec du contenu kDrive préexistant. Les chemins conteneur sont restés identiques : aucune ré-identification, aucun historique de visionnage perdu.

Chemin hôteChemin conteneur
/mnt/nas_videos/Séries/data/series — fusionné
/mnt/nas_videos/Video Cuisine/data/culture_cuisine — fusionné
/mnt/nas_videos/video/<13 autres>/data/<13 autres>
/home/debian/jellyfin/config/config

Compose : stack Portainer 5, projet compose 5. Sauvegarde docker-compose.yml.bak-260830.

sudo docker compose -p 5 -f /var/lib/docker/volumes/portainer_data/_data/compose/5/docker-compose.yml up -d --force-recreate

Disponible pour de futures bibliothèques

Le montage expose aussi ce qui vivait déjà dans Videos_NAS et qui n'est branché sur aucune bibliothèque : Video Culture Arts et Peinture (130,8 Go), Video Architecture et Urbanisme (29,4 Go), Video concerts (3,5 Go).

Pièges rencontrés — à ne pas re-découvrir

  1. Le point de montage n'était pas vide. Sous l'ancien CIFS subsistaient 15 dossiers vides. Laissés en place, un montage rclone mort ferait voir à Jellyfin des dossiers vides au lieu d'une erreur — et il purgerait ses bibliothèques. Vérifié (0 fichier réel, 65 536 octets de dossiers) puis supprimés, montage arrêté le temps de l'opération.
  2. grep -c renvoie 1 quand il ne trouve rien et tue un script en set -e. Le redéploiement avait réussi, seule la vérification a échoué.
  3. Docker ne montre pas :shared dans .HostConfig.Binds, il le normalise dans .Mounts[].Propagation. Vérifier là.
  4. Le projet compose est 5 (l'ID de stack), pas jellyfin — lire le label com.docker.compose.project avant tout redéploiement, sous peine de créer une pile en double.

Retour arrière

  1. Décommenter la ligne 36 de /etc/fstab (sauvegarde /etc/fstab.bak-260830)
  2. sudo systemctl disable --now kdrive-video.service
  3. Restaurer docker-compose.yml.bak-260830 et redéployer

Tant que le NAS n'a pas été vidé, le retour arrière est complet.

À signaler, hors périmètre

/home/debian/jellyfin/config (688 Mo — tout l'historique de visionnage et les métadonnées) n'est pas dans vps_backup.sh, qui ne couvre que BookStack, Immich, Joplin, Mealie, Readeck, Baïkal et ~/Documents. Cela se compresserait bien. À traiter séparément.

0_Claude et le Jux_VPS

15_Joplin

joplin_to_obsidian

Imagejoplin_to_obsidian-joplin_to_obsidian
EtatUp 9 hours
Compose projectjoplin_to_obsidian
Reseaujoplin_joplin_network
URLhttps://joplin.juxjux.ovh

Volumes

Source (hote)DestinationTypeMode
/home/debian/Documents/Joplin_Obsidian/home/debian/Documents/Joplin_Obsidianbindrw

joplin-nginx

Imagenginx:alpine
EtatUp 9 hours
Compose projectjoplin
Reseaujoplin_joplin_network
URLhttps://joplin.juxjux.ovh

Ports

HoteContainerIP
2230180/tcp0.0.0.0
2230180/tcp::

joplin

Docker image for Joplin Server

Imagejoplin/server:latest
Version3.4.3
EtatUp 9 hours
Compose projectjoplin
Reseaujoplin_joplin_network
URLhttps://joplin.juxjux.ovh
Sourcehttps://github.com/laurent22/joplin.git

Ports

HoteContainerIP
2230022300/tcp0.0.0.0
2230022300/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/joplin-data/home/joplin/.config/joplinbindrw

joplin-db

Imagepostgres:15-alpine
EtatUp 9 hours
Compose projectjoplin
Reseaujoplin_joplin_network
URLhttps://joplin.juxjux.ovh

Volumes

Source (hote)DestinationTypeMode
/home/debian/joplin-db-data/var/lib/postgresql/databindrw

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueLe container Joplin est un serveur de synchronisation (sync server), pas un serveur de notes interrogeable. Pas d'API de lecture du contenu. Le container joplin_to_obsidian est un script de migration ponctuelle vers Obsidian.

Ce que nous pouvons faire ensemble


Sauvegarde de la base de données

Sauvegarde automatique quotidienne de la base PostgreSQL joplin-db vers kDrive Infomaniak. Mise en place le 2026-06-01.

Paramètres

Script/opt/backups/vps_backup.sh
CronTous les jours à 2h du matin (0 2 * * *)
Container DBjoplin-db (PostgreSQL 15)
Commandepg_dump -U joplin -d joplin
Taille base (disque)~1.4 Go (notes + pièces jointes stockées en BLOB)
Format archive.7z (compression niveau 5)
DestinationkDrive Infomaniak — TOOJUX/jux_vps/joplin (dossier ID 1427920)
Rétention7 jours glissants
Nommage fichierjoplin_db_YYYY-MM-DD.7z

Note

La base est volumineuse (~1.4 Go) car Joplin stocke toutes les pièces jointes en BLOB dans PostgreSQL. L'archive compressée pèse ~500 Mo à 1 Go. Quota kDrive consommé : ~3.5 à 7 Go pour 7 jours.


Observatoire Joplin-Compression

Mis ? jour le 14/06/2026 12:50 ? dernier run compression : 2026-06-14T10:47

Bilan global

Ressources totales (actuelles)736 fichiers
Poids total actuel119.7 Mo
Ressources compress?es424
Poids avant compression451.5 Mo
?conomie r?alis?e356.3 Mo (-78.9%)
Ignor?es (gain insuffisant)212
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
20xh87pWrRt82z0DbO9n3yQZIP2250 KB-81%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 15/06/2026 03:00 ? dernier run compression : 2026-06-15T03:00

Bilan global

Ressources totales (actuelles)736 fichiers
Poids total actuel119.9 Mo
Ressources compress?es425
Poids avant compression452.0 Mo
?conomie r?alis?e356.4 Mo (-78.8%)
Ignor?es (gain insuffisant)212
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
20xh87pWrRt82z0DbO9n3yQZIP2250 KB-81%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 16/06/2026 03:00 ? dernier run compression : 2026-06-16T03:00

Bilan global

Ressources totales (actuelles)736 fichiers
Poids total actuel119.9 Mo
Ressources compress?es425
Poids avant compression452.0 Mo
?conomie r?alis?e356.4 Mo (-78.8%)
Ignor?es (gain insuffisant)212
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
20xh87pWrRt82z0DbO9n3yQZIP2250 KB-81%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 27/08/2026 19:34 ? dernier run compression : 2026-08-27T03:00

Bilan global

Ressources totales (actuelles)729 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 28/08/2026 03:00 ? dernier run compression : 2026-08-28T03:00

Bilan global

Ressources totales (actuelles)729 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 29/08/2026 03:00 ? dernier run compression : 2026-08-29T03:00

Bilan global

Ressources totales (actuelles)729 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 30/08/2026 03:00 ? dernier run compression : 2026-08-30T03:00

Bilan global

Ressources totales (actuelles)747 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 31/08/2026 03:00 ? dernier run compression : 2026-08-31T03:00

Bilan global

Ressources totales (actuelles)747 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 01/09/2026 03:00 ? dernier run compression : 2026-09-01T03:00

Bilan global

Ressources totales (actuelles)747 fichiers
Poids total actuel117.2 Mo
Ressources compress?es446
Poids avant compression483.2 Mo
?conomie r?alis?e383.2 Mo (-79.3%)
Ignor?es (gain insuffisant)228
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
6Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
77EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
8bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
9UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
10SrJi1UyeNGf8OhaRsaOCGqJPEG745 KB-79%
1187mV49tXupZcpt2wplcGjUJPEG685 KB-59%
12JsJFO6dIzqMKLA7clqW8nGJPEG683 KB-66%
13VSyNmO0uN1fNNeqN6XZucOJPEG674 KB-19%
14hExoJEEWT2tHz1demE5NhmJPEG674 KB-84%
15slTzAxAQ4xi0pMvzsLIDez?670 KB

Observatoire Joplin-Compression

Mis ? jour le 02/09/2026 03:00 ? dernier run compression : 2026-09-02T03:00

Bilan global

Ressources totales (actuelles)799 fichiers
Poids total actuel129.6 Mo
Ressources compress?es481
Poids avant compression501.9 Mo
?conomie r?alis?e389.7 Mo (-77.6%)
Ignor?es (gain insuffisant)229
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 03/09/2026 03:00 ? dernier run compression : 2026-09-03T03:00

Bilan global

Ressources totales (actuelles)834 fichiers
Poids total actuel133.1 Mo
Ressources compress?es484
Poids avant compression502.5 Mo
?conomie r?alis?e390.1 Mo (-77.6%)
Ignor?es (gain insuffisant)261
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 04/09/2026 03:00 ? dernier run compression : 2026-09-04T03:00

Bilan global

Ressources totales (actuelles)870 fichiers
Poids total actuel133.8 Mo
Ressources compress?es493
Poids avant compression504.0 Mo
?conomie r?alis?e391.1 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 05/09/2026 03:00 ? dernier run compression : 2026-09-05T03:00

Bilan global

Ressources totales (actuelles)872 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 06/09/2026 03:00 ? dernier run compression : 2026-09-06T03:00

Bilan global

Ressources totales (actuelles)872 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 07/09/2026 03:00 ? dernier run compression : 2026-09-07T03:00

Bilan global

Ressources totales (actuelles)872 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 08/09/2026 03:00 ? dernier run compression : 2026-09-08T03:00

Bilan global

Ressources totales (actuelles)872 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 09/09/2026 03:00 ? dernier run compression : 2026-09-09T03:00

Bilan global

Ressources totales (actuelles)872 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 10/09/2026 03:00 ? dernier run compression : 2026-09-10T03:00

Bilan global

Ressources totales (actuelles)889 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 11/09/2026 03:00 ? dernier run compression : 2026-09-11T03:00

Bilan global

Ressources totales (actuelles)889 fichiers
Poids total actuel134.7 Mo
Ressources compress?es495
Poids avant compression508.2 Mo
?conomie r?alis?e394.4 Mo (-77.6%)
Ignor?es (gain insuffisant)266
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 12/09/2026 03:00 ? dernier run compression : 2026-09-12T03:00

Bilan global

Ressources totales (actuelles)893 fichiers
Poids total actuel135.2 Mo
Ressources compress?es496
Poids avant compression510.6 Mo
?conomie r?alis?e396.5 Mo (-77.7%)
Ignor?es (gain insuffisant)269
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 13/09/2026 03:00 ? dernier run compression : 2026-09-13T03:00

Bilan global

Ressources totales (actuelles)893 fichiers
Poids total actuel135.2 Mo
Ressources compress?es496
Poids avant compression510.6 Mo
?conomie r?alis?e396.5 Mo (-77.7%)
Ignor?es (gain insuffisant)269
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 14/09/2026 03:00 ? dernier run compression : 2026-09-14T03:00

Bilan global

Ressources totales (actuelles)910 fichiers
Poids total actuel137.0 Mo
Ressources compress?es500
Poids avant compression510.8 Mo
?conomie r?alis?e396.5 Mo (-77.6%)
Ignor?es (gain insuffisant)279
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 15/09/2026 03:00 ? dernier run compression : 2026-09-15T03:00

Bilan global

Ressources totales (actuelles)917 fichiers
Poids total actuel137.5 Mo
Ressources compress?es500
Poids avant compression510.8 Mo
?conomie r?alis?e396.5 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 16/09/2026 03:00 ? dernier run compression : 2026-09-16T03:00

Bilan global

Ressources totales (actuelles)917 fichiers
Poids total actuel137.5 Mo
Ressources compress?es500
Poids avant compression510.8 Mo
?conomie r?alis?e396.5 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 17/09/2026 03:00 ? dernier run compression : 2026-09-17T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 18/09/2026 03:00 ? dernier run compression : 2026-09-18T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 19/09/2026 03:00 ? dernier run compression : 2026-09-19T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 20/09/2026 03:00 ? dernier run compression : 2026-09-20T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 21/09/2026 03:00 ? dernier run compression : 2026-09-21T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 22/09/2026 03:00 ? dernier run compression : 2026-09-22T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 23/09/2026 03:00 ? dernier run compression : 2026-09-23T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 24/09/2026 03:00 ? dernier run compression : 2026-09-24T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 25/09/2026 03:00 ? dernier run compression : 2026-09-25T03:00

Bilan global

Ressources totales (actuelles)920 fichiers
Poids total actuel138.8 Mo
Ressources compress?es503
Poids avant compression515.8 Mo
?conomie r?alis?e400.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 26/09/2026 03:00 ? dernier run compression : 2026-09-26T03:00

Bilan global

Ressources totales (actuelles)922 fichiers
Poids total actuel139.1 Mo
Ressources compress?es505
Poids avant compression518.1 Mo
?conomie r?alis?e402.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 27/09/2026 03:00 ? dernier run compression : 2026-09-27T03:00

Bilan global

Ressources totales (actuelles)922 fichiers
Poids total actuel139.1 Mo
Ressources compress?es505
Poids avant compression518.1 Mo
?conomie r?alis?e402.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 28/09/2026 03:00 ? dernier run compression : 2026-09-28T03:00

Bilan global

Ressources totales (actuelles)922 fichiers
Poids total actuel139.1 Mo
Ressources compress?es505
Poids avant compression518.1 Mo
?conomie r?alis?e402.2 Mo (-77.6%)
Ignor?es (gain insuffisant)285
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 29/09/2026 03:00 ? dernier run compression : 2026-09-29T03:00

Bilan global

Ressources totales (actuelles)931 fichiers
Poids total actuel140.2 Mo
Ressources compress?es513
Poids avant compression524.8 Mo
?conomie r?alis?e407.9 Mo (-77.7%)
Ignor?es (gain insuffisant)286
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 30/09/2026 03:00 ? dernier run compression : 2026-09-30T03:00

Bilan global

Ressources totales (actuelles)931 fichiers
Poids total actuel140.2 Mo
Ressources compress?es513
Poids avant compression524.8 Mo
?conomie r?alis?e407.9 Mo (-77.7%)
Ignor?es (gain insuffisant)286
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 01/10/2026 03:00 ? dernier run compression : 2026-10-01T03:00

Bilan global

Ressources totales (actuelles)932 fichiers
Poids total actuel140.7 Mo
Ressources compress?es513
Poids avant compression524.8 Mo
?conomie r?alis?e407.9 Mo (-77.7%)
Ignor?es (gain insuffisant)287
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%

Observatoire Joplin-Compression

Mis ? jour le 02/10/2026 03:00 ? dernier run compression : 2026-10-02T03:00

Bilan global

Ressources totales (actuelles)932 fichiers
Poids total actuel140.7 Mo
Ressources compress?es513
Poids avant compression524.8 Mo
?conomie r?alis?e407.9 Mo (-77.7%)
Ignor?es (gain insuffisant)287
Erreurs0

Top 15 ressources les plus lourdes (?tat actuel)

#IDFormatTaille actuelleGain compression
1vVO2ePdMvtty3sXZy5nY6M?3146 KB
2rHfnJYnQeGAcNgRbYPmDqNPNG1808 KB-0%
3VasIoF2e9EGuNQt38aOFMxJPEG1633 KB-66%
4TzWK21r4n0yvbEtJh02DGBJPEG1529 KB-63%
5mLOzpeA8XSX2APbtzYsus4JPEG1013 KB-26%
6M0C32hKC2hMqPAxpRGiVgpJPEG937 KB-87%
7Hn6z6lvvbJzRsX0KGM8FNWJPEG928 KB-53%
8Gz99SArqVWevqIJXe6osFPJPEG915 KB-25%
963CxmGlTsKAXd02QcxFntjJPEG897 KB-28%
10GGNUibagtNqGrPbYl7OfSQJPEG887 KB-25%
11Pz07yWDFjH1EXWXOquGEAeJPEG864 KB-31%
127EyAL9NNysJzWke6NT4ttJJPEG803 KB-76%
13bz9Twmb2F5lj0mPIQi48IBJPEG798 KB-81%
14UbAqQY3cEbH62vioIHU6PjJPEG776 KB-87%
155wpsuLJtyM19FIifc9Iz5xJPEG755 KB-26%
0_Claude et le Jux_VPS

16_Kavita

Kavita

Kavita is a fast, feature rich, cross platform reading server. Built with the goal of being a full solution for all your reading needs. Setup your own server and share your reading collection with your friends and family.

Image jvmilazz0/kavita:latest
Version latest
Etat Up (healthy)
Compose project kavita
Réseau kavita_default
URL https://kavita.juxjux.ovh
Source https://github.com/Kareadita/Kavita

Ports

Hote Container IP
5471 5000/tcp 0.0.0.0

Volumes

Source (hote) Destination Type Mode
/home/debian/docker/kavita/config /kavita/config bind rw
/home/debian/livres /manga bind rw

Integration Claude Code — MCP

Statut MCP MCP actif
Outils (prefix) mcp__kavita__
Configuration Script Python : C:\Users\eliob\.claude\mcp_kavita.py | Auth : JWT via POST /api/Account/login

Outils opérationnels (confirmés 2026-06-25)

Ce que nous pouvons faire ensemble


REX — 2026-06-25

Statistiques bibliothèque

Stat Valeur
Bibliothèques 53 (toutes de type Book/epub+PDF)
Séries 2 976
Fichiers 5 519
Volumes 1 173
Taille totale ~79 Go
Auteurs/contributeurs indexés 3 475
Genres indexés 6 990
Tags 0

Étiquettes Calibre → genres Kavita

Les étiquettes appliquées via Calibre sont visibles dans Kavita sous le champ genres, pas tags (qui reste toujours vide, totalTags: 0).

Mécanisme : Calibre écrit ses étiquettes dans <dc:subject> du fichier epub lors du writeback → Kavita lit ce champ et le mappe en genres.

Exemple confirmé — "Il faut s'adapter" (Barbara Stiegler, lib. Actualités, ID série 4210) :

Conditions pour que ça fonctionne :

La bibliothèque Actualités (ID 63) est entièrement étiquetée et correctement indexée.

Lecture du contenu

Le MCP ne permet pas de lire le contenu des livres — uniquement les métadonnées. Kavita expose des endpoints de lecture (/api/Reader/image, /api/Reader/epub-file) mais non implémentés dans le MCP. Pour les epub, la lecture via appel API direct + parsing HTML serait techniquement faisable au cas par cas.

Corrections endpoints MCP (2026-06-25)

4 outils retournaient 404 suite à des changements d'API dans la version Kavita en production. Corrections appliquées dans mcp_kavita.py :

Outil Ancien endpoint (404) Nouveau endpoint (200)
get_collections GET /api/Collection/list GET /api/Collection
get_reading_lists GET /api/ReadingList/lists?includePromoted=true POST /api/ReadingList/lists body {}
get_want_to_read POST /api/Want-To-Read/get-list POST /api/Want-To-Read
get_user_stats GET /api/Stats/user/0/read GET /api/Stats/user-stats?userId={id}

Note : le userId est désormais extrait dynamiquement du payload de login (data["id"]) et stocké dans _user_id.

Limitations MCP identifiées

Problème pipeline Calibre → Kavita — À résoudre

Constat (2026-06-25) : les fichiers enrichis par Calibre (avec étiquettes + métadonnées ISBN) ne remplacent pas les fichiers originaux dans le dossier Kavita. Kavita lit depuis le dossier source original (/manga = kDrive Sync_NAS-Maison/Foxy) qui contient les fichiers sans métadonnées.

Calibre, en mode par défaut, copie les fichiers dans sa propre arborescence et les enrichit là — les originaux restent intacts. Résultat : 98% des fichiers ont des métadonnées correctes dans Calibre, mais Kavita voit des genres vides.

Questions ouvertes à clarifier :

Piste de solution : exporter les fichiers enrichis depuis la bibliothèque Calibre vers le dossier source Kavita (via "Enregistrer sur le disque" dans Calibre), en remplacement des originaux. Peut s'automatiser. À instruire.

0_Claude et le Jux_VPS

17_Komga

komga

Imagegotson/komga
Version1.25.0
EtatUp 9 hours
Compose projectkomga
Reseaukomga_default
URLhttps://komga.juxjux.ovh
Sourcehttps://github.com/gotson/komga

Ports

HoteContainerIP
2560025600/tcp0.0.0.0
2560025600/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/komga/config/configbindrw
/home/debian/komga/databindrw
/etc/timezone/etc/timezonebindro
/tmpvolumerw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__komga__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_komga.py | Auth : Basic Auth (Base64 login:password)

Outils disponibles

Ce que nous pouvons faire ensemble


Lenteur d'affichage des pages PDF — diagnostic et correctif (2026-08-30)

Symptome : temps d'attente de 4 a 6 secondes a chaque page d'un PDF, y compris sur une page deja consultee. Decourageant a l'usage.

Ce qui n'est PAS en cause : la definition de rendu

Premier reflexe : abaisser la definition des pages. Ce n'est pas possible, et cela n'aurait pratiquement rien change.

La resolution de rasterisation des PDF est cablee en dur dans Komga, dans StaticConfiguration.kt :

@Bean("pdfResolution") fun pdfResolution(): Float = 3200F
@Bean("pdfImageType")  fun pdfImageType() = ImageType.JPEG

PdfExtractor calcule scale = 3200 / min(largeur, hauteur), soit 3200 px sur le petit cote : une page A4 sort en 3200 × 4040 = 12,9 Mpx, 0,75 a 1,4 Mo de JPEG.

Aucune propriete komga.pdf.* n'existe dans les metadonnees de configuration Spring du jar (verifie sur la 1.25.0 installee), et la documentation officielle n'expose rien de tel.

Attention — deux variables inertes dans la stack Portainer 7 : KOMGA_PDF_RENDERING_DPI=72 et KOMGA_IMAGE_QUALITY=LOW ne correspondent a aucune propriete existante. Spring les ignore en silence. Elles laissent croire a un reglage actif : ne pas s'y fier. Laissees en place le 2026-08-30 sur decision de Julien.

La vraie cause : le montage rclone etait en cache d'ecriture seule

kdrive-komga.service tournait en --vfs-cache-mode writes, qui ne met en cache que les ecritures. Chaque lecture repartait vers kDrive, indefiniment. Or PDFBox saute d'abord a la table xref en fin de fichier, puis picore les objets : plusieurs allers-retours reseau par page.

C'etait le seul montage kDrive reste en writes : music, livres, audiobooks, photo et romans etaient deja en full avec un plafond de 10G. Une exception oubliee, pas un choix.

Mesures — ou passait reellement le temps

Livre temoin : Geo 2012 - Iles de Reve.pdf, 96,8 Mo, 140 pages.

OperationResultat
Page rendue en JPEG12,9 Mpx — 4,5 a 6,0 s
Page PDF brute (aucun rendu)60 a 90 Ko — 3,8 a 4,2 s
Acces aleatoire de 1 Mo sur le montage0,52 a 0,67 s, identique a la 2e lecture
Lecture sequentielle du fichier entier84 a 111 Mo/s (97 Mo en ~1 s)

Le plancher de ~3,9 s etait commun au rendu et a la page brute : la preuve que le coupable etait l'I/O, pas la rasterisation, qui n'ajoutait que 0,6 a 2 s.

Consequence contre-intuitive : lire un fichier de 100 Mo de bout en bout (~1 s) coute moins cher que d'y picorer trois pages en acces aleatoire (~2 s). C'est le principe du prechauffage decrit plus bas.

Correctif applique le 2026-08-30

Options ajoutees a l'ExecStart de kdrive-komga.service (sauvegarde : kdrive-komga.service.bak-260830) :

--vfs-cache-mode full --vfs-cache-max-size 8G --vfs-cache-max-age 6h
--vfs-cache-poll-interval 1m --vfs-read-chunk-size 32M
--vfs-read-chunk-size-limit 512M
Avant (writes)Apres (full)
1re page d'un livre froid4,5 a 6,0 s3,4 s
Pages suivantes4,5 a 6,0 s0,69 a 0,84 s
Meme page redemandee6,0 s (aucun gain)0,99 s

Facteur 6 a 7 sur tout ce qui suit la premiere page. Les 0,7 s residuels sont la rasterisation PDFBox : le plancher est desormais le CPU du VPS, plus rien a voir avec kDrive.

Pieges a ne pas refaire

Piste non deployee : le prechauffage a l'ouverture

--vfs-cache-mode full telecharge a la demande, pas d'un bloc. Un demon peut forcer la lecture sequentielle complete des l'ouverture du livre, ce qui supprime les 3,4 s de la premiere page.

Ecrit et teste, non installe (le cache seul suffisait) : Jux-scripts/Komga-Cache/precharger_komga.py + komga-precharge.service, avec un README.md detaillant mesures, deploiement et retour arriere.

Declencheur retenu : GET /api/v1/books/{id}/manifest dans le journal nginx — appel emis par le lecteur web avant la premiere page (verifie dans le JS du webreader). Repli sur pages/1-3 pour les clients tiers. La suppression du fichier est deleguee a rclone : --vfs-cache-max-age vaut mieux qu'une suppression a la fermeture, car un livre rouvert dix minutes plus tard reste chaud.

Retour arriere

sudo cp /etc/systemd/system/kdrive-komga.service.bak-260830 \
        /etc/systemd/system/kdrive-komga.service
sudo systemctl daemon-reload
sudo systemctl restart kdrive-komga.service
sudo docker restart komga

Note : la section « Integration Claude Code — MCP » ci-dessus est perimee. Le script C:\Users\eliob\.claude\mcp_komga.py a disparu avec le profil Windows eliob ; il a ete reecrit sans dependance dans Jux-scripts/MCP/mcp_komga.py, mais n'est pas enregistre sur le poste julie (seuls bookstack et kdrive le sont).


Nouveaux fichiers invisibles de la bibliotheque — 2026-09-02

Symptome : un magazine depose (Beaux Arts de septembre 2026) n'apparait pas dans Komga, malgre plusieurs scans manuels.

Cause : le cache de listing du montage, --dir-cache-time 72h

rclone conserve la liste des fichiers d'un dossier pendant 72 h sans jamais la reverifier. Un fichier ajoute sur kDrive apres le dernier listing reste donc invisible du montage — et donc de Komga — pendant jusqu'a trois jours. Aucun scan ne peut y remedier : Komga ne voit que ce que le systeme de fichiers lui montre.

Preuve relevee le 2026-09-02 sur Arts/Beaux Arts/Beaux Arts 2026 :

VueContenu
Le montage (ls)5 fichiers, listing fige au 5 mai
kDrive en direct (rclone lsl)7 fichiers, dont deux deposes le 01/09 a 14:21

Ce n'etait pas un seul magazine : la purge du cache a fait apparaitre 20 livres d'un coup — Revue du Vin de France (juin, juillet-aout, septembre), Saveurs, Monde Gourmand × 3, Elle a Table, Cuisine et Vins, Connaissance des Arts × 4, Destination Portugal/Italie/Espagne, Beaux Arts × 3. Des mois de nouveautes.

Fausses pistes — ne pas les reprendre

Reparation immediate

kdrive-komga.service n'a pas de flag --rc : il est le seul montage rclone du VPS qu'on ne peut pas rafraichir par rclone rc vfs/refresh. Le seul moyen de purger son cache de listing est donc de redemarrer le service.

sudo systemctl restart kdrive-komga.service
ls "/home/debian/komga/Arts/Beaux Arts/Beaux Arts 2026/"   # le fichier apparait
sudo docker restart komga                                  # ancienne ref FUSE
# puis scan de chaque bibliotheque :
curl -u USER:PASS -X POST http://127.0.0.1:25600/api/v1/libraries/{id}/scan

Le cache VFS de donnees (les 8 Go sur disque) survit au redemarrage du service : seul le cache de listing, qui vit en memoire, est perdu. Rien n'est retelecharge.

Deux pieges rencontres pendant la reparation

Correctif durable — APPLIQUE le 2026-09-02

Ne pas baisser --dir-cache-time : sur un dossier de cette taille, une valeur courte provoque une instabilite permanente (kDrive ne repond pas assez vite entre deux expirations, le dossier apparait vide). 72 h reste le bon reglage — ce qui manquait, c'etait la capacite a rafraichir a la demande.

Trois actions, appliquees le 2026-09-02 :

  1. Flag --rc ajoute au montage — il en etait depourvu, seul de tous les montages du VPS (sauvegarde de l'unit : kdrive-komga.service.bak-260902) :
    --rc --rc-addr 127.0.0.1:5574 --rc-user=rcadmin --rc-pass=RcKomga2026!
    Le rafraichissement du listing prend 18 s pour 1 580 dossiers et 38 187 fichiers, sans redemarrer quoi que ce soit :
    rclone rc --rc-addr 127.0.0.1:5574 --rc-user=rcadmin --rc-pass='RcKomga2026!' \
          vfs/refresh recursive=true
  2. Regle ufw DENY 5574/tcp ajoutee. Les ports 5572, 5573, 5575, 5576 et 5577 etaient bloques depuis l'incident du 2026-06-09, mais pas 5574 — il n'existait pas encore. Les six sont desormais couverts uniformement. L'ecoute reste sur 127.0.0.1 de toute facon.
  3. Cron 45 3 * * * → Jux-scripts/Komga-Cache/komga_scan.sh : rafraichit le listing puis relance les 23 bibliotheques, avant le scan interne de Komga a 4 h, pour que celui-ci en profite aussi. Journal : /home/debian/logs/komga_scan.log. Modele repris de navidrome_scan.sh, en production depuis juin 2026.

Execution de controle : vfs/refresh 18 s, 23 scans lances, 24 s au total, code de sortie 0.

Rafraichissement immediat, quand un fichier vient d'etre depose et qu'on ne veut pas attendre la nuit :

bash /home/debian/Documents/Jux_univers/Jux-scripts/Komga-Cache/komga_scan.sh

Les identifiants du script vivent dans /home/debian/.komga_scan.env (chmod 600), hors de l'arbre Syncthing ; le script lui-meme est versionne dans Jux-scripts/ et se replique sur les 7 appareils.

Note annexe : Syncthing sur le poste julie n'avait pas detecte seul le nouveau script — les deux instances s'annoncaient idle avec 0 fichier en attente. Il a fallu forcer le scan par POST /rest/db/scan?folder=afltj-njyuy&sub=.... A garder en tete avant de conclure a une panne de synchronisation.

0_Claude et le Jux_VPS

18_Mealie

mealie

Mealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and mealie will automatically import the relevant data or add a family recipe with the UI editor

Imageghcr.io/mealie-recipes/mealie:latest
Versionv3.16.0
EtatUp 9 hours (healthy)
Compose projectmealie2
Reseaumealie2_default
URLhttps://mealie.juxjux.ovh
Sourcehttps://github.com/mealie-recipes/mealie

Ports

HoteContainerIP
99259000/tcp0.0.0.0
99259000/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/docker/mealie/backups/app/backupsbindrw
/home/debian/docker/mealie/config/app/configbindrw
/home/debian/docker/mealie/data/app/databindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__mealie__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_mealie.py | Auth : OAuth2 Bearer Token via POST /api/auth/token

Outils disponibles

Ce que nous pouvons faire ensemble


Sauvegarde de la base de données

Sauvegarde automatique quotidienne de la base SQLite de Mealie vers kDrive Infomaniak. Mise en place le 2026-06-01.

Paramètres

Script/opt/backups/vps_backup.sh
CronTous les jours à 2h du matin (0 2 * * *)
Type baseSQLite — /app/data/mealie.db (dans le container)
Méthodedocker cp mealie:/app/data/mealie.db
Taille base~2.9 Mo
Format archive.7z (compression niveau 5)
DestinationkDrive Infomaniak — TOOJUX/jux_vps/mealie (dossier ID 1427921)
Rétention7 jours glissants
Nommage fichiermealie_db_YYYY-MM-DD.7z
0_Claude et le Jux_VPS

19_Navidrome

navidrome-navidrome-1

🎧 Your Personal Streaming Service

Image deluan/navidrome:latest
Version 0.61.2
Etat Up
Compose project navidrome
Reseau navidrome_default
URL https://navidrome.juxjux.ovh
Source https://github.com/navidrome/navidrome

Ports

Hote Container IP
4533 4533/tcp 0.0.0.0

Volumes

Source (hote) Destination Type Mode
/home/debian/music /music bind rw, :shared
/home/debian/docker/navidrome/data /data bind rw

Integration Claude Code — MCP

Statut MCP MCP actif
Outils (prefix) mcp__navidrome__
Configuration Script Python : C:\Users\eliob\.claude\mcp_navidrome.py | Auth : Subsonic API avec hachage MD5 (user + token + sel)

Outils disponibles

Ce que nous pouvons faire ensemble


Scans automatiques

Trois mécanismes automatiques assurent la fraîcheur de la bibliothèque :

Cron Script Type Rôle
*/5 * * * * /home/debian/monitor-rclone.sh Watchdog Détecte FUSE mort → restart service + restart container (recovery auto)
30 4 * * * /home/debian/navidrome_scan.sh Quick scan vfs/refresh + scan quotidien (MAJ des titres existants)
0 3 * * 1 /home/debian/navidrome_fullscan.sh Full scan vfs/refresh + restart container → full scan hebdomadaire (détecte nouveaux albums/artistes)

Log commun : /var/log/navidrome_scan.log

Quick scan vs Full scan

Le quick scan (startScan via API Subsonic) ne traverse que les dossiers déjà connus de Navidrome — il ne détecte pas les nouveaux artistes ou albums ajoutés sur kDrive. Seul un full scan indexe les nouveaux dossiers.

Le full scan est déclenché automatiquement au démarrage du container. C'est pourquoi navidrome_fullscan.sh fait un restart container plutôt qu'un simple appel API.

Auth RC sur kdrive-music.service

Depuis rclone 1.74.3, vfs/refresh exige une authentification RC. Le service kdrive-music.service a été mis à jour le 2026-06-24 avec --rc-user=rcadmin --rc-pass=RcMusic2026!.

Commande de refresh manuel :

rclone rc --rc-addr 127.0.0.1:5576 --rc-user=rcadmin --rc-pass=RcMusic2026! vfs/refresh recursive=true

REX — 2026-06-24 : FUSE mort récurrent

Contexte

Le FUSE /music est mort en cours de journée. Symptôme Navidrome : stat /music: transport endpoint is not connected lors du scan.

Cause

Le service kdrive-music.service peut rester active (running) avec un FUSE mort — le process rclone est vivant mais la connexion noyau FUSE est cassée. Systemd ne détecte pas ce cas et ne redémarre pas le service.

Solution mise en place

Refactorisation de monitor-rclone.sh pour utiliser systemctl restart (au lieu d'un rclone mount direct) et redémarrer les containers Docker après remontage. Le watchdog tourne toutes les 5 minutes — la panne est détectée et corrigée automatiquement sans intervention.

Procédure manuelle si besoin

sudo systemctl restart kdrive-music.service
ls /home/debian/music | head -5
sudo docker restart navidrome-navidrome-1

Puis force-fermer Symfonium et relancer — le token de session Navidrome est invalidé après le restart du container.


REX — 2026-06-24 : nouveaux albums non détectés

Contexte

Les Négresses Vertes (et d'autres albums récemment ajoutés sur kDrive) n'apparaissaient pas dans Navidrome malgré le cron quotidien.

Cause

Double problème :

  1. Cache VFS 72h : --dir-cache-time 72h sur kdrive-music.service — les nouveaux dossiers kDrive ne sont pas visibles dans le mount avant expiration ou vfs/refresh.
  2. Quick scan insuffisant : le scan quotidien (startScan API) est un quick scan qui ne traverse que les dossiers déjà connus. Il ne détecte pas de nouveaux artistes.

Solution immédiate

rclone rc --rc-addr 127.0.0.1:5576 --rc-user=rcadmin --rc-pass=RcMusic2026! vfs/refresh recursive=true
sudo docker restart navidrome-navidrome-1

Le restart container déclenche un full scan au démarrage (~20 min pour 16 000 titres). Vérifier avec getScanStatus ("scanning":false = terminé).

Solution pérenne

Full scan hebdomadaire chaque lundi à 3h UTC (navidrome_fullscan.sh) — garantit que tout nouvel album ajouté dans la semaine est indexé au plus tard le lundi matin.


REX — 2026-06-13 : FUSE corrompu / Symfonium inaccessible

Contexte

Après l'incident sécurité rclone du 2026-06-09 (CVE-2026-41179), le service kdrive-music.service a été relancé. Il est resté actif 4 jours sans crash apparent, mais le mount FUSE /home/debian/music était silencieusement corrompu.

Symptômes

Cause

Le process rclone était vivant mais la connexion noyau FUSE était morte. Pas de crash = pas de restart automatique par systemd.

Procédure de résolution

  1. Redémarrer le service rclone : sudo systemctl restart kdrive-music.service
  2. Vérifier que le mount répond : ls /home/debian/music | head -5
  3. Redémarrer le container Navidrome — nécessaire même avec :shared, car le container garde l'ancienne référence FUSE corrompue
  4. Sur les appareils : force-fermer Symfonium et relancer

Notes

0_Claude et le Jux_VPS

20_NodeExporter

node-exporter

Imageprom/node-exporter:latest
EtatUp 9 hours
Compose projectgemini_grafana
Reseaugemini_grafana_monitor_net

Ports

HoteContainerIP
91009100/tcp0.0.0.0
91009100/tcp::

Volumes

Source (hote)DestinationTypeMode
/proc/host/procbindro
/sys/host/sysbindro
//rootfsbindro

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueExporte des métriques système (CPU, RAM, disque, réseau) au format Prometheus sur /metrics. Pas de MCP. Données consommées par Prometheus puis visualisées dans Grafana.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

21_Prometheus

prometheus

Imageprom/prometheus:latest
EtatUp 9 hours
Compose projectgemini_grafana
Reseaugemini_grafana_monitor_net
Sourcehttps://github.com/prometheus/prometheus

Ports

HoteContainerIP
90909090/tcp0.0.0.0
90909090/tcp::

Volumes

Source (hote)DestinationTypeMode
/opt/monitoring/prometheus.yml/etc/prometheus/prometheus.ymlbindro
/opt/monitoring/prometheus_data/prometheusbindrw

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueAPI REST Prometheus sur /api/v1. Requêtes PromQL via /api/v1/query et /api/v1/query_range. Pas de MCP configuré — appels directs via PowerShell/Python.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

22_Readeck

readeck

Imagecodeberg.org/readeck/readeck:latest
EtatUp 9 hours
Compose projectreadeck
Reseaureadeck_default
URLhttps://readeck.juxjux.ovh

Ports

HoteContainerIP
45678000/tcp0.0.0.0
45678000/tcp::

Volumes

Source (hote)DestinationTypeMode
/home/debian/readeck/exports/exportsbindrw
/readeckvolumerw
/home/debian/readeck/data/readeck/databindrw

Integration Claude Code — MCP

Statut MCPMCP actif
Outils (prefix)mcp__readeck__
ConfigurationScript Python : C:\Users\eliob\.claude\mcp_readeck.py | Auth : token API Bearer (MFA actif sur le compte web)

Outils disponibles

Ce que nous pouvons faire ensemble


Sauvegarde de la base de données

Sauvegarde automatique quotidienne de la base SQLite de Readeck vers kDrive Infomaniak. Mise en place le 2026-06-01.

Paramètres

Script/opt/backups/vps_backup.sh
CronTous les jours à 2h du matin (0 2 * * *)
Type baseSQLite — /readeck/data/db.sqlite3 (dans le container)
Méthodedocker cp readeck:/readeck/data/db.sqlite3
Taille base~8.5 Mo
Format archive.7z (compression niveau 5)
DestinationkDrive Infomaniak — TOOJUX/jux_vps/readeck (dossier ID 1427922)
Rétention7 jours glissants
Nommage fichierreadeck_db_YYYY-MM-DD.7z

Note

Le volume /readeck (non bindé) contient les fichiers des articles (images, HTML). La base SQLite ne couvre que les métadonnées et le texte extrait — les contenus médias ne sont pas inclus dans ce backup.


Incident résolu — pages trop lourdes rejetées (2026-08-20)

Symptôme : l'extension navigateur Readeck échouait à sauvegarder certaines pages, avec une erreur indiquant une page trop lourde.

Cause

Le vhost nginx qui sert readeck.juxjux.ovh (fichier trompeur sites-enabled/radicale.juxjux.ovh, voir plus haut) n'avait pas de directive client_max_body_size. Nginx applique alors sa limite par défaut de 1 Mo. L'extension navigateur envoie le contenu complet de la page (DOM) en POST plutôt qu'une simple URL — une page riche en images dépasse facilement ce seuil, d'où un rejet (413) que l'extension affiche comme « page trop lourde ».

Correctif

Fichiersites-enabled/radicale.juxjux.ovh
ModificationAjout de client_max_body_size 100M; dans le bloc serveur 443, juste après server_name readeck.juxjux.ovh;
Sauvegarde/home/debian/nginx-backups/radicale.juxjux.ovh.bak-260820
Vérificationsudo nginx -t puis sudo nginx -s reload, testé en conditions réelles — la sauvegarde de pages précédemment refusées fonctionne

Piège rencontré : le premier fichier de sauvegarde a été déposé par erreur dans sites-enabled/ lui-même. Comme nginx inclut sites-enabled/* sans filtrer sur l'extension, ce doublon a déclenché un warning conflicting server name. Toujours sauvegarder les fichiers de vhost en dehors de sites-enabled/ (ex. /home/debian/nginx-backups/).

Si une page dépasse encore 100 Mo, augmenter la valeur dans ce même fichier puis recharger nginx.

0_Claude et le Jux_VPS

23_Syncthing

Dernière vérification complète : 2026-08-11. Syncthing assure la synchronisation de fichiers entre le VPS Jux (hub), les postes Windows et Ubuntu, le téléphone et la tablette.

Le container sur le VPS

Imagesyncthing/syncthing:latest
Versionv2.1.2 « Hafnium Hornet » (go1.26.5, build noupgrade)
Containersyncthing — running (healthy), démarré le 2026-07-31
Politique de redémarrageunless-stopped
Projet compose33 (l'ID de stack Portainer, pas syncthing)
Réseau33_syncthing_net
URLhttps://syncthing.juxjux.ovh
Clé APIKWwkF5dD5CxeyGwFJ9ejFLHiohALysyF
Device IDHKY4MM4-3ACZXNE-PVUUI6W-4MEYOR4-SYRXXHG-F4U6EPO-OWBDE62-ZBVHJQ3
Sourcegithub.com/syncthing/syncthing

Ports

HôteContainerRôle
83848384/tcpinterface web / API REST
2200022000/tcp + udpprotocole de synchronisation (BEP)
2102721027/udpdécouverte locale

Volumes

Source (hôte)DestinationType
volume anonyme/var/syncthingvolume
/home/debian/Documents/var/syncthing/Documentsbind
/home/debian/Public/var/syncthing/Publicbind
/home/debian/docker/syncthing/config/var/syncthing/configbind
/home/debian/docker/syncthing/data1/var/syncthing/data1bind
/home/debian/docker/syncthing/data2/var/syncthing/data2bind
/home/debian/joplin-data/var/syncthing/joplin-databind

Plusieurs volumes sont montés mais un seul est réellement partagé (voir ci-dessous).


Le maillage

Un seul dossier partagé

IDafltj-njyuy
LibelléTablette VPS Syncthing
Chemin VPS/home/debian/Documents
Chemin WindowsD:\Syncthing
Typesendreceive
Contenu1 284 fichiers, 495 dossiers, 1 061 Mo

Point d'attention fréquent : Jux_univers, komga-pdf, Jux_Obsidian, Ouvrages… ne sont pas des partages Syncthing distincts — ce sont des sous-dossiers de l'unique dossier afltj-njyuy. Il n'y a rien d'autre à configurer pour qu'ils se synchronisent.

Appareils (état au 2026-08-11)

NomDevice ID (début)ÉtatDernier contact
syncthing-vpsHKY4MM4hub, toujours actif—
PC-Julien 08/2026XLNMUWSconnecté2026-08-11
XIAOMI15ProITCNNE7connecté2026-08-11
Jux_UbuntuY3FSVEFhors ligne2026-08-08
PCNexteQF2XTKMhors ligne2026-08-07
SM-T720UUB72GLhors ligne2026-07-23
NAS SASNEXTESBLUVCWhors ligne depuis 6 mois2026-01-30

Le VPS sert de hub : deux appareils qui ne se voient jamais directement restent synchronisés en passant par lui.


Le poste Windows « PC-Julien 08/2026 » (2026-08-10)

MachineDESKTOP-B7J2KGP, utilisateur julie
Device IDXLNMUWS-P23BMTA-CJPC52K-VOS733O-YGBB2QF-GDA4EI6-YH7TZGP-FENRWA2
InterfaceSyncTrayzor 2.2.0, winget GermanCoding.SyncTrayzor — le fork maintenu
Home SyncthingD:\SyncthingHome
Interface webhttp://127.0.0.1:8384 — clé API PhAm5RvM9gJEzVEosHUWp9fPg2hKLhwr
Démarrageclé HKCU:\…\CurrentVersion\Run, entrée SyncTrayzor -minimized

Trois pièges rencontrés

1. Ne pas prendre SyncTrayzor.SyncTrayzor (1.1.29). Ce paquet winget est le projet d'origine, abandonné depuis 2021 et antérieur à Syncthing 2.x. Le fork maintenu est GermanCoding.SyncTrayzor (2.2.0). Il embarque son propre syncthing.exe (v2.1.2) et le pilote.

2. Le home Syncthing ne doit pas être sous %LOCALAPPDATA% sur ce poste. Claude Code s'exécute dans un conteneur MSIX : ce qu'il écrit dans %LOCALAPPDATA% atterrit en réalité dans …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\. Le profil créé depuis une session Claude était donc invisible pour SyncTrayzor, qui a démarré sur un profil vierge — le poste est resté déconnecté du maillage sans qu'aucun message ne le signale. Symptômes : API locale en 403, plus aucune ligne écrite dans syncthing.log, appareil vu hors ligne côté VPS. Correctif : profil déplacé dans D:\SyncthingHome et <SyncthingCustomHomePath> renseigné dans %APPDATA%\SyncTrayzor\config.xml.

Get-CimInstance Win32_Process -Filter "Name='syncthing.exe'" | Select-Object CommandLine
# doit afficher --home=D:\SyncthingHome

3. Ne jamais faire tourner deux instances sur le même home. Le binaire winget Syncthing.Syncthing avait d'abord été lancé par tâche planifiée ; il a fallu l'arrêter et supprimer la tâche avant d'installer SyncTrayzor, sous peine de verrouillage de la base.

Faire rejoindre le maillage à un poste dont la copie locale est périmée

Méthode à reproduire telle quelle. Un poste qui arrive avec des fichiers vieux de plusieurs jours peut, en sendreceive, ressusciter des fichiers supprimés ailleurs et générer des conflits en série sur toutes les machines.

  1. Sauvegarder hors de l'arbre synchronisé tout fichier modifié localement (voir plus bas).
  2. Ajouter le dossier en receiveonly : l'état du maillage fait autorité, les divergences locales sont retenues sans être poussées.
  3. Attendre needFiles = 0 — ici 229 fichiers / 547 Mo rapatriés.
  4. Basculer en sendreceive : PATCH /rest/config/folders/afltj-njyuy avec {"type":"sendreceive"}.

Constaté lors de cette bascule : la synchronisation a écrasé CLAUDE.md par la version du maillage et déposé les modifications locales dans CLAUDE.sync-conflict-20260810-230652-I4M5WXU.md. Rien n'est perdu, mais il faut penser à rouvrir le fichier de conflit. Contrôle : GET /rest/db/localchanged?folder=afltj-njyuy.


Identité perdue : « PC-Elio+Jux » (supprimé le 2026-08-11)

Ce même poste Windows préexistait dans le maillage sous le nom PC-Elio+Jux (I4M5WXU-…), vu pour la dernière fois le 2026-08-07 à 22:16.

Un device ID Syncthing est sa clé privée (cert.pem / key.pem, rangés dans le home sous le profil Windows). Le profil C:\Users\eliob ayant disparu, la clé a disparu avec lui : l'identité est irrécupérable, et l'appareil ne pouvait pas être « reconnecté » — seulement remplacé par un nouvel ID. Le disque D:, lui, a survécu intact mais figé au 2026-08-06.

Leçon : sauvegarder cert.pem et key.pem hors du profil Windows si l'on tient à conserver l'identité d'un appareil au travers d'une réinstallation.

L'entrée a été retirée du VPS (appareil + liste de partage du dossier) par PUT /rest/config, après sauvegarde de la configuration complète. Elle subsiste sur les autres appareils (Xiaomi, PCNexte, SM-T720, Jux_Ubuntu, NAS), où elle apparaît hors ligne : à retirer à la main sur chacun.


Piloter Syncthing depuis Claude

Il n'y a plus de MCP Syncthing. Le script mcp_syncthing.py ne vivait que dans C:\Users\eliob\.claude\, hors périmètre Syncthing — il a disparu avec le profil. Passer par l'API REST directe, qui couvre tout ce que faisait le MCP.

Authentification : en-tête X-API-Key. Base VPS : https://syncthing.juxjux.ovh/rest. Base locale Windows : http://127.0.0.1:8384/rest.

BesoinAppel
Configuration complèteGET /config — et PUT /config pour la remplacer
Appareils connectésGET /system/connections
Dernier contact par appareilGET /stats/device
État d'un dossierGET /db/status?folder=afltj-njyuy
Divergences localesGET /db/localchanged?folder=afltj-njyuy
Appareils en attente d'acceptationGET /cluster/pending/devices
Modifier un dossierPATCH /config/folders/{id}
Identité de l'instanceGET /system/status → myID
Lancer un scanPOST /db/scan?folder={id}

Appairer un appareil sans toucher à l'interface : ajouter l'entrée dans devices et dans la liste devices du dossier, puis PUT /rest/config. C'est ainsi que « PC-Julien 08/2026 » a rejoint le maillage. L'appareil distant doit toutefois accepter le nouveau venu de son côté, sauf si un appareil introducer s'en charge.


Points de vigilance


⚠ Syncthing n'est pas une sauvegarde — corrigé le 2026-08-30

Constat de départ : le dossier afltj-njyuy est en sendreceive avec versioning = AUCUNE (vérifié par GET /rest/config/folders, aucun .stversions sur le VPS). Syncthing fait de la réplication : une suppression ou un écrasement sur l'un des 7 appareils se propage partout en quelques secondes, sans retour arrière possible. Sept copies d'un fichier effacé font zéro copie.

Ce n'était pas théorique — c'est arrivé deux fois : le CLAUDE.md écrasé par le maillage le 2026-08-10, et les 308 suppressions provoquées par un simple renommage de dossier le 2026-08-28. C'était le seul trou de l'architecture de sauvegarde : les 6 services sauvegardés chaque nuit sont des bases de données, et ~/Documents n'y figurait pas.

Ce qui a été mis en place

Un septième service dans /opt/backups/vps_backup.sh (cron 0 2 * * *), sur le modèle de backup_baikal : tar de ~/Documents → 7z -mx=1 → upload vers le dossier kDrive 1485489, rotation documents_day{1-7}.7z. Plus une copie mensuelle le 1er de chaque mois (documents_month{01-12}.7z, dossier kDrive 1486390), qui donne une année glissante de recul. Sauvegarde du script avant modification : /opt/backups/vps_backup.sh.bak-260830. Le bilan de fin de log passe de 6/6 à 7/7.

Deux garde-fous dans la fonction :

Le périmètre, mesuré le 2026-08-30

Après le rangement fait par Julien le même jour (retrait de APK temp, des conflits de komga-pdf, et déplacement de Suretés vers le NAS), l'arbre est passé de 1,6 Go à 493 Mo. Maillage cohérent : 1 267 fichiers des deux côtés, needFiles = 0, aucun .stignore.

DossierFichiersTaille
Jux_univers609380,5 Mo
Ouvrages672,1 Mo
Kobo134,4 Mo
Jux_Obsidian6493,2 Mo
Vocaux12,9 Mo
Alteris, PDF temps, komga-pdf, komga-compressed1~0

À retenir : 73 % de tout l'arbre Syncthing est le coffre Cryptomator « Vault 2603 » — 513 fichiers .c9r pour 359,5 Mo, à l'intérieur de Jux_univers. Le reste de Jux_univers (Jux-scripts, Claude-pcelio+jux, 2026, EMOA) ne pèse que 6,2 Mo. Trier cet arbre par taille ne donne donc plus rien : le seul arbitrage réel est de savoir si le coffre reste ou non dans l'arbre répliqué. Décision de Julien le 2026-08-30 : il reste, et il en existe par ailleurs une copie sur kDrive.

Seules exclusions du tar : .stfolder et .stversions, qui sont des métadonnées Syncthing. Tout le reste est sauvegardé, y compris les dossiers de transit komga-pdf et komga-compressed — un PDF qui y attend son traitement n'existe nulle part ailleurs.

Restauration — vérifiée, pas supposée

Une sauvegarde jamais restaurée n'est pas une sauvegarde. Test complet fait le jour même :

  1. archive re-téléchargée depuis kDrive — attention, curl -L obligatoire, voir la page A_liens entre Claude et le KDRIVE ;
  2. 7z t → Everything is Ok ;
  3. tar extrait : 1 760 entrées, et surtout masterkey.cryptomator bien présent — sans lui le coffre serait irrécupérable ;
  4. un fichier témoin (CLAUDE.md, 151 849 octets) extrait puis comparé à la source : identique à l'octet près.

Profondeur de rétention (2026-08-30)

Deux séries indépendantes, toutes deux sans purge — la suppression via l'API kDrive ne fonctionne pas, donc on se contente d'écraser un nom qui revient :

SérieNomReculPoids total
Quotidiennedocuments_day{1-7}.7z7 jours~3,4 Go
Mensuelledocuments_month{01-12}.7z1 an~5,9 Go

Le tar est produit par une fonction commune documents_tar(). Le 1er du mois il est construit deux fois (~33 s de plus) : les deux séries restent ainsi indépendantes, un échec de l'une n'empêchant pas l'autre. Les autres jours, la fonction mensuelle sort en succès sans rien faire, pour ne pas inscrire un faux échec au bilan.

Ce que cette sauvegarde ne couvre pas

0_Claude et le Jux_VPS

24_Yourls

yourls

Imageyourls:latest
EtatUp 9 hours
Compose projectyourls
Reseauyourls_default
URLhttps://yourls.juxjux.ovh

Ports

HoteContainerIP
808580/tcp0.0.0.0
808580/tcp::

Volumes

Source (hote)DestinationTypeMode
/var/lib/docker/volumes/yourls_yourls_plugins/_data/var/www/html/user/pluginsvolumerw
/home/debian/docker/yourls/ports.conf/etc/apache2/ports.confbindrw
/home/debian/docker/yourls/000-default.conf/etc/apache2/sites-available/000-default.confbindrw
/var/lib/docker/volumes/yourls_yourls_html/_data/var/www/htmlvolumerw
/var/lib/docker/volumes/yourls_yourls_user/_data/var/www/html/uservolumerw

yourls-db

Imagemysql:8.0
EtatUp 9 hours (healthy)
Compose projectyourls
Reseauyourls_default
URLhttps://yourls.juxjux.ovh

Volumes

Source (hote)DestinationTypeMode
/var/lib/docker/volumes/yourls_yourls_mysql_data/_data/var/lib/mysqlvolumerw

Integration Claude Code — API directe

Statut MCPPas de MCP — API directe possible
Note techniqueAPI REST Yourls sur /yourls-api.php. Auth : signature HMAC ou token. Pas de MCP configuré — appels directs possibles.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

25_StirlingPDF

stirling-pdf

Suite complète de manipulation de PDF — open source, auto-hébergée

Imagestirlingtools/stirling-pdf:latest
EtatUp (healthy)
Compose projectstirlingpdf
Reseaustirlingpdf_default
URLhttps://spdf.juxjux.ovh
Sourcehttps://github.com/Stirling-Tools/Stirling-PDF

Ports

HoteContainerIP
80908080/tcp0.0.0.0

Variables

VariableValeur
DOCKER_ENABLE_SECURITYfalse
LANGSfr_FR

Volumes

HoteContainer
/opt/stirling-pdf/configs/configs
/opt/stirling-pdf/logs/logs

Notes


Integration Claude Code

Statut MCPPas de MCP — API directe possible
Note techniqueAPI REST sur /api — scriptable via PowerShell/Python httpx.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

26_JDownloader

jdownloader

Gestionnaire de téléchargements avancé — interface web noVNC, supporte hôtes premium et lien direct

Imagejlesage/jdownloader-2:latest
EtatUp (running)
Compose projectjdownloader
Reseaujdownloader_default
URLhttps://jdownloader.juxjux.ovh
Sourcehttps://github.com/jlesage/docker-jdownloader-2

Ports

HoteContainerIP
58005800/tcp127.0.0.1

Variables

VariableValeur
USER_ID1000
GROUP_ID1000
TZEurope/Paris

Volumes

HoteContainer
/opt/jdownloader/config/config
/home/debian/downloads/output

Notes


Integration Claude Code

Statut MCPPas de MCP — interface web uniquement (noVNC)
Note techniquePas d'API REST publique documentée. Pilotage uniquement via l'interface graphique.

Ce que nous pouvons faire ensemble

0_Claude et le Jux_VPS

27 - Rustdesk

RustDesk — Serveur auto-hébergé (hbbs/hbbr)

Qu'est-ce que c'est

RustDesk est un logiciel de bureau à distance open-source (alternative à TeamViewer/AnyDesk). Il repose sur deux briques serveur :

Auto-héberger ces deux services évite de dépendre des serveurs publics RustDesk (rendezvous/relais tiers) : tout le trafic de contrôle passe par une infrastructure qu'on maîtrise.

Poids du service Docker

Élément Valeur
Image rustdesk/rustdesk-server:latest (amd64) 5,61 Mo compressée
Image (arm64) 5,2 Mo
Image (armv7) 5,04 Mo
Nombre de containers 2 (hbbs + hbbr)
RAM au repos quelques dizaines de Mo par container (binaires Rust natifs, pas de VM/interpréteur)
CPU au repos négligeable
CPU/RAM en charge dépend du nombre de sessions actives relayées par hbbr (le flux vidéo transite par lui si pas de P2P direct) — reste très léger pour un usage perso/familial (quelques sessions simultanées max)

Pour comparaison, c'est très inférieur au poids des autres containers déjà en place sur le VPS Jux (BookStack/MariaDB, Immich, etc.).

Ports requis (conditions réseau)

Port Protocole Service Rôle
21115 TCP hbbs Test de type NAT
21116 TCP + UDP hbbs UDP = enregistrement ID + heartbeat / TCP = hole punching + connexion
21117 TCP hbbr Service de relais
21118 TCP hbbs Client web (optionnel)
21119 TCP hbbr Client web (optionnel)
21114 TCP hbbs Console web — Pro uniquement, pas utile en OSS

Si le client web n'est pas utilisé, 21118/21119 peuvent rester fermés (recommandé : ces deux ports font confiance aux en-têtes X-Real-IP/X-Forwarded-For sans les valider, donc à n'exposer que derrière un reverse proxy qui les fixe lui-même, jamais en direct).

docker-compose.yml (référence officielle RustDesk)

services:
  hbbs:
    container_name: hbbs
    image: rustdesk/rustdesk-server:latest
    command: hbbs
    volumes:
      - ./data:/root
    network_mode: "host"
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: hbbr
    image: rustdesk/rustdesk-server:latest
    command: hbbr
    volumes:
      - ./data:/root
    network_mode: "host"
    restart: unless-stopped
services:
  hbbs:
    container_name: hbbs
    image: rustdesk/rustdesk-server:latest
    command: hbbs -r rustdesk.exemple.com:21117
    ports:
      - "21115:21115"
      - "21116:21116"
      - "21116:21116/udp"
      - "21118:21118"
    volumes:
      - ./data:/root
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: hbbr
    image: rustdesk/rustdesk-server:latest
    command: hbbr
    ports:
      - "21117:21117"
      - "21119:21119"
    volumes:
      - ./data:/root
    restart: unless-stopped

Variable d'environnement utile : ALWAYS_USE_RELAY=Y sur hbbs pour forcer systématiquement le passage par le relais (utile si on veut masquer les IP réelles des clients, au prix d'un peu plus de charge sur hbbr).

Clé de chiffrement et configuration client

VPS Jux vs NAS Synology sasnexte — analyse

RustDesk propose officiellement un guide d'installation Synology (DSM 6 et DSM 7.2/Container Manager), donc l'hébergement NAS est une voie supportée en soi — la question n'est pas la faisabilité technique mais la joignabilité réseau.

Critère VPS Jux (51.77.141.54) NAS sasnexte (82.66.244.248)
IP publique fixe Oui Non confirmée — SSH déjà signalé comme parfois inaccessible depuis l'extérieur (fail2ban/whitelist)
network_mode: host (recommandé Linux) Disponible (Debian) Non disponible sous DSM (Docker/Container Manager Synology tourne dans une couche réseau propriétaire) — nécessite le mapping de ports classique + redirection sur la box
Port forwarding Déjà maîtrisé (nginx, certbot, ufw) Dépend de la box du FAI, potentiellement CGNAT résidentiel
Exposition déjà en place 34 containers en prod, expérience du durcissement (incident du 9 juin 2026) Usage actuel = uniquement syncs rclone sortants vers kDrive, pas de service entrant exposé
Impact en cas d'indisponibilité VPS pro, uptime élevé Dépend de l'alimentation/connexion internet du domicile

Conclusion : le VPS reste le choix le plus robuste pour un usage "accès à distance depuis n'importe où". Le NAS serait une option seulement si l'IP publique/DDNS et le port forwarding sont déjà fiables — ce qui n'est pas le cas aujourd'hui d'après le comportement SSH observé.

Prochaine étape proposée

Ajouter la stack rustdesk sur le VPS (Portainer, comme les autres services), avec ufw restreint aux ports 21115-21119 (TCP+UDP sur 21116) et 21118/21119 fermés tant que le client web n'est pas nécessaire.

Incident client Windows — BSOD à l'installation (2026-07-31)

Contexte : installation du client RustDesk sur le PC Windows 10 (eliob). L'installation s'est terminée par plusieurs écrans bleus consécutifs.

Diagnostic

Fix appliqué

Neutralisation des deux dossiers de drivers sans désinstaller RustDesk (le contrôle à distance standard, moniteur physique branché, ne dépend pas d'eux) :

Stop-Service -Name "RustDesk" -Force
Stop-Process -Name "rustdesk" -Force -ErrorAction SilentlyContinue
Rename-Item "C:\Program Files\RustDesk\usbmmidd_v2" "usbmmidd_v2.disabled"
Rename-Item "C:\Program Files\RustDesk\drivers\RustDeskPrinterDriver" "RustDeskPrinterDriver.disabled"
Start-Service -Name "RustDesk"

Note importante : ces commandes nécessitent une session PowerShell réellement élevée (clic droit → "Exécuter en tant qu'administrateur", accepter l'UAC). Une session non élevée renvoie la même erreur Impossible d'ouvrir le service aussi bien pour Stop-Service que pour le renommage des dossiers dans Program Files — ça peut faire croire à tort qu'on est admin alors que non.

Résultat

Traversée VPS — client configuré (2026-07-31)

Le client RustDesk du PC eliob passe désormais par le serveur auto-hébergé (hbbs/hbbr sur le VPS Jux, voir plus haut) au lieu des relais publics RustDesk. Confirmé côté serveur : containers hbbs/hbbr up, ufw ouvert sur 21115-21117 (v4+v6), clé publique id_ed25519.pub en place. Tout le trafic de contrôle à distance de ce PC transite donc par une infrastructure maîtrisée plutôt que par un tiers.

0_Claude et le Jux_VPS

D_la solution contacts et calendrier

Solution d'unification des contacts et du calendrier de Julien.

État au 3 août 2026 — déployé et opérationnel de bout en bout. Seul vdirsyncer (agrégation Google/Infomaniak) reste à faire.


1. Objectif

Unifier la base de contacts et de calendriers, dispersée entre plusieurs sources (Google, Infomaniak, téléphone), autour d'un point central auto-hébergé sur le VPS juxjux.ovh, synchronisé vers tous les clients existants.

Baïkal est la source de vérité unique. Roundcube, InfCloud et DAVx5 en sont des clients ; vdirsyncer sera le seul composant qui écrit depuis l'extérieur vers Baïkal.

2. Architecture réellement déployée

Composant Rôle Emplacement État
Baïkal Serveur CardDAV + CalDAV, stockage central Docker, VPS juxjux En service
InfCloud Agenda et contacts web Statique, servi par nginx En service
Roundcube Interface web des contacts Docker, VPS juxjux En service
Nginx Reverse proxy HTTPS Hôte VPS En service
DAVx5 Pont de synchronisation vers Android Téléphone Opérationnel
Fossify Agenda Client calendrier Téléphone (via DAVx5) Opérationnel
vdirsyncer Agrège Google et Infomaniak vers Baïkal VPS, cron Non déployé
Thunderbird Client mail, indépendant de ce circuit Téléphone Inchangé

3. Accès

Service URL Identifiant
Agenda + contacts web https://baikal.juxjux.ovh/infcloud/ Julien (compte Baïkal)
Contacts web (Roundcube) https://secretariat.juxjux.ovh julien.bertrand@ik.me (compte mail Infomaniak)
Administration Baïkal https://baikal.juxjux.ovh/admin/ compte admin Baïkal
Découverte DAV (DAVx5) https://baikal.juxjux.ovh/dav.php/ Julien

Utilisateur Baïkal : Julien — avec un J majuscule. La casse compte dans les URLs DAV.

Certificats Let's Encrypt valides jusqu'au 1er novembre 2026 pour les deux domaines. Celui de baikal.juxjux.ovh existait déjà mais avait expiré le 8 février 2026 (vestige d'une tentative antérieure) ; il a été renouvelé le 3 août.

4. Déploiement

Stack sur le VPS : /home/debian/baikal/docker-compose.yml, projet compose baikal. Sources versionnées : Syncthing/Jux_univers/Jux-scripts/Baikal-Contacts/.

Fichier Rôle
docker-compose.yml Stack Baïkal + Roundcube
baikal.juxjux.ovh.conf Vhost Baïkal (.well-known forcés en HTTPS + service d'InfCloud)
secretariat.juxjux.ovh.conf Vhost Roundcube
infcloud-config.js Configuration InfCloud
finaliser_tls.sh Vérifie le DNS puis lance certbot
vps_backup.sh Script de sauvegarde complet, Baïkal inclus
push_bookstack.py Publication de cette page via l'API BookStack
cd /home/debian/baikal && sudo docker compose -p baikal up -d
Service Image Port local Base RAM
baikal ckulka/baikal:nginx 127.0.0.1:8088 SQLite ~38 Mo
roundcube roundcube/roundcubemail:latest (1.7.2) 127.0.0.1:8083 SQLite ~32 Mo
InfCloud fichiers statiques (13 Mo sur disque) — aucune 0

Les deux containers pèsent environ 70 Mo au total, contre environ 600 Mo avec l'architecture MariaDB initialement prévue. Ce choix était important : le VPS était en pression mémoire au moment du déploiement (swap à 3,8/4,0 Go).

5. Écarts avec le plan initial

Le plan préparé prévoyait une configuration qui ne pouvait pas fonctionner en l'état. Écarts constatés et corrigés :

Point Prévu Réel Raison
Port Baïkal 8081 8088 8081 est occupé par FreshRSS. 8088 correspond au vhost baikal.juxjux.ovh préexistant
Port Roundcube 8082 8083 8082 est ciblé par un vhost nextcloud mort
Domaine Roundcube mail.juxjux.ovh secretariat.juxjux.ovh Aucun DNS n'existait ; mail. prêtait à confusion avec les MX OVH du domaine
Base Roundcube MariaDB SQLite ~400 Mo de RAM économisés, suffisant en mono-utilisateur
Vhost Baïkal À créer Déjà présent Le fichier baikal.conf préparé n'a pas servi
Agenda web Plugin calendar Roundcube InfCloud Plugin inutilisable, voir §6.2

6. Pièges rencontrés

6.1 Les plugins carddav et calendar ne sont pas dans l'image Roundcube

L'image officielle ne fournit ni carddav ni calendar. Les déclarer dans ROUNDCUBEMAIL_PLUGINS ne fait que les activer — s'ils sont absents, Roundcube part en erreur fatale.

Il faut les faire installer par composer au démarrage, via ROUNDCUBEMAIL_COMPOSER_PLUGINS (et non ROUNDCUBEMAIL_INSTALL_PLUGINS, qui n'existe pas dans cette image) :

ROUNDCUBEMAIL_COMPOSER_PLUGINS: "roundcube/carddav"
ROUNDCUBEMAIL_PLUGINS: "carddav"

Le premier démarrage est alors plus long (téléchargement composer).

6.2 Le plugin calendar de Roundcube est une impasse

Trois obstacles successifs, testés le 3 août :

a) Il casse le tout premier démarrage. Le script d'initialisation de base de kolab/calendar s'exécute avant que l'entrypoint n'écrive la configuration Roundcube : il tombe sur le DSN MySQL par défaut et échoue en SQLSTATE[HY000] [2002] No such file or directory. Cette erreur fatale empêche la régénération de l'autoloader composer, ce qui casse aussi le plugin carddav :

PHP Fatal error: Uncaught Error: Interface
"MStilkerich\RCMCardDAV\Frontend\RcmInterface" not found
in /var/www/html/plugins/carddav/carddav.php:43

Symptôme : HTTP 500 permanent, alors que les fichiers du plugin sont bien présents sur le disque — c'est vendor/composer/autoload_psr4.php qui ne contient aucune entrée carddav.

b) Ce premier obstacle est contournable. Réinstallé après que Roundcube ait été initialisé une première fois, la configuration existe déjà dans le volume et l'initialisation aboutit (Creating database schema... [OK]). Vérifié.

c) Mais le plugin ne sait pas parler à Baïkal. La seule version installable, kolab/calendar 3.2.9.1, ne livre que les pilotes database, kolab et ldap — aucun pilote caldav. Il ne créerait qu'un agenda local dans Roundcube, sans lien avec Baïkal ni le téléphone : pire qu'inutile, on pourrait y saisir des rendez-vous en croyant qu'ils se synchronisent.

Les versions qui embarquent le pilote CalDAV (3.5.7, 3.6.1) dépendent de kolab/libkolab, qui réclame pear/http_request2 — paquet bloqué par composer pour faille de sécurité (PKSA-jrt3-xndd-g4sz). Ne pas contourner ce garde-fou sur un service exposé sur internet.

Conclusion : agenda web assuré par InfCloud (§7), plugin calendar définitivement écarté.

6.3 Baïkal ignore X-Forwarded-Proto — fuite HTTP sur la découverte

Baïkal ne tient pas compte de X-Forwarded-Proto et générait ses redirections de découverte en HTTP nu :

/.well-known/carddav -> http://baikal.juxjux.ovh/dav.php

C'est exactement le risque identifié dès la conception : CardDAV et CalDAV envoient les identifiants à chaque synchronisation. Un client suivant cette redirection part sur du HTTP.

Corrigé en court-circuitant Baïkal directement dans le vhost :

location = /.well-known/carddav {
    return 301 https://$host/dav.php/;
}
location = /.well-known/caldav {
    return 301 https://$host/dav.php/;
}

À vérifier après tout reload nginx : le rechargement n'est pas instantané, un test lancé dans la foulée peut encore montrer l'ancien comportement.

6.4 Roundcube exige un serveur IMAP pour authentifier

Roundcube n'a pas de base d'utilisateurs propre : son écran de login valide les identifiants contre le serveur IMAP configuré. Sans IMAP joignable, aucune connexion n'est possible — donc aucun accès aux contacts non plus.

L'idée d'un Roundcube « contacts et agenda seulement, sans IMAP » n'est pas réalisable. La configuration retenue pointe vers ssl://mail.infomaniak.com:993, ce qui couvre le compte julien.bertrand@ik.me (le domaine ik.me est servi par l'infrastructure Infomaniak).

Si un jour le compte passe en double authentification, il faudra générer un mot de passe d'application Infomaniak.

6.5 Baïkal doit être installé en SQLite

L'installeur Baïkal propose MySQL ou SQLite. Choisir SQLite : la stack ne contient aucun serveur MySQL, cocher « Enable MySQL » mène à une impasse. Base à /var/www/baikal/Specific/db/db.sqlite, dans le volume baikal-data.

7. InfCloud — l'agenda web

Client CalDAV/CardDAV entièrement côté navigateur : aucun backend, aucune base, du HTML/JS servi en statique par nginx. Affiche agenda et contacts.

Réserve assumée : projet figé depuis 2015, interface datée, embarque jQuery 2.1.4. Acceptable parce qu'il n'a aucun composant serveur : rien à maintenir, rien à patcher. La seule alternative maintenue serait SOGo, au prix d'environ 500 Mo de RAM et d'une base PostgreSQL.

7.1 Les trois pièges d'InfCloud

a) Le bloc regex du vhost avale tous les JS. Le vhost Baïkal contient déjà :

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { proxy_pass http://127.0.0.1:8088; }

En nginx, un bloc regex ~* a priorité sur un bloc préfixe ordinaire. Tous les fichiers JavaScript d'InfCloud auraient donc été proxifiés vers Baïkal. Comme InfCloud est presque intégralement du JavaScript, la page serait restée blanche — symptôme difficile à diagnostiquer. Il faut ^~, qui passe devant les regex :

location ^~ /infcloud/ {
    alias /home/debian/baikal/infcloud/;
    index index.html;
    location ~ /\. { deny all; }
}

b) L'endpoint par défaut vise DAViCal. Le config.js livré pointe /caldav.php/ ; Baïkal expose /dav.php/.

c) Le href doit viser les principals, pas la racine DAV. InfCloud accole le nom d'utilisateur au href. Avec /dav.php/ il demandait /dav.php/Julien/ → 404. La documentation du fichier le précise : « globalNetworkCheckSettings : principal URL WITHOUT the USER/ part ». Chez Baïkal, la bonne valeur est donc :

'/dav.php/principals/',

Après toute modification de config.js, rechargement forcé du navigateur (Ctrl+Maj+R) : le fichier est mis en cache.

7.2 Digest → Basic : le blocage d'authentification

Baïkal était configuré en dav_auth_type: Digest et annonçait WWW-Authenticate: Digest realm="BaikalDAV".

InfCloud ne sait faire que du Basic. Ses requêtes partaient donc en 401 en boucle, alors que DAVx5 — qui gère Digest — fonctionnait parfaitement avec le même compte. Le symptôme prêtait à confusion : les identifiants étaient bons.

Diagnostic par les logs nginx, où le champ utilisateur est renseigné mais la réponse reste 401 :

83.195.45.93 - Julien "PROPFIND /dav.php/ HTTP/2.0" 401

Correctif : dav_auth_type: Basic dans /var/www/baikal/config/baikal.yaml, puis docker restart baikal.

Ce n'est pas un pis-aller. Digest repose sur MD5, est considéré comme obsolète, et impose au serveur de stocker une empreinte exploitable ; Basic sur TLS est aujourd'hui la recommandation, et tout est en HTTPS ici, y compris les redirections de découverte (§6.3).

Les mots de passe restent valides : Baïkal calcule la même empreinte md5(username:auth_realm:password) dans les deux modes (Baikal\Core\PDOBasicAuth::validateUserPass), avec auth_realm: BaikalDAV conservé en interne — même si le serveur annonce désormais realm="sabre/dav" côté client. Rien à redéfinir, DAVx5 bascule tout seul.

Sauvegarde : /var/www/baikal/config/baikal.yaml.bak-260803-digest (dans le container).

8. Sauvegarde

Baïkal a été ajouté à /opt/backups/vps_backup.sh le 3 août 2026 (cron quotidien à 2h UTC).

La fonction archive deux volumes, via un tar intermédiaire puis 7z :

Sans le second, la restauration est incomplète. Testée le 3 août : upload HTTP 200, aucun résidu temporaire.

InfCloud n'a pas besoin d'être sauvegardé (fichiers statiques réinstallables), mais son config.js est versionné dans Jux-scripts/Baikal-Contacts/.

9. Vérifications effectuées le 3 août 2026

Test Résultat
GET /dav.php/ HTTP 401 — authentification bien exigée
PROPFIND /dav.php/ HTTP 401 et non 405 — nginx laisse passer les méthodes DAV étendues
.well-known/carddav et caldav 301 vers HTTPS
Installation Baïkal Utilisateur Julien, carnet et calendrier default créés
Login Roundcube IMAP Infomaniak accepté
Découverte CardDAV Roundcube Carnet résolu à .../dav.php/addressbooks/Julien/default/
Écriture d'un contact vCard 3.0 écrite par RCMCardDAV v5.1.3, relue dans Baïkal, accents UTF-8 préservés
Synchronisation DAVx5 5 rendez-vous d'août écrits dans Baïkal par DAVx5/4.5.18-ose, synctoken du calendrier à 6
InfCloud 32 ressources servies en 200 ; PROPFIND sur principals, addressbooks et calendars tous en 207
Dotfiles InfCloud .htaccess bloqué en 403
Sauvegarde Baïkal Archive uploadée sur kDrive, HTTP 200

Note : dans la table carddav_addressbooks de Roundcube, une seconde ligne nommée %N avec une URL vide n'est pas une erreur — c'est le template de rcmcarddav v5, qui porte les réglages appliqués aux carnets découverts.

10. Reste à faire

10.1 vdirsyncer — agrégation Google et Infomaniak

Seule brique du plan initial encore absente. Objectif : faire remonter dans Baïkal les contacts existants sur Google et Infomaniak, pour que Baïkal devienne le point central réel et pas un silo de plus.

Décision à prendre avant déploiement :

Recommandation : démarrer en one-way le temps de vérifier que l'import est fidèle, puis basculer si besoin.

10.2 Nettoyage

Quatre vhosts morts traînent dans /etc/nginx/sites-enabled/, vestiges des tentatives précédentes : radicale, agendav, infcloud, nextcloud. Le dernier cible le port 8082, ce qui a contraint le choix du port de Roundcube. Attention : le vhost nommé radicale.juxjux.ovh sert en réalité Readeck — ne pas le supprimer sans vérifier.

11. Checklist sécurité

12. Commandes utiles

# État de la stack
sudo docker ps --filter name=baikal --filter name=roundcube

# Logs
sudo docker logs roundcube --tail 50
sudo docker logs baikal --tail 50

# Redéployer
cd /home/debian/baikal && sudo docker compose -p baikal up -d

# Inspecter la base Baïkal
sudo docker cp baikal:/var/www/baikal/Specific/db/db.sqlite /tmp/bk.sqlite
sudo sqlite3 /tmp/bk.sqlite "SELECT COUNT(*) FROM cards;"
sudo sqlite3 /tmp/bk.sqlite "SELECT COUNT(*) FROM calendarobjects;"
sudo sqlite3 /tmp/bk.sqlite "SELECT id, username FROM users;"

# Méthode d'authentification annoncée par Baïkal
curl -s -D - -o /dev/null -X PROPFIND -H 'Depth: 0' \
  https://baikal.juxjux.ovh/dav.php/ | grep -i www-authenticate

# Suivre les requêtes DAV des clients (DAVx5, InfCloud, Roundcube)
sudo tail -f /var/log/nginx/access.log | grep dav.php

# Vérifier la découverte DAV
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" \
  https://baikal.juxjux.ovh/.well-known/carddav

13. Choix d'architecture — pourquoi ces outils

Radicale écarté : stockage fichier brut, pas de vraie gestion. La stack Radicale/InfCloud initialement envisagée n'a pas été mise en place — seul InfCloud a finalement été retenu, en client de Baïkal.

Nextcloud écarté : trop lourd pour l'usage visé (PHP-FPM + base + Redis + écosystème complet), alors que le VPS fait déjà tourner PostGIS, Metabase, BookStack, FreshRSS.

Baïkal retenu : léger, CardDAV et CalDAV natifs, interface d'administration suffisante. Développé par des bénévoles sous l'organisation sabre-io (mainteneurs de SabreDAV, la librairie sous-jacente) — pas de société commerciale derrière, mais communauté active et outil robuste pour un usage personnel sur la durée.

Roundcube retenu comme interface de saisie des contacts, Baïkal n'ayant pas de vraie UI de consultation : léger, traduit en français, projet actif (version 1.7.2 en août 2026). A rejoint la famille Nextcloud en 2023 tout en restant indépendant, sous licence GPL. Réserves constatées à l'usage : il impose une authentification IMAP (§6.4) et ne couvre pas l'agenda (§6.2).

InfCloud retenu pour l'agenda web : sans backend, donc sans coût mémoire ni surface d'attaque serveur, et couvre agenda et contacts. Ancien mais fonctionnel.

SOGo envisagé et écarté : suite complète et maintenue, mais environ 500 Mo de RAM et une base PostgreSQL sur un VPS déjà en pression mémoire, et il aurait fait doublon avec Roundcube.

Thunderbird containerisé (VNC/noVNC) envisagé puis écarté : fonctionnel mais plus lourd et moins adapté au multi-accès qu'un vrai webmail.

0_Claude et le Jux_VPS

E_la gestion du SWAP du VPS par Claude

REX 260803 — Session Claude sur le VPS Jux

Session du 2026-08-02 (soir) au 2026-08-03 (matin). Quatre chantiers, tous appliqués et vérifiés. Le sujet principal de cette page — le swap — est traité en partie 1 ; les autres chantiers suivent car ils s'expliquent mutuellement (l'allègement JVM est ce qui a fait apparaître la question du swap).

# Chantier État Gain / résultat
1 Swap saturé à 95 % Résolu 4 Go → 8 Go, swappiness 60 → 10
2 Allègement JVM Komga + StirlingPDF Appliqué Komga −292 Mio (−41 %), Stirling borné à 2 Go
3 OCR StirlingPDF impossible sur PNG Résolu Cause trouvée + script de contournement
4 Connexion Claude Code sur le VPS Alteris Résolu Identifiants recopiés depuis le VPS Jux

1. Swap saturé — le vrai diagnostic

Symptôme

Swap à 3,8 / 4,0 Go (95 %), alors que ~4,6 Gi de RAM restaient disponibles. Il se remplissait nuit après nuit et ne se vidait jamais.

Ce que ce n'était PAS

Un manque de mémoire. vmstat 2 3 montrait si/so ≈ 0 : aucun thrashing, rien ne ramait. C'est le point contre-intuitif de ce diagnostic — un swap plein n'est pas synonyme de machine à genoux.

Le risque réel était ailleurs : il ne restait que 253 Mio de swap libre. En cas de pic, l'OOM killer aurait commencé à tuer des containers.

Cause

vm.swappiness = 60 (valeur par défaut). Pendant les batchs de nuit — backup 2h, scan Komga 4h (230 lignes de scan cette nuit-là), scans Audiobookshelf 4h et Navidrome 4h30 — le noyau préférait pousser les pages anonymes des applications vers le swap plutôt que de réclamer son cache de pages.

Une fois en swap, ces pages n'en ressortent jamais d'elles-mêmes : elles n'y reviennent que si le processus les retouche. D'où une accumulation qui ne fait que croître, nuit après nuit.

Fixes appliqués

a) vm.swappiness = 10, persisté dans /etc/sysctl.d/99-swap.conf. Le noyau réclame désormais son cache de pages avant de swapper. C'est ce qui empêche l'accumulation de recommencer.

b) Second fichier de swap /swapfile2 de 4 Go → swap total 8 Go, persisté dans /etc/fstab (sauvegarde : /etc/fstab.bak-260803), validé par sudo swapon -a pour garantir un redémarrage sûr.

Méthode choisie délibérément : ajouter un second fichier évite tout swapoff, donc tout risque. Un swapoff -a aurait dû recharger 3,8 Go dans 4,6 Go disponibles — faisable mais serré, plusieurs minutes d'I/O intense, et un pic pendant l'opération aurait pu faire tuer un container.

État après intervention

Avant Après
Swap total 4,0 Go 8,0 Go
Swap libre 253 Mio 4,2 Go
vm.swappiness 60 10
Disque libre 39 Go 35 Go

Ce qui reste

Les 3,8 Go de pages froides restent en swap. C'est assumé : elles ne coûtent rien en performance et se libéreront au fil des redémarrages. Un docker restart libère instantanément le swap du container concerné.

Top détenteurs au 2026-08-03 : komga 954 Mio, yourls-db 389, stirling-pdf 354, Immich-SERVER 212, Immich-DB 197, mealie 189, Kavita 158, jellyfin 131.

Le redémarrage de Komga rendra donc presque un giga à lui seul.

Commandes de diagnostic

swapon --show                      # taille et occupation de chaque zone
vmstat 2 3                         # si/so : y a-t-il un swap ACTIF ?
cat /proc/sys/vm/swappiness

Swap par container :

cat /sys/fs/cgroup/system.slice/docker-$(docker inspect NOM --format '{{.Id}}').scope/memory.swap.current

Swap par processus :

for p in /proc/[0-9]*; do s=$(awk '/^VmSwap:/{print $2}' $p/status 2>/dev/null); \
  [ -n "$s" ] && [ "$s" -gt 0 ] && echo "$s $(tr -d '\0' < $p/cmdline | cut -c1-60)"; done | sort -rn | head

À surveiller

Le lendemain matin, après une nuit de batchs : si le swap utilisé a peu bougé, swappiness=10 a fait son travail. S'il remonte malgré tout, la piste suivante est de réduire les consommateurs réels plutôt que de rejouer sur les réglages noyau.


2. Allègement JVM Komga + StirlingPDF

Appliqué le 2026-08-02 à 22h, après vérification du backup quotidien (BILAN 5/5 OK).

Service Avant Après Résultat
Komga (stack 7) -Xmx4g -Xms2g -XX:MaxRAMPercentage=70.0, limits 4500M / reservations 3000M, 707 Mio -Xmx1g, limits 1500M / reservations 256M 415 Mio (−292, −41 %)
StirlingPDF (stack 89) JVM sans limite, 722 Mio -Xmx512m, limits 2g 785 Mio — pas de réduction

Bilan hôte : swap 3,7 → 2,2 Go juste après l'opération, mémoire disponible 4,4 → 4,6 Gi. L'essentiel du gain vient de Komga : c'est le -Xms2g qui pré-allouait 2 Go de heap au démarrage.

Pourquoi StirlingPDF ne baisse pas

À dire franchement plutôt que de maquiller le résultat : le process java conserve 799 Mio de RSS malgré -Xmx512m. Le heap n'est qu'une partie du total (metaspace, code cache, piles de threads), et Stirling lance en plus LibreOffice (soffice.bin, ~98 Mio), unoserver et Xvfb pour ses conversions.

Le bénéfice obtenu n'est pas une baisse mais un plafond : la consommation ne peut plus déborder, alors qu'elle était non bornée.

La limite portée de 1 Go à 2 Go — décision critique

Le plan initial prévoyait 1 Go. Il a été corrigé avant application, grâce au chantier OCR mené le même jour : l'OCR fait tourner ocrmypdf et tesseract comme processus Python, hors JVM. -Xmx ne les borne pas — seul le plafond cgroup du container s'applique.

Pic mesuré : 894 à 969 Mio pour une seule page A4 300 dpi. Un plafond de 1 Go aurait provoqué un OOM kill dès le premier OCR. La version 1 Go est conservée en /home/debian/stirling-compose-new.yml.orig1g mais ne doit pas être utilisée.

Vérifications après déploiement

Piège de déploiement

Les projets compose s'appellent 7 et 89 — les IDs de stack Portainer — et non komga / stirlingpdf. La procédure documentée initialement aurait échoué dessus.

sudo docker compose -p 7 -f /var/lib/docker/volumes/portainer_data/_data/compose/7/docker-compose.yml up -d

3. OCR StirlingPDF impossible sur les images PNG

Symptôme

HTTP 500 sur tout OCR d'image PNG. L'interface web n'affiche aucun détail exploitable — le diagnostic passe obligatoirement par docker logs stirling-pdf.

Deux refus cumulés d'ocrmypdf 17.4.0

  1. UnsupportedImageFormatError: The input image has an alpha channel. — tout PNG avec transparence
  2. Une fois l'alpha retiré, un second blocage apparaît : DpiError: Input file is an image, but has no resolution (DPI) in its metadata. StirlingPDF ne transmet pas --image-dpi à ocrmypdf

Le point à retenir : les erreurs sont séquentielles. Corriger la transparence seule ne suffit pas, le DPI bloque juste après — ce qui explique pourquoi aucun réglage de l'interface ne pouvait s'en sortir.

Solution sans outil (interface web)

Convert → Image to PDF, puis OCR sur le PDF obtenu. Les deux problèmes disparaissent puisque l'entrée n'est plus une image. Validé en test, HTTP 200.

Solution scriptée

Jux-scripts/Stirling-OCR/ocr_image.py — aplatit l'alpha sur fond blanc et force 300 dpi avant envoi.

py "D:\Syncthing\Jux_univers\Jux-scripts\Stirling-OCR\ocr_image.py" mon_image.png

Accepte un fichier ou un dossier. Options : -l fra+eng, -o sortie.pdf, --dpi 400, --skip-text. Testé depuis le PC Windows et depuis le VPS ; texte restitué à l'identique.

Chemin sur le VPS : /home/debian/Documents/Jux_univers/Jux-scripts/ (et non ~/Syncthing/...).

Détails techniques


4. Connexion Claude Code sur le VPS Alteris

Symptôme

Au lancement de claude en SSH (PuTTY / CMD / PowerShell), Claude Code demande de se connecter et affiche une URL. Impossible de la copier : Ctrl+C, clic droit, rien ne fonctionnait. La mention verte « copied » s'affichait pourtant.

Cause

Le « copied » venait de Claude Code tournant sur le VPS : il copiait l'URL dans le presse-papier du serveur Linux, qui n'a aucun lien avec celui du PC Windows à travers SSH. Le presse-papier Windows restait donc vide, d'où le collage à blanc dans le navigateur.

À noter au passage : dans un terminal SSH, Ctrl+C envoie un signal d'interruption au programme — il peut tuer le processus de login au lieu de copier.

Cause réelle du re-login

Le fichier ~/.claude/.credentials.json d'Alteris avait expiresAt: 0 — jeton invalide. Le VPS Jux, lui, disposait d'identifiants sains (compte Pro, refresh token valide).

Solution retenue

Recopier les identifiants depuis le VPS Jux, commande lancée depuis Alteris :

scp debian@51.77.141.54:.claude/.credentials.json ~/.claude/.credentials.json && chmod 600 ~/.claude/.credentials.json

Vérifié : 504 octets, permissions 600, jeton complet. Claude Code ne redemande plus de login et rafraîchit le token seul au démarrage (l'access token expiré n'est pas un problème, le refresh token est valide).

Conséquence : les deux VPS partagent désormais le même jeu d'identifiants. Si l'un redemande un login, refaire le même scp depuis celui qui fonctionne encore.

Alternative si les deux tombent : claude setup-token depuis le PC Windows (le navigateur s'ouvre en local), puis export CLAUDE_CODE_OAUTH_TOKEN=... dans le ~/.bashrc du serveur.


5. Découverte annexe — port PostgreSQL 5432 bloqué sur Alteris

publier_recherche.py échoue sur sa partie PostgreSQL : Connection timed out (10060).

Contournement sans toucher au pare-feu — exécuter le SQL en local sur Alteris :

pscp fichier.sql debian@79.137.14.202:/tmp/
sudo docker cp /tmp/fichier.sql alteris_postgis:/tmp/i.sql
sudo docker exec alteris_postgis psql -U alteris_admin -d alteris_geo -f /tmp/i.sql

Rouvrir le port exposerait à nouveau une base de données directement sur internet. Décision à prendre sciemment, surtout après l'incident du 2026-06-09.


Fichiers, sauvegardes et rollbacks

Élément Chemin Rôle
Compose Komga (avant) /var/lib/docker/volumes/portainer_data/_data/compose/7/docker-compose.yml.bak-260802 Rollback Komga
Compose Stirling (avant) /var/lib/docker/volumes/portainer_data/_data/compose/89/docker-compose.yml.bak-260802 Rollback Stirling
Version Stirling 1 Go /home/debian/stirling-compose-new.yml.orig1g Ne pas utiliser (OOM sur OCR)
fstab (avant) /etc/fstab.bak-260803 Rollback swap
Réglage swappiness /etc/sysctl.d/99-swap.conf vm.swappiness = 10
Second swap /swapfile2 (4 Go) Marge de swap
Script OCR Jux-scripts/Stirling-OCR/ocr_image.py + README.md Contournement OCR images

Rollback JVM : restaurer le .bak-260802 de la stack et redéployer avec sudo docker compose -p {7|89} -f ... up -d.


Références

01_Les recherches de Claude

Pages de publication des résultats d'analyse et de production de Claude Code sur le contenu du VPS

01_Les recherches de Claude

01A_Kdrive_les explorations

RCH-20260529-0003 — Livres et ressources evoquant la ville de Genes dans Foxy

Date2026-05-29
ServicekDrive Infomaniak
ContexteConstituer un corpus documentaire autour de Genes (Genovese, Ligurie) dans la bibliotheque kDrive — dossier SYNC-pour_VPS/Sync_NAS-Maison/Foxy
Outils utilisésAPI REST Infomaniak kDrive v3 — search + metadata v2 | PowerShell
RequêteGET /3/drive/591617/files/search?query={Genes|Genova|Genovese|Genoa|Ligurie}&limit=20 | filtre manuel sur résultats

Résultats

3 livres directement sur Gênes (la ville), 1 presentation Ligurie, des photos de Ligurie (2011), et des recettes genovese (cuisine). Recherche couvrant les termes : Genes, Genova, Genovese, Genoa, Ligurie.

Points clés

Limites

L'API v2 ne retourne pas le chemin (path) des fichiers — impossible de localiser précisément le sous-dossier sans navigation manuelle. Le champ path est vide dans la réponse.

Localisation des ressources

URLs—
Chemins["kDrive 591617 / Private (5) / SYNC-pour_VPS (534292) / Sync_NAS-Maison (534293) / Foxy (401926) / [sous-dossier inconnu]"]
IDs{"531552": "Antoine-Marie Graziani - Histoire de Genes.epub (5.2 MB)", "531550": "Histoire de de Genes - Histoire.epub (0.8 MB)", "531549": "Histoire de la République de Gênes - Emile Vincens - Histoire.epub (0.9 MB)", "501392": "210526-Ligurie.pptx (31.9 MB)"}
Auteurs / Source["Antoine-Marie Graziani (Histoire de Genes)", "Emile Vincens (Histoire de la République de Gênes)"]
Métadonnées{"formats": ["epub", "pptx", "jpg", "mp4"], "livres_genes": 3, "photos_ligurie": 20, "videos_recettes_genovese": 2, "dossier_foxy_id": 401926, "kdrive_id": 591617}

Tags

#Genes   #Gênes   #Ligurie   #Italie   #histoire   #kDrive   #epub   #bibliotheque

Suite / Pistes

1/ Explorer le dossier Culture Italie (ID:1185062) pour trouver d'autres ressources sur Genes. 2/ Verifier dans Calibre (ID:1211295) si des livres Genes y sont catalogues. 3/ Corriger l'API v2 pour obtenir le chemin des fichiers (utiliser /3/ au lieu de /2/). 4/ Croiser avec Kavita si ces epubs y sont importes.


RCH-20260529-0004 — Approfondissement corpus Gênes — Culture Italie et Bibliotheque Calibre

Date2026-05-29
ServicekDrive Infomaniak
ContexteSuite de RCH-20260529-0003. Explorer Culture Italie (ID:1185062) et Bibliotheque Calibre (ID:1211295) pour compléter le corpus #Genes.
Outils utilisésAPI REST kDrive v3 — navigation par ID + listing sous-dossiers | PowerShell
RequêteGET /3/drive/591617/files/{1185194|1185151|1185105|1185085|1211295}/files?limit=100 + filtres regex Genes/Ligurie

Résultats

Culture Italie contient un dossier Ligurie (Cuisine Italie/Ligurie) avec 2 fichiers. Calibre contient Graziani mais uniquement pour Pascal Paoli (Corse), pas Genes. Vincens absent de Calibre. Plusieurs livres sur l'Italie générale potentiellement exploitables.

Points clés

Limites

Calibre n'a pas les livres sur Gênes de Vincens et de la version anonyme. Seul Graziani y est mais pour un autre ouvrage. Les 3 epubs Genes sont uniquement dans Foxy, non indexés dans Calibre. La recherche ne couvre pas les sous-sous-dossiers de Calibre (trop nombreux).

Localisation des ressources

URLs—
Chemins["Foxy/Culture Italie/Cuisine Italie/Ligurie", "Foxy/Culture Italie/Histoire Italie", "Foxy/Culture Italie/Art de vivre Italie", "Foxy/Bibliotheque Calibre/Antoine-Marie Graziani"]
IDs{"1185345": "Dossier Ligurie dans Cuisine Italie", "1185347": "210526-Ligurie.pptx (31.9 MB) — dans Cuisine Italie/Ligurie", "1185349": "IMG_3782.pdf — dans Cuisine Italie/Ligurie", "1362307": "Calibre/Antoine-Marie Graziani (Pascal Paoli — pas Gênes)", "1185194": "Histoire Italie (4 livres generaux)", "1185085": "Art de vivre Italie (5 ressources)", "1185201": "L'Italie de Botticelli à Bonaparte.epub", "1185199": "Les guerres d'Italie — Un conflit européen.epub", "1185196": "Bella Italia - Un itinéraire amoureux (Christiane Rance).epub", "1185090": "Sacrés Italiens (Alberto Toscano).epub", "1185089": "Portraits d'Italie (Laurent Bolard).epub", "1185087": "Geo Hors-Serie Dolce Vita Avril-Mai 2025.pdf"}
Auteurs / Source—
Métadonnées{"corpus_genes_directs": 3, "ressources_ligurie": 2, "livres_italie_generale": 9, "calibre_graziani_titre": "Pascal Paoli - Pere de la patrie corse", "vincens_dans_calibre": false}

Tags

#Genes   #Genes   #Ligurie   #Italie   #Calibre   #kDrive   #Culture Italie   #histoire

Suite / Pistes

1/ Importer les 3 epubs Genes (IDs 531549-531552) dans Calibre pour les indexer. 2/ Lire le PPTX Ligurie (ID:1185347) pour en extraire le contenu. 3/ Explorer 'Bella Italia' et 'Les guerres d'Italie' pour mentions de Genes. 4/ Rechercher 'Genes' dans le dossier Histoire (ID:503138) de Foxy.


01_Les recherches de Claude

01_Portainer - les explorations

Journal des recherches réalisées avec Claude Code sur le service Portainer.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/152
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

02_Bookstack_les explorations

Journal des recherches réalisées avec Claude Code sur le service Bookstack.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/153
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

03_Homarr_les explorations

Journal des recherches réalisées avec Claude Code sur le service Homarr.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/154
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

04_Audiobookshelf_les explorations

Journal des recherches réalisées avec Claude Code sur le service Audiobookshelf.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/155
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

05_BentoPDF_les explorations

Journal des recherches réalisées avec Claude Code sur le service BentoPDF.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/156
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

06_Cadvisor_les explorations

Journal des recherches réalisées avec Claude Code sur le service Cadvisor.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/157
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

07_Calibre-web_les explorations

Journal des recherches réalisées avec Claude Code sur le service Calibre-web.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/158
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

08_Dozzle_les explorations

Journal des recherches réalisées avec Claude Code sur le service Dozzle.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/159
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

09_FileBrowser_les explorations

Journal des recherches réalisées avec Claude Code sur le service FileBrowser.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/160
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

10_FreshRSS_les explorations



RCH-20260529-0002 — Articles Inkscape dans la categorie claude_foss

Date 2026-05-29
Service FreshRSS
Contexte Second passage apres creation de la categorie claude_foss et ajout du flux Inkscape News. Verifier si des articles sur Inkscape sont desormais indexes.
Outils utilisés API GReader FreshRSS directe — stream/contents/user/-/label/claude_foss — search_foss.py
Requête GET /reader/api/0/stream/contents/user/-/label/claude_foss?n=100&q=Inkscape

Résultats

100 articles retournes depuis la categorie claude_foss (7 flux). 10 articles provenant du flux Inkscape News (feed/615) sont presents. Note : le parametre q= de l'API GReader ne filtre pas reellement par mot-cle — il retourne tous les articles du stream. Le filtrage Inkscape est donc a faire cote client.

Points clés

Limites

Le parametre q= de l'API GReader FreshRSS ne filtre pas par mot-cle. Pour une recherche thematique precise, il faut recuperer tous les articles et filtrer cote client sur title + content. A corriger dans search_foss.py.

Localisation des ressources

URLs ["https://inkscape.org/news/2026/05/13/inkscape-supports-german-petition-to-recognize-ope/", "https://inkscape.org/news/2026/05/06/inkscape-144-boosts-performance-and-crushes-crashe/", "https://inkscape.org/news/2026/04/02/artist-interview-meet-jorge-who-made-a-short-film/", "https://inkscape.org/news/2026/03/02/inkscape-is-hiring-2026-1/", "https://inkscape.org/news/2025/12/26/bugs-banished-inkscape-143-is-out/", "https://inkscape.org/news/2025/10/12/indiafoss-2025/", "https://inkscape.org/news/2025/06/08/libre-graphics-meeting-2025/", "https://inkscape.org/news/2025/06/01/inkscape-summit-nuremberg/", "https://inkscape.org/news/2025/05/12/2-in-1-release-inkscape-142-is-out/", "https://inkscape.org/news/2025/02/05/inkscape-summit-frankfurt-2025/"]
Chemins —
IDs ["feed/615 (Inkscape News)", "user/-/label/claude_foss"]
Auteurs / Source ["Inkscape Project"]
Métadonnées {"articles_inkscape": 10, "articles_total_stream": 100, "flux_claude_foss": 7, "derniere_version": "Inkscape 1.4.4", "date_derniere_version": "2026-05-06", "periode_couverte": "2025-02 a 2026-05"}

Tags

#Inkscape   #logiciel-libre   #SVG   #dessin-vectoriel   #FOSS   #FreshRSS   #claude_foss

Suite / Pistes

1/ Corriger search_foss.py pour filtrer cote client sur title+content. 2/ Ajouter flux Libre Graphics Meeting et Planet Inkscape si existants. 3/ Relancer apres quelques jours pour capter les nouveaux articles. 4/ Croiser avec Kavita (livres SVG/Inkscape) et kDrive (tutoriels eventuels).


01_Les recherches de Claude

11_Gitea_les explorations

Journal des recherches réalisées avec Claude Code sur le service Gitea.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/162
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

12_Grafana_les explorations

Journal des recherches réalisées avec Claude Code sur le service Grafana.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/163
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

13_Immich_les explorations

Journal des recherches réalisées avec Claude Code sur le service Immich.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/164
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

14_Jellyfin_les explorations

Journal des recherches réalisées avec Claude Code sur le service Jellyfin.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/165
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

15_Joplin_les explorations

Journal des recherches réalisées avec Claude Code sur le service Joplin.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/166
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

16_Kavita_les explorations

Journal des recherches réalisées avec Claude Code sur le service Kavita.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/167
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

17_Komga_les explorations

Journal des recherches réalisées avec Claude Code sur le service Komga.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/168
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

18_Mealie_les explorations

Journal des recherches réalisées avec Claude Code sur le service Mealie.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/169
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

19_Navidrome_les explorations

Journal des recherches réalisées avec Claude Code sur le service Navidrome.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/170
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

20_NodeExporter_les explorations

Journal des recherches réalisées avec Claude Code sur le service NodeExporter.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/171
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

21_Prometheus_les explorations

Journal des recherches réalisées avec Claude Code sur le service Prometheus.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/172
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

22_Readeck_les explorations

Journal des recherches réalisées avec Claude Code sur le service Readeck.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/173
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

23_Syncthing_les explorations

Journal des recherches réalisées avec Claude Code sur le service Syncthing.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/174
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

24_Yourls_les explorations

Journal des recherches réalisées avec Claude Code sur le service Yourls.
Documentation technique : https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/175
Chaque entrée est automatiquement enregistrée dans la table recherches (PostgreSQL Alteris, DB 35 Metabase).


RCH-AAAAMMJJ-NNNN — [Objet de la recherche]

DateAAAA-MM-JJ
Service[nom du service]
Contexte[Pourquoi cette recherche — quelle question, quel besoin, quel problème]
Outils utilisés[MCP utilisé / API directe / PowerShell / Python / recherche web...]
Requête[query exacte, paramètres, filtres, commandes]

Résultats

[Description des résultats obtenus — texte libre, liste, tableau selon le volume]

Points clés

Limites

[Ce qui manque, erreurs rencontrées, données absentes, pistes non abouties]

Localisation des ressources

URLs[liens directs vers les ressources trouvées]
Chemins[chemins fichiers, répertoires, arborescences]
IDs[IDs containers, pages, assets, items...]
Auteurs / Source[auteurs, éditeurs, provenance]
Métadonnées[dates, formats, tailles, langues, coordonnées...]

Tags

#tag1   #tag2   #tag3

Suite / Pistes

[Questions ouvertes, actions à entreprendre, recherches complémentaires à lancer]


01_Les recherches de Claude

25_StirlingPDF

RCH-20260822-0001 — Consommation mémoire de StirlingPDF à la compression d'un PDF de 129 Mo (validation de la chaîne Komga-PDF)

Date2026-08-22
ServiceStirlingPDF
ContexteTest de bout en bout de la chaîne automatisée Komga-PDF depuis le poste Windows julie, entré dans le maillage Syncthing le 2026-08-10. Objectif secondaire : mesurer la marge réelle sous le plafond mémoire de 2 Go posé le 2026-08-02, jamais éprouvé sur un gros fichier.
Outils utilisésplink SSH, journalctl -u komga-watch, docker stats stirling-pdf, API /api/v1/misc/compress-pdf (appelée par komga_compress_vps.py)
RequêteDépôt d'un PDF de 129,2 Mo dans D:\Syncthing\komga-pdf\ ; relevé de docker stats stirling-pdf toutes les 15 s jusqu'à la fin du traitement.

Résultats

Chaîne validée sans intervention manuelle : Syncthing dépose le fichier sur le VPS à 11:24:50 UTC, inotify déclenche, le script détecte le PDF à 11:24:53 après l'attente de 3 s, StirlingPDF rend le fichier compressé à 11:26:40 — 1 min 50 s au total, retour du fichier sur le poste julie dans la foulée. Compression : 129,2 Mo → 55,4 Mo, soit -57 %, taux identique à celui du numéro de juin 2026 du même magazine. Consommation du container : 701 Mio à t+15 s, 1001 Mio à t+30 s, pic à 1,069 Gio à t+60 s, puis redescente et stabilisation vers 1,04 Gio jusqu'à la fin.

Points clés

Limites

Les logs de komga-watch partent uniquement dans journald, qui a été tourné depuis le démarrage du service le 2026-07-08 : tous les traitements de juin et juillet sont irrécupérables, journalctl ne montrait rien avant ce test. Aucun historique consultable des compressions passées. Un seul fichier mesuré, donc pas de courbe taille/mémoire — le point à 129 Mo est isolé. La qualité visuelle du PDF compressé n'a pas été contrôlée dans le cadre de ce test.

Localisation des ressources

Procédure complète : page BookStack 220. Scripts VPS : /home/debian/komga_compress_vps.py et /home/debian/komga_watch_vps.sh. Service : komga-watch.service (systemd, actif depuis le 2026-07-08, PID 690). Dépôt : D:\Syncthing\komga-pdf\ → /home/debian/Documents/komga-pdf/. Sortie : /home/debian/Documents/komga-compressed/. Stack StirlingPDF : ID 89, container stirling-pdf, JAVA_TOOL_OPTIONS=-Xmx512m, limits.memory=2g. Fichier de test : La Revue du Vin de France - Septembre 2026.pdf.

Tags

#StirlingPDF #compression #memoire #komga-pdf #Syncthing #VPS

Suite / Pistes

1/ Ajouter une redirection des logs vers un fichier dans komga_watch_vps.sh, pour conserver un historique des compressions au-delà de la rotation journald.
2/ Mesurer un fichier nettement plus gros (200 Mo et au-delà) pour savoir si le plateau de 1 Gio tient ou si la consommation repart.
3/ Contrôler la qualité visuelle du PDF compressé avant de généraliser le taux de -57 % comme acceptable sur ce type de source.

RCH-20260802-0001 — Echec OCR sur images PNG — deux refus cumules d'ocrmypdf (canal alpha + DPI absent)

Date2026-08-02
ServiceStirlingPDF
ContexteJulien signale une erreur HTTP 500 lors d'un OCR sur une image PNG via StirlingPDF. L'interface web n'affiche aucun detail exploitable, le diagnostic passe par les logs du container.
Outils utilisésdocker logs stirling-pdf, API /api/v1/misc/ocr-pdf, Pillow, tesseract --list-langs
RequêtePOST /api/v1/misc/ocr-pdf (multipart fileInput, languages=[fra], ocrType=Force-OCR) sur PNG RGBA, puis sur variantes aplaties et converties, avec mesure docker stats en parallele.

Résultats

Deux erreurs distinctes et cumulees dans ocrmypdf 17.4.0, revelees seulement dans les logs : (1) UnsupportedImageFormatError — The input image has an alpha channel ; (2) une fois l'alpha retire, DpiError — Input file is an image, but has no resolution (DPI) in its metadata. StirlingPDF ne transmet pas l'option --image-dpi a ocrmypdf, donc tout PNG sans DPI dans ses metadonnees echoue. Deux contournements valides en test : voie interface web (Convert > Image to PDF puis OCR sur le PDF, HTTP 200) et voie scriptee (aplatissement de l'alpha sur fond blanc + DPI force a 300, HTTP 200). Texte reconnu restitue a l'identique sur une page de test en francais. Mesure memoire : pic a 894 Mio pour une seule page A4 300 dpi.

Points clés

Limites

Mesure realisee sur une page A4 300 dpi generee synthetiquement ; un document multi-pages ou un scan haute resolution consommera davantage. Le pic de 894 Mio est un plancher, pas un maximum.

Localisation des ressources

URLs["https://spdf.juxjux.ovh", "https://spdf.juxjux.ovh/swagger-ui/index.html"]
Chemins["D:\\Syncthing\\Jux_univers\\Jux-scripts\\Stirling-OCR\\ocr_image.py", "D:\\Syncthing\\Jux_univers\\Jux-scripts\\Stirling-OCR\\README.md", "/home/debian/stirling-compose-new.yml", "/home/debian/stirling-compose-new.yml.orig1g"]
IDs["stack Portainer 89", "container stirling-pdf", "page BookStack 211"]
Auteurs / Source—
Métadonnées{"ocrmypdf": "17.4.0", "tesseract": "5.3.4", "endpoint_ocr": "POST /api/v1/misc/ocr-pdf", "pic_memoire_ocr": "894 MiB / page A4 300 dpi", "limite_memoire_retenue": "2g"}

Tags

#StirlingPDF   #OCR   #ocrmypdf   #tesseract   #PNG   #alpha   #DPI   #memoire   #Docker

Suite / Pistes

Verifier apres l'application du compose allege (2026-08-02 19h) que compress-pdf ET l'OCR fonctionnent toujours avec memory=2g et -Xmx512m.


RCH-20260530-0001 — Mise en place API StirlingPDF pour compression PDF automatisée (workflow geo_loud)

Date2026-05-30
ServiceStirlingPDF
ContexteÉtape 3 du workflow geo_loud : automatiser la compression des 127 PDFs lourds (>75 Mo) déplacés dans \\NASMAISON\foxy\geo_loud\. Objectif : appeler l'API StirlingPDF depuis le PC, écraser chaque fichier avec sa version compressée, mettre à jour la DB SQLite. Fichier de test : 000209_L'inde.pdf (314 Mo).
Outils utilisésStirlingPDF API REST (JWT Bearer) | curl.exe | plink (PuTTY) pour SSH nginx | Python 3.14 + requests | SQLite nas_geographie.db
Requête APIPOST https://spdf.juxjux.ovh/api/v1/misc/compress-pdf — multipart/form-data champ fileInput, header Authorization: Bearer <token>

Résultats

Auth JWT résolue. nginx corrigé (client_max_body_size 500M). Test de compression réussi sur 000209_L'inde.pdf : 314 Mo → 311.7 Mo (0.7% de gain — PDF déjà optimisé en images JPEG). Script nas_geo_compress.py opérationnel pour traitement en batch de tous les fichiers.

Points clés

Limites

Script nas_geo_compress.py

Emplacement : C:\Users\eliob\.claude\nas_geo_compress.py
Lancement : py C:\Users\eliob\.claude\nas_geo_compress.py
Dépendances : pip install requests (sqlite3 et os natifs Python)

Le script ajoute automatiquement les colonnes taille_compresse_octets et date_compression à la table fichiers si elles n'existent pas encore.

"""
Étape 3 du workflow geo_loud : compression PDF via StirlingPDF.
- Lit les fichiers statut='deplace' dans nas_geographie.db
- Envoie chaque PDF à l'API StirlingPDF
- Écrase le fichier d'origine avec la version compressée
- Met à jour la DB (taille_compresse_octets, date_compression)
"""
import sqlite3
import requests
import os
from datetime import datetime

DB_PATH = r"C:\Users\eliob\Documents\nas_geographie.db"
GEO_LOUD = r"\\NASMAISON\foxy\geo_loud"
STIRLING_URL = "https://spdf.juxjux.ovh"
STIRLING_USER = "admin"
STIRLING_PASS = "Motdepasse18!"


def get_token():
    r = requests.post(
        f"{STIRLING_URL}/api/v1/auth/login",
        json={"username": STIRLING_USER, "password": STIRLING_PASS},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["session"]["access_token"]


def init_db_columns(conn):
    cur = conn.cursor()
    cols = {row[1] for row in cur.execute("PRAGMA table_info(fichiers)")}
    if "taille_compresse_octets" not in cols:
        cur.execute("ALTER TABLE fichiers ADD COLUMN taille_compresse_octets INTEGER")
    if "date_compression" not in cols:
        cur.execute("ALTER TABLE fichiers ADD COLUMN date_compression TEXT")
    conn.commit()


def get_pending(conn):
    cur = conn.cursor()
    cur.execute("""
        SELECT id, nom, chemin_geo_loud, taille_octets
        FROM fichiers
        WHERE statut = 'deplace'
          AND extension IN ('.pdf', '.PDF')
          AND (date_compression IS NULL)
        ORDER BY taille_octets DESC
    """)
    return cur.fetchall()


def compress_file(token, filepath):
    with open(filepath, "rb") as f:
        r = requests.post(
            f"{STIRLING_URL}/api/v1/misc/compress-pdf",
            headers={"Authorization": f"Bearer {token}"},
            files={"fileInput": (os.path.basename(filepath), f, "application/pdf")},
            timeout=600,
            stream=True,
        )
    r.raise_for_status()
    return r.content


def update_db(conn, file_id, taille_compresse):
    conn.execute("""
        UPDATE fichiers
        SET taille_compresse_octets = ?, date_compression = ?
        WHERE id = ?
    """, (taille_compresse, datetime.now().isoformat(), file_id))
    conn.commit()


def fmt_mo(octets):
    return f"{octets / 1_048_576:.1f} Mo"


def main():
    print("Connexion à StirlingPDF...")
    token = get_token()
    print("Token JWT OK")

    conn = sqlite3.connect(DB_PATH)
    init_db_columns(conn)
    pending = get_pending(conn)
    print(f"{len(pending)} fichier(s) PDF à compresser\n")

    if not pending:
        print("Rien à faire.")
        conn.close()
        return

    total_avant = sum(r[3] for r in pending)
    total_apres = 0
    ok = 0
    errors = []

    for i, (file_id, nom, chemin_geo_loud, taille_avant) in enumerate(pending, 1):
        filepath = chemin_geo_loud or os.path.join(GEO_LOUD, nom)
        if not os.path.exists(filepath):
            print(f"[{i}/{len(pending)}] ABSENT  {nom}")
            errors.append((nom, "fichier absent"))
            continue

        taille_reel_avant = os.path.getsize(filepath)
        print(f"[{i}/{len(pending)}] {nom}")
        print(f"    avant : {fmt_mo(taille_reel_avant)}", end=" ", flush=True)

        try:
            compressed = compress_file(token, filepath)
            taille_apres_compression = len(compressed)
            gain = (taille_reel_avant - taille_apres_compression) / taille_reel_avant * 100

            tmp = filepath + ".tmp"
            with open(tmp, "wb") as f:
                f.write(compressed)
            os.replace(tmp, filepath)

            update_db(conn, file_id, taille_apres_compression)
            total_apres += taille_apres_compression
            ok += 1
            print(f"-> après : {fmt_mo(taille_apres_compression)} (gain {gain:.1f}%)")

        except Exception as e:
            print(f"-> ERREUR : {e}")
            errors.append((nom, str(e)))
            tmp = filepath + ".tmp"
            if os.path.exists(tmp):
                os.remove(tmp)

    conn.close()

    print(f"\n{'='*50}")
    print(f"Terminé : {ok}/{len(pending)} compressés")
    if ok:
        gain_total = (total_avant - total_apres) / total_avant * 100
        print(f"Volume avant : {fmt_mo(total_avant)}")
        print(f"Volume après : {fmt_mo(total_apres)}")
        print(f"Gain total   : {gain_total:.1f}%  ({fmt_mo(total_avant - total_apres)} récupérés)")
    if errors:
        print(f"\nErreurs ({len(errors)}) :")
        for nom, msg in errors:
            print(f"  {nom} : {msg}")


if __name__ == "__main__":
    main()

Localisation des ressources

URLshttps://spdf.juxjux.ovh (UI) | https://spdf.juxjux.ovh/swagger-ui/index.html (API docs, après login)
CheminsScript : C:\Users\eliob\.claude\nas_geo_compress.py | DB : C:\Users\eliob\Documents\nas_geographie.db | Fichiers source : \\NASMAISON\foxy\geo_loud\ | nginx vhost : /etc/nginx/sites-enabled/spdf.juxjux.ovh
IDsStack Portainer : stirlingpdf (ID 89) | Container : stirling-pdf | Port interne : 8090
Métadonnées{"fichiers_a_traiter": 127, "volume_total_go": 13.577, "test_fichier": "000209_L-inde.pdf", "test_avant_mo": 314, "test_apres_mo": 311.7, "test_gain_pct": 0.7, "nginx_max_body": "500M", "token_duree_h": 24}

Tags

#StirlingPDF #compression #PDF #geo_loud #API #JWT #nginx #Python #NAS #workflow

Suite / Pistes

1/ Lancer le script sur l'ensemble des 127 fichiers — surveiller le gain réel par catégorie de PDF.
2/ Mettre à jour la page BookStack 210 avec les colonnes DB ajoutées (taille_compresse_octets, date_compression) et le bilan de compression une fois le batch terminé.
3/ Si le gain moyen est insuffisant, explorer d'autres niveaux de compression StirlingPDF ou un outil alternatif (Ghostscript direct).
4/ Après compression de tous les fichiers : lancer l'étape 4 (restauration) via nas_geo_loud.py restaurer.

02_les petites procédures de Claude

02_les petites procédures de Claude

A - synthèse des procédures et état de fonctionnement

Rédigé le 13/09/2026, ligne Seedbox-Films ajoutée le 14/09. La colonne « Dernière utilisation connue » est figée à cette date : la valeur vivante est relue chaque matin par le canari et affichée dans le tableau « Procédures » en pied de la page de veille du jour.

Ce que cette page fait

Depuis juin, les procédures se sont multipliées : compression de PDF et de photos, conversion de musique, sauvegardes, synchronisations, tunnels. Chacune a sa page détaillée. Celle-ci les rassemble en une ligne chacune — quoi, où, quand, dernière trace, comment vérifier — pour répondre vite à « est-ce que ça tourne encore ? ».

Trois familles selon qui peut les voir : le VPS observe directement ce qui tourne chez lui et, par le tunnel, le NAS ; il ne voit pas le PC. Les procédures du PC laissent donc un petit fichier témoin dans l'arbre Syncthing (Jux-scripts/Etat-Infra/temoins/) à chaque passe réelle, et c'est lui que le canari lit.

Automatiques sur le VPS

Tournent sans intervention. Le canari du matin les relit chaque jour ; toute dérive apparaît dans la page de veille.

ProcédureCe qu'elle faitOù / quandDernière utilisation connueVérification
Sauvegardes VPS → kDrive
page 176
vps_backup.sh : BookStack, Immich, Joplin, Mealie, Readeck, Baïkal + ~/Documents (Syncthing) en 7z vers kDrive. Rotation 7 jours ; copie mensuelle de Documents sur 12 mois.VPS · cron 2h UTC (14 min, Joplin en tête)13/09 02:13 UTC — BILAN 8/8tail -3 /opt/backups/backup.log → BILAN 8/8 OK. Première ligne de la veille.
Komga-PDF
page 220
Un PDF déposé dans D:\Syncthing\komga-pdf\ revient compressé par StirlingPDF dans komga-compressed/ (−57 à −66 %). Écriture atomique, 3 tentatives, journal persistant.VPS · service komga-watch (inotify + rebalayage 10 min)09/09 — Cuisine et Vins de France 09-10.2026, 59,9 → 20,5 Mio en 62 sjournalctl -u komga-watch -n 20 ; /home/debian/logs/komga_compress.log. Le canari teste le login Stirling chaque matin (panne muette du 7 au 9/09).
Komga-Cache
page 168
komga_scan.sh : vfs/refresh du montage kDrive puis scan des 23 bibliothèques, avant le scan interne de Komga à 4 h. Sans lui un fichier déposé reste invisible jusqu'à 72 h.VPS · cron 3h45 UTC13/09 — 23 scans, aucun échectail /home/debian/logs/komga_scan.log → aucun echec.
Seedbox-Films
page 318
seedbox_films.sh : les films du dossier FILMS de la seedbox (WebDAV) copiés vers kDrive Videos_NAS/video/movies sans toucher le disque du VPS, puis vfs/refresh du montage et scan de la seule bibliothèque Jellyfin « Films récents ». copy jamais sync ; mémoire locale des copies (kDrive liste les gros fichiers frais avec retard).VPS · cron toutes les 5 min, muet si rien de nouveau14/09 — 7 films, 13,4 Gio en 196 s (~73 Mo/s)tail /home/debian/logs/seedbox_films.log ; sonde « Seedbox-Films » des tâches nocturnes et ligne « Seedbox » du tableau des procédures de la veille.
Scan Navidrome
page 170
Quick scan quotidien (titres existants) et full scan hebdomadaire par redémarrage du conteneur (nouveaux albums), après vfs/refresh du montage music.VPS · cron 4h30 UTC quotidien, lundi 3h UTC complet13/09 04:30 UTCtail /var/log/navidrome_scan.log ; API getScanStatus → scanning:false.
Scan Audiobookshelf
page 155
Scan des 36 bibliothèques par l'API (JWT).VPS · cron 4h UTC13/09 — SCAN OK 36/36tail /var/log/abs_scan.log → SCAN OK.
Compression Joplin
page 222
Images stockées en base PostgreSQL recompressées en JPEG 85 % ; observatoire réécrit sur la page 166. Terminée depuis juin, ne traite que les nouvelles ressources.VPS · timer systemd 3h UTC13/09 — 893 ressources, 396,5 Mo économisés (−77,7 %)sudo grep -c Traceback /var/log/joplin-compress.log doit rester stable ; page 166 datée du jour.
Veille FreshRSS → BookStack
page 252
Page « Veille AAAA-MM-JJ » : articles du jour par thème, dédoublonnés, critères lus dans la page 252. Porte aussi l'état de l'infrastructure et le tableau des procédures.VPS · cron 5h30 UTC13/09 07:30 — page 314, 13 432 caractèresLa page du jour existe dans le chapitre 251 ; tail /home/debian/logs/veille_freshrss.log.
Canari Etat-Infra
page 251
etat_infra.py : sauvegardes, 17 services web, conteneurs, certificats servis, montages, Syncthing, WireGuard, NAS, Komga-PDF, journaux nocturnes, disque, agenda Baïkal, procédures → JSON du jour, rendu dans la veille. Muet quand tout va bien.VPS · cron 5h15 UTC13/09 07:15 — vert, 0 anomalieLigne du haut de la veille (Sonde absente = le collecteur n'a pas tourné) ; /home/debian/logs/etat_infra.log ; python3 etat_infra.py --dry-run.
monitor-rclone
page 170
Vérifie les 7 montages FUSE ; si l'un est mort : restart du service rclone puis des conteneurs qui le lisent. Silencieux quand tout va bien.VPS · cron toutes les 5 min12/09 00:20 UTC — recovery de /home/debian/photo (Immich redémarré)tail /home/debian/logs/rclone-monitor.log ; ligne « interventions depuis hier » de la veille.
Montages rclone kDrive
page 165
Six montages media (photo, romans, komga, livres, music, audiobooks) + /mnt/nas_videos pour Jellyfin. Cache VFS full plafonné, sauf video en minimal. RC sur 127.0.0.1 uniquement.VPS · services systemd permanentspermanent — 7/7 répondent le 13/09ls de chaque point de montage ; rclone rc … vfs/stats ; ligne « Montages rclone » de la veille.
disk_monitorAlerte au-delà de 85 % de disque, purge /tmp/rclone-spool* de plus d'une heure (incident du 24/06).VPS · cron toutes les 30 min13/09 20:00 — 78 %tail /var/log/disk_monitor.log.

Sur le NAS sasnexte

Le VPS y accède par le tunnel WireGuard (10.0.0.2). Les journaux vivent dans /volume1/homes/SAS_NEXTE/logs/.

ProcédureCe qu'elle faitOù / quandDernière utilisation connueVérification
Synchro NAS → kDrive
page 238
sync_kdrive_complete.sh : miroir rclone sync de audiobooks, music, photo/2026 et Komga vers SYNC-pour_VPS/Sync-SASNEXTE. Version durcie du 28/08 (config absolue, refus de source vide, --max-delete).NAS · planificateur DSM, quotidien13/09 — 4/4 sans CRITICALgrep -l CRITICAL logs/sync_*_$(date +%Y%m%d)*.log doit être vide ; ligne « NAS sasnexte » de la veille (lecture par ssh).
Photos NAS — compression par lots
page 285
Inventaire (photos.sqlite) → lot par album (traiter_lot_nas.py, originaux intacts) → validation dans Synology Photos (supprimer = refuser) → bascule en root (basculer_lot_nas.py --go). Photos < 2 Mo exclues, EXIF/mtime vérifiés.NAS · manuel, lot par lot28/08 — lot 2022 (359 photos, 1,47 Go) en validation ; doublons : 75 fichiers en quarantainepython3 traiter_lot_nas.py --lot X --lister ; colonne statut de photos.sqlite.
Navidrome-Paroles (Beets)
page 312
Conteneur beets-paroles : beet lyrics (LRCLIB) → ecrire_paroles.py (SYLT/USLT seulement) → propager_paroles.sh vers kDrive → full scan Navidrome. Beets n'écrit jamais dans les fichiers.NAS · manuel, chaîne finir_paroles.sh en setsid11-12/09 — 13 139 fichiers écrits, 10 998 paroles synchronisées en base (avant : 15)Navidrome : compte des titres avec paroles ; conteneur à l'arrêt entre deux passes. Point ouvert : décalage 2-3 s dans le lecteur web.
Video → kDrive
page 290
Les 694 Go du partage video copiés dans Private/Videos_NAS/ et vérifiés par rclone check --download ; Jellyfin lit kDrive (×13 plus rapide que le CIFS via WireGuard).fait le 30/08 · reste : suppression sur le NAS après observation30/08 — 0 différence sur 4 056 fichiers, 629 films dans Jellyfinsystemctl status kdrive-video ; montage /mnt/nas_videos dans le canari.

Sur le poste julie (PC)

Le VPS ne voit pas le PC. Ces procédures déposent un témoin (Jux-scripts/Etat-Infra/temoins/<id>.json, dans l'arbre Syncthing) à chaque passe réelle ; c'est ce témoin que la veille affiche. « Non observé » = aucune passe depuis l'ajout du témoin (13/09).

ProcédureCe qu'elle faitOù / quandDernière utilisation connueVérification
Photos-Caesium
page 284
Dépôt dans D:\Procedures photos\Tofs a compresse\, résultat dans Tofs-compressed\ (caesiumclt q80, EXIF et GPS conservés, −64 % mesuré). Dossiers hors Syncthing volontairement.PC · tâche planifiée Photos-Caesium (ONLOGON, pythonw), sondage 15 s27/08 — 71 photos, 251 → 90 Mo en 22 sGet-CimInstance Win32_Process -Filter "Name='pythonw.exe'" ; D:\Procedures photos\logs\ ; témoin photos-caesium.
Musique-FLAC
page 298
Dépôt dans D:\Musique\FLAC à encoder\, MP3 V0 dans MP3 fait\. Tags lus dans le FLAC, réécrits, relus dans le MP3 et comparés ; durée vérifiée (un FLAC tronqué se convertit sans erreur).PC · tâche planifiée Musique-FLAC à créer par Julien ; sinon flac_mp3.py à la main04/09 — Dry Cleaning, 11 pistes, 824 → 81 Mo en 50 sD:\Musique\logs\flac_mp3.log ; témoin musique-flac.
Livres-ISBN
page 300
inventaire_livres.py (métadonnées lues dans les fichiers) puis resoudre_livres.py (BnF, OpenLibrary) → CSV rangé par rayon, à relire. Lecture seule sur \\NASMAISON\foxy : Julien saisit.PC · manuel, par lots déposés dans D:\Procedures Calibre\Dossier à renseigner\04-05/09 — lot Cuisine Géo : 619 fichiers, 233 ISBN (41 pré-cochés)CSV dans D:\Procedures Calibre\ISBN\ ; témoin livres-isbn.
Calibre-MetadonneesPour les 1 572 livres déjà dans metadata.db : corriger_auteurs.py, resoudre_isbn.py, appliquer_isbn.py (rien sans --go). La source Google de Calibre est morte : seul l'ISBN fonctionne.PC · manuel, Calibre fermé pour écrire31/08 — 76 auteurs corrigeables, 121 ISBN proposés ; relecture en attentepropositions.csv ; fetch-ebook-metadata.exe -I isbn:… rend une fiche complète.
Mealie-Recettes
page 315
Note Joplin publiée (carnet « A transcrire dans Mealie » obligatoire) → Claude structure → recette Mealie avec photo, catégories = cuisine, tags = ingrédients.PC · à la demande, outils MCP lire_note_joplin / creer_recette13/09 — köttbullar, brochettes d'espadonRecette visible dans Mealie ; témoin mealie.
Surveillance Blink
page 275
Sonde le module Sync toutes les 30 s et balaie le /24 toutes les 5 min ; CSV dans D:\Logs\Blink\. Mesure seulement, ne réveille rien.PC · dossier Démarrage (Surveillance Blink.cmd, pythonw)en service depuis le 30/08pythonw.exe présent ; surveiller_blink.py --resume. Non relayé dans la veille (hors Syncthing).
Scan LAN
page 275
scan_lan.py --ports : balayage ping, ARP, OUI, ports, DNS inverse du réseau maison.PC · à la demande23/08 — 9 appareils—
PC-Health
page 249
collect_bsod.ps1 (élevé) : arrêts anormaux, codes bugcheck, pilote AMD, SMART → ligne ajoutée au journal de la page 249.PC · manuel, toutes les 1-2 semaines25/08 — 4 épisodes inexpliqués ; action en attente : pilote AMDJournal de la page 249 ; smartctl -A /dev/pd0 (Unsafe_Shutdown_Count).
Kobo — dépôt d'epub
page 271
Un epub déposé dans D:\Syncthing\Kobo\ est servi par nginx à juxjux.ovh/56ifciz, à taper dans le navigateur bêta de la liseuse (USB en panne).Syncthing + vhost nginx VPS · à la demande22/08 — 1 fichier en lignecurl -I https://juxjux.ovh/56ifciz/ → 200 ; ligne « Kobo » de la veille (date du dernier fichier).

Liaisons permanentes

Pas des procédures à proprement parler, mais tout le reste repose dessus.

ProcédureCe qu'elle faitOù / quandDernière utilisation connueVérification
Maillage Syncthing
page 174
Un seul dossier afltj-njyuy partagé par 8 appareils, hub VPS. Réplication, pas sauvegarde : la sauvegarde de ~/Documents couvre ce trou depuis le 30/08.permanent · SyncTrayzor sur le PC (home D:\SyncthingHome)13/09 — 3 appareils vus depuis hierGUI http://127.0.0.1:8384 ; ligne « Syncthing » de la veille (tolérances par appareil dans config.json).
Tunnel WireGuard
page 245
VPS 10.0.0.1 (hub) ↔ NAS 10.0.0.2 ↔ PC 10.0.0.3. Lecteur S: → \\10.0.0.2\NEXTE. Le service Windows meurt après un plantage sec ; relance automatique posée le 13/09.permanent · service Windows + wg0 sur le VPS13/09 — poignées de main NAS et PC à la minuteTest-NetConnection 10.0.0.2 -Port 445 côté PC ; sudo wg show côté VPS ; ligne « WireGuard » de la veille.
Baïkal + DAVx5
page 247
Contacts et agenda : Baïkal source de vérité, DAVx5 (15 min) sur le téléphone, InfCloud et Roundcube en web. Sauvegardé chaque nuit.permanent · conteneurs baikal, roundcubepermanent — agenda affiché chaque matinBloc « Agenda » sous la ligne du haut de la veille (lecture directe de db.sqlite) ; curl -X PROPFIND sur /dav.php/.
Serveurs MCPBookStack et kDrive (npm), et les serveurs Python stdlib de Jux-scripts/MCP/ : Portainer, Syncthing, Komga, Navidrome, Readeck, Mealie.PC · au démarrage de chaque session Claude Code13/09 — mcp_mealie.py ajoutéOutils listés en début de session ; un MCP en échec n'apparaît pas.

Chantiers en attente (relevé du 13/09)

Ajouter une procédure au tableau

  1. Une entrée dans Jux-scripts/Etat-Infra/procedures.json : id, nom, page BookStack, source (journal avec chemin et motif, dossier, domaine d'une sonde existante, temoin, ou manuel avec une date), et cadence_heures si elle doit tourner régulièrement — au-delà la ligne passe « En retard ».
  2. Pour une procédure du PC : appeler ecrire_temoin("<id>", "résumé") en fin de passe (fonction de dix lignes, déjà présente dans compress_photos.py, flac_mp3.py, isbn_commun.py, joplin_mealie.py). Le témoin ne doit jamais faire échouer la procédure.
  3. python3 etat_infra.py --dry-run sur le VPS montre le tableau sans rien publier.

Le tableau de la veille ne lève pas d'alerte en tête de page : c'est un récapitulatif. Les alertes viennent des sondes dédiées (sauvegardes, journaux nocturnes, Komga-PDF, NAS…), qui couvrent déjà ce qui est critique.

02_les petites procédures de Claude

260801 - Mon Linux OS sur SASNEXTE

Claude prend la main en MCP pour monter et manager une distribution Linux ubiquiste - disponible 

02_les petites procédures de Claude

260528_Essai sur \\NASMAISON\foxy\Géographie\

Workflow geo_loud — Optimisation des fichiers lourds
Contexte

Le dossier \\NASMAISON\foxy\Géographie\ contient 1 312 fichiers (PDF et EPUB) pour un total de 32,9 Go. Parmi eux, 127 fichiers dépassent 75 Mo et représentent 13,6 Go — soit 41 % du volume total concentré sur moins de 10 % des fichiers.

L'objectif est de sortir ces fichiers lourds pour les optimiser (compression PDF), puis de les remettre exactement à leur emplacement d'origine sans perdre l'arborescence.
Architecture du système
Fichier     Rôle
nas_indexer.py     Scanne le NAS et crée la base SQLite
nas_geographie.db     Référentiel de tous les fichiers avec métadonnées et statut
nas_geo_loud.py     Script checkout/checkin — déplace et restaure les fichiers lourds

La base SQLite est la source de vérité : elle connaît à tout moment l'emplacement original de chaque fichier et son statut.
Colonnes de traçabilité (table fichiers)
Colonne     Description
chemin_absolu     Chemin d'origine complet sur le NAS
chemin_geo_loud     Chemin dans le dossier de travail après déplacement
statut     original / deplace / restaure
date_deplacement     Horodatage du déplacement
date_restauration     Horodatage de la restauration
Workflow complet
Étape 1 — Indexation initiale
1
python nas_indexer.py "\\NASMAISON\foxy\Géographie" --output nas_geographie.db

Résultat : 1 312 fichiers indexés en ~22 secondes, 0 erreur.
Étape 2 — Export (checkout)

Déplace les 127 fichiers > 75 Mo vers \\NASMAISON\foxy\geo_loud\ :
1
2
3
4
python nas_geo_loud.py export \
  --db nas_geographie.db \
  --dest \\NASMAISON\foxy\geo_loud \
  --confirmer

Ce que fait le script :

    Interroge la base pour tous les fichiers statut = 'original' et taille > 75 Mo
    Renomme chaque fichier {id:06d}_{nom_original} pour éviter les collisions de noms
    Déplace physiquement le fichier vers geo_loud/
    Met à jour la base : statut = 'deplace', chemin_geo_loud, date_deplacement

    Le préfixe numérique garantit l'unicité même si deux sous-dossiers contiennent un fichier de même nom.

Étape 3 — Optimisation PDF

Traiter les fichiers dans \\NASMAISON\foxy\geo_loud\ avec l'outil d'optimisation. Les fichiers peuvent être traités dans n'importe quel ordre et en plusieurs sessions.
Étape 4 — Restauration (checkin)
1
2
3
python nas_geo_loud.py restaurer \
  --db nas_geographie.db \
  --dest \\NASMAISON\foxy\geo_loud

Ce que fait le script :

    Lit tous les enregistrements statut = 'deplace' dans la base
    Pour chaque fichier présent dans geo_loud/ : déplace vers son chemin_absolu d'origine
    Recrée les sous-dossiers si nécessaire
    Met à jour : statut = 'restaure', date_restauration
    Ignore les fichiers absents de geo_loud/ (pas encore optimisés)

Étape 5 — Vérification du statut
1
python nas_geo_loud.py statut --db nas_geographie.db

Affiche :
1
2
3
4
Statut         Fichiers     Total Go
--------------------------------------
  deplace           127       13.577
  original        1 185       19.275
Vues SQL utiles (Metabase / DB Browser)
1
2
3
4
5
6
7
8
-- Fichiers encore dans geo_loud
SELECT nom, ROUND(taille_octets/1048576.0,1) AS mo, date_deplacement, chemin_absolu
FROM fichiers WHERE statut = 'deplace'
ORDER BY taille_octets DESC;

-- Bilan par statut
SELECT statut, COUNT(*) AS nb, ROUND(SUM(taille_octets)/1073741824.0,3) AS go
FROM fichiers GROUP BY statut;
Paramètres disponibles
Paramètre     Défaut     Description
--db     nas_geographie.db     Chemin vers la base SQLite
--dest     \\NASMAISON\foxy\geo_loud     Dossier de travail
--seuil     75     Seuil en Mo pour la sélection
--confirmer     (off)     Bypass la confirmation interactive
Ré-indexation après optimisation
1
python nas_indexer.py "\\NASMAISON\foxy\Géographie" --output nas_geographie.db --vider
Fichiers du projet
Fichier     Emplacement
nas_indexer.py     C:\Users\eliob\Documents\nas_indexer.py
nas_geo_loud.py     C:\Users\eliob\Documents\nas_geo_loud.py
nas_rapport.py     C:\Users\eliob\Documents\nas_rapport.py
nas_geographie.db     C:\Users\eliob\Documents\nas_geographie.db

02_les petites procédures de Claude

260611_procédure Komga-PDF par Claude sur StirlingPDF

Présentation

La procédure Komga-PDF est un script de compression de fichiers PDF pour réduire considérablement la taille du stockage des bibliothèques d'ouvrages de la collection de Julien.

L'acquisition de fichiers issus de bases de données Internet accumule des fichiers PDF en haute résolution (images surtout). Ces fichiers sont synchronisés entre les NAS Synology et un disque dur kDrive Infomaniak de 6 To.

Contexte

Des points de montage Rclone relient les répertoires kDrive et les containers Docker installés sur le VPS OVH juxjux.ovh. Ces containers lisent les PDF à la volée — permettant ainsi de construire une infrastructure de très forte densité de connaissances digitales (epub, pdf, images, vidéos, musiques...) avec une solution serveur d'entrée de gamme (10 €/mois tout inclus).

La lecture réseau est multi-support : PC, tablette, téléphone. Elle est aussi nomade, séquentielle et pressée. La compacité des fichiers PDF devient donc nécessaire pour diffuser rapidement sur les réseaux. Un magazine ou un ouvrage informatique ne doit pas peser 130 Mo sur un écran de 10 pouces.

Procédure

Architecture technique

Élément Chemin / URL
Dépôt (toutes machines) Syncthing/komga-pdf/
Dossier VPS (Syncthing) /home/debian/Documents/komga-pdf/
Destination VPS /home/debian/Documents/komga-compressed/
API compression https://spdf.juxjux.ovh/api/v1/misc/compress-pdf
Scripts VPS /home/debian/komga_compress_vps.py + /home/debian/komga_watch_vps.sh
Logs journalctl -u komga-watch -f (sur le VPS) + journal persistant /home/debian/logs/komga_compress.log

Scripts

Le service tourne entièrement sur le VPS — plus de dépendance Ubuntu ni de SSH persistant.

Fichier Rôle
komga_compress_vps.py Compression : liste les PDFs locaux (extension insensible à la casse), envoie à StirlingPDF, écrit dans komga-compressed/ de façon atomique. Idempotent. Vérifie que la réponse est bien un PDF et met à l'écart un fichier après 3 échecs.
komga_watch_vps.sh Surveillance : traite le backlog au démarrage, puis boucle inotifywait -t 600. Le délai impose un rebalayage périodique, indispensable car les événements survenant pendant une compression sont perdus (voir REX 2026-08-23).
/etc/systemd/system/komga-watch.service Service system (pas user), actif au boot, Restart=always.

Gérer le service (VPS)

sudo systemctl status komga-watch
sudo systemctl restart komga-watch
journalctl -u komga-watch -f

Retour d'expérience (2026-08-23) — Deux fichiers bloqués sans la moindre trace

Deux PDF déposés le 22/08 stagnaient dans komga-pdf/ sans aucune ligne au journal : ni erreur, ni tentative. Le service était pourtant active, et deux autres fichiers étaient passés normalement le matin même à 06:13.

La cause — une course perdue sur les événements inotify

komga_watch_vps.sh appelait inotifywait une seule fois par tour de boucle, puis lançait la compression. Pendant toute la durée du traitement, plus personne n'écoutait le dossier.

Horodatage Événement
06:13:07 inotifywait rend la main (dépôt de « Le Grand Livre… »)
06:13:10 le script Python liste le dossier — 2 PDF trouvés
06:13:10 → 06:15:16 2 min 06 s de compression, aucune écoute inotify
06:15:16 inotifywait redémarre — les événements de la fenêtre sont perdus

Les deux fichiers « Les secrets de… » sont arrivés dans cette fenêtre. Leur close_write et leur moved_to sont tombés dans l'angle mort, et le glob() du script était déjà passé. Ils sont devenus invisibles pour de bon — jusqu'au dépôt d'un autre fichier, qui aurait relancé un balayage complet.

Preuves relevées au moment du diagnostic :

Le défaut est structurel et se reproduit dès que plusieurs fichiers arrivent ensemble — précisément le cas où la compression dure le plus longtemps.

Le correctif — un délai sur inotifywait

inotifywait -q -t 600 -e close_write,moved_to "$SOURCE_DIR"

-t rend la main au bout de 600 s même sans événement, ce qui garantit un rebalayage périodique. Le traitement étant idempotent — et désormais silencieux quand il n'y a rien de neuf — un balayage à vide ne coûte rien. Plus aucun fichier ne peut rester orphelin : au pire 10 minutes de latence.

Vérification du correctif, en reproduisant le bug

Le scénario a été rejoué volontairement. Un PDF a été déposé dans le dossier par lien matériel (ln), qui ne produit qu'un IN_CREATE — événement non surveillé par le script. C'est l'équivalent exact d'un événement perdu.

Horodatage Constat
07:51:09 démarrage du guetteur, balayage initial
07:51:56 dépôt du fichier — aucune ligne au journal, donc aucun événement émis
08:01:10 le rebalayage périodique le trouve : « 1 PDF(s) à traiter (sur 1 présents) »

600 secondes pile après le démarrage. Avec l'ancien script, ce fichier serait resté indéfiniment invisible.

La compression a ensuite échoué en HTTP 400 — le PDF de test faisait 193 octets sans table xref, StirlingPDF le refuse à raison. Cet échec a validé trois autres correctifs du même coup :

Artefacts de test supprimés après contrôle.

Les autres défauts corrigés dans la même passe

# Défaut Correctif
1 glob("*.pdf") ignorait les .PDF — régression par rapport à l'ancien find -iname comparaison sur suffix.lower()
2 write_bytes() écrivait le fichier final directement dans un dossier Syncthing : propagation possible d'un PDF incomplet écriture en .part puis os.replace(), atomique
3 aucune validation de la réponse : une page d'erreur HTML renvoyée en HTTP 200 était enregistrée en .pdf vérification de la signature %PDF-
4 timeout=300 trop juste — un fichier de 148 Mio prend environ 3 min porté à 900 s
5 si la compression ne gagnait rien, le résultat était écrit quand même l'original est recopié tel quel, ce qui clôt proprement le traitement
6 un fichier en échec était retenté sans fin — grave avec le rebalayage toutes les 10 min, soit 144 envois par jour mémoire des échecs dans ~/.komga_compress_state.json, mise à l'écart après 3 tentatives
7 get_token() sans protection : Stirling indisponible = traceback, lot entier perdu message d'erreur explicite, sortie propre
8 mkdir(exist_ok=True) sans parents=True corrigé
9 aucun journal persistant — journald seul, tourné régulièrement /home/debian/logs/komga_compress.log, en plus de stdout

La mise à l'écart après trois tentatives s'appuie sur la signature du fichier (taille + date de modification) : redéposer une version corrigée portant le même nom relance donc le traitement normalement.

Déblocage des deux fichiers et mesure mémoire

Fichier Original Compressé Gain
Les secrets de la photo lifestyle — Baptiste Dulac 148,4 Mio 30,1 Mio -80 %
Les secrets de la série photo — Frédéric Landragin 51,4 Mio 38,6 Mio -25 %

Traitement en 4 min 05 s. Pic mémoire de stirling-pdf : 1 426 Mio sur les 2 Go du plafond (71 %), aucun OOM kill — c'est le plus gros fichier jamais passé dans la chaîne. Troisième confirmation que porter la limite à 2 Go était le bon choix : le plafond de 1 Go envisagé le 2026-08-02 aurait tué le container.

Sauvegardes et versionnement

Retour d'expérience (2026-08-22) — Test de bout en bout depuis le poste julie

Première validation complète de la chaîne depuis le redémarrage du service le 2026-07-08, et premier passage depuis le PC Windows julie (entré dans le maillage Syncthing le 2026-08-10). Aucune intervention manuelle : dépôt du fichier dans D:\Syncthing\komga-pdf\, tout le reste s'est enchaîné seul.

Chronologie mesurée — 1 min 50 s entre le dépôt sur le VPS et le fichier compressé :

Étape Horodatage (UTC)
Syncthing dépose le .tmp sur le VPS, inotify déclenche 11:24:50
Fin de l'attente de 3 s, le script détecte le PDF 11:24:53
StirlingPDF rend le fichier compressé 11:26:40
Retour du fichier compressé sur le poste julie (Syncthing) 11:26

Résultat de compression :

Fichier Original Compressé Gain
La Revue du Vin de France - Septembre 2026.pdf 129,2 Mo 55,4 Mo -57%

Même taux que le numéro de juin 2026 du même magazine (-57 %) — la compression est reproductible d'un numéro à l'autre pour une source identique.

Mesure mémoire — marge plus étroite qu'attendu

C'est le point neuf de ce test. Le fichier de 129 Mo est le plus gros passé dans la chaîne à ce jour (précédent record : 96,6 Mo le 2026-06-13). Consommation du container stirling-pdf, relevée toutes les 15 s :

t+ Mémoire
15 s 701 Mio
30 s 1001 Mio
45 s 1,036 Gio
60 s 1,069 Gio (pic)
75 s 1,047 Gio
90 s 1,039 Gio (terminé)

Point d'attention — aucun log persistant (résolu le 2026-08-23)

Les logs partent uniquement dans journald (komga_watch_vps.sh écrit sur stdout, capté par systemd). Le journal a été tourné depuis le démarrage du service : tous les traitements de juin et juillet sont irrécupérables, journalctl -u komga-watch ne montrait rien avant ce test.

Pour conserver un historique consultable, ajouter une redirection vers un fichier dans le script, ou poser un journalctl --unit komga-watch en rotation propre. Non fait à ce jour.

Corrigé le 2026-08-23 : le script Python écrit désormais chaque ligne dans /home/debian/logs/komga_compress.log en plus de stdout. Voir le REX du 2026-08-23 ci-dessus.

Retour d'expérience (2026-06-13) — Refactorisation VPS

Problème de l'architecture Ubuntu : le service tournait sur Ubuntu avec un SSH persistant vers le VPS. Deux défauts structurels :

Solution : service systemd sur le VPS lui-même. inotifywait local, pas de SSH persistant. Le script traite le backlog à chaque démarrage avant d'entrer dans la boucle de surveillance.

Résultats de compression (2026-06-13) :

Fichier Original Compressé Gain
Beaux Arts - Juin 2026.pdf 75.8 Mo 61.1 Mo -19%
Connaissance des Arts - Juin 2026.pdf 57.3 Mo 35.2 Mo -39%
La Revue du Vin de France - Juin 2026.pdf 93.3 Mo 39.9 Mo -57%
Livre lacto fermentation.pdf 96.6 Mo 19.6 Mo -80%
Monde Gourmand N°93 - Juin 2026.pdf 41.2 Mo 17.4 Mo -58%

Points techniques :

Retour d'expérience (2026-06-12)

Résultats de compression :

Fichier Original Compressé Gain
Monde Gourmand N°93 - Juin 2026.pdf 42 Mo 17 Mo -58%
Connaissance des Arts - Juin 2026.pdf 57 Mo 35 Mo -39%
02_les petites procédures de Claude

260614 - procedure Joplin-compression

Contexte — instructions de Julien (260614)

J'utilise l'application Joplin sur tous mes appareils. C'est ma mémoire de tout (travail, hobbies, maison...) et donc à force, la base de données se remplit. Elle se compose de notes à l'intérieur desquelles on trouve des images. Même en n'important que des captures d'écran, le poids de ces images est devenu important — de l'ordre de 300 Mo initialement estimé (476 Mo constatés en réalité, voir ci-dessous).

Appareils synchronisés sous Joplin :

Objectif de la procédure :

  1. Compresser le stock d'images contenues dans la base de données Joplin via un process fiable de remplacement
  2. Monter un système de compression automatique quotidienne des nouvelles images

Principes définis par Julien :

  1. Tenir un carnet de bord (observatoire) du poids digital de la BDD Joplin dans la page BookStack Joplin, avec les 15 pièces jointes les plus lourdes
  2. Mettre en place sur le VPS une procédure duplication → compression → remplacement d'images, qui se propage via la sync Joplin sur tous les appareils

Exploration technique — Claude, 14/06/2026

Infrastructure Joplin sur le VPS

Contrairement à ce qu'on pourrait attendre, Joplin Server n'utilise pas SQLite mais PostgreSQL.

Container Image Rôle
joplin joplin/server:latest Serveur de sync Joplin
joplin-db postgres:15-alpine Base de données
joplin-nginx nginx:alpine Reverse proxy interne
joplin_to_obsidian image custom Container migration (actif, sans impact)

Volume de données : /home/debian/joplin-data → /home/joplin/.config/joplin (bind mount)

Connexion DB : POSTGRES_HOST=joplin-db, POSTGRES_DATABASE=joplin, POSTGRES_USER=joplin

Important : le port 5432 de joplin-db n'est pas exposé à l'extérieur du réseau Docker. Tout script de manipulation doit tourner sur le VPS et se connecter via l'IP interne Docker.

Structure de la base de données

La table centrale est items (23 tables au total). Chaque note, ressource et paramètre Joplin est une ligne dans cette table.

Colonnes clés :

Répartition par type :

jop_type Signification Nombre Poids total
0 Ressource (image/fichier joint) 736 476 MB
1 Note 699 8,7 MB
4 Tag 733 4,5 MB
13 NoteTag (relation note↔tag) 250 3,9 MB
2 Carnet (Folder) 94 707 KB
6 Master Key 87 19 KB
5 Setting 39 —

Analyse des ressources (jop_type = 0)

Les ressources sont stockées comme bytes bruts dans la colonne content. Le format est détectable via les magic bytes :

La colonne mime_type est vide pour toutes les ressources — le type est implicite dans les bytes du contenu.

Top 15 ressources les plus lourdes (état initial) :

Rang ID Taille Format
1 0xh87pWrRt82z0DbO9n3yQ 12,2 MB ZIP (page_1.png 7MB + page_2.png 5MB)
2 M0C32hKC2hMqPAxpRGiVgp 7,2 MB PNG
3 UbAqQY3cEbH62vioIHU6Pj 6,0 MB PNG
4 ZPQJVSjptMSxE71pV7JbAt 5,9 MB PNG
5 h4Lhw1Trx9wgmD7doX9NyZ 5,9 MB PNG
6 sbktcNb4IUj0yIovgDt0fL 5,3 MB PNG
7 jtzuGpvrRTR12iLzwhcSNn 5,2 MB PNG
8 VasIoF2e9EGuNQt38aOFMx 4,9 MB JPEG
9 ZACDcQWzQzDLdnV7Qnf933 4,3 MB PNG
10 hExoJEEWT2tHz1demE5Nhm 4,3 MB PNG
11 veu4HT3bStx07gRUlAEYvG 4,2 MB PNG
12 bz9Twmb2F5lj0mPIQi48IB 4,2 MB JPEG
13 TzWK21r4n0yvbEtJh02DGB 4,2 MB JPEG
14 eD165w1bdEHJg0tq3qWok5 4,2 MB PNG
15 HD4SeqIx252nP9nh8HDVnH 4,1 MB PNG

Architecture retenue

Choix de compression — décision Julien, 14/06/2026

PNG → JPEG 85% (lossy). Toutes les images, qu'elles soient PNG ou JPEG à l'origine, sont converties/re-sauvegardées en JPEG qualité 85. Gain estimé : 50–75% par image. Acceptable pour des captures d'écran.

Pour les ZIP multi-pages : chaque image interne est convertie en JPEG 85%, le ZIP est reconstruit.

Phase 1 — Observatoire

Script joplin_observatoire.py sur le VPS :

Phase 2 — Compression (script principal)

Script joplin_compress.py sur le VPS :

Connexion : psycopg2 → IP Docker interne de joplin-db : 5432

Traitement par ressource :

  1. Lire le blob content depuis items (jop_type=0)
  2. Détecter le format (magic bytes)
  3. Ouvrir avec Pillow, convertir en JPEG 85 (quality=85, optimize=True)
  4. Pour les ZIP multi-pages : dézipper → compresser chaque image → reconstruire le ZIP
  5. Si le gain est > 5% : mettre à jour content, content_size, updated_time en base
  6. Logger le résultat (ID, taille avant, taille après, ratio)

Tracking des items traités : fichier JSON local /home/debian/joplin_compress_log.json — évite de retraiter les ressources déjà compressées lors des passages quotidiens.

Propagation sync : Joplin détecte les changements via updated_time. Lors de la prochaine synchronisation de chaque client, les ressources compressées sont re-téléchargées automatiquement.

Phase 3 — Service systemd (cron quotidien)

Timer systemd joplin-compress.timer → joplin-compress.service :


Mise en production — 14/06/2026

Résultat du premier run (stock complet)

Ressources traitées736 au total
Compressées424
Ignorées (gain < 5%)312
Erreurs0
Poids avant476 Mo
Poids après119,7 Mo
Économie356 Mo (-78,9%)

Scripts déployés sur le VPS

ScriptRôleOptions
/home/debian/joplin_compress.py Compression Pillow PNG/JPEG → JPEG 85%, ZIP multi-pages, mise à jour PostgreSQL --dry-run (simulation) / --limit N (N ressources max)
/home/debian/joplin_observatoire.py Stats DB + top 15 → mise à jour page BookStack Joplin (ID 166) —

Log tracking : /home/debian/joplin_compress_log.json — liste des ressources déjà traitées, évite les doublons aux runs suivants.

Timer systemd

Servicejoplin-compress.service
Timerjoplin-compress.timer
DéclenchementChaque nuit à 3h UTC (OnCalendar=*-*-* 03:00:00)
Logs/var/log/joplin-compress.log
Statutactive (waiting) — prochain run : 15/06/2026 03:00 UTC

Notes techniques


Réexamen du 2026-08-27 — Caesium n'apporte rien, mais la base pèse 1 263 Mo

Question posée : la procédure Photos-Caesium (page 284), qui compresse les photos du PC avec caesiumclt, pourrait-elle profiter aussi à Joplin ? Réponse mesurée : non pour les images, mais l'examen a mis au jour un problème dix fois plus lourd.

1. Le gisement image est épuisé

État au 2026-08-27 : 729 ressources, 117,2 Mo (contre 476 Mo avant la procédure de juin, soit -79,3 %). Répartition par signature :

SignatureFormatNombrePoids
ffd8ffe0JPEG/JFIF — produits par Pillow551105 Mo
25504446PDF55,0 Mo
89504e47PNG restants424,3 Mo
ffd8ffe1JPEG avec EXIF (originaux)241,7 Mo
autresWebP, SVG, HTML, GIF, MP41071,3 Mo

Test réalisé sur deux échantillons extraits de la base (20 JPEG tirés au hasard, 5,20 Mo ; les 20 plus gros PNG, 3,84 Mo), compressés avec caesiumclt 1.4.0 sur le PC — aucune installation sur le VPS :

PopulationPasse CaesiumGainCoût qualité
551 JPEG (105 Mo)--lossless-5,0 %aucun, pixels intacts
-q 85 (mozjpeg vs libjpeg)-14,8 %2e génération de perte
-q 80-32,0 %perte visible sur du texte
42 PNG (4,3 Mo)--lossless-27,7 %aucun
--lossless --zopfli-29,8 %aucun (mais très lent)
-q 80-69,1 %quantification, mauvais pour du texte

Conclusion : un passage Caesium sans risque récupérerait environ 6,5 Mo sur 117, soit -5,5 %. Le jeu n'en vaut pas la chandelle. La procédure de juin a pris l'essentiel du gain, et une seconde passe lossy sur des captures d'écran dégraderait le texte pour un bénéfice marginal.

Réserve méthodologique : la procédure actuelle convertit les PNG en JPEG q85. Pour des captures d'écran, le JPEG est un mauvais format — il crée du crénelage autour du texte. Une optimisation PNG sans perte (-27,7 % mesurés) serait meilleure en qualité pour un gain comparable. Priorité faible : il n'arrive que 3 à 4 images par semaine.

Vérification que le script quotidien fonctionne toujours : les 12 ressources les plus récentes sont toutes en ffd8ffe0 dès qu'elles ont une taille significative, donc bien passées par Pillow. L'image du 27/08 (113 ko) correspond exactement à la ligne de log [OK] NkiVrkTlkYIp033uedJsdd PNG 900KB -> 113KB (87.4%). Le dispositif est vivant.

2. Le vrai poids : la table events, 1 072 Mo pour 7,28 millions de lignes

La base joplin pèse 1 263 Mo. Les images, TOAST compris, n'en représentent que 172.

TableTotal (avec index)Table seuleLignes vivantes
events1 072 Mo500 Mo7 287 073
items (notes + images)172 Mo2 048 ko2 642
changes8 080 ko3 992 ko0
tout le reste~2,5 Mo——

Les index d'events pèsent à eux seuls 573 Mo (events_id_unique 284 Mo, events_pkey 156 Mo, plus deux index secondaires).

Origine

TaskService.runTask() écrit un événement au début et à la fin de chaque tâche de fond (EventType.TaskStarted puis TaskCompleted). Une de ces tâches tourne toutes les ~10 secondes. Cadence mesurée : 23 400 lignes par jour, sans interruption depuis le 30/09/2025. Soit environ 1 Go par an.

Ces lignes ne servent à rien : EventModel ne lit jamais que le dernier événement par (type, nom), via lastEventByTypeAndName (orderBy('counter','desc').first()). Les 7,28 millions d'autres sont mortes.

Cause : un interrupteur laissé sur « off »

Joplin Server livre sa propre tâche de purge, désactivée par défaut. Dans l'image installée (joplin/server 3.7.1) :

dist/env.js:122    EVENTS_AUTO_DELETE_ENABLED: false
dist/env.js:123    EVENTS_AUTO_DELETE_AFTER_DAYS: 30

dist/utils/setupTaskService.js:105
    if (config.EVENTS_AUTO_DELETE_ENABLED) {
        tasks.push({
            id: TaskId.DeleteOldEvents,
            schedule: '0 0 * * *',
            run: (models) => models.event().deleteOldEvents(
                     config.EVENTS_AUTO_DELETE_AFTER_DAYS * Day),
        });
    }

Le container joplin ne définit pas la variable (seul MAX_ITEM_SIZE figure parmi les réglages non standard). La tâche DeleteOldEvents n'a donc jamais été enregistrée, et rien n'a jamais été purgé.

Ce que ça coûte

Correction — à appliquer

Purge à 30 jours : il resterait ~702 000 lignes au lieu de 7 282 457, soit -90,4 %. La sauvegarde maigrit immédiatement (pg_dump n'exporte que les lignes vivantes) ; le disque n'est rendu qu'après un VACUUM FULL.

  1. Activer le mécanisme officiel — stack Portainer 16, service joplin, ajouter aux variables d'environnement :
          - EVENTS_AUTO_DELETE_ENABLED=1
          - EVENTS_AUTO_DELETE_AFTER_DAYS=30
    puis mettre la stack à jour. La tâche s'exécute alors chaque nuit à minuit UTC — sans conflit avec la sauvegarde de 2 h.
  2. Rendre l'espace au disque, une fois le premier passage effectué :
    sudo docker exec joplin-db psql -U joplin -d joplin -c "VACUUM FULL events;"
    Verrou exclusif, mais bref une fois la table réduite.

Variante plus douce, si l'on préfère éviter que le premier passage supprime 6,58 millions de lignes en une seule instruction : faire le rattrapage par lots avant d'activer la tâche — créer CREATE INDEX CONCURRENTLY tmp_events_created ON events(created_time), boucler des DELETE … WHERE ctid IN (SELECT ctid … LIMIT 500000), retirer l'index, puis VACUUM FULL.

3. Bug corrigé le 2026-08-27 — l'observatoire ne tournait plus depuis 72 jours

joplin_observatoire.py plantait chaque nuit depuis la mi-juin : psycopg2.OperationalError: connection to server at "172.27.0.4" … Connection refused. L'IP Docker de joplin-db était passée à 172.27.0.3 lors d'une recréation du container.

Le correctif du 2026-06-19, qui remplaçait l'IP figée par une résolution dynamique, n'avait été appliqué qu'à joplin_compress.py — l'observatoire avait été oublié. La compression, elle, a continué de fonctionner normalement pendant toute la période.

Même correctif appliqué (docker inspect joplin-db au démarrage), sauvegarde joplin_observatoire.py.bak-260827. Exécution de contrôle réussie : page 166 réalimentée — 729 ressources, 117,2 Mo, -79,3 %.

Leçon : le compteur de tracebacks du log est un bon canari. sudo grep -c Traceback /var/log/joplin-compress.log renvoyait 72 — une par nuit — sans que personne ne s'en aperçoive, parce que la partie compression, elle, écrivait des lignes normales.

02_les petites procédures de Claude

260615 - Immich performance

260615 -instructions pour la procédure Immich Performance
Les photos de famille (et des vidéos) sont un patrimoine important pour notre famille. Donc elles font l'objet de beaucoup d'attention....et de volume de stockage. Les photos sont stockées sur les 2 NAS - Nasmaison et Sasnexte synchronisées à travers les outils Synology. A partir de Sasnexte, un script journalier Synology les propulse sur le VPS Kdrive pour être lues en lecture seule par toute la famille (elles sont également sur deux autres disques durs USB....). 

Aujourd'hui, le dossier photos du Sasnexte que l'on doit considérer comme le cœur de ce dispositif nécessite une observation un peu plus fine car : 
- des compressions vidéos doivent être faites pour les rendre plus faciles en lecture sur les portables en mobilité
- des compressions images lorsque le poids est aberrant pour l'usage
- des doublons existent forcément.

Immich performance est une procédure importante du livre de Claude. 

Réponse de Claude


Inventaire par Claude Code le 01/10/2025


SAS_NEXTE@NEXTE:~$ sudo du -h --max-depth=2 /volume1/photo/ | sort -h  
0 /volume1/photo/1968-1994 - photos famille dont Noumea/1982  
0 /volume1/photo/2009-mariage Zymny  
0 /volume1/photo/2014- été/140714-Lyon chez Pierre  
0 /volume1/photo/2020 - Automne Noel/noel2020  
0 /volume1/photo/2024/202401 - Hiver Automne  
0 /volume1/photo/2025/DCIM  
0 /volume1/photo/@eaDir/clientd.tmp.dir  
0 /volume1/photo/@eaDir/cloud.tmp.dir  
0 /volume1/photo/@eaDir/@recycle  
0 /volume1/photo/@eaDir/@tmp  
4.0K /volume1/photo/@eaDir/@drive.queues  
24K /volume1/photo/@eaDir/sharesnap_share_configuration  
32K /volume1/photo/2010 - été/@eaDir  
40K /volume1/photo/2011- Ete/@eaDir  
52K /volume1/photo/2021-été covidé/@eaDir  
84K /volume1/photo/@eaDir/980710-photo CV julien.jpg  
264K /volume1/photo/@eaDir/131124-elio pas content.jpg  
352K /volume1/photo/2009 Nouvel an Réveillon/@eaDir  
432K /volume1/photo/@eaDir/2015-soirée mexicaine.jpg  
440K /volume1/photo/1968-1994 - photos famille dont Noumea/Givet  
548K /volume1/photo/@eaDir/150314-Zoee en 18X24.png  
616K /volume1/photo/2009 Nouvel an Réveillon  
656K /volume1/photo/1968-1994 - photos famille dont Noumea/1977  
656K /volume1/photo/@eaDir/7b06435c-6bad-4eb0-aa38-af03bdfbfbc8.jpg  
672K /volume1/photo/@eaDir/PhotoLab445379.jpg  
792K /volume1/photo/@eaDir/160220-elio en 18X24.png  
848K /volume1/photo/2011 - printemps/@eaDir  
900K /volume1/photo/2016 ACDC/@eaDir  
1.5M /volume1/photo/1968-1994 - photos famille dont Noumea/1976  
1.7M /volume1/photo/1968-1994 - photos famille dont Noumea/Pierre-001  
2.1M /volume1/photo/1968-1994 - photos famille dont Noumea/1969  
3.0M /volume1/photo/1968-1994 - photos famille dont Noumea/1978  
3.4M /volume1/photo/1968-1994 - photos famille dont Noumea/1968  
3.4M /volume1/photo/1968-1994 - photos famille dont Noumea/1980  
3.5M /volume1/photo/2014-mars-repas chez maman/@eaDir  
4.1M /volume1/photo/1999/@eaDir  
4.3M /volume1/photo/2014 - 4 ans Zoée/@eaDir  
4.9M /volume1/photo/1968-1994 - photos famille dont Noumea/1979  
4.9M /volume1/photo/2016 ACDC  
5.3M /volume1/photo/1986 - Californie/@eaDir  
5.3M /volume1/photo/Cartes de voeux/@eaDir  
5.5M /volume1/photo/2010-hiver/@eaDir  
6.0M /volume1/photo/1968-1994 - photos famille dont Noumea/1992  
6.6M /volume1/photo/1930-2016 - Photos BERTRAND MER/Elio  
6.6M /volume1/photo/2016-best photos pour 70 ans/Elio  
6.7M /volume1/photo/1999  
6.9M /volume1/photo/1968-1994 - photos famille dont Noumea/Etats-Unis 1986  
7.4M /volume1/photo/2015 - Noël/@eaDir  
7.6M /volume1/photo/1930-2016 - Photos BERTRAND MER/Les communions solennelle s  
7.6M /volume1/photo/2016-best photos pour 70 ans/Les communions solennelles  
7.8M /volume1/photo/1968-1994 - photos famille dont Noumea/1994  
7.9M /volume1/photo/2013-Serbie/@eaDir  
8.0M /volume1/photo/2014/@eaDir  
8.4M /volume1/photo/1968-1994 - photos famille dont Noumea/1990  
8.5M /volume1/photo/2004 - été/@eaDir  
8.5M /volume1/photo/2022-Noel/@eaDir  
8.6M /volume1/photo/2015 - Automne/@eaDir  
8.9M /volume1/photo/1930-2016 - Photos BERTRAND MER/Les amis, la famille en n oir et blanc  
8.9M /volume1/photo/2016-best photos pour 70 ans/Les amis, la famille en noir et blanc  
9.5M /volume1/photo/1968-1994 - photos famille dont Noumea/1981  
9.9M /volume1/photo/2018 - Noel/@eaDir  
10M /volume1/photo/#recycle/2016 - 70 ans maman_DiskStation_Nov-04-1745-2020 _CaseConflict  
11M /volume1/photo/1930-2016 - Photos BERTRAND MER/Album de la famille de Re née Campanella  
11M /volume1/photo/2010 - naissance Zoée/@eaDir  
11M /volume1/photo/2014/Noël 2014  
11M /volume1/photo/2016-best photos pour 70 ans/Album de la famille de Renée Campanella  
12M /volume1/photo/2013 Marseille/@eaDir  
12M /volume1/photo/2014-mars-repas chez maman  
12M /volume1/photo/2015-Hiver/@eaDir  
12M /volume1/photo/2015-inventaire maison assurances/@eaDir  
13M /volume1/photo/1968-1994 - photos famille dont Noumea/1975  
14M /volume1/photo/1968-1994 - photos famille dont Noumea/1983  
15M /volume1/photo/2005 - été/@eaDir  
16M /volume1/photo/2016-mai juin/@eaDir  
16M /volume1/photo/2016 - Valras/@eaDir  
17M /volume1/photo/2004 - été  
17M /volume1/photo/2010 - naissance Zoée  
18M /volume1/photo/1968-1977/@eaDir  
18M /volume1/photo/2014 - 4 ans Zoée  
18M /volume1/photo/2014/Anniversaire_Elio_2014  
18M /volume1/photo/2016-avril avant crète/@eaDir  
19M /volume1/photo/1930-2016 - Photos BERTRAND MER/Grand-père Emile et mamie Rosa  
19M /volume1/photo/2016-best photos pour 70 ans/Grand-père Emile et mamie Ro sa  
21M /volume1/photo/1930-2016 - Photos BERTRAND MER/@eaDir  
21M /volume1/photo/1930-2016 - Photos BERTRAND MER/L'album de Papa et Maman  
21M /volume1/photo/2016-best photos pour 70 ans/L'album de Papa et Maman  
21M /volume1/photo/2016- photos Maman Papa/@eaDir  
22M /volume1/photo/2011 - Automne/@eaDir  
22M /volume1/photo/2013 Noël/@eaDir  
22M /volume1/photo/2014-Hiver Printemps/@eaDir  
23M /volume1/photo/2014 - Automne Noel/@eaDir  
24M /volume1/photo/2011 - jour de l'an/@eaDir  
24M /volume1/photo/2014-mur effondré - Ville de Toulon/@eaDir  
25M /volume1/photo/2009 - Papa/@eaDir  
25M /volume1/photo/2010-hiver  
25M /volume1/photo/2021-été covidé/2021 - après vacances  
25M /volume1/photo/Cartes de voeux  
26M /volume1/photo/1968-1994 - photos famille dont Noumea/1984  
27M /volume1/photo/1930-2016 - Photos BERTRAND MER/Enfants Mer et cousins  
27M /volume1/photo/2008 Toscane/@eaDir  
27M /volume1/photo/2016 - 70 ans Maman/@eaDir  
27M /volume1/photo/2016-best photos pour 70 ans/Enfants Mer et cousins  
27M /volume1/photo/2022-automne a Noel/@eaDir  
29M /volume1/photo/2018 - Noel  
30M /volume1/photo/2008 - mariage Héléna et Jérome/@eaDir  
30M /volume1/photo/2012 - Eté/@eaDir  
30M /volume1/photo/#recycle/2016 - 70 ans maman_DiskStation_Nov-04-1745-2020 _CaseConflict_1  
31M /volume1/photo/2025/2501 à 2502  
32M /volume1/photo/2015 - Noël  
33M /volume1/photo/2014/Carnaval 2014  
34M /volume1/photo/2016-best photos pour 70 ans/@eaDir  
35M /volume1/photo/2014-Barcelone/@eaDir  
36M /volume1/photo/2013/@eaDir  
36M /volume1/photo/2016-Parc Vert Coteau/soirée janvier 2016  
36M /volume1/photo/2024/2024 - Nouvel an Arriège  
37M /volume1/photo/2015 - Automne  
38M /volume1/photo/2014/Février 2014  
39M /volume1/photo/2011 - Noel/@eaDir  
39M /volume1/photo/2020 - Automne Noel/@eaDir  
40M /volume1/photo/2014/Sept_2014_4ans_Zoée  
40M /volume1/photo/@eaDir/SYNO@.fileindexdb  
41M /volume1/photo/2016-Parc Vert Coteau/avril 2016 état  
41M /volume1/photo/2022-Noel  
43M /volume1/photo/@eaDir  
44M /volume1/photo/2009 - Papa  
44M /volume1/photo/2012/@eaDir  
45M /volume1/photo/1930-2016 - Photos BERTRAND MER/Papa juin 2009 - Le livre d'Alain  
45M /volume1/photo/2016-best photos pour 70 ans/Papa juin 2009 - Le livre d' Alain  
47M /volume1/photo/2005 - été  
47M /volume1/photo/2008 Toscane  
50M /volume1/photo/2019-Cabaret Vert/@eaDir  
51M /volume1/photo/2015 - Juillet Valras/@eaDir  
52M /volume1/photo/2021-hiver printemps/@eaDir  
53M /volume1/photo/2015-Hiver  
53M /volume1/photo/2018-défi Genes/@eaDir  
54M /volume1/photo/2008 - été Hautes Alpes/@eaDir  
54M /volume1/photo/2009 - Elio/@eaDir  
55M /volume1/photo/2013-Serbie  
58M /volume1/photo/2013 Marseille  
58M /volume1/photo/2015-inventaire maison assurances  
62M /volume1/photo/2007-1er janvier/@eaDir  
62M /volume1/photo/2016 - Valras  
64M /volume1/photo/2014- été/@eaDir  
67M /volume1/photo/2009 - été Irlande/@eaDir  
67M /volume1/photo/2016-mai juin  
70M /volume1/photo/1968-1994 - photos famille dont Noumea/Nouméa  
70M /volume1/photo/2011- Ete/GARD juillet 2011  
71M /volume1/photo/2020 - Hiver Confinement COVID/@eaDir  
73M /volume1/photo/2022-hiver à Paques/@eaDir  
73M /volume1/photo/2024/202412 - Automne Noel  
75M /volume1/photo/2013 - Printemps/@eaDir  
76M /volume1/photo/2016-Parc Vert Coteau  
76M /volume1/photo/2024/@eaDir  
79M /volume1/photo/2012 - Eté/2012 - Bretagne  
79M /volume1/photo/2014-Hiver Printemps  
81M /volume1/photo/2013 Noël  
82M /volume1/photo/2017-Voyage à Turin/@eaDir  
84M /volume1/photo/2016-Venasque/@eaDir  
86M /volume1/photo/1986 - Californie  
88M /volume1/photo/2023-ete/@eaDir  
91M /volume1/photo/2009 - été Ardèche/@eaDir  
93M /volume1/photo/2016-avril avant crète  
94M /volume1/photo/2007-1er janvier  
96M /volume1/photo/2021-Automne et Noel/@eaDir  
97M /volume1/photo/2008 - été Hautes Alpes  
99M /volume1/photo/PhotoLibrary/2025  
100M /volume1/photo/2014- Porto - Primavera/@eaDir  
107M /volume1/photo/2014-mur effondré - Ville de Toulon  
108M /volume1/photo/2023 - Automne Noel/@eaDir  
111M /volume1/photo/2009 - été Irlande  
111M /volume1/photo/2015- printemps/@eaDir  
114M /volume1/photo/2025/2504 et 2505  
125M /volume1/photo/2010 - été  
125M /volume1/photo/2010 - été/Beauduc  
125M /volume1/photo/2014 - Automne Noel  
130M /volume1/photo/2016-Crete/@eaDir  
131M /volume1/photo/2011 - jour de l'an  
138M /volume1/photo/2021-été covidé/2021 avant vacances  
139M /volume1/photo/2013  
140M /volume1/photo/2018 - Valras/@eaDir  
143M /volume1/photo/2016-Automne Noel/@eaDir  
145M /volume1/photo/2013-Pays Bas/@eaDir  
146M /volume1/photo/2014-Barcelone  
150M /volume1/photo/2023-Hiver à Paques/@eaDir  
152M /volume1/photo/2008 - mariage Héléna et Jérome  
153M /volume1/photo/2017-Automne Noel/@eaDir  
154M /volume1/photo/2014/Mai_Juin 2014  
157M /volume1/photo/2014/Avril 2014  
159M /volume1/photo/2022-automne a Noel  
162M /volume1/photo/2009 - été Ardèche  
173M /volume1/photo/2014 - 5 jours en Corse/@eaDir  
178M /volume1/photo/2016-best photos pour 70 ans/Ma famille pour mes 70 ans  
178M /volume1/photo/2020 -Printemps/@eaDir  
179M /volume1/photo/1930-2016 - Photos BERTRAND MER  
180M /volume1/photo/1968-1994 - photos famille dont Noumea  
181M /volume1/photo/2019- Hiver Printemps/@eaDir  
181M /volume1/photo/2022 - été Flandres NL Paris/@eaDir  
183M /volume1/photo/2012  
184M /volume1/photo/2009 - Elio  
186M /volume1/photo/2014/2014-été  
192M /volume1/photo/2016- photos Maman Papa  
203M /volume1/photo/1968-1977  
206M /volume1/photo/1967 à 2000 - photos famille Bertrand/@eaDir  
213M /volume1/photo/2023-Mai à Vacances Eté/@eaDir  
214M /volume1/photo/2019-Automne/@eaDir  
222M /volume1/photo/2015 - Juillet Valras  
229M /volume1/photo/2020 - Automne Noel  
230M /volume1/photo/2018-printemps/@eaDir  
258M /volume1/photo/2021-hiver printemps  
281M /volume1/photo/2014- été  
282M /volume1/photo/2018 - automne noel/@eaDir  
323M /volume1/photo/2011 - Noel  
325M /volume1/photo/2018-défi Genes  
348M /volume1/photo/2005 - naissance Elio/@eaDir  
354M /volume1/photo/2011 - printemps  
368M /volume1/photo/2011 - Automne  
381M /volume1/photo/2017-Hiver-Printemps/@eaDir  
384M /volume1/photo/2016-Venasque  
407M /volume1/photo/2020 -Printemps  
409M /volume1/photo/2016-best photos pour 70 ans  
419M /volume1/photo/2016 - 70 ans Maman  
434M /volume1/photo/2020 - Hiver Confinement COVID  
439M /volume1/photo/2017-Voyage à Turin  
460M /volume1/photo/2023-Mai à Vacances Eté  
462M /volume1/photo/2011- Ete/LIGURIE aout 2011  
500M /volume1/photo/2013 - Printemps  
511M /volume1/photo/2023-ete  
515M /volume1/photo/2022-hiver à Paques  
520M /volume1/photo/2012 - Eté/2012 - été Buis  
525M /volume1/photo/2016-Crete  
528M /volume1/photo/2014- Porto - Primavera  
531M /volume1/photo/2011- Ete  
535M /volume1/photo/2023-Vacances D NL B/@eaDir  
573M /volume1/photo/2023 - Automne Noel  
575M /volume1/photo/2016-été Ré Gers/@eaDir  
580M /volume1/photo/2018-Barcelone Primavera Sound/@eaDir  
618M /volume1/photo/2019-Cabaret Vert  
629M /volume1/photo/2019 Bretagne Alpes/@eaDir  
635M /volume1/photo/2013-Pays Bas  
663M /volume1/photo/2021-Automne et Noel  
667M /volume1/photo/2014  
685M /volume1/photo/2015- printemps  
700M /volume1/photo/2017-été Scandinavie/@eaDir  
718M /volume1/photo/2024/2024 - Eté Italie Autriche  
759M /volume1/photo/2018 - Valras  
809M /volume1/photo/#recycle/2025  
817M /volume1/photo/2016-Automne Noel  
846M /volume1/photo/2025/2506 à 2509  
860M /volume1/photo/#recycle  
907M /volume1/photo/2019-Automne  
920M /volume1/photo/2017-Automne Noel  
935M /volume1/photo/2023-Hiver à Paques  
941M /volume1/photo/2024/2024-Porto  
944M /volume1/photo/cecile tri 2022/@eaDir  
945M /volume1/photo/PhotoLibrary/DCIM  
956M /volume1/photo/2005 - naissance Elio  
964M /volume1/photo/2020 - été Vienne Venise/@eaDir  
991M /volume1/photo/2025  
1.1G /volume1/photo/2014 - 5 jours en Corse  
1.1G /volume1/photo/2015-Croatie Autriche/@eaDir  
1.1G /volume1/photo/2018-the Alpen/@eaDir  
1.1G /volume1/photo/PhotoLibrary  
1.2G /volume1/photo/2021-été covidé/2021 - vacances Aout Mont Blanc Cantal  
1.2G /volume1/photo/2022 - été Flandres NL Paris  
1.3G /volume1/photo/2019- Hiver Printemps  
1.3G /volume1/photo/2021-été covidé  
1.4G /volume1/photo/2018-printemps  
1.5G /volume1/photo/2016-été Ré Gers/Vidéo Aveyron Ré et Gers  
1.5G /volume1/photo/2024/2024-Via Reggio  
1.8G /volume1/photo/2018 - automne noel  
1.9G /volume1/photo/2012 - Eté/2012- été Italia  
2.0G /volume1/photo/2017-Hiver-Printemps  
2.7G /volume1/photo/2012 - Eté  
2.8G /volume1/photo/2019 Bretagne Alpes  
2.8G /volume1/photo/2020 - été Vienne Venise  
2.9G /volume1/photo/1967 à 2000 - photos famille Bertrand  
3.2G /volume1/photo/2023-Vacances D NL B  
3.6G /volume1/photo/2018-Barcelone Primavera Sound  
3.7G /volume1/photo/cecile tri 2022  
3.8G /volume1/photo/2024  
4.1G /volume1/photo/2016-été Ré Gers  
4.2G /volume1/photo/2017-été Scandinavie  
5.7G /volume1/photo/2018-the Alpen  
6.4G /volume1/photo/2015-Croatie Autriche  
79G /volume1/photo/

02_les petites procédures de Claude

Montages Rclone Sasnexte et Kdrive

Architecture

NAS Sasnexte (Synology)
    └── rclone sync (WebDAV) ──► kDrive Infomaniak
                                      └── rclone mount (FUSE) ──► VPS Jux
                                                                     └── containers Docker

Le NAS pousse les médias vers kDrive une fois par jour via le planificateur DSM. Le VPS monte kDrive en FUSE en permanence — les containers accèdent aux fichiers en lecture.


Remote rclone (NAS sasnexte)

Fichier : /volume1/homes/SAS_NEXTE/.config/rclone/rclone.conf

[kdrive_music]
type = webdav
url = https://591617.connect.kdrive.infomaniak.com
vendor = other
user = julien.bertrand@nexte.fr
pass = [obfusqué rclone]

Note : le remote s'appelle kdrive_music mais sert à synchroniser tous les contenus (musique, photos, audiobooks, Komga). Nom historique à ne pas confondre avec un remote dédié musique.

Mot de passe WebDAV : régénéré le 2026-06-23 (compte julien.bertrand@nexte.fr, espace kDrive 591617). Mise à jour via rclone config update kdrive_music pass $(rclone obscure NOUVEAU_MDP).


Script unifié (NAS sasnexte)

Emplacement : /volume1/homes/SAS_NEXTE/scripts/sync_kdrive_complete.sh
Planificateur DSM : tâche déclenchée quotidiennement — commande : /volume1/homes/SAS_NEXTE/scripts/sync_kdrive_complete.sh

Note sudo : le script contient sudo -u SAS_NEXTE rclone .... Si la tâche DSM est configurée pour tourner en tant que SAS_NEXTE, retirer le sudo -u SAS_NEXTE (inutile et peut bloquer). Si elle tourne en root, le garder.

Le script n'est plus recopie ici : il est versionne dans l'arbre Syncthing, seule source de verite — Jux-scripts/NAS-Sync/sync_kdrive_complete.sh, deploye sur le NAS dans /volume1/homes/SAS_NEXTE/scripts/. La version en ligne ci-dessous datait du 2026-06-23 et n'avait aucune protection ; elle a ete remplacee le 2026-08-28 par la version durcie decrite plus bas. Sauvegarde de l'ancienne sur le NAS : sync_kdrive_complete.sh.bak-260828.

Déploiement : écrire via vi depuis SSH — le heredoc et les éditeurs Windows introduisent des CRLF qui cassent bash. Après édition : sed -i 's/\r//' script.sh pour vérifier.


Syncs actifs

Nom Source NAS Destination kDrive Notes
audiobooks /volume1/audiobooks SYNC-pour_VPS/Sync-SASNEXTE/audiobooks  
music /volume1/music SYNC-pour_VPS/Sync-SASNEXTE/music  
photo /volume1/photo/2026 SYNC-pour_VPS/Sync-SASNEXTE/photo/2026 Année courante seulement
komga /volume1/Komga SYNC-pour_VPS/Sync-SASNEXTE/Komga  

Non géré ici :


Options rclone — justifications

Option Rôle
--delete-excluded Supprime sur kDrive les fichiers exclus qui auraient pu y être uploadés
--ignore-errors Poursuit la sync si un fichier est inaccessible (NAS Synology parfois occupé)
--delete-during Supprime les fichiers obsolètes au fil du scan, pas en fin de run
--fast-list Réduit les appels API WebDAV (un seul listing récursif)
@eaDir/** Dossiers de métadonnées Synology (miniatures)
#recycle/** Corbeille Synology
@__thumb/** Miniatures Synology
*.@SynoResource / *.@SynoEAStream Flux de ressources étendues Synology
--transfers=4 4 fichiers en parallèle — équilibre entre perf et charge WebDAV
--checkers=8 8 vérifications de hash en parallèle
--timeout=5m Timeout par opération I/O
--contimeout=2m Timeout de connexion initiale

Côté VPS — montages FUSE correspondants

Les services systemd sur le VPS montent les dossiers kDrive en FUSE :

Service systemd Point de montage Source kDrive
rclone-audiobookshelf.service /home/debian/audiobookshelf/audiobooks SYNC-pour_VPS/Sync-SASNEXTE/audiobooks
kdrive-music.service /home/debian/music SYNC-pour_VPS/Sync-SASNEXTE/music
rclone-photo.service /home/debian/photo SYNC-pour_VPS/Sync-SASNEXTE/photo
kdrive-komga.service /home/debian/komga SYNC-pour_VPS/Sync-SASNEXTE/Komga

Remote VPS : kdrive: — remote natif Infomaniak (@infomaniak/mcp-server-kdrive), compte julien.bertrand@live.fr, kDrive ID 591617.


Logs


Panne du 2026-08-28 — les 4 syncs a l'arret, cause : rclone.conf deplace

Symptome : les photos de l'ete 2026 deposees la veille sur le NAS ne remontaient pas sur kDrive. Ni par la tache planifiee, ni par un lancement manuel du script — ce qui excluait d'emblee un probleme de reseau ou de quota.

Message dans le journal du jour (/volume1/homes/SAS_NEXTE/logs/sync_photo_AAAAMMJJ_*.log) :

NOTICE: Config file "/var/services/homes/SAS_NEXTE/.config/rclone/rclone.conf" not found - using defaults
CRITICAL: Failed to create file system for "kdrive_music:...": didn't find section in config file ("kdrive_music")

Cause : le 2026-08-27 a 10:16, le dossier .config du home a ete range dans /volume1/homes/SAS_NEXTE/Fichiers techniques/. Le script ne passait pas --config : rclone cherchait donc $HOME/.config/rclone/rclone.conf et ne trouvait plus le remote. Les quatre syncs sont mortes d'un coup (photo, music, komga, audiobooks), des le run suivant.

Correction : fichier recopie a sa place (chmod 600) ; une copie subsiste dans Fichiers techniques et sert desormais de secours automatique (voir plus bas).

Ce que cet incident apprend


Durcissement du script (2026-08-28)

Source de verite : Jux-scripts/NAS-Sync/sync_kdrive_complete.sh (arbre Syncthing, disponible sur toutes les machines). Le comportement nominal est inchange — memes 4 syncs, memes options rclone, meme emplacement, la tache DSM n'a pas besoin d'etre modifiee.

Protection Ce qu'elle evite
--config en chemin absolu La panne ci-dessus : le script ne depend plus de $HOME ni de l'utilisateur qui le lance
Restauration automatique de la config depuis Fichiers techniques/.config/rclone/rclone.conf Un nouveau deplacement du fichier ne coupe plus la synchro ; l'evenement est journalise
Controles prealables : rclone present, section [kdrive_music] presente, remote reellement joignable Partir en synchro avec un mot de passe WebDAV revoque ou kDrive injoignable
Refus de synchroniser une source absente ou vide Le scenario catastrophe : un volume non monte ou un dossier vide, qui en mode miroir viderait la destination kDrive
--max-delete par service (photo 500, les autres 1000) Une suppression de masse imprevue : la sync s'interrompt et attend un oeil humain
Ligne === BILAN: X/4 OK === et fichier d'etat logs/etat_sync.txt Avoir a lire quatre journaux pour savoir si la nuit s'est bien passee
Code de sortie non nul en cas d'echec + entree dans le journal systeme DSM L'echec silencieux
Purge des journaux de plus de 90 jours L'accumulation dans logs/

Mode d'emploi

S=/volume1/homes/SAS_NEXTE/scripts/sync_kdrive_complete.sh
$S                                  # les 4 syncs (ce que lance la tache DSM)
DRY_RUN=1 $S                        # essai a blanc, rien n'est ecrit sur kDrive
SERVICES="photo music" $S           # un sous-ensemble seulement
SERVICES="photo" FORCE_MAX_DELETE=1 $S   # apres verification, lever le garde-fou

cat /volume1/homes/SAS_NEXTE/logs/etat_sync.txt   # resultat du dernier run

Canari — savoir en une commande si la nuit s'est bien passee

cat /volume1/homes/SAS_NEXTE/logs/etat_sync.txt
grep -l CRITICAL /volume1/homes/SAS_NEXTE/logs/sync_*_$(date +%Y%m%d)*.log

Notifications — pourquoi pas synodsmnotify

Sur DSM 7.4, synodsmnotify n'accepte pas de titre libre : tout libelle est rejete par title: '...' is neither mail string key nor i18n format, y compris les formes i18n:... essayees. Le script utilise donc synologset1 sys err 0x11100000, qui ecrit dans le journal systeme DSM (Centre de journalisation).

Action restante cote DSM (a faire par Julien, compte admin) : dans Planificateur de taches → tache de synchronisation → Parametres, cocher « Envoyer les details d'execution par e-mail » et « uniquement lorsque le script se termine anormalement ». C'est maintenant efficace : l'ancien script retournait toujours 0, la version durcie retourne 1 des qu'un service echoue.

Tests de validation passes le 2026-08-28


REX déploiement 2026-06-23

02_les petites procédures de Claude

260727 - Claude en MCP sur le NASmaison

Le NASmaison est un petit Synology DS218j installé à la maison de Julien. IL sert surtout de stockage des livres et des films. Egalement des cartes rasters, le dossier personnel de Cécile, Elio et Zoée. IL a une copie miroir du dossier musique et komga, mais plus photos.

Il est synchronisé avec le NAS SASNEXTE pour musique et Komga.

Il compose au quotidien 6 procédures hyperbacups de la bibliothèque de livres en direction du Kdrive :

Claude a désormais une connexion MCP privilégiée sur le NASmaison. Et peut notamment garantir le transfert sécurisé des dossiers 

 

 

 

 

 

02_les petites procédures de Claude

260731-Claude et SASNEXTE sur le PC Elio+Jux

WireGuard sasnexte sur le PC Elio+Jux — diagnostic et résolution

Date : 2026-07-31 | Machine : PC Windows eliob | NAS cible : sasnexte (82.66.244.248) Statut : RÉSOLU — tunnel activé, lecteur S: mappé sur \\10.0.0.2\NEXTE

Question initiale

WireGuard a été monté sur ce PC et sur le NAS sasnexte, mais le disque du NAS n'apparaissait pas comme lecteur dans l'explorateur de fichiers Windows. Pourquoi ?

Réponse courte

Deux causes cumulées :

  1. Le tunnel n'était pas activé sur le PC : la config vps_maisonpc_sasnexte était importée dans l'application WireGuard, mais jamais activée (aucun service WireGuardTunnel$*, aucun adaptateur réseau, wg show vide).
  2. Un lecteur réseau ne se crée jamais tout seul : la découverte réseau Windows (broadcast/mDNS/WS-Discovery) ne traverse pas un tunnel de couche 3 — le NAS n'apparaîtra jamais spontanément dans « Réseau ». Il faut mapper manuellement une lettre avec net use.

Topologie du tunnel vps_maisonpc_sasnexte

Réseau 10.0.0.0/24, hub-and-spoke avec le VPS Jux comme serveur (wg0, port UDP 51820) :

IP Machine État (2026-07-31)
10.0.0.1 VPS Jux (51.77.141.54) — hub Serveur, forwarding OK (ACCEPT in wg0 dans FORWARD)
10.0.0.2 NAS sasnexte (endpoint 82.66.244.248) Connecté, handshake actif, 485 Gio transférés
10.0.0.3 PC Windows eliob Connecté (après activation du tunnel)
10.0.0.4 PC maison (peer MkzKqDe…) Jamais connecté (pas d'endpoint)

Clé publique serveur VPS : zbsY/bl4fHU1eR29PjTruK0Nrmp/BQORSlBGSh3Nkyo=

Diagnostic détaillé

Côté PC (avant activation)

Après activation du tunnel

SSH sasnexte depuis l'extérieur

Le SSH sas_nexte@82.66.244.248 (IP publique) refusait le mot de passe le 2026-07-31 alors que le même mot de passe fonctionne en SMB via le tunnel → le mot de passe est bon, c'est le SSH public qui est filtré (fail2ban/whitelist). Passer par le tunnel : ssh sas_nexte@10.0.0.2 (port 22 ouvert).

Résolution appliquée (2026-07-31)

  1. Tunnel activé dans l'app WireGuard (fait par Julien) → handshake OK avec le VPS
  2. Identifiants SMB enregistrés dans le gestionnaire d'identification Windows :
    cmdkey /add:10.0.0.2 /user:sas_nexte /pass:"xAPIJU5108§"
    
  3. Lecteur mappé :
    net use S: \\10.0.0.2\NEXTE /persistent:yes
    
  4. Vérifié : S: liste bien le contenu du partage NEXTE

Important : le lecteur S: ne fonctionne que si le tunnel WireGuard est actif. Après un reboot, le tunnel se réactive automatiquement (service WireGuardTunnel$vps_maisonpc_sasnexte en démarrage auto) et Windows reconnecte S: grâce à /persistent:yes + identifiants cmdkey.

Partages SMB disponibles sur \10.0.0.2

ActiveBackupforBusiness, audiobooks, chat, home (dossier perso SAS_NEXTE), homes, Iso VM, music, NetBackup, NEXTE (mappé sur S:), Public_s, RAW, Ressources_NEXTE, retro, web, web_packages

Pour mapper un partage supplémentaire (les identifiants sont déjà enregistrés) :

net use R: \\10.0.0.2\Ressources_NEXTE /persistent:yes

Points ouverts


Restauration du 2026-08-27 — après la réinstallation de Windows

Statut : RÉSOLU. Tunnel rétabli, S: remonté. Le poste s'appelle désormais julie — c'est la même machine que « PC Elio+Jux », réinstallée le 2026-08-08 (voir CLAUDE.md).

Ce qui s'était passé

La réinstallation de Windows a emporté WireGuard et, avec lui, la clé privée du peer 10.0.0.3. Elle vivait dans C:\Program Files\WireGuard\Data\Configurations, chiffrée par DPAPI — irrécupérable, exactement comme l'identité Syncthing PC-Elio+Jux perdue au même moment.

Le diagnostic se lit d'une seule commande sur le VPS :

peer: cMDglLZZrrZUL4QdtB5nHQFe0U5fdzXzaWnmihw1b0o=
  endpoint: 83.195.45.93:63884
  allowed ips: 10.0.0.3/32
  latest handshake: 19 days, 23 hours, 41 minutes ago

19 jours et 23 heures avant le 27/08 à 21 h ramènent au 7 août en soirée, soit la veille de la réinstallation (8 août à 12:21). Le NAS, lui, faisait des handshakes toutes les quelques secondes : côté VPS et côté NAS, rien n'était cassé. Seul le poste avait disparu.

Recherche préalable infructueuse, mais qui valait la peine : aucun .conf exporté nulle part sur D:, ni dans l'arbre Syncthing, ni dans le profil. Le point ouvert « exporter le .conf pour Ubuntu » de juillet n'avait jamais été fait — sans quoi l'identité aurait pu être restaurée telle quelle.

Décision : réutiliser l'adresse 10.0.0.3, pas le peer libre 10.0.0.4

Le peer 10.0.0.4 était disponible, mais changer d'adresse aurait invalidé la documentation et, surtout, aurait risqué de buter sur d'éventuelles règles du pare-feu Synology référençant 10.0.0.3. On garde donc l'adresse et on ne remplace que la clé publique — le NAS n'a pas été touché.

Nouvelle identité du poste

Clé publique (nouvelle) UfqCwYB3T/XFl9qbpFR/8YSibq3Yta83fB9D2GAiW2A=
Clé publique (ancienne, morte) cMDglLZZrrZUL4QdtB5nHQFe0U5fdzXzaWnmihw1b0o=
Adresse 10.0.0.3/24, inchangée
Fichier client D:\WireGuard\vps_maisonpc_sasnexte.conf — hors de l'arbre Syncthing, une clé privée n'a rien à faire sur les 7 appareils du maillage

Paire générée par une implémentation X25519 en Python pur (aucune dépendance à installer), validée au préalable contre le vecteur de test de la RFC 7748 § 6.1 avant d'être utilisée.

Configuration cliente :

[Interface]
PrivateKey = <clé privée>
Address = 10.0.0.3/24

[Peer]
PublicKey = zbsY/bl4fHU1eR29PjTruK0Nrmp/BQORSlBGSh3Nkyo=
Endpoint = 51.77.141.54:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

AllowedIPs = 10.0.0.0/24 et non 0.0.0.0/0 : seul le trafic du VPN passe par le tunnel, la navigation ordinaire n'est pas détournée par le VPS. PersistentKeepalive = 25 maintient l'association NAT de la Livebox.

Côté VPS

Sauvegarde ‌/etc/wireguard/wg0.conf.bak-260827, remplacement de la clé publique du peer 10.0.0.3 et suppression de son Endpoint périmé, puis application sans redémarrer l'interface :

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg syncconf plutôt que wg-quick down/up : c'est le point important. Un redémarrage de l'interface aurait coupé le peer du NAS et remis ses compteurs à zéro. Après syncconf, le NAS a conservé son handshake et ses 962,99 Gio de compteur, sans la moindre interruption.

Vérifié au passage : -A FORWARD -i wg0 -j ACCEPT bien présent (posé par le PostUp), ip_forward = 1, 51820/udp ouvert dans ufw.

Côté poste

winget install --id WireGuard.WireGuard -e
& "C:\Program Files\WireGuard\wireguard.exe" /installtunnelservice "D:\WireGuard\vps_maisonpc_sasnexte.conf"
cmdkey /add:10.0.0.2 /user:sas_nexte /pass:"xAPIJU5108§"
net use S: \\10.0.0.2\NEXTE /persistent:yes

/installtunnelservice évite entièrement l'interface graphique : il crée le service WireGuardTunnel$vps_maisonpc_sasnexte, le met en démarrage automatique et l'active dans la foulée. Le nom du tunnel est celui du fichier — d'où le choix de conserver vps_maisonpc_sasnexte.

⚠ Tout cela doit être tapé par Julien dans sa propre console, jamais depuis Claude Code. Le piège MSIX (page 282) ne concerne pas que les installeurs : cmdkey écrit dans %APPDATA%\Microsoft\Credentials et net use /persistent dans HKCU\Network, deux emplacements virtualisés par le conteneur. Lancées depuis une session Claude, ces commandes auraient annoncé un succès sans rien créer pour l'utilisateur.

Vérifié en direct le 2026-08-27 : une fois S: monté depuis la console de Julien, Test-Path S:\ répond False depuis la session Claude Code. Le cloisonnement joue aussi sur les lettres de lecteur — c'est un cas de plus à ajouter à la liste de la page 282.

Vérification finale

Contrôle Résultat
Test-NetConnection 10.0.0.2 -Port 445 True
net use S: « La commande s'est terminée correctement »
wg show sur le VPS — peer 10.0.0.3 endpoint 83.195.45.93:60519, handshake 36 s, 10,47 Kio reçus / 2,76 Kio envoyés
wg show sur le VPS — peer 10.0.0.2 (NAS) intact, handshake 30 s, 962,99 Gio — non perturbé

Le rappel de juillet reste valable : ne pas diagnostiquer au ping, le NAS ignore l'ICMP même tunnel actif. Test-NetConnection 10.0.0.2 -Port 445 est le seul témoin fiable.

Point ouvert, reformulé

Le peer 10.0.0.4 (MkzKqDe…) est toujours libre et n'a jamais servi. Pour raccorder la session Ubuntu, lui générer sa propre paire de clés — ne pas recopier le .conf du poste Windows, une clé privée ne se partage pas entre deux machines.

Piege du 2026-08-27 — un lecteur mappe en console administrateur reste invisible de l'explorateur

Apres la restauration du tunnel, S: n'apparaissait nulle part dans l'explorateur, et le premier reflexe (« le VPN ne marche pas ») etait faux : le service tournait, le VPS enregistrait des handshakes et du trafic.

Cause : Windows attribue deux jetons au compte administrateur — un filtre (normal) et un complet (eleve) — et les lecteurs reseau ne traversent pas cette frontiere. Les commandes d'installation (winget, /installtunnelservice) exigeant l'elevation, tout avait ete tape dans la meme console admin : net use avait donc cree S: pour le seul jeton eleve. L'explorateur, qui tourne en jeton normal, ne pouvait pas le voir.

Symptomes trompeurs :

Correctif : rejouer le mappage dans une console non elevee (Win+R → powershell ; l'invite doit afficher C:\Users\julie et non C:\WINDOWS\system32).

[Security.Principal.WindowsPrincipal]::new([Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole('Administrators')   # doit repondre False
net use S: \10.0.0.2\NEXTE /persistent:yes

Les identifiants poses par cmdkey sont, eux, communs aux deux jetons (stockes par utilisateur) : inutile de les refaire.

Alternative permanente, si le cloisonnement gene : poser EnableLinkedConnections a 1, ce qui fait partager les lecteurs entre les deux jetons. Necessite un redemarrage.

New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name EnableLinkedConnections -PropertyType DWord -Value 1 -Force

Second point de confusion, sans gravite : WireGuard n'affiche ni fenetre ni icone dans la zone de notification. C'est la consequence directe de /installtunnelservice, qui installe le tunnel comme service Windows — precisement ce qui garantit qu'il remonte au demarrage sans intervention. Pour le voir, lancer WireGuard depuis le menu Demarrer : le tunnel y figure, actif, avec ses compteurs.

Regle a retenir : ne jamais diagnostiquer un tunnel a l'absence d'un lecteur dans l'explorateur. Les deux temoins fiables sont Test-NetConnection 10.0.0.2 -Port 445 cote poste, et sudo wg show cote VPS.

02_les petites procédures de Claude

260827-Tofs à compresse sur le PC Windows

On dépose des photos dans un dossier, on les récupère compressées dans un autre. Rien à lancer, rien à régler au coup par coup. C'est le principe de la procédure Komga-PDF appliqué aux images, mais entièrement sur le PC julie — le VPS n'intervient pas.

DépôtD:\Procedures photos\Tofs a compresse\
RésultatD:\Procedures photos\Tofs-compressed\
Moteurcaesiumclt v1.4.0 — binaire Rust, aucune dépendance
ScriptJux-scripts/Photos-Caesium/compress_photos.py — stdlib seule
Profil actifq80 — environ -62 %, sans redimensionnement
Délai43 secondes entre le dépôt et la livraison

La seule chose à ne jamais toucher : l'option -e dans options_communes de config.json. Elle conserve l'EXIF, et ce n'est pas le comportement par défaut de Caesium. Sans elle, dates de prise de vue et coordonnées GPS sont purement supprimées — silencieusement. Ce n'est pas une précaution théorique : c'est déjà arrivé, le 14 juillet 2026, et 275 photos y ont laissé leur GPS définitivement.


Au quotidien

Déposez les photos dans Tofs a compresse\ et n'attendez rien d'autre : la tâche Photos-Caesium tourne en permanence et les prend d'elle-même. Les fichiers compressés apparaissent dans Tofs-compressed\ avec la même arborescence — un album déposé revient en album.

20:43:51   dépôt dans Tofs a compresse\
20:44:32   déclenchement (après 20 s sans changement)
20:44:34   livraison dans Tofs-compressed\

Le délai tient au garde-fou : la surveillance attend 20 secondes sans le moindre changement avant de traiter, ce qui évite d'attraper un fichier en cours de copie. Si vous videz une carte SD de 300 photos, elle patiente jusqu'à la fin du transfert.

Ce qui devient de vos originaux :

À la main

Trois lanceurs à double-cliquer dans D:\Procedures photos\ :

LanceurEffet
Compresser maintenant.cmdune passe, puis sortie
Simuler le gain.cmdcompresse en zone tampon, annonce le gain, jette le résultat
Surveillance (fenetre visible).cmdla boucle, console à l'écran
py -3.12 compress_photos.py --une-fois
py -3.12 compress_photos.py --simulation
py -3.12 compress_photos.py --profil sans-perte --une-fois
py -3.12 compress_photos.py --profils
py -3.12 compress_photos.py                     # surveillance continue

La surveillance automatique

Tâche planifiée Photos-Caesium (ONLOGON), en place depuis le 2026-08-27 :

schtasks /Create /TN "Photos-Caesium" /TR '"C:\Users\julie\AppData\Local\Programs\Python\Python312\pythonw.exe" "D:\Syncthing\Jux_univers\Jux-scripts\Photos-Caesium\compress_photos.py"' /SC ONLOGON /RL LIMITED /F

pythonw.exe et non python.exe, sans quoi une console s'ouvre à chaque ouverture de session. Vérification par schtasks /Query /TN "Photos-Caesium" /V /FO LIST ou taskschd.msc ; retrait par /Delete.

Cette tâche doit être créée depuis la console de Julien, jamais depuis une session Claude Code. Une session Claude tourne dans un conteneur MSIX : la tâche figerait des chemins virtualisés et ne ferait rien, sans le moindre message. Voir la page 282.


Profils de compression

Définis dans config.json, modifiables sans toucher au code. --profil <nom> surcharge ponctuellement.

ProfilOptionsGain sur photos de téléphone
q80 (actif)-q 80-59 à -72 %
q90-q 90environ -45 %
sans-perte--lossless-23 %
web-3000px-q 80 --long-edge 3000 --no-upscaleenviron -85 %

Options communes à tous les profils : -e --keep-dates --min-savings 1%.

Le profil actif ne redimensionne pas. q80 ne touche ni aux dimensions ni au nombre d'étiquettes EXIF. web-3000px, qui ramènerait le grand côté à 3 000 pixels, figure dans config.json mais n'est pas sélectionné — à n'activer que sur demande explicite.

« Sans altérer la qualité » coûte les deux tiers du gain

C'était la demande initiale, et elle mérite d'être précisée : les deux modes de Caesium n'ont rien de comparable en rendement.

D'où q80 par défaut. Pour des originaux irremplaçables, basculer sur sans-perte dans config.json, ou traiter ce lot-là avec --profil sans-perte.


Ce qui est garanti : EXIF, GPS, dates, dimensions

Vérifié deux fois, par la mesure et non par relecture du code.

Contrôle du 2026-09-28 — la chaîne réelle, de bout en bout

Trois photos du Xiaomi 15T Pro, dont deux géolocalisées, déposées sans rien lancer : c'est la surveillance qui les a prises, comme pour un dépôt ordinaire.

ContrôleRésultat
Bloc EXIFidentique à l'octet près — 52 334 / 52 740 / 52 782 octets
Coordonnées GPS43.675676, 4.634059 avant et après, au chiffre près
Date de prise de vueidentique à la seconde
Étiquettes EXIF72 → 72 (58 → 58 pour la photo sans GPS)
Dimensions4096×3072 inchangées
Date de fichier (mtime)identique — --keep-dates tient
Poids13,1 Mo → 5,1 Mo, -61 %

Les 72 étiquettes conservées couvrent tout ce que l'appareil écrit : marque, modèle, objectif, ouverture, temps de pose, ISO, orientation, balance des blancs, et le bloc GPS complet. Rien n'est aplati ni simplifié — Caesium ne réécrit que les données d'image.

Mesure de référence du 2026-08-27

71 photos de téléphone (lot « Ligurie 2026 »), Ryzen 5 2600X, --threads 0 :

TailleDurée
Originaux251,1 Mo—
q8090,4 Mo (-64,0 %)22 s
sans-perte-22,8 %—

Soit environ 12 Mo/s de débit : un vidage de carte SD de 8 Go se traite en une dizaine de minutes. Le contrôle EXIF de ce jour-là portait sur trois fichiers et donnait déjà un bloc EXIF identique à l'octet (1 819 / 52 665 / 52 597 octets), IFD GPS présent, dimensions inchangées.

L'outil de contrôle

Jux-scripts/Photos-Caesium/comparer_exif.py — stdlib seule. Prend deux dossiers et compare fichier par fichier : bloc EXIF octet par octet, GPS converti en degrés décimaux, DateTimeOriginal, appareil, dimensions, nombre d'étiquettes, mtime, poids.

py -3.12 comparer_exif.py <dossier_reference> <dossier_sortie>

Il rend un verdict global, et se prête au contrôle de sanité : lancé avec le même dossier des deux côtés, il doit tout déclarer conforme. À rejouer après toute modification de profil, de config.json ou du binaire.


⚠ L'incident du 2026-07-14 — le -e manquant

Une passe antérieure à la mise en place de cette procédure a été lancée sans -e.

Dégâts constatés le 2026-08-28, sur les photos de l'été 2026 : 275 fichiers dépouillés de tout bloc EXIF — date et GPS. Signature nette : 493 Ko de moyenne pour les fichiers traités, contre 1 103 Ko pour les 76 intacts du même voyage.

Conséquence différée, invisible sur le moment. Sans DateTimeOriginal, Immich se rabat sur la date du fichier. Or le WebDAV kDrive ne préserve pas les mtime : à la première resynchronisation, six semaines plus tard, les 275 photos sont allées se ranger au jour de la synchro et la chronologie du voyage s'est effondrée.

Le GPS est définitivement perdu. Seule la date a pu être reconstruite, depuis le nom des fichiers, par dater_photos_nas.py. Récit complet : page 164.

À faire avant toute passe de compression : vérifier -e dans la ligne de commande, et contrôler l'EXIF d'un fichier de sortie avant de traiter le lot. Un fichier de sortie sans bloc EXIF doit faire arrêter la passe immédiatement — les originaux ne sont pas toujours récupérables.


PC et NAS : le même moteur, une garantie de plus sur le NAS

Le stock photo du NAS suit sa propre procédure, en quatre étapes avec validation humaine (page 285). Le moteur, lui, est rigoureusement le même.

PC (compress_photos.py)NAS (traiter_lot_nas.py)
Binairecaesiumclt 1.4.0, identique
Profil-q 80, identique
Options communes-e --keep-dates --min-savings 1%, identiques
Date et propriétaire réimposés puis revérifiésnonoui (os.utime, os.chown, puis relecture)

La différence ne porte pas sur l'EXIF, protégé à l'identique par -e des deux côtés. Elle porte sur la date de fichier et le propriétaire, pour une raison propre au NAS : les photos y appartiennent à admin:users, et une compression lancée sans privilèges les réattribuerait toutes en cassant SMB et Synology Photos. Sur le PC il n'y a qu'un utilisateur, et la mesure montre que --keep-dates suffit.


Formats

Pris en charge : JPEG, PNG, WebP, GIF, TIFF.

Non pris en charge : HEIC (iPhone) et RAW. Ces fichiers partent dans non-traites\ — jamais supprimés — avec une ligne au journal. Si le besoin HEIC se présente, il faudra une étape de conversion en amont : Caesium ne sait pas le lire.


Arborescence

D:\Procedures photos\
├── Tofs a compresse\          ← dépôt (sous-dossiers acceptés)
├── Tofs-compressed\           ← résultat, même arborescence
├── originaux-traites\         ← originaux après traitement
├── non-traites\               ← formats non pris en charge
├── echecs\                    ← abandons après 3 tentatives
├── bin\caesiumclt.exe
├── logs\photos_compress.log
├── config.json
├── Compresser maintenant.cmd
├── Simuler le gain.cmd
└── Surveillance (fenetre visible).cmd

Le script, lui, vit dans Jux-scripts/Photos-Caesium/, donc dans l'arbre Syncthing : versionné et disponible sur toutes les machines. Seules les données restent locales.

Pourquoi les dossiers sont hors de Syncthing

Ils avaient d'abord été créés dans D:\Syncthing\, puis déplacés. Ne pas les y remettre.

Il n'existe qu'un seul dossier Syncthing dans tout le maillage (afltj-njyuy), partagé avec 7 appareils dont le Xiaomi et la tablette SM-T720. Tout ce qui y tombe se réplique partout. C'est supportable pour Komga-PDF — un PDF de 130 Mo de temps en temps — mais un vidage de carte SD descendrait intégralement sur les téléphones, avant même que la compression ait commencé.

Conséquence assumée : le dépôt à distance n'est pas possible, on dépose depuis le PC.


Maintenance

Reste à faire : décider du sort du lot de démonstration laissé dans Tofs-compressed\Ligurie 2026\ (71 photos, 90 Mo), qui sert à juger la qualité q80 à l'œil.


Annexe — fonctionnement interne

  1. Sondage toutes les 15 s du dossier de dépôt. Il n'y a pas d'inotify sous Windows ; le sondage est de toute façon la partie robuste du dispositif.
  2. Déclenchement après 20 s sans le moindre changement dans l'arborescence — taille ou date d'un fichier quelconque. Plafond de sécurité à 15 min, au-delà duquel on traite quand même.
  3. Le lot entier part en un seul appel à caesiumclt, qui parallélise sur tous les cœurs (--threads 0).
  4. Écriture d'abord dans .staging, puis déplacement : jamais de fichier partiel visible dans Tofs-compressed\.
  5. Structure préservée (-R -S).
  6. Collision de nom en sortie : suffixe (2), (3)… Rien n'est jamais écrasé.
  7. Gain inférieur à 1 % (--min-savings 1%) : Caesium n'écrit rien, le script recopie l'original tel quel.
  8. Mémoire des échecs : 3 tentatives (clé taille + date, dans .etat.json), puis mise à l'écart dans echecs\.
  9. Journal persistant avec rotation à 5 Mo.

Les points 2, 4, 7, 8 et 9 reprennent d'emblée les correctifs apportés à komga_watch_vps.sh le 2026-08-23 (page 220) : événements perdus pendant le traitement, écriture non atomique, absence de mémoire des échecs, journal volatil. Autant ne pas refaire les mêmes erreurs.

config.json, clé apres_traitement : deplacer (défaut), supprimer, ou laisser. laisser fait retraiter le dépôt en boucle à chaque passe — à réserver aux tests.


Annexe — pièges rencontrés à l'installation

  1. --dry-run de Caesium ne mesure rien. L'option existe et s'exécute sans erreur, mais le rapport JSON renvoie compressed_size == original_size, soit 0,0 % de gain : elle simule l'écriture, pas la compression. Le mode --simulation du script compresse donc réellement dans .staging, relève le chiffre, puis jette le résultat.
  2. -e n'est pas le défaut — perte silencieuse des dates et du GPS. Voir l'incident ci-dessus.
  3. --json est la bonne interface de pilotage. Caesium renvoie un rapport structuré, une entrée par fichier (original_path, compressed_size, status…) plus un summary. Le script s'appuie dessus plutôt que de parser la sortie texte.
  4. --min-savings rend inutile le garde-fou maison. Sur Komga-PDF il avait fallu écrire à la main la règle « si la compression ne gagne rien, recopier l'original » ; Caesium l'implémente nativement.
  5. Créer la tâche planifiée depuis Claude Code : à éviter (piège MSIX). La création avait d'ailleurs été refusée par le garde-fou de session — ce qui tombait bien.
  6. Le binaire ne s'installe pas. caesiumclt.exe est un exécutable Rust statique de 5,7 Mo, sans dépendance ni installeur : on le dépose dans bin\ et on le met à jour en le remplaçant.

Annexe — le binaire

Versioncaesiumclt v1.4.0, publiée le 8 juillet 2026
Sourcegithub.com/Lymphatus/caesium-clt/releases
Archivecaesiumclt-v1.4.0-x86_64-pc-windows-msvc.zip — 2 296 760 octets
SHA-256a56454a83207fc25830f4d12679d7385c0906060f2ce5f54345ac5a4cf94b00f
LicenceGPL / MPL selon les composants (bin\LICENSE.md)

Le même dépôt publie caesiumclt-v1.4.0-x86_64-unknown-linux-musl.tar.gz, statique — c'est lui qui tourne sur le NAS, sans Docker ni Entware.


Annexe — pourquoi 100 % local, contrairement à Komga-PDF

Komga-PDF passe par le VPS. Photos-Caesium non, et c'est délibéré. Trois raisons, par ordre d'importance :

  1. Il n'y a pas de service à réutiliser. Komga-PDF s'appuie sur StirlingPDF, déjà déployé et qui expose compress-pdf en HTTP. Pour les images, aucun équivalent : Caesium est un binaire en ligne de commande, pas un service. L'héberger sur le VPS n'apporterait pas une API, juste un exécutable — qu'on peut aussi bien poser sur le PC.
  2. Le CPU. La compression JPEG est du calcul pur, massivement parallélisable. Le Ryzen 5 2600X offre 12 threads et ne fait généralement rien ; le VPS fait tourner une trentaine de conteneurs, avec un swap déjà occupé et un antécédent de saturation disque à 100 %.
  3. Le transfert. Les photos sont déjà sur place. Les envoyer au VPS pour les faire revenir consommerait deux fois le débit montant de la Livebox sans contrepartie.

Le seul cas qui justifierait le VPS serait de pouvoir déposer depuis le téléphone pendant que le PC est éteint — c'est précisément ce qui avait fait choisir le VPS pour Komga-PDF. Le portage serait trivial (binaire linux-musl statique, script en stdlib seule). À reconsidérer si le besoin apparaît.


Voir aussi

Copie de référence de cette page : Jux-scripts/Photos-Caesium/doc_bookstack_284.md. Mise en place le 2026-08-27, page réécrite intégralement le 2026-09-28.

02_les petites procédures de Claude

260828-Tofs à compresse sur SASNEXTE

Compression des photos du NAS SASNEXTE

Procédure en service depuis le 2026-08-28, première bascule réelle le 2026-09-28. Même moteur que la procédure Photos-Caesium du PC (page 284), mais avec une validation humaine avant tout écrasement. Copie de référence : Jux-scripts/Photos-Caesium/doc_bookstack_285.md.

En bref

Les photos du NAS sont déjà à leur place dans /volume1/photo : on ne dépose rien. La procédure les prend là où elles sont, les compresse dans un dossier d'attente, et n'écrase l'original que ce que vous avez validé.

Ce qui déclenche rien — c'est vous qui choisissez un lot
Où valider photos_reprise dans Synology Photos
Comment refuser supprimer la photo du dossier de validation
Moteur caesiumclt v1.4.0 musl, natif sur DSM
Gain constaté -50 à -65 % selon les albums
Débit sur le DS220+ 1,55 à 1,75 Mo/s

Le refus ne demande aucune action. Une photo absente du dossier de validation au moment de la bascule voit son original conservé, sans rien à cocher ni saisir. L'inaction est le comportement sûr : un lot abandonné en route, une session interrompue, un oubli — rien ne se perd par négligence, seulement par décision explicite.


La procédure, en quatre commandes

1. Voir les lots disponibles

python3 /volume1/homes/SAS_NEXTE/scripts/traiter_lot_nas.py --lister

Affiche chaque sous-dossier avec son nombre de photos à traiter et son poids, du plus lourd au plus léger. C'est ce qu'on passe ensuite à --lot.

2. Compresser un lot — les originaux ne sont pas touchés

python3 /volume1/homes/SAS_NEXTE/scripts/traiter_lot_nas.py --lot "2026/2026-Automne"

--lot accepte un préfixe d'album ou de chemin : 2022 prend toute l'année, 2026/2026-Automne un seul sous-album. Le préfixe suffit, inutile de taper les accents. Les photos compressées arrivent dans /volume1/homes/SAS_NEXTE/Photos/photos_reprise, en reproduisant l'arborescence.

3. Valider dans Synology Photos

Ouvrez photos_reprise dans l'application, en plein écran, et supprimez les photos dont la qualité ne convient pas. Ce qui reste vaut validation.

4. Basculer

python3 /volume1/homes/SAS_NEXTE/scripts/basculer_lot_nas.py --lot "2026/2026-Automne"
sudo python3 /volume1/homes/SAS_NEXTE/scripts/basculer_lot_nas.py --lot "2026/2026-Automne" --go

La première ligne est une simulation : elle annonce combien de photos seront remplacées et combien sont refusées. La seconde écrase pour de vrai.

⚠ Le sudo n'est pas décoratif. Les photos appartiennent à admin:users. Lancée sous SAS_NEXTE, la bascule les réattribuerait toutes et casserait l'accès SMB et Synology Photos. Le script refuse de s'exécuter sans root (geteuid), avec un message explicite.


La règle : on ne compresse pas une photo de moins de 2 Mo

Aucun bénéfice à recompresser une numérisation ancienne de 700 Ko pour lui gagner 80 Ko, au prix de la réécriture d'un fichier irremplaçable.

Seuil Fichiers à traiter Poids couvert Gain estimé Durée
1 Mo 12 253 (74,6 %) 95,6 % 21,6 Go 6,6 h
2 Mo 9 077 (55,3 %) 82,4 % 18,6 Go 5,7 h
3 Mo 4 839 (29,5 %) 55,4 % 12,5 Go 3,8 h

À 2 Mo on écarte 45 % des fichiers pour seulement 18 % du poids. Descendre à 1 Mo ajouterait 3 Go de gain contre 3 176 fichiers supplémentaires ; monter à 3 Mo sacrifierait 6 Go pour n'économiser que deux heures.

Effet secondaire heureux : les albums de numérisations anciennes sortent d'eux-mêmes du périmètre. 1967 à 2000 - photos famille Bertrand (536 images, 2,62 Go) et 2005 - naissance Elio (869 images) ont zéro fichier à traiter. La règle protège le patrimoine le plus fragile sans qu'on ait eu à le désigner.


Ce qui est garanti

EXIF, GPS, dimensions

Vérifié sur les fichiers du NAS puis, après la bascule du 2026-09-28, sur les photos réellement écrasées : bloc EXIF identique à l'octet près, IFD GPS présent et coordonnées au chiffre près, dimensions inchangées, jeu complet d'étiquettes (72 sur un Xiaomi 15T Pro, 54 et 45 sur des photos plus anciennes).

Cela dépend entièrement de l'option -e, qui n'est pas le défaut de Caesium — voir l'incident du 14 juillet en page 284, qui a coûté le GPS de 275 photos.

La date de modification, et pourquoi elle compte

Immich construit sa chronologie à partir du DateTimeOriginal EXIF quand il existe, et du mtime du fichier quand il n'existe pas — cas des images WhatsApp, des captures d'écran et des scans. 1 853 photos, soit 10,5 % du stock, sont dans ce cas (colonne origine_date de la base).

Les deux scripts ne se reposent donc pas sur --keep-dates : ils relèvent mtime, atime, uid, gid et permissions avant traitement, les réimposent par os.utime / os.chown / os.chmod, puis relisent le fichier et lèvent une exception si le mtime a bougé d'une seconde. Assertion vérifiée fichier par fichier.

Preuve : 26 photos témoins, dates identiques à la seconde, propriétaire restauré, originaux intacts. Le contrôle intégré a d'ailleurs détecté 26 écarts lors d'un essai en non-privilégié, contre 0 en root — c'est lui qui a établi l'obligation du sudo.

Ce que la procédure apporte face à une compression au fil de l'eau


Où en est le chantier

Inventaire du 2026-09-28 : 17 715 images, 41,41 Go, dont 9 014 à retraiter (30,80 Go) et 8 701 écartées (10,61 Go). 417 vidéos (21,22 Go) sont mises de côté pour un chantier ultérieur.

Lots basculés

Lot Photos Avant Après Gain
2022 (4 albums) 359 1 501 Mo 518 Mo 983 Mo
2026/2026-Automne 22 (+1 refusée) 94,05 Mo 46,44 Mo 47,6 Mo
Total 381 1 031 Mo

Reste à faire


La base est actualisée chaque nuit

Une photo ajoutée après le dernier inventaire est invisible de traiter_lot_nas.py, qui travaille à partir de la base. C'est exactement ce qui s'est produit le 2026-09-28 avec l'album 2026-Automne à Noel, créé après l'inventaire du 28 août : il a fallu reconstruire la base avant de pouvoir le traiter.

D'où une tâche nocturne, posée le 2026-09-28.

Script /volume1/homes/SAS_NEXTE/scripts/inventaire_nuit.sh
Tâche DSM quotidienne, 2 h, utilisateur SAS_NEXTE
Commande bash /volume1/homes/SAS_NEXTE/scripts/inventaire_nuit.sh
Journal /volume1/homes/SAS_NEXTE/logs/inventaire_nuit.log, rotation à 2 Mo
Durée 9 min 20 pour 17 715 images

Utilisateur SAS_NEXTE, surtout pas root : l'inventaire ne fait que lire /volume1/photo, et en root les fichiers produits appartiendraient à root — un lancement manuel ultérieur échouerait alors à les écraser.

Trois protections, parce que personne ne regarde tourner une tâche de nuit

  1. Verrou par PID — un inventaire qui déborde ne se fait pas doubler. Le test porte sur le PID enregistré (kill -0) et non sur ps, dont la sortie est tronquée sur DSM.
  2. La base n'est plus supprimée avant reconstruction. Elle est bâtie dans photos.sqlite.tmp puis remplacée à la fin par os.replace, après sauvegarde rotative sur 7 jours (photos_j1.sqlite à photos_j7.sqlite). Vérifié : un plantage en cours de route laisse la base et le suivi de validation intacts, sans .tmp résiduel.
  3. ⚠⚠ Refus d'écrire sur source vide. Zéro image trouvée = refus et code 2. Un soir où /volume1/photo ne serait pas monté, un inventaire vide écraserait sinon la base — et avec elle le suivi des lots en cours de validation. Même principe que le refus de source vide de sync_kdrive_complete.sh.

Le canari du matin la surveille

Entrée inventaire dans la section nas de Etat-Infra/config.json (max_heures: 30, attendu BILAN NUIT: OK). La sonde est greffée sur la session SSH que la vérification NAS ouvre déjà — aucune connexion supplémentaire. Elle alerte si le journal est absent, vieux de plus de 30 h, ou si le dernier bilan est en échec ; muette le reste du temps.

L'inventaire conserve le suivi des lots lors d'une reconstruction. Statuts, lots, tailles obtenues et dates de traitement sont reportés depuis la base précédente pour toute photo dont le chemin n'a pas changé. Sans cela, le passage nocturne effacerait chaque nuit l'avancement des lots en validation.


Annexe — la base et les statuts

Sorties dans /volume1/homes/SAS_NEXTE/inventaire/, accessibles en SMB sous \\10.0.0.2\home\inventaire\ : photos.csv (tableur ou Metabase), photos.sqlite (SQL), videos.csv, resume.txt.

Colonnes de la table photos : album, chemin, nom, format, octets, mo, date_prise_vue, origine_date, date_modif, largeur, hauteur, appareil, gps_lat, gps_lon, a_traiter, motif_ecart, empreinte, doublon_de, quasi_doublon, statut, lot, octets_apres, date_traitement.

⚠ Les chemins sont relatifs à /volume1/photo (2022-hiver à Paques/IMG….jpg), et l'album est le premier segment du chemin : toutes les photos de /volume1/photo/2026/<sous-album>/ portent donc l'album 2026. C'est pourquoi --lot accepte aussi un chemin.

Statut Signification
a_traiter retenue par le seuil, pas encore compressée
ecarte sous le seuil, ou format non pris en charge
en_validation compressée, en attente du jugement dans Synology Photos
bascule validée et écrasée — octets porte la nouvelle taille
refuse supprimée du dossier de validation : original conservé
sans_gain la compression n'apportait rien, original conservé

Requêtes utiles :

-- ce qui sera traité, par album
SELECT album, count(*) AS n, round(sum(mo)/1024, 2) AS go
FROM photos WHERE a_traiter = 1 GROUP BY album ORDER BY go DESC;

-- où en sont les lots
SELECT lot, statut, count(*) FROM photos
WHERE lot IS NOT NULL AND lot != '' GROUP BY lot, statut;

-- les photos dont la chronologie Immich dépend du mtime
SELECT album, count(*) FROM photos WHERE origine_date = 'mtime' GROUP BY album;

-- exclure un album entier du traitement
UPDATE photos SET a_traiter = 0, motif_ecart = 'exclu manuellement' WHERE album = '...';

La chaîne d'outils

Six scripts dans Jux-scripts/Photos-Caesium/, stdlib seule, déployés sur le NAS dans /volume1/homes/SAS_NEXTE/scripts/.

Script Étape Rôle
inventaire_photos_nas.py 1 recense tout, détecte les doublons, propose la sélection
inventaire_nuit.sh 1 lanceur nocturne : verrou, journal, bilan pour le canari
nettoyer_doublons_nas.py 1 bis écarte les doublons certains, en quarantaine
traiter_lot_nas.py 3 compresse un lot vers le dossier de validation
basculer_lot_nas.py 4 écrase les originaux validés, constate les refus
comparer_versions.py — compare la qualité de deux versions d'une même photo (DQT)

Garde-fous intégrés : traiter_lot_nas.py appelle caesiumclt sans -R, dossier par dossier — aucun @eaDir ne peut être touché, sans avoir besoin d'option d'exclusion. Liste de fichiers explicite limitée aux JPEG : passer un dossier ferait traiter les PNG et TIFF en lossy. Sortie validée (FF D8, taille inférieure) avant dépôt. Budget --minutes, reprise en relançant la même commande.


Annexe — les correctifs du 2026-09-28

La chaîne n'avait jamais été jouée jusqu'à la bascule. Six défauts, tous découverts en conditions réelles, tous dormant depuis le 28 août.

⚠⚠ os.replace() ne traverse pas deux partages Synology. Errno 18, Invalid cross-device link — 359 échecs d'un coup. Chaque partage DSM est un sous-volume Btrfs distinct : /volume1/homes et /volume1/photo sont deux devices pour le noyau, malgré le /volume1 commun. remplacer() copie désormais vers un tampon .nouveau créé à côté de l'original (même sous-volume), y pose permissions, propriétaire et dates, puis os.replace — atomique. Le fichier de validation n'est supprimé qu'après succès et vérification du mtime. Aucun dégât : le try/except a tenu, les 359 originaux et la base sont restés intacts.

⚠ Le bilan annonçait un succès après un échec total : « 983,47 Mo récupérés » s'affichait sous « 0 original remplacé, 359 échecs », parce qu'il additionnait le gain théorique du lot. Un bilan qui ment ainsi est pire qu'une absence de bilan. Le gain est désormais compté photo par photo au moment du succès, et tout échec déclenche une ligne disant explicitement que les originaux sont inchangés.

⚠ --lot ne savait viser qu'une année entière : les cinq sous-albums de 2026 étaient fondus dans un lot 2026 de 115 photos. Le filtre porte maintenant sur l'album ou le chemin, et --lister groupe sur les deux premiers segments. Rétrocompatible.

⚠ --lister exigeait --lot, alors qu'il sert précisément à découvrir quoi passer à --lot.

⚠ Les messages de fin donnaient des commandes inutilisables — python3 basculer_lot_nas.py … sans chemin, sans sudo, sans --go, d'où un « No such file » depuis le répertoire personnel. Chemins absolus et trois étapes numérotées désormais.

⚠ purger_vides() ne supprimait jamais rien : Synology dépose un @eaDir de vignettes dans chaque dossier, compté comme du contenu par os.listdir(). photos_reprise gardait donc l'apparence de lots encore en attente de validation. @eaDir et Thumbs.db sont maintenant ignorés, puis emportés avec le dossier.


Annexe — les doublons

L'inventaire a trouvé 1 334 doublons exacts (1,93 Go) et 1 278 quasi-doublons. Méthode : SHA-256 intégral mais calculé uniquement entre fichiers de taille identique — 2 360 candidats sur 17 835, ce qui évite de hacher 41 Go. Les quasi-doublons sont repérés par DateTimeOriginal + dimensions identiques.

Sur les 1 334, seuls 75 ont été écartés (190 Mo, en quarantaine dans /volume1/homes/SAS_NEXTE/doublons_ecartes, jamais effacés directement).

⚠ Un doublon inter-albums n'est pas une erreur, c'est souvent une intention

1930-2016 - Photos BERTRAND MER et 2016-best photos pour 70 ans partagent 516 fichiers identiques : c'est une sélection faite pour un anniversaire. Les supprimer aurait vidé l'album. Ne jamais dédoublonner sur la seule empreinte — 1 018 fichiers laissés intacts pour cette raison.

Le critère de conservation : la relation de préfixe

Un suffixe de copie est toujours ajouté au nom d'origine. Si un nom du groupe est préfixe strict de tous les autres, c'est l'original. Structurel, sans heuristique. Couvre _1, - Copie, et les cascades de conflits Syncthing (un fichier existait en 7 exemplaires).

Deux pièges à ne pas refaire :

Mode prudent par défaut (décision de Julien : « la règle la plus prudente, tant pis s'il reste des doublons ») : un groupe sans relation de préfixe n'est pas traité. 264 groupes de photos renommées (20150808_185538.jpg ↔ Croatie_août_2015_142.jpg, 0,60 Go) laissés en l'état — choisir le nom qui survit est une décision humaine.

Seconde passe --conflits : 24 fichiers de plus. Le nommage Google Drive français Copie de P1060905 (conflit du 19-03-2018 à 00h18).jpg encadre l'original au lieu de le suffixer, donc le critère de préfixe ne pouvait pas le voir. Garde-fou : on n'écarte un conflit que s'il subsiste un exemplaire propre dans le groupe — 6 fichiers laissés en place car tous les exemplaires de leur groupe étaient des copies de conflit.


Annexe — ⚠⚠ les fichiers « (conflit) » sont les ORIGINAUX

Contre-intuitif, et vérifié : sur ce stock, un Copie de X (conflit du …).jpg est la meilleure version, et le fichier au nom propre portant le même radical est une recompression dégradée.

Mesuré sur 12 paires par la table de quantification JPEG (DQT — somme basse = moins dégradé) : 10 cas sur 12 donnent la version conflit gagnante, avec un DQT de 292 contre 700 à 1 000, une taille 2 à 3 fois supérieure et un bloc EXIF trois fois plus riche, à dimensions rigoureusement identiques. Un événement de mars 2018 a réécrit ces photos en qualité réduite.

La consigne « supprimer tout ce qui porte (conflit) » aurait détruit la meilleure version de 10 photos. Ce qui les a sauvées : le garde-fou « n'écarter un conflit que s'il subsiste un exemplaire propre dans le groupe » — et il les a écartées pour une raison qui n'était pas la bonne (leurs octets diffèrent, elles n'étaient donc pas des doublons exacts). Un garde-fou conservateur protège aussi contre les erreurs qu'on n'avait pas prévues.

Décision en attente : remplacer les versions dégradées par les versions de conflit et leur rendre leur nom. Outils prêts, jamais exécutés en écriture : comparer_versions.py (comparaison DQT) et renommer_conflits.py (retire l'encadrement, ne renomme que si le nom cible est libre).


Annexe — pièges SSH et DSM

Une bannière SSH qui répond ne prouve pas que l'accès soit ouvert. Le port 22 renvoyait SSH-2.0-OpenSSH_8.2, annonçait publickey,password et évaluait les identifiants avant de les rejeter — ce qui a conduit à soupçonner à tort le groupe administrators, puis la vérification en deux étapes. Les deux hypothèses étaient fausses : le service était désactivé et le port fermé par les règles DSM.

Le compte Unix est SAS_NEXTE en majuscules (uid 1026), 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.

Le § du mot de passe ne survit pas à Git Bash → plink. Le construire 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.

Autres pièges :


Annexe — Immich, ce qu'il faut savoir d'ici

Immich lit /home/debian/photo sur le VPS — le miroir kDrive de /volume1/photo — et ignore les dossiers personnels : le dossier de validation ne l'affecte donc pas. Bibliothèque externe 89bfcdc1-1604-47a1-90a3-975d2f6c4639, chemin /mnt/media/photo. Relecture après traitement : resynchronisation puis POST /api/libraries/{id}/scan.

Il n'existe pas de MCP Immich dans ces sessions (perdu avec le profil eliob). Passer par l'API : POST /api/auth/login → JWT, puis POST /api/search/metadata (withExif: true, accepte isOffline, originalFileName, takenAfter/takenBefore, pagine par nextPage) et GET /api/assets/statistics.

⚠ GET /api/timeline/buckets?size=MONTH est le seul moyen fiable d'obtenir des totaux : le champ total de la recherche ne renvoie que le compte de la page courante.

Bibliothèque au 2026-08-28 : 18 156 éléments, dont 2 datés de l'an 4501 — des scans du Nikon LS-5000 dont le fichier portait une date aberrante, corrigés depuis à 1979. Récit complet : page 164.


Annexe — la machine et le stock

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

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

Composition de /volume1/photo au relevé initial :

Contenu Fichiers Poids Traité ?
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
@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. Un échantillon constitué ainsi fausse gravement la taille moyenne.


Annexe — pourquoi le NAS et pas le PC

Le PC est sept fois plus rapide (11,4 Mo/s contre 1,55 sur le J4025), mais le tunnel WireGuard est en étoile via le VPS et plafonne à 4,01 Mo/s. Faire passer 53 Go de lecture et de réécriture y prendrait plus de quatre heures en saturant le lien, PC allumé. Le NAS travaille la nuit, gratuitement.

Cet arbitrage vaut pour le stock complet. Sur un lot de quelques dizaines de mégaoctets, le calcul s'inverse — mais la procédure de validation, elle, reste la même.


Points de vigilance permanents

1. La sauvegarde. sync_kdrive_complete.sh ne synchronise que /volume1/photo/2026 vers kDrive, et en miroir (rclone sync --delete-during). Les JPEG de 1967 à 2025 n'ont aucune copie hors du NAS par cette voie. Une archive Hyper Backup (NEXTE_1.hbk) tourne chaque nuit, mais son périmètre exact n'a pas été confirmé. À établir avant toute réécriture de masse.

2. La compression sur place est irréversible. Le profil q80 est un ré-encodage. C'est toute la raison d'être de l'étape de validation.

3. Ne jamais toucher aux @eaDir. Les compresser casserait Synology Photos, qui les régénérerait aussitôt.

4. Synology Photos indexe le dossier de validation et génère ses vignettes : comptez du temps machine et quelques gigaoctets de @eaDir supplémentaires, restitués dès le dossier vidé. Hyper Backup le sauvegardera aussi la nuit suivante — gonflement temporaire, résorbé après la bascule.

5. HEIC et vidéos restent hors de portée. Pour les vidéos, le levier serait un ré-encodage H.265 : un tout autre chantier, très au-delà d'un J4025.


Voir aussi

02_les petites procédures de Claude

260830 - Basculement des videos de SASNEXTE vers kDrive

260830 - Basculement des vidéos de SASNEXTE vers kDrive

Objectif : libérer 694 Go sur le NAS sasnexte en déplaçant /volume1/video vers kDrive, en répliquant l'arborescence à l'identique. Jellyfin lira ensuite depuis kDrive — procédure 2, documentée sur la page 165 (14_Jellyfin).

Statut au 2026-08-30 : étapes 1 à 5 terminées. Les 694 Go sont sur kDrive, vérifiés, et Jellyfin les lit déjà. Seule l'étape 6 reste — la suppression sur le NAS — volontairement en attente.


Mesures du 2026-08-30

Le dossier video

df est trompeur : ses 4,0 To sont le volume /volume1 entier, pas le partage vidéo.

Dossier Taille
movies 163,1 Go
cinema_italie 111,0 Go
fantastique_et_SF 84,4 Go
series 83,6 Go
documentaires 60,6 Go
cinema_realisateurs 47,1 Go
culture_cuisine 31,7 Go
animes 27,7 Go
cinema_europe 24,2 Go
historiques 21,7 Go
cinema_asie 12,0 Go
spectacles 11,6 Go
palettes 8,9 Go
cinema_UK 7,3 Go
alladomanda 2,0 Go
#recycle (corbeille DSM, non transférée) 10,5 Go
Total transféré 694,55 Go — 4 044 fichiers

Seulement ~423 vidéos réelles (266 mkv, 94 mp4, 54 avi, 7 vob). Le reste est de l'habillage Jellyfin : 2 989 jpg (vignettes trickplay), 408 nfo, 170 png, 40 srt.

Autres partages du volume, pour situer

video 707 Go · Komga 552 Go · audiobooks 374 Go · music 133 Go · photo 84 Go · homes 36 Go. Le solde des 4,0 To est constitué d'@ActiveBackup, @docker et des snapshots.

Débits mesurés

Trajet Débit
NAS vers kDrive (rclone WebDAV, 1 flux) 44 Mo/s
NAS vers kDrive (3 transferts parallèles) 62 à 78 Mio/s
kDrive vers VPS 97,6 Mo/s
kDrive vers NAS 89,5 Mo/s
NAS vers VPS aujourd'hui (CIFS via WireGuard) 5,0 Mo/s
Disque local NAS (lecture) 49 à 58 Mo/s

Conséquence contre-intuitive : la bascule améliore la lecture au lieu de la dégrader. Jellyfin plafonne aujourd'hui à 5,0 Mo/s (40 Mbit/s) : suffisant pour un 1080p courant, juste pour un remux, et incompatible avec deux flux simultanés. Via kDrive, le VPS descend à 780 Mbit/s. Le goulot était le tunnel WireGuard depuis Toulon, pas kDrive.

Espace kDrive

Capacité 6,60 To · utilisé 4,21 To · libre 2,39 To. Après bascule : environ 1,69 To restants. Renouvellement de l'abonnement le 2026-09-20.


Le dossier video n'avait AUCUNE sauvegarde

Vérifié le 2026-08-30 : aucune des 4 tâches Hyper Backup (2509NEXTE, Toojux_Home, Alteris, Bckup_Vero_photos) ne mentionne video, pas de snapshot (#snapshot absent), et il ne fait pas partie des 4 dossiers de sync_kdrive_complete.sh.

Le déplacement ne fait donc pas passer de deux copies à une. Il déplace l'unique copie d'un DS220+ à deux baies sans sauvegarde vers une infrastructure redondée avec corbeille. C'est une amélioration, pas une prise de risque.

Les deux risques réellement nouveaux :


Procédure

# Étape Durée Réversible
0 Analyse de doublons NAS contre Videos_NAS 10 min oui
1 rclone copy — fait, 08:35 → 11:03 (2 h 28) 2 h 28 oui
2 rclone check --download — fait, 11:05 → 13:21, 0 différence sur 4 056 fichiers 2 h 16 oui
3 à 5 Bascule Jellyfin — faite, voir page 165 30 min oui
6 Suppression sur le NAS : 694 Go libérés, volume de 75 % à ~62 % — EN ATTENTE 5 min non

Script : /volume1/homes/SAS_NEXTE/scripts/basculement_video.sh (source de vérité dans Jux-scripts/). Journal : /volume1/homes/SAS_NEXTE/logs/basculement_video_260830.log. Verrou : /volume1/homes/SAS_NEXTE/logs/basculement_video.pid.

rclone --config /volume1/homes/SAS_NEXTE/.config/rclone/rclone.conf copy \
  /volume1/video kdrive_music:Videos_NAS/video \
  --exclude '/#recycle/**' --exclude '**/@eaDir/**' \
  --exclude '**/.DS_Store' --exclude '**/Thumbs.db' \
  --create-empty-src-dirs \
  --transfers 3 --checkers 8 --retries 3 --low-level-retries 10 \
  --stats 5m --stats-one-line -v

copy, jamais sync : la source n'est jamais modifiée par le script. La suppression est un geste manuel séparé, en étape 6.

Étape 2 — pourquoi la vérification par téléchargement est obligatoire

Le WebDAV kDrive n'expose aucun hash (rclone backend features kdrive: donne Hashes: []). Après transfert, rclone ne peut comparer que les tailles. Pour un déplacement qui se termine par une suppression de la source, c'est insuffisant : il faut rclone check --download, qui retélécharge tout et compare les empreintes calculées à la volée. 694 Go à 89,5 Mo/s = environ 2 h 10. Non négociable avant l'étape 6.


Étape 0 — résultat de l'analyse de doublons

Videos_NAS (racine kDrive) pèse 246,7 Go : Video Culture Arts et Peinture 130,80 · Video Cuisine 83,10 · Video Architecture et Urbanisme 29,38 · Video concerts 3,46.

culture_cuisine et Video Cuisine ne se recoupent pas du tout. Le NAS porte Chef's Table et Man vs Food, kDrive porte Rick Stein, Jamie Oliver, Entre les Bras. Zéro collision de nom.

Seuls 2 vrais doublons, 1,60 Go, tous deux contre Videos_NAS et non à l'intérieur du périmètre transféré :

Décision : ils ont été transférés quand même. Ces deux fichiers appartiennent à des bibliothèques Jellyfin distinctes ; 1,6 Go ne justifiait pas de casser la réplication.


Emplacement final : Private/Videos_NAS/video/

La destination initiale SYNC-pour_VPS/Sync-SASNEXTE/video était une erreur de conception, corrigée le jour même sur remarque de Julien.

Cet espace est celui des copies miroir du NAS : quatre dossiers que sync_kdrive_complete.sh synchronise chaque jour en rclone sync --delete-during. Or video n'est pas une copie — après l'étape 6, c'est l'original, lu directement par Jellyfin. Le nom promettait une synchronisation qui n'existe pas, et surtout il tendait un piège : le jour où quelqu'un ajoute video à ce script — geste naturel vu l'emplacement — un sync depuis une source NAS vidée effacerait les 694 Go.

Le déplacement a pris 2 secondes : rclone moveto, Server side directory move succeeded, aucun octet retransféré. Le remote kDrive annonce DirMove: True — toute réorganisation de l'arborescence kDrive est donc gratuite, quelle que soit la volumétrie.

Deux fusions décidées dans la foulée

Source Destination Volume
video/series Videos_NAS/Séries (qui était vide) 399 objets, 77,8 Gio
video/culture_cuisine Videos_NAS/Video Cuisine (77,4 Gio existants) 286 objets, 29,6 Gio

Vérification de non-collision faite avant : Séries était vide, et les deux ensembles cuisine n'avaient aucun nom commun au premier niveau (Chef's table, Man VS Food d'un côté ; France, India, Globe cooker, Cuisines des Terroirs de l'autre). 126 s en tout, côté serveur.

Les comptes tombent juste : 4 056 − 399 − 286 = 3 371 objets restants dans video/, et 77,393 + 29,566 = 106,959 Gio dans Video Cuisine.

Arborescence finale

Private/Videos_NAS/            878,7 Gio, 4 781 objets   <- monté sur /mnt/nas_videos
├── Séries/                     77,8 Gio   -> /data/series
├── Video Cuisine/             107,0 Gio   -> /data/culture_cuisine
├── Video Culture Arts et Peinture/  130,8 Gio   (aucune bibliothèque)
├── Video Architecture et Urbanisme/  29,4 Gio   (aucune bibliothèque)
├── Video concerts/              3,5 Gio   (aucune bibliothèque)
└── video/                     541,6 Gio, 3 371 objets
    ├── movies, cinema_italie, fantastique_et_SF, documentaires,
    ├── cinema_realisateurs, animes, cinema_europe, historiques,
    └── cinema_asie, spectacles, palettes, cinema_UK, alladomanda

⚠ video/@eaDir subsiste (11 objets) : l'exclusion **/@eaDir/** écarte le contenu du dossier, pas le dossier lui-même, et --create-empty-src-dirs l'a recréé. Sans conséquence, mais à ne pas confondre avec un oubli.


Pièges rencontrés — à ne pas re-découvrir

  1. ps w tronque sa sortie sur DSM. Un test de vivacité ps w | grep -c a renvoyé 0 alors que le processus tournait — ce qui a conduit à lancer une seconde copie sur la même destination. Les deux ont été arrêtées par SIGTERM, sans corruption (rclone compare les tailles et réécrit tout fichier tronqué). Toujours utiliser ps -eo pid,sid,args.
  2. nohup ne suffit pas à détacher sur DSM. Utiliser setsid script.sh < /dev/null > /dev/null 2>&1 &. Un verrou par PID a été ajouté au script pour rendre le double-lancement impossible.
  3. Faux doublons .VOB de 1,07 Go. Les segments DVD-Video sont tous plafonnés à 1 073 739 776 octets : la taille identique ne prouve rien. Cinq faux positifs relevés entre un Scola du NAS et un DVD Architectures de kDrive. Même leçon que le dédoublonnage photo du 2026-08-28 — une signature faible ne fait pas un doublon.
  4. Le quota-used-bytes WebDAV de kDrive est peu fiable : il renvoie 0 pour certains dossiers pourtant pleins (il donnait 102,6 Go pour Videos_NAS, dont la taille réelle est 246,7 Go). Passer par rclone size, ou par l'API du drive pour l'espace global.
  5. df sur un partage Synology rapporte le volume entier, pas le partage. Toujours confirmer par du -sb.
  6. find -iname '*.jpg' sans exclure @eaDir fausse tout recensement (rappel de la page 285).

Pièges d'accès SSH au NAS (rappel page 285)

02_les petites procédures de Claude

260901-reprise des règles du pare-feu de SASNEXTE

.....en profondeur ! 

Durcissement du NAS : de 28 ports exposés à 8

Constat de départ, mesuré depuis le VPS (hors LAN, hors VPN) : tous les ports en écoute du NAS répondaient depuis Internet, y compris NFS, SMB, FTP et le démon rsync.

La méthode qui a marché

Plutôt que de raisonner sur les règles du pare-feu, mesurer la surface réelle : lister les ports en écoute côté NAS, puis tester chacun depuis une machine extérieure. L'écart entre ce qu'on croit fermé et ce qui répond est la seule donnée qui compte.

Trois pièges rencontrés

1. L'ordre des règles. Le pare-feu Synology applique la première règle qui correspond, puis s'arrête. Une règle « Service terminal chiffré → Tous → Autoriser » placée en tête annulait complètement les règles « port 22 → Refuser » situées plus bas. Toute autorisation doit précéder le refus qu'elle contourne ; une règle placée après un refus qui la couvre est du décor.

2. Les libellés tronqués. « Interface de Gestion, File Station, Audio Statio… » masquait une longue liste d'applications — dont FTP et VPN Server. C'est ce qui expliquait qu'un port reste ouvert alors que la règle qui le concernait avait été supprimée. Toujours dérouler la liste complète derrière les points de suspension.

3. Éteindre un service est plus robuste que le filtrer. NFS a résisté à toutes les manipulations de règles ; il s'est fermé instantanément une fois le service désactivé. Un service éteint ne dépend d'aucune règle, d'aucun ordre, d'aucun profil actif.

Résultat

Fermés : SMB (445/139), NFS (2049, 111, 662, 892, 4045), FTP (21), rsync daemon (873), Note Station, File Station, WS-Discovery et une dizaine d'autres.

Restent : 22 (voulu — les deux VPS), 80/443/6690 (filtrés par pays), 5108/5109 (DSM), 5510 et 6281 (en cours d'identification).

Deux subtilités utiles

Le pare-feu Synology ne filtre que l'entrant. Le NAS va chercher les fichiers sur une seedbox en FTP : c'est une connexion sortante, soumise à aucune règle. Le port 21 du NAS n'y jouait aucun rôle et a pu être fermé sans rien casser. Bien distinguer « la machine se connecte » de « on se connecte à la machine » avant d'écrire une règle.

Le VPN rend la restriction indolore. En passant par le tunnel, le trafic arrive avec l'adresse source du VPN (10.8.0.0/24) et non l'IP publique du poste. Autoriser ce sous-réseau suffit, depuis n'importe où. Corollaire : le sous-réseau du VPN doit être explicitement autorisé sur le port 22 — il n'est couvert ni par 192.168.0.0/16 ni par 172.16.0.0/12. Sans cette règle, activer le pare-feu coupe l'accès SSH par le tunnel.

Point vérifié au passage : le VPN est OpenVPN (paquet VPNCenter, UDP 1194), et non WireGuard comme supposé. Testé par un vrai handshake — le serveur répond.

Erreurs commises pendant l'intervention

Consignées parce qu'elles sont instructives :

Une image supprimée à tort (page « Calcul Patterns Route Commune »), faute d'avoir compris que les pages pointent parfois sur l'URL scaled-. Restaurée depuis l'archive.
Diagnostic erroné : « vos suppressions de règles ne prennent pas effet ». La vraie cause était la règle englobante au libellé tronqué.
Test sur les mauvais ports : DSM déclaré « non exposé » après un test sur 5000/5001, alors qu'il écoute sur 5108/5109 — ports personnalisés.
Accès DSM supposé indisponible sans l'avoir vérifié. L'accès SMB au partage administrateur homes existait, et a permis de lire authorized_keys.

Les deux garde-fous qui ont évité des dégâts : l'archive systématique avant suppression, et la vérification après chaque action plutôt que la confiance dans l'effet attendu.

fail2ban sur le VPS juxjux (23 septembre 2026)

Même sujet, autre machine. Le durcissement ci-dessus portait sur le NAS ; ce volet concerne le VPS juxjux.ovh, dont la porte SSH était restée battante.

Le constat. Le fichier /var/log/btmp, qui enregistre les tentatives de connexion échouées, pesait 251 Mo. Il ne s'agissait pas d'un problème de journaux : 364 743 tentatives depuis le 1er septembre, le compte root visé 163 300 fois, admin 13 219, ubuntu 12 568. Une seule adresse en comptait 87 745 — c'est elle qui gonflait la moyenne à 17 000 par jour, alors que le rythme de fond est d'environ 3 000. Purger ce fichier aurait fait disparaître la mesure, pas les attaques : il est le thermomètre, pas la fièvre.

Le piège qui aurait rendu l'installation inutile. Sur ce Debian 12, /var/log/auth.log n'existe pas — les connexions ne sont écrites que dans journald. Avec sa configuration par défaut, fail2ban surveille ce fichier absent. Ici l'échec a été franc : le service est tombé en failed dès l'installation, sur ERROR Have not found any log file for sshd jail. Le vrai danger était la variante silencieuse — une jail qui démarre, affiche « 0 banni », et laisse conclure que les attaques ont cessé. La ligne backend = systemd règle le problème, et le contrôle à faire est double : Journal matches: _SYSTEMD_UNIT=sshd.service dans le statut de la jail, et un compteur de bannis non nul.

La même leçon que le VPN du NAS, sur une autre infrastructure. La question de la liste blanche est celle qui pouvait coûter le plus cher : une erreur ici ferme la porte de l'extérieur, y compris pour nous. Les adresses publiques semblaient l'évidence, mais l'historique des connexions du VPS montrait des accès depuis six adresses 92.184.113.x différentes et une adresse italienne — des connexions en partage 4G et en vacances, pas la box de la maison. La réponse solide est ailleurs : le VPS est le hub du maillage WireGuard, et une connexion par le tunnel lui arrive avec l'adresse source 10.0.0.3, privée et immuable, indépendante de tout opérateur. C'est exactement ce qui avait été constaté sur le NAS avec son OpenVPN en 10.8.0.0/24. Deux machines, deux VPN différents, la même conclusion : autoriser le sous-réseau du tunnel vaut mieux que courir après des adresses publiques. Vérifié avant d'armer la jail, pas après : ssh debian@10.0.0.1 fonctionne et le serveur voit bien 10.0.0.3.

La liste blanche retenue compte donc trois filets, du plus sûr au moins sûr : 10.0.0.0/24 (le tunnel, qui couvre aussi le NAS en 10.0.0.2), puis 83.195.45.93 pour la maison et 82.66.244.248 pour le bureau. Nuance utile entre ces deux dernières : l'adresse du bureau est fixe par construction — Free en attribue une à chaque Freebox, et celle-ci n'a pas bougé en quatre ans — tandis qu'Orange ne garantit rien en offre grand public. C'est aussi pourquoi le point de contact WireGuard du NAS n'a jamais eu besoin d'être retouché.

Ce que fail2ban n'est pas. La crainte naturelle — « et si mon PC ou le NAS tombe en panne ? » — repose sur un malentendu qu'il vaut la peine de lever : ce n'est pas une liste d'accès. Le port 22 reste ouvert à tous ; fail2ban compte les échecs et ne ferme qu'après cinq ratés en dix minutes. Depuis n'importe quelle machine et n'importe quelle adresse, une connexion avec le bon mot de passe passe du premier coup. La liste blanche ne sert qu'à une chose : éviter de se bannir soi-même en se trompant plusieurs fois. Et un bannissement dure une heure, pas davantage. Restent, en dernier recours, le tunnel puis la console KVM de l'hébergeur, qui ne dépend ni du réseau ni de SSH.

Réglages et résultat. Jail sshd, cinq échecs tolérés sur dix minutes, bannissement d'une heure, configuration dans /etc/fail2ban/jail.local (jamais jail.conf, écrasé aux mises à jour). L'action de bannissement passe par ufw plutôt que par une chaîne iptables parallèle, puisque le pare-feu est déjà en place : les blocages apparaissent bien en tête de ufw status numbered, avant la règle qui autorise le port 22. Dans les secondes suivant le démarrage : 131 échecs détectés, trois adresses bannies.

Une erreur commise au passage, dans l'esprit de la section précédente : la sauvegarde de l'ancienne configuration avait été déposée dans /etc/logrotate.d/. Or logrotate lit tous les fichiers de ce dossier, sans considération d'extension — d'où un duplicate log entry for /var/log/btmp et un fichier entier ignoré. Une sauvegarde ne se range jamais dans un dossier que lit un service ; elle a été déplacée vers /root/logrotate-sauvegardes/.

Ce qui reste ouvert

Sur la sauvegarde

Destination unique : si le NAS refuse, plus rien ne sort du VPS.
Aucune rétention sur le VPS (staging vidé après transfert).
Restauration jamais testée — une sauvegarde non restaurée n'est pas une sauvegarde.
Disque VPS à 87 % (9,3 Go libres).
HyperBackup non surveillé : toute la profondeur d'historique en dépend.

Sur le NAS

Identifier et fermer 5510 et 6281.
DSM (5108/5109) reste accessible depuis Internet — si maintenu, activer 2FA et le blocage automatique.
Inverser le sens du transfert : que le NAS tire depuis le VPS, ce qui permettrait de fermer SSH sur le NAS définitivement plutôt que provisoirement. Le compte synobackup existe déjà pour cela.

Sur le VPS (ajouté le 23/09/2026)

Passer à une clé SSH plutôt qu'un mot de passe : cela supprimerait à la fois le risque de se bannir sur une faute de frappe et tout intérêt aux 3 000 tentatives quotidiennes. Retirer la règle du pare-feu qui ouvre le port 2222, derrière lequel plus rien n'écoute. Et adosser au canari du matin une sonde sur la jail, pour que son extinction ne passe pas inaperçue.

02_les petites procédures de Claude

260903-Capture du texte sur applications Android vers Joplin

Récupérer le texte affiché par une application Android — un article de presse, typiquement — et le déposer dans Joplin ou dans le coffre Obsidian, depuis le PC.

Mis en place le 2026-09-03 sur le poste julie. Reproductible sur un autre PC, la procédure d'installation figure plus bas.

Le principe

Le script appelle uiautomator dump, un outil livré avec Android, qui exporte l'arbre d'accessibilité de l'écran en XML. On en tire les attributs text et content-desc.

Ce n'est PAS de la reconnaissance optique. On récupère le texte réel de l'application, avec ses accents, sa ponctuation et sa casse exacts. Aucune erreur de lecture possible, contrairement à un OCR sur capture d'écran.

Rien n'est installé sur la tablette. Tout passe par adb, déjà présent avec le SDK Android.

Ce qu'il faut sur le PC

Élément Rôle
Python 3.12 le script n'utilise que la bibliothèque standard — rien à installer en plus
adb fourni par platform-tools du SDK Android
Un appareil joignable l'émulateur emulator-5554, ou un vrai téléphone en débogage USB

Le script est dans l'arbre Syncthing, donc déjà présent sur toutes les machines :

Jux-scripts/Android-Texte/capturer_texte.py
Jux-scripts/Android-Texte/README.md

Usage

# ecran courant, affiche dans la console
py -3.12 capturer_texte.py

# vers un fichier / le presse-papiers
py -3.12 capturer_texte.py -o article.txt
py -3.12 capturer_texte.py --presse-papiers

# vers Joplin ou Obsidian
py -3.12 capturer_texte.py --joplin
py -3.12 capturer_texte.py --obsidian
Option Défaut Rôle
-o, --fichier — fichier UTF-8
--presse-papiers — copie dans le presse-papiers Windows
--joplin — crée une note Joplin
--carnet Captures Android carnet Joplin, créé s'il manque
--obsidian — dépose un .md dans le coffre
--coffre D:\Syncthing\Jux_Obsidian racine du coffre
--dossier Captures Android sous-dossier du coffre
--titre deviné titre de la note
--defiler — fait défiler et accumule
--serie emulator-5554 identifiant adb
--adb — chemin d'adb.exe
--tri-position — trier par coordonnées (voir pièges)

Codes de sortie : 0 succès, 1 erreur adb, 2 échec Joplin, 3 échec Obsidian.

Les deux destinations

Obsidian — la plus simple

Écrit un .md dans <coffre>\Captures Android\, avec l'en-tête YAML des notes existantes :

---
title: ...
created: 2026-09-03 04:54:54Z
updated: 2026-09-03 04:54:54Z
source: capture Android
---

Ni jeton, ni application ouverte, ni service à activer. Le coffre étant dans Syncthing, la note part sur tous les appareils par la synchronisation habituelle. Les noms de fichier sont assainis pour Windows et un suffixe (2), (3)… évite d'écraser.

Joplin — via le Web Clipper, en local

Mise en place, une seule fois par PC :

  1. Joplin → Outils → Options → Web Clipper → Activer le service
  2. Copier le jeton affiché dans D:\Android\joplin_token.txt

La variable d'environnement JOPLIN_TOKEN est prioritaire si elle existe.

⚠ Le jeton doit être HORS de l'arbre Syncthing. Déposé par erreur dans D:\Syncthing\Jux_univers\Mes Notepads\ le 2026-09-03, il s'est répliqué sur les sept appareils du maillage avant d'être déplacé. Le risque reste modéré — l'API n'écoute que sur 127.0.0.1 du PC, détenir le jeton ailleurs ne donne aucun accès distant — mais la régénération est immédiate depuis les options de Joplin. Même principe que /home/debian/.komga_scan.env côté VPS.

Pourquoi pas le Joplin Server du VPS

joplin.juxjux.ovh est un serveur de synchronisation, pas une API de notes : les items y sont sérialisés pour la synchro, on ne peut pas y créer une note proprement. La seule voie praticable est l'API locale du client de bureau, sur http://127.0.0.1:41184.

Corollaire : Joplin doit être ouvert sur le PC au moment de la capture.

Les lanceurs du bureau

Deux fichiers .cmd sur le bureau : Capturer vers Joplin et Capturer vers Obsidian.

Ils vérifient la présence de Python et du script, écrivent une copie du texte dans %TEMP%\derniere_capture.txt, consignent les erreurs dans D:\Android\capture_texte.log et affichent les dernières lignes du journal en cas d'échec.

Pourquoi des .cmd et pas des raccourcis .lnk : un .lnk créé depuis Claude Code vers une cible sous %LOCALAPPDATA% fige un chemin virtualisé et ne fait rien du tout (voir page 282, section 6). Un .cmd est du texte brut : ses chemins sont littéraux et fonctionnent depuis l'explorateur.

Pièges rencontrés

⚠ 1. L'ordre du document, pas les coordonnées

Une première version triait les fragments par coordonnées bounds. Faux : dès qu'une partie du contenu est hors écran — le cas courant avec une WebView — ses bounds deviennent aberrants et les paragraphes ressortent mélangés.

L'ordre de l'arbre XML est l'ordre du document, donc l'ordre de lecture. C'est le comportement par défaut. --tri-position rétablit l'ancien, pour de rares interfaces natives dont l'arbre ne suit pas la mise en page.

⚠ 2. --defiler est souvent inutile

Une WebView expose l'intégralité du document chargé à l'accessibilité, pas seulement la partie visible. Un article de presse entier est capturé en un seul appel.

--defiler ne sert vraiment que pour les listes à chargement progressif — fil d'actualité, boîte de réception — où le contenu n'existe pas tant qu'on n'y est pas descendu.

⚠ 3. Le titre est deviné, et pas toujours trouvable

Sans --titre, le script prend la plus longue des huit premières lignes, entre 30 et 120 caractères, en écartant dates, heures, signatures (Par X), Mis à jour, Lire aussi.

Trois versions ont été nécessaires :

Règle essayée Résultat obtenu
première ligne substantielle « Éditos & Analyses » — la rubrique
la plus longue des premières « Le 01/09/2026 à 06h45 | Mis à jour… » — la date
+ filtre, plancher à 20 caractères « trottinettes spatiales » — une bribe de phrase
+ plancher à 30 caractères correct, ou repli sur la date

Il faut capturer depuis le HAUT de l'article. Une fois qu'on a défilé loin, l'en-tête sort de l'arbre et aucun titre n'est trouvable : la note prend alors la date (Capture Android du 03-09-2026 a 07h18). C'est délibéré — mieux vaut une date qu'un titre faux. Sinon, --titre "...".

⚠ 4. cmd clipboard n'existe pas

Sur les images « Google Play », adb shell cmd clipboard répond No shell command implementation. D'où le passage par clip.exe côté Windows, en UTF-16LE.

⚠ 5. Ne pas faire défiler la tablette par adb à l'aveugle

Sept input swipe enchaînés pour « remonter en haut » ont fait sortir l'application Les Échos de l'article et atterrir sur un écran de recherche. Les gestes longs déclenchent des navigations imprévues.

Laisser l'utilisateur positionner la vue lui-même.

⚠ 6. Vérifier Joplin sur TOUTES les pages

GET /folders est paginé. Avec 106 carnets, une vérification limitée à la première page conclut à tort que le carnet n'existe pas. Le script, lui, suit has_more correctement.

# faux : ne lit que la page 1
Invoke-RestMethod "http://127.0.0.1:41184/folders?token=$j"

Installer sur un autre PC

  1. Python 3.12 — winget install --id Python.Python.3.12 --scope user
  2. platform-tools — via le SDK Manager d'Android Studio, ou l'archive seule de Google
  3. Adapter ADB_DEFAUT en tête du script, ou passer --adb
  4. Pour Obsidian : adapter COFFRE_DEFAUT, ou passer --coffre
  5. Pour Joplin : activer le Web Clipper et déposer le jeton hors de Syncthing
  6. Recopier les deux .cmd du bureau en corrigeant les chemins en tête de fichier

Le script lui-même n'a rien à installer : stdlib seule.

Limites

Vérifié le 2026-09-03

Si ça ne marche pas

Le journal D:\\Android\\capture_texte.log est le point d'entrée : les lanceurs y écrivent la sortie d'erreur et en affichent les dernières lignes en cas d'échec.

Une exécution saine ressemble à ceci :

===== 03/09/2026  7:42:55 - Joplin =====
  ecran 1 : 29 nouveaux fragments
29 fragments -> C:\\Users\\julie\\AppData\\Local\\Temp\\derniere_capture.txt
Joplin : note creee dans « Captures Android » — e4e99c3f...

Échec transitoire observé le 2026-09-03 à 07:23. La capture avait réussi — fichier de secours de 6,7 Ko écrit, article complet — mais aucune note n'avait été créée. Rejoué à l'identique quelques minutes plus tard : succès, sans qu'aucune modification n'ait été faite entre-temps.

Cause non établie. Deux hypothèses restent ouvertes : Joplin indisponible ou en cours de synchronisation à cet instant, ou un problème d'encodage sur la sortie d'erreur sous console .cmd. Une piste a été écartée par la mesure : le chemin Python codé en dur dans les .cmd pointe sous %LOCALAPPDATA%, mais l'installation y est bien réelle — le chemin conteneur …\\Packages\\Claude_pzs8sxrjxfjjc\\LocalCache\\Local\\Programs\\Python\\… n'existe pas. C'est d'ailleurs le test à retenir pour trancher ce type de doute (page 282, section 6).

C'est pour cette raison que les lanceurs journalisent : si le cas se reproduit, le message sera conservé.

En cas d'échec, le texte n'est jamais perdu : il reste dans %TEMP%\\derniere_capture.txt.

Contrôles rapides

# la tablette repond-elle ?
& 'D:\Android\Sdk\platform-tools\adb.exe' devices

# le service Web Clipper est-il actif ?
Invoke-WebRequest 'http://127.0.0.1:41184/ping' -UseBasicParsing   # -> JoplinClipperServer

# le jeton est-il en place ?
Test-Path 'D:\Android\joplin_token.txt'

Voir aussi

02_les petites procédures de Claude

260904-conversion des fichiers FLAC en MP3 avec Tags vérifiés

Conversion des fichiers FLAC en MP3, avec tags vérifiés

Mise en place le 2026-09-04 sur le poste Windows julie. Script versionné dans Jux-scripts/Musique-FLAC/, documentation de référence : le README.md du même dossier.

On dépose des FLAC dans un dossier, on les récupère encodés en MP3 dans un autre, sans rien lancer à la main. C'est la troisième procédure bâtie sur ce moule, après Komga-PDF (compression de PDF) et Photos-Caesium (compression de photos), dont elle reprend les garde-fous éprouvés : écriture par fichier provisoire, mémoire des échecs, journal persistant, attente d'une période de calme avant de toucher au dépôt.

Sa particularité : elle ne fait pas confiance au convertisseur. Les tags sont lus dans le FLAC par le script lui-même, réécrits explicitement, puis relus dans le MP3 produit et comparés champ par champ. Un MP3 auquel il manque un tag n'est pas livré.

Pourquoi localement, et pourquoi ffmpeg

Le VPS n'intervient pas. L'encodage MP3 est du calcul pur : le Ryzen 5 2600X (12 fils) est très largement supérieur au VPS pour cet usage, et les fichiers sont déjà sur le poste. Aucun aller-retour réseau, aucune API à maintenir — même raisonnement que pour Photos-Caesium.

Aucun encodeur n'était présent sur ce poste : ni ffmpeg, ni lame, ni flac, et Python n'a pas

Emplacements

Rôle Chemin
Dépôt D:\Musique\FLAC à encoder\
Résultat D:\Musique\MP3 fait\
Originaux après conversion D:\Musique\FLAC traités\
Échecs (après 3 tentatives) D:\Musique\echecs\
Binaire D:\Musique\bin\ffmpeg.exe
Configuration D:\Musique\config.json
Journal D:\Musique\logs\flac_mp3.log
Mémoire des traitements D:\Musique\etat.json
Script Jux-scripts\Musique-FLAC\flac_mp3.py (synchronisé, donc versionné)

Les dossiers de travail sont volontairement hors de l'arbre Syncthing, pour la même raison que Photos-Caesium : il n'existe qu'un seul dossier Syncthing dans tout le maillage (afltj-njyuy), partagé avec 7 appareils. Un album FLAC de 400 Mo déposé dedans descendrait intégralement sur le Xiaomi et la SM-T720.

L'arborescence du dépôt est reproduite à l'identique en sortie : on dépose le dossier de l'album, on récupère le dossier de l'album.

Usage

Trois lanceurs à double-cliquer dans D:\Musique\ :

En ligne de commande :

py -3.12 flac_mp3.py --une-fois
py -3.12 flac_mp3.py --simulation
py -3.12 flac_mp3.py --profil 320 --une-fois
py -3.12 flac_mp3.py --profils
py -3.12 flac_mp3.py --verifier "D:\Musique\MP3 fait\album\01 - titre.mp3"
py -3.12 flac_mp3.py --oublier-echecs
py -3.12 flac_mp3.py                    # surveillance continue

--verifier relit les tags d'un MP3 déjà produit et les affiche : c'est l'outil de contrôle à la main, indépendant de toute conversion.

Profils de qualité

Définis dans config.json, V0 par défaut.

Profil Options LAME Débit moyen
V0 -q:a 0 ~245 kbps VBR — transparent, réglage de référence
V2 -q:a 2 ~190 kbps VBR — nettement plus léger
320 -b:a 320k 320 kbps CBR — compatibilité matérielle maximale
256 / 192 -b:a … débits fixes intermédiaires

Ce que fait le script, dans l'ordre

  1. Attend que le dépôt soit calme. Sondage toutes les 15 s ; le traitement ne démarre qu'après 20 s sans le moindre changement dans l'arborescence (nombre de fichiers, volume total, date la plus récente). C'est ce qui évite d'attraper un fichier en cours de copie. Plafond de 15 min, après quoi le traitement est forcé.
  2. Lit le FLAC lui-même : bloc STREAMINFO (durée, fréquence, canaux) et bloc VORBIS_COMMENT (tous les tags), présence d'un bloc PICTURE.
  3. Refuse d'emblée un FLAC dépourvu de title, artist ou album — liste réglable par tags_obligatoires.
  4. Encode en écrivant chaque tag explicitement (voir le piège n°1 plus bas), pochette comprise, vers un fichier .staging-… et non directement vers la destination.
  5. Relit les trames ID3v2 du MP3 produit et les compare aux tags attendus.
  6. Recompare la durée du MP3 à celle du FLAC (voir le piège n°3 — c'est le contrôle le plus utile de la chaîne).
  7. Ne publie le MP3 que si tout passe. Le fichier provisoire est renommé en place (opération atomique) ; en cas d'échec il est supprimé et rien n'apparaît en sortie.
  8. Déplace l'original dans FLAC traités\. Les fichiers d'accompagnement (cover.jpg, .cue, .log, .m3u…) suivent l'album ; les images sont en plus copiées en sortie. Les dossiers vidés sont élagués, de sorte que le dépôt se vide de lui-même.

En cas d'échec, le fichier est retenté 3 fois (clé taille + date de modification, mémorisée dans etat.json), puis écarté dans echecs\ accompagné d'un .erreur.txt qui dit pourquoi.

Correspondance des tags

Les tags Vorbis du FLAC sont traduits en trames ID3v2 standard :

Vorbis ID3v2 Remarque
TITLE TIT2
ARTIST TPE1
ALBUM TALB
ALBUMARTIST / ALBUM ARTIST TPE2
DATE / YEAR TYER (v2.3) ou TDRC (v2.4) voir piège n°2
TRACKNUMBER + TRACKTOTAL TRCK = 3/12 recomposé, voir piège n°1
DISCNUMBER + DISCTOTAL TPOS = 1/2 recomposé
GENRE TCON
COMPOSER TCOM
ORGANIZATION / LABEL / PUBLISHER TPUB
COPYRIGHT TCOP
ISRC TSRC
BPM TBPM
COMMENT / DESCRIPTION COMM
LYRICS / UNSYNCEDLYRICS USLT
bloc PICTURE APIC pochette
tout le reste TXXX:<nom> REPLAYGAIN_*, MUSICBRAINZ_*… conservés tels quels

Aucun tag n'est perdu : ce qui n'a pas de trame dédiée part en TXXX sous son propre nom, et c'est relu tel quel à la vérification.

Pièges — à ne pas re-découvrir

1. ffmpeg -map_metadata 0 perd les totaux de piste et de disque. C'est la raison d'être de la réécriture explicite (-map_metadata -1 puis un -metadata par champ). Mesuré sur le même FLAC source :

ffmpeg nu ce script
piste track 3 + TXXX:tracktotal 12 TRCK 3/12
disque disc 1 + TXXX:disctotal 2 TPOS 1/2
éditeur TXXX:organization TPUB

Un lecteur qui affiche « piste 3 sur 12 » lit TRCK, pas un TXXX non standard. La conversion naïve produit donc des albums qui s'affichent mal sans que rien ne le signale.

2. ID3v2.3 ne sait pas stocker une date complète. Sa trame TYER ne contient que l'année : un DATE=2024-03-17 devient 2024. Ce n'est pas une perte de tag mais une limite du format — le script le classe en écart toléré et ne bloque pas. "id3v2_version": 4 dans config.json conserve la date entière (trame TDRC), au prix de la compatibilité avec les vieux lecteurs matériels. La vérification fonctionne dans les deux cas. v2.3 est le défaut retenu.

3. ⚠ Un FLAC tronqué se convertit sans la moindre erreur. Vérifié : sur un FLAC coupé au tiers, ffmpeg sort en code 0 et produit un MP3 parfaitement valide… de 0,27 s au lieu de 2,00 s. Ni le code de retour, ni la validité du MP3, ni les tags ne trahissent quoi que ce soit — les tags sont même intacts, puisqu'ils vivent en tête de fichier. Seule la comparaison des durées l'attrape, d'où verifier_duree activé par défaut. C'est le contrôle le plus utile de toute la chaîne, et le seul qui protège d'une livraison silencieusement mutilée.

4. Le bloc VORBIS_COMMENT est en petit-boutiste, alors que tout le reste du format FLAC est en gros-boutiste. Se tromper de sens donne des longueurs de champ aberrantes et un parseur qui part dans le décor.

5. Les tailles ID3 ne se lisent pas toutes pareil. L'en-tête ID3v2 et les trames v2.4 utilisent des entiers syncsafe (7 bits utiles par octet, le 8ᵉ toujours à 0) ; les trames v2.3, elles, portent une taille sur 32 bits ordinaires. Un seul mode de lecture pour les deux versions donne des trames décalées.

6. Valeurs multiples. Vorbis autorise plusieurs ARTIST dans un même fichier, ID3v2.3 non. Elles sont jointes par ; — et c'est cette même chaîne qui sert de valeur attendue à la vérification, donc la comparaison reste exacte.

7. pythonw.exe + binaire console = cascade de fenêtres noires. Le script passe creationflags=CREATE_NO_WINDOW à tous ses appels ffmpeg. Sans ce drapeau, un lancement en tâche planifiée par pythonw.exe (qui n'a pas de console) fait allouer une fenêtre par appel. Même piège que la surveillance Blink du 2026-08-30.

8. Pas d'inotify sous Windows : la surveillance se fait par sondage, pas par événements.

Surveillance automatique à l'ouverture de session

À créer par Julien dans sa propre console, pas depuis Claude Code — une tâche créée depuis le conteneur MSIX risquerait de figer un chemin virtualisé (page BookStack 282) :

schtasks /Create /TN "Musique-FLAC" /TR "\"C:\Users\julie\AppData\Local\Programs\Python\Python312\pythonw.exe\" \"D:\Syncthing\Jux_univers\Jux-scripts\Musique-FLAC\flac_mp3.py\"" /SC ONLOGON /RL LIMITED /F

pythonw.exe (et non python.exe) pour qu'aucune fenêtre n'apparaisse. Vérification : schtasks /Query /TN "Musique-FLAC" /V /FO LIST, ou taskschd.msc. Pour retirer : schtasks /Delete /TN "Musique-FLAC" /F.

Contrôle depuis une session Claude : Get-CimInstance Win32_Process -Filter "Name='pythonw.exe'".

Mesures de mise en place (2026-09-04)

Premier album réel — Dry Cleaning, Secret Love (2026-09-04)

Source FLAC 24 bits / 96 kHz, 11 pistes, 41 min 10 s d'audio.

Volume 823,7 Mo → 81,0 Mo, soit 9,8 % du FLAC
Durée 50 s pour tout l'album, environ 49 × le temps réel
Tags 18 par piste, tous vérifiés, aucun écart — pas même sur la date
Pochette conservée sur les 11 pistes (JPEG 600×600)
Dépôt vidé de lui-même ; Cover.jpg copiée en sortie, .m3u et .nfo suivis dans FLAC traités\

Tags exotiques restitués sans perte en TXXX : INVOLVEDPEOPLE (la liste complète des crédits, plus de 500 caractères), UPC, ITUNESADVISORY, MEDIATYPE, PRODUCER. Totaux recomposés en TRCK 3/11 et TPOS 1/1.

Le rééchantillonnage est automatique et inévitable : MP3 plafonne à 48 kHz, un FLAC 96 kHz est donc ramené à 48 kHz et 16 bits par ffmpeg, sans intervention. La tolérance d'une seconde sur la durée absorbe l'écart sans difficulté (mesuré : aucun signalement sur les 11 pistes).

Ne pas se fier au ratio relevé sur l'essai de synthèse (55 %) : une onde sinusoïdale ne compresse comme rien de réel. Le chiffre utile est celui de ce tableau.

Reste à faire

02_les petites procédures de Claude

260904 - ISBN des livres pour indexation Calibre

ISBN des livres pour indexation Calibre

Procédure en trois étapes, arrêtée le 2026-09-20. Copie de référence : Jux-scripts/Livres-ISBN/doc_bookstack_300.md.

Le processus

1. Julien dépose les EPUB et PDF à identifier dans

D:\Procedures Calibre\Dossier à renseigner

avec leurs sous-dossiers s'il veut retrouver ses rayons dans le CSV.

2. Claude lance le script (ou Julien, c'est une seule commande) :

py -3.12 D:\Syncthing\Jux_univers\Jux-scripts\Livres-ISBN\renseigner.py

Il produit un seul fichier, dans le dépôt lui-même, daté du jour, dans l'ordre des fichiers :

D:\Procedures Calibre\Dossier à renseigner\260920-livres-isbn.csv

3. Claude écrit dans les fichiers déposés ce qu'il a trouvé — l'ISBN, et le titre/auteur du catalogue quand la proposition est sûre :

py -3.12 D:\Syncthing\Jux_univers\Jux-scripts\Livres-ISBN\ecrire_metadonnees.py --go

L'outil est ebook-meta.exe, celui de Calibre : ce qu'il écrit, Calibre le lit à l'ajout, par construction. Décision de Julien (2026-09-20) : écrire même quand la recherche peut être erronée — « c'est moi qui valide les livres un par un ensuite ; si l'ISBN est faux, je le vois. Ça me fait gagner un temps fou. » Chaque fichier est copié à côté avant l'écriture, contrôlé après, restauré si le contrôle échoue. Le CSV reçoit une colonne ecrit.

4. Julien ajoute les livres un à un dans Calibre, vérifie, valide, corrige, le CSV ouvert à côté (LibreOffice Calc l'ouvre directement, séparateur ;). Une fois le lot fait, il vide le dépôt — Calibre a copié les fichiers dans sa bibliothèque, les originaux sont dans Foxy.

Aucun script n'écrit dans Calibre ni dans Foxy. Le dépôt est une copie de travail ; les deux scripts refusent tout dossier réseau.

Lire le CSV

Une ligne d'intitulé === rayon === (n) précède chaque sous-dossier. Puis, par livre :

Colonne Ce qu'elle dit
confiance o : ISBN sûr, à saisir tel quel. ? : trouvé en catalogue mais à vérifier (comparer titre/auteur à la couverture). Vide : rien trouvé
a_saisir Ce que Julien devra taper dans Calibre — rien, isbn, titre, auteur ou une combinaison. Le reste, Calibre le lira tout seul dans le fichier à l'ajout
isbn, titre, auteur Les valeurs à reporter
provenance fichier (lu dans le livre), BnF, OpenLibrary
calibre_lira isbn si Calibre lira l'ISBN de lui-même
remarque Les avertissements : fichier que Calibre ne sait pas ouvrir, nom à renommer, doublon, titre suspect

Dans Calibre, l'ISBN se saisit dans Modifier les métadonnées → Identifiants sous la forme isbn:9782…. Ensuite Télécharger les métadonnées complète la fiche — mais uniquement le résumé : le réglage Préférences → Partage → Téléchargement des métadonnées → Champs à télécharger ne doit garder que Résumé. Les étiquettes sont le classement de Julien, jamais écrasées.

Ce que fait le script, et pourquoi

Pièges connus

Historique

02_les petites procédures de Claude

260911- Paroles dans ma musique / paroles sur Navidrome

En une phrase

Navidrome n'affiche dans son lecteur web que les paroles synchronisées et embarquées dans les fichiers ; on les fait chercher sur LRCLIB par Beets (en conteneur sur le NAS), un script les écrit dans les tags sans rien toucher d'autre, on pousse les fichiers modifiés vers kDrive, Navidrome les relit.

1. Le diagnostic — pourquoi « Absence de paroles » était normal

Le symptôme : Dancing Queen d'ABBA affichait « Absence de paroles » dans le lecteur web, alors qu'un fichier Dancing Queen.lrc synchronisé était posé à côté du MP3 et que l'API Subsonic (getLyricsBySongId) renvoyait bien ces paroles horodatées.

Vérifié dans le code de Navidrome 0.63.2 :

État de la bibliothèque le 2026-09-11 avant travaux : 16 077 titres, 485 avec paroles en base, 15 synchronisées — donc 15 titres affichables dans l'interface web, sur 16 000.

2. Architecture retenue

Élément Choix Pourquoi
Où ça tourne NAS sasnexte, Container Manager, sur /volume1/music C'est l'original. Le VPS ne lit qu'un miroir kDrive (/home/debian/music) que sync_kdrive_complete.sh écrase chaque nuit : y écrire serait perdu
Recherche Beets 2.14.0 (lscr.io/linuxserver/beets), plugin lyrics, source LRCLIB seule Gratuit, sans clé, la seule source qui fournit des paroles synchronisées. Genius/Google ne donnent que du texte brut, invisible du web
Écriture dans les fichiers ecrire_paroles.py (mutagen), pas Beets Voir le piège n°1 : Beets réécrit tous ses champs
Propagation propager_paroles.sh (rclone forcé) Voir le piège n°2 : le padding ID3
Enchaînement finir_paroles.sh en setsid 7 h de traitement, le NAS finit seul

Les fichiers : docker-compose.yml, config.yaml (Beets), ecrire_paroles.py, propager_paroles.sh, finir_paroles.sh, README.md — dans Jux-scripts/Navidrome-Paroles/, déployés sur le NAS dans /volume1/homes/SAS_NEXTE/scripts/ et /volume1/docker/beets-paroles/config/.

Configuration Beets, l'essentiel :

import:
  autotag: no        # jamais de re-identification MusicBrainz
  copy: no
  move: no           # jamais de deplacement / renommage
  write: no          # Beets N'ECRIT JAMAIS dans les fichiers (piege n°1)
  incremental: yes
  duplicate_action: keep   # piege n°4
ignore: ['#recycle', '@eaDir', '@__thumb', '.*', '*~', 'System Volume Information', 'lost+found']
plugins: lyrics web
lyrics:
  auto: no
  sources: [lrclib]
  synced: yes        # preferer les paroles horodatees
  keep_synced: yes   # ne jamais retoucher un titre deja synchronise
  force: yes         # re-interroger les 485 titres qui n'ont que du texte brut
  fallback: null     # rien trouve -> fichier intact

3. La procédure, telle qu'elle a été jouée le 2026-09-11

Sur le NAS (SSH sas_nexte, docker exige sudo et vit dans /usr/local/bin/) :

D=/usr/local/bin/docker
cd /volume1/docker/beets-paroles && sudo $D compose up -d
sudo $D exec beets-paroles beet version            # 2.14.0
sudo $D exec beets-paroles beet lyrics --help | grep keep-synced   # l'option doit exister

Inventaire — Beets indexe la bibliothèque sans rien écrire (-A = tel quel, -W = aucun tag réécrit) :

sudo $D exec beets-paroles beet import -A -W /music      # 25 min, 15 770 titres
# + 25 dossiers reimportes avec -I (piege n°4)          -> 16 069 titres
sudo $D exec beets-paroles beet stats

Essai sur un album, avec repère posé avant :

/volume1/homes/SAS_NEXTE/scripts/propager_paroles.sh --repere
sudo $D exec beets-paroles beet lyrics 'album:Gold - Greatest Hits'        # 19/19 en 20 s
sudo $D exec beets-paroles python3 /config/ecrire_paroles.py --simulation --filtre "ABBA/Gold"
sudo $D exec beets-paroles python3 /config/ecrire_paroles.py --filtre "ABBA/Gold" --controle 19
/volume1/homes/SAS_NEXTE/scripts/propager_paroles.sh                       # 19 fichiers, 4 s

Côté VPS, rafraîchir le listing du montage et scanner :

rclone rc --rc-addr 127.0.0.1:5576 --rc-user=rcadmin --rc-pass='RcMusic2026!' vfs/refresh recursive=true dir='ABBA/Gold - Greatest Hits'
curl "https://navidrome.juxjux.ovh/rest/startScan?u=julien&p=…&v=1.16.0&c=claude&f=json"

Résultat : Dancing Queen synced: true en base Navidrome, start: 20320 (20,32 s), après un simple quick scan — la date du dossier ayant changé, Navidrome relit ses fichiers.

Toute la bibliothèque, sans surveillance :

/volume1/homes/SAS_NEXTE/scripts/propager_paroles.sh --repere
sudo $D exec -d beets-paroles sh -c 'beet lyrics >> /config/lyrics_run.log 2>&1; echo "FIN rc=$?" >> /config/lyrics_run.log'
setsid /volume1/homes/SAS_NEXTE/scripts/finir_paroles.sh < /dev/null > /dev/null 2>&1 &

finir_paroles.sh attend la ligne FIN, lance ecrire_paroles.py --controle 50 (50 fichiers tirés au hasard dont l'empreinte audio est comparée avant/après — le moindre écart arrête tout), puis propager_paroles.sh. Il n'y a pas de propagation si l'écriture a le moindre échec : on préfère un état non poussé à un état partiel.

Suivi :

tail /volume1/homes/SAS_NEXTE/logs/paroles_finir.log
sudo $D exec beets-paroles sh -c 'echo "$(grep -c "Found lyrics" /config/lyrics_run.log) / $(grep -c "Fetching lyrics" /config/lyrics_run.log)"'

Mesures : lancé à 18h08, terminé à 0h34, 0,64 titre/s, 86 % de paroles trouvées (voir le bilan en §7) ; le cron VPS de 4h30 (vfs/refresh + quick scan) relit ensuite la bibliothèque. Pour ne pas attendre : bash /home/debian/navidrome_fullscan.sh.

Contrôle final, sur le VPS :

sudo cp /home/debian/docker/navidrome/data/navidrome.db /tmp/nd.db
sudo cp /home/debian/docker/navidrome/data/navidrome.db-wal /tmp/nd.db-wal
sudo sqlite3 /tmp/nd.db "select count(*), sum(lyrics like '%\"synced\":true%') from media_file where lyrics not in ('','[]')"

Avant : 485|15. Dans le lecteur web, recharger la page et remettre le titre dans la file : la file de lecture conserve l'objet chanson tel qu'il était au moment de l'ajout, sans les paroles.

4. Les pièges — dans l'ordre où ils ont mordu

1. Beets écrit tous ses champs, pas seulement les paroles. Premier essai avec import.write: yes : sur Dancing Queen, Beets a réencodé toutes les trames texte et ajouté TRCK 0/0, TPOS 0/0, TDRC 0000, TDOR 0000, TBPM 0, TCMP 0 et un UFID vide — des valeurs qu'il n'avait pas, écrites comme des défauts. Sur 16 000 fichiers, une pollution durable des tags. Les 19 originaux d'ABBA ont été restaurés depuis kDrive (rclone copy … --ignore-times), Beets passé en write: no, et ecrire_paroles.py écrit lui-même, en ne touchant qu'aux trames de paroles : SYLT (horodatée) + USLT (texte brut) pour les MP3, ©lyr pour M4A, LYRICS pour FLAC. Vérifié à l'octet sur ABBA : trames d'origine de tailles identiques, empreinte audio identique, ID3v1 conservé, propriétaire admin:users conservé.

2. Le padding ID3 rend les modifications invisibles à la synchro. Le WebDAV kDrive n'expose ni empreinte ni date fiable : sync_kdrive_complete.sh ne compare que les tailles. Or, mesuré sur 40 MP3 au hasard, 30 ont ≥ 2 048 octets de padding — des paroles y tiennent souvent sans changer la taille du fichier. Le NAS aurait eu les paroles et Navidrome ne les aurait jamais vues. propager_paroles.sh liste les fichiers audio postérieurs à un repère et les pousse avec rclone copy --files-from --ignore-times, taille identique ou non. Le ré-envoi donne au fichier une nouvelle date côté kDrive, ce qui invalide aussi le cache VFS du VPS.

3. Les ACL Synology ne laissent passer que root dans le conteneur. docker exec -u 1024:100 (l'uid admin, propriétaire des fichiers) échoue en Permission denied sur /music : le partage est en mode 000, ses droits sont dans les ACL DSM, que le conteneur n'évalue pas pour un utilisateur ordinaire. Tout tourne donc en root dans le conteneur. Sans conséquence sur les fichiers : mutagen réécrit en place, même inode, le propriétaire reste admin:users. En revanche, un rclone copy de restauration lancé par sas_nexte recrée les fichiers sous cet utilisateur → chown admin:users derrière.

4. Vingt-deux albums sautés comme « doublons ». Même artiste et même titre d'album dans deux dossiers (The Suburbs et The Suburbs _ Month Of May, les disques 2 et 3 d'un best of, une édition deluxe…) : en mode silencieux Beets les saute (« This album is already in the library! »), et l'état incrémental les note comme traités — une relance ne les reprend pas. Correctif : duplicate_action: keep, puis réimport explicite des dossiers avec -I. Pour les extraire du journal, prendre la ligne qui précède chaque « already in the library » ; les multi-disques y sont regroupés sur une seule ligne séparée par ; , à découper. 15 770 → 16 069 titres.

5. Beets 2.x stocke les chemins relatifs à directory. items.path contient ABBA/Gold - Greatest Hits/…, pas /music/… : première passe de ecrire_paroles.py en 19 échecs « No such file ». Le script préfixe /music.

6. Deux fois du LRC = chaque ligne en double. Beets met du texte LRC dans SYLT et dans USLT ; Navidrome en fait deux entrées synchronisées, et le lecteur web concatène toutes les entrées synchronisées. ecrire_paroles.py écrit le LRC dans SYLT et le texte brut dans USLT.

7. nohup ne détache pas sur DSM : setsid … < /dev/null > /dev/null 2>&1 &, et vérifier par ps -eo pid,sid,args — ps w tronque et fait croire à un processus mort.

5. Ce que la chaîne ne fait pas

6. Pour un nouvel album, plus tard

D=/usr/local/bin/docker
sudo $D exec beets-paroles beet import -A -W /music        # incremental : seuls les nouveaux dossiers
/volume1/homes/SAS_NEXTE/scripts/propager_paroles.sh --repere
sudo $D exec beets-paroles beet lyrics 'added:-1w..'       # ou 'album:Titre'
sudo $D exec beets-paroles python3 /config/ecrire_paroles.py
/volume1/homes/SAS_NEXTE/scripts/propager_paroles.sh

Puis le cron VPS de 4h30 fait le reste. Le conteneur beets-paroles peut rester arrêté entre deux usages (sudo $D compose stop) : sa base /config/beets.db et l'état paroles_ecrites.json survivent.

7. Bilan du 2026-09-12

Étape Heure Résultat
beet lyrics (16 069 titres) 18h08 → 0h34 13 830 paroles trouvées (86 %), 0,64 titre/s
ecrire_paroles.py --controle 50 0h34 → 1h51 13 139 fichiers écrits, 10 979 synchronisés, 50 contrôles audio OK, 1 échec : un .mp3.part (téléchargement inachevé) — la chaîne s'est arrêtée avant propagation, comme prévu
propager_paroles.sh 6h05 → 6h46 13 139 fichiers, 102,7 Gio, 0 erreur, 50 Mio/s — en session setsid, a survécu à une coupure SSH
navidrome_fullscan.sh 8h10 → 8h32 21 min
Base Navidrome 16 077 titres, 13 160 avec paroles, 10 998 synchronisées (avant : 485 / 15)

Poids ajouté : 48,6 Mio sur 102,6 Gio (+0,046 %), 3,9 Ko par fichier en moyenne. 8 815 fichiers sur 13 137 n'ont pas changé de taille — les paroles ont tenu dans le padding ID3 : sans la propagation forcée, 67 % des fichiers seraient restés invisibles pour la synchro quotidienne. Le piège n°2 n'était pas théorique.

Le fichier .mp3.part de Suki Waterhouse est à supprimer à la main (ou à ajouter à ignore dans config.yaml).

Point ouvert : Julien constate 2–3 s de retard des paroles dans le lecteur web. Ce n'est ni le scan (l'affichage est piloté côté navigateur par la position de lecture) ni les données (LRCLIB et le .lrc d'origine s'accordent à 0,3 s près sur Dancing Queen). À tester dans Symfonium sur le même titre : en phase = le rendu du lecteur web (react-jinke-music-player) est en cause, et le modèle Navidrome connaît un offset LRC que le lecteur web ignore.

02_les petites procédures de Claude

260913-recettes de Joplin vers MEALIE par Claude

Mise en place le 2026-09-13. Mealie est utilisé tous les jours par toute la famille, mais renseigner une recette à la main est fastidieux : sections d'ingrédients, étapes, catégories, tags, photo. La procédure confie ce travail à Claude à partir d'une simple note Joplin.

1. La procédure, côté Julien

  1. Capturer la recette dans une note Joplin, dans le carnet « A transcrire dans Mealie » — texte libre, copié-collé d'un site, clip web, réponse d'un assistant, dictée, photos du téléphone. Aucune mise en forme n'est exigée.
  2. Publier la note : clic droit sur la note → Publier la note → copier le lien (https://joplin.juxjux.ovh/shares/xxxxxxxx).
  3. Coller le lien à Claude. C'est tout.

Le carnet est le garde-fou (demandé par Julien le 2026-09-13) : publier une note ne vaut pas consigne, seul le carnet le fait. Une note publiée pour une autre raison — un résumé de match de hockey, une liste, un article — est refusée par le script même si Claude se trompe sur son contenu. La page publiée ne dit pas dans quel carnet vit la note ; la base Joplin Server sur le VPS le sait (items.jop_parent_id, interrogée par SSH). Si la base est injoignable, le doute vaut refus.

Claude lit la note, la structure, crée la recette avec sa photo, et rend le lien Mealie. En retour il signale ce qu'il a dû décider seul (catégorie ou tag créé, quantités absentes, photo de remplacement), pour que Julien puisse corriger d'un mot.

Où est le travail de Claude

Une note de recette est rarement au carré : un copié-collé de site mêle recette et bavardage ; une réponse d'assistant argumente (« je choisirais l'espadon… ») au lieu de lister ; une photo de carnet manuscrit ne dit rien à un parseur. Un script ne peut pas trier ça. Claude, lui, lit la note comme un lecteur et en tire :

Champ Mealie Ce que Claude en fait
Nom reformulé en titre de recette (le titre Joplin est souvent une note de travail)
Description l'esprit du plat, les choix qui comptent — pas les étapes
Personnes, temps repris s'ils sont dans la note, estimés sinon (et signalés comme estimés)
Ingrédients listés en sections (Marinade, Sauce, Riz coco…) — Mealie les affiche titrées
Étapes rédigées à l'impératif, titrées, sans le bavardage
Notes ce qui ne rentre ni dans les ingrédients ni dans les étapes : variantes, choix du poisson, conseils
Catégories cuisine / pays / type de plat — c'est la convention de la base (Turquie, Italia, Poisson, Dessert…)
Tags ingrédients principaux — c'est l'autre convention de la base (Courgettes, Feta, Lait de coco…)
Source l'URL de la note Joplin, dans le champ URL d'origine de Mealie
Image la première vraie photo de la note ; les autres en photos secondaires

Claude réutilise les catégories et tags existants avant d'en créer, et signale toute création. Les temps sont en minutes nues (« 30 »), comme le reste de la base.

2. L'outillage

Tout est dans Jux-scripts/Mealie-Recettes/ et Jux-scripts/MCP/, stdlib Python seule — rien à installer, réplicable sur toutes les machines par Syncthing.

joplin_mealie.py — la mécanique

py -3.12 joplin_mealie.py lire <url_note_publiee>          # texte + images, avec verdict "photo ou pas"
py -3.12 joplin_mealie.py creer fiche.json [--simulation]  # creation, image, photos secondaires
py -3.12 joplin_mealie.py image <slug> <url_ou_fichier>    # poser / remplacer l'image principale
py -3.12 joplin_mealie.py organiseurs                      # categories et tags existants
py -3.12 joplin_mealie.py supprimer <slug>

Fiche JSON minimale :

{
  "nom": "Brochettes d'espadon satay, riz coco",
  "description": "…", "personnes": 4,
  "temps_preparation": "25", "temps_cuisson": "20", "temps_total": "60",
  "categories": ["Asiatique", "Poisson"],
  "tags": ["Espadon", "Lait de coco", "Cacahouetes"],
  "ingredients": [{"titre": "Marinade", "items": ["2 c. à soupe de sauce soja", "…"]}, "600 g d'espadon"],
  "etapes": [{"titre": "Marinade", "texte": "…"}, "Servir avec le riz."],
  "notes": [{"titre": "Quel poisson ?", "texte": "…"}],
  "source": "https://joplin.juxjux.ovh/shares/…",
  "image": "https://joplin.juxjux.ovh/shares/…?resource_id=…",
  "images_secondaires": ["https://…"]
}

mcp_mealie.py — les mêmes gestes en outils MCP

Enregistré le 2026-09-13 dans ~/.claude.json du poste julie (projet Claude-pcelio+jux), comme les autres MCP Python : command = chemin absolu de python.exe, args = chemin du script. 13 outils :

Le MCP importe joplin_mealie.py depuis le dossier voisin : une seule implémentation, deux façons de l'appeler (le CLI reste utile quand le MCP n'est pas chargé, ou depuis Ubuntu / la VM).

3. Première recette réelle — l'exemple du 2026-09-13

Note : https://joplin.juxjux.ovh/shares/EqODt1SvmX6OKzdr867bpZ — Brochette de poisson Satay sauce. Une réponse d'assistant collée telle quelle : classement de cinq poissons avec des étoiles, « je choisirais l'espadon », marinade en liste, sauce satay sans quantités, riz coco et accompagnement en prose.

Résultat : Brochettes d'espadon satay, riz coco — 5 sections d'ingrédients, 5 étapes titrées, 2 notes, catégories Asiatique + Poisson, 8 tags dont un créé (Espadon), photo. Le classement des poissons est allé dans une note, pas dans les étapes.

Ce qu'a révélé ce premier passage :

Deuxième recette — un clip web (même jour)

Note Uhp5DRRLdhLh2IlmAv8Bkg : la page entière du blog L'instant nordique clippée dans Joplin — menus, encarts, articles liés, formulaire de commentaire, pied de page, 19 images dont 3 fois le logo. La recette des köttbullar tient au milieu. Résultat : Köttbullar, boulettes de viande suédoises à la crème — 3 sections d'ingrédients, 7 étapes titrées, photo de la poêle en principale, l'assiette en photo secondaire.

Ce que Claude a dû arbitrer, consigné dans une note « Incohérences de la source » de la recette : la liste du site dit « 5 ml de lait » mais l'étape en met 4 cuillères à soupe (retenu) ; la sauce soja apparaît à la dernière étape sans figurer dans la liste (ajoutée) ; « 2 piments » est reproduit tel quel mais signalé comme douteux dans une recette suédoise ; nombre de personnes absent (4 pour 450 g, estimé). Le contrôle du carnet a fonctionné dans les deux sens le même jour : la note du pâté Lamourette, dans « Trucs et astuces », est refusée par creer.

4. Pièges relevés

  1. Un clip web embarque tout le site : navigation, articles liés, formulaire, 19 images. La recette est au milieu ; tout le reste est à ignorer, et les images du site ne sont pas toutes des photos du plat (logo, vignettes d'autres articles, portrait de l'auteur). Regarder les candidates avant de choisir.
  2. Une note publiée est publique — l'URL suffit, sans identifiant. Ne pas y mettre autre chose que la recette. Le champ URL d'origine de Mealie la garde : dépublier la note casse ce lien, sans effet sur la recette.
  3. Les images de la note se téléchargent par ?resource_id= sur l'URL du partage, anonymement. Les photos de téléphone arrivent en pleine taille (1 920 × 1 440, 500 Ko à 800 Ko) — Mealie les redimensionne lui-même.
  4. Mealie n'analyse pas les ingrédients : ils sont stockés en texte libre (note / display), comme les 141 recettes existantes. Le champ title du premier ingrédient d'une section porte le titre de section — c'est ainsi que Mealie fait ses en-têtes.
  5. POST /api/recipes ne prend que le nom et renvoie le slug ; tout le reste passe par un PUT du corps complet relu (GET puis mise à jour), sinon l'API efface ce qu'on n'a pas renvoyé.
  6. Les temps sont des chaînes libres dans Mealie. La base utilise des minutes nues (« 60 », « 30 ») — 31 recettes sur 141 n'en ont aucun. S'y tenir.
  7. 59 recettes sur 141 n'ont pas de catégorie au 2026-09-13 : les plus récentes ont été saisies vite. Rien n'empêche de les reprendre une par une avec lire_recette + mise à jour — chantier possible.
  8. Le CLI claude n'est pas dans le PATH du poste (application de bureau) : le MCP a été inscrit à la main dans .claude.json, sauvegarde .claude.json.bak-260913-mealie. Il faut relancer la session pour qu'il soit chargé.
  9. Piège d'atelier, sans rapport avec Mealie : l'outil Bash de Claude Code abîme les \x.. dans un heredoc Python — deux fichiers réparés en cours de route. Écrire les scripts avec l'outil d'édition, les exécuter avec Bash.

5. Identifiants

Mealie : jubertrand@gmail.com / mot de passe dans CLAUDE.md (OAuth2 password, POST /api/auth/token, formulaire username/password, jeton valable 48 h). Surchargeables par MEALIE_URL, MEALIE_USER, MEALIE_PASS.

02_les petites procédures de Claude

260914-les films de la Seedbox sur le Kdrive et indexation automatique Jellyfin

Mise en place le 14/09/2026. Scripts et README dans Jux-scripts/Seedbox-Films/ (arbre Syncthing). Tableau de bord : ligne « Seedbox » du tableau des procédures en pied de la veille du jour, et sonde « Seedbox-Films » des tâches nocturnes.

Le besoin, et ce qui a été écarté

Faire passer un film de la seedbox (pool372.seedbox.fr, accessible en WebDAV — c'est un Nextcloud) jusqu'à Jellyfin, sans le faire transiter par le PC, et que Jellyfin l'indexe tout seul.

Retenu : rclone sur le VPS, seedbox déclarée comme second remote à côté de kdrive. Le VPS pilote, mais le flux WebDAV de la seedbox est réécrit tel quel dans le flux WebDAV de kDrive — le disque du VPS n'est pas touché. La seedbox et kDrive restent « deux mondes » : le seul point de contact est le dossier FILMS de l'une vers le dossier movies de l'autre.

Le circuit

seedbox (WebDAV Nextcloud)            kDrive (WebDAV)                    VPS
Seedbox/FILMS/*.mkv  --rclone copy-->  Videos_NAS/video/movies  --FUSE-->  /mnt/nas_videos/video/movies
                                       (id 1482703)                        = /data/movies dans Jellyfin
                                                                           bibliothèque « Films récents »

Un film terminé sur la seedbox est dans Jellyfin 5 à 11 minutes plus tard : jusqu'à 5 min pour qu'il soit tenu pour stable, jusqu'à 5 min avant le passage du cron, ~1 min de copie par film, ~30 s de scan.

Ce que fait seedbox_films.sh (cron VPS toutes les 5 min)

  1. Verrou par PID — un double lancement copierait deux fois les mêmes fichiers.
  2. Liste la seedbox (rclone lsjson) : c'est la seule source de vérité (voir le piège kDrive ci-dessous).
  3. Retient ce qui est présent sur la seedbox, stable depuis 5 min, et absent de sa mémoire (/home/debian/.seedbox_films.copies, une ligne taille ⇥ nom par fichier copié). Exclut *.part, *.!qB, *.aria2 et les dossiers cachés. Rien à faire → sort en silence, le journal ne grossit que quand il se passe quelque chose.
  4. Vérifie que kDrive répond, puis rclone copy --files-from-raw vers kdrive:…/Videos_NAS/video/movies, en --size-only (le WebDAV kDrive n'expose ni hash ni date). copy, jamais sync : la seedbox n'est jamais modifiée, et une suppression sur la seedbox ne supprime rien sur kDrive.
  5. Si la copie a réussi, les fichiers entrent en mémoire, puis :
    • rclone rc vfs/refresh dir=video/movies sur le montage kdrive-video (port 5578). Sans cela le montage garde son listing 72 h et Jellyfin ne voit rien — le même piège que Komga (page 168) ;
    • POST /Items/{id}/Refresh sur la seule bibliothèque « Films récents » (a8c97a7ab1c7545488876ca753a24ab3), avec une clé API Jellyfin dédiée seedbox-films — pas un scan général des 15 bibliothèques sur kDrive.
  6. Si la copie a échoué : rien n'entre en mémoire, tout est retenté au passage suivant.

--simulation passe --dry-run à rclone et s'arrête avant la mémoire et le rafraîchissement.

Première exécution — 14/09/2026

ÉtapeMesure
Copie seedbox → kDrive7 films, 13,4 Gio en 196 s (~73 Mo/s), disque du VPS intact
Rafraîchissement du montage3 s
Scan Jellyfin30 s plus tard, .nfo, affiches, fonds et logos produits pour 6 films sur 7
IdentificationLa Corde au cou (Dead Man's Wire), Dreams, Michael, La Vallée des fous, Que la bête meure, Vivaldi et moi (Primavera) — et un raté : The.Mandalorian.And.Grogu.2026.Multi.Truefrench.Imax.WEBRIP.mp4, resté sous son nom brut (trop de jetons après l'année). À identifier à la main, ou nommer Titre (Année).ext sur la seedbox avant copie

Pièges rencontrés — à ne pas redécouvrir

Où sont les choses sur le VPS

QuoiOù
Script (propagé par Syncthing)/home/debian/Documents/Jux_univers/Jux-scripts/Seedbox-Films/seedbox_films.sh
Cron*/5 * * * *, crontab de debian (sauvegarde crontab.bak-260914)
Journal/home/debian/logs/seedbox_films.log (+ seedbox_films.cron.log, sortie brute)
Mémoire des copies/home/debian/.seedbox_films.copies, amorcée le 14/09 avec les 7 premiers films
Secrets/home/debian/.seedbox_films.env (chmod 600, hors Syncthing) : clé API Jellyfin, id de la bibliothèque, mot de passe RC du montage video
Remote rclone seedbox/home/debian/.config/rclone/rclone.conf (sauvegarde .bak-260914) — type = webdav, vendor = nextcloud, url = https://pool372.seedbox.fr/files/remote.php/dav/files/seedbox4f65a4ad8f8a0

Sécurité — le mot de passe de la seedbox

Il n'existe qu'à un seul endroit : rclone.conf du VPS, obscurci, permissions 600. Consigne explicite de Julien : il n'est ni dans CLAUDE.md, ni dans le README, ni dans cette page, ni dans la mémoire de Claude — contrairement aux autres identifiants de l'infrastructure. Il a été saisi par Julien depuis sa propre console. S'il change : rclone config password seedbox pass 'nouveau' sur le VPS, à taper par Julien.

Canari du matin

Deux entrées ajoutées le 14/09 dans Jux-scripts/Etat-Infra/ :

Lecture : ERREUR : seedbox injoignable toutes les 5 min = mot de passe changé ou seedbox arrêtée ; AVERTISSEMENT : vfs/refresh a echoue = montage kdrive-video mort, monitor-rclone.sh s'en occupe.

Débits mesurés

TrajetDébit
seedbox.fr → kDrive, piloté par le VPS, 2 flux~73 Mo/s (13,4 Gio en 196 s ; 10 Gio en 143 s)
kDrive → conteneur Jellyfin (mesure du 30/08)65,6 Mo/s
Pour mémoire : ce qu'aurait fait FileZilla2 × le volume sur la ligne Orange du PC

Non fait, à décider

02_les petites procédures de Claude

260916-Proxy pour IP étrangères — les proxys de la seedbox dans Firefox

1. Le besoin

Ma Seedbox inclut des proxys — j'aimerais bien m'en servir :

  1. par défaut le proxy France, car il intègre Adblock (donc plus de pub, normalement) ;
  2. les autres proxys pour regarder les TV publiques étrangères (surtout l'Italie).
Pays Serveur Port Note
France proxy-fr.seedbox.fr 3128 Adblock inclus
Italie proxy-it.seedbox.fr 3128
Royaume-Uni proxy-uk.seedbox.fr 3128
Allemagne proxy-de.seedbox.fr 3128
Espagne proxy-es.seedbox.fr 3128
Portugal proxy-pt.seedbox.fr 3128
Belgique proxy-be.seedbox.fr 3128
Pays-Bas proxy-nl.seedbox.fr 3128
Irlande proxy-ie.seedbox.fr 3128
Pologne proxy-pl.seedbox.fr 3128
République Tchèque proxy-cz.seedbox.fr 3128
Finlande proxy-fi.seedbox.fr 3128
Lituanie proxy-lt.seedbox.fr 3128

2. Ce qui a été vérifié avant de choisir (2026-09-16)

Sondage depuis le poste julie, sans identifiants, sur 8 des 13 serveurs :

3. Solution retenue : FoxyProxy dans Firefox, en mode « par motifs »

Une extension Firefox qui choisit le proxy selon le site visité :

Pourquoi pas le proxy système de Windows : il s'appliquerait à tout (Syncthing, Steam, mises à jour, WireGuard…), Windows gère mal l'authentification proxy, et un fichier PAC sait router par site mais ne peut pas porter d'identifiants. Il est fourni en variante (§7), à ne retenir que pour faire passer une autre application que Firefox.

4. Les fichiers — Jux-scripts/Seedbox-Proxy/

Fichier Rôle
generer_config.py Source de vérité : une table (pays, serveur, code ISO, couleur, domaines TV) produit les deux fichiers ci-dessous. Stdlib seule : py -3.12 generer_config.py
foxyproxy_seedbox.json Fichier d'import FoxyProxy : 13 proxys, 27 domaines de télévision publique, liste d'exclusion, champs identifiants vides
seedbox.pac Variante « proxy système », même routage, sans identifiants
README.md Résumé de cette page

Le mot de passe seedbox ne s'écrit nulle part dans l'arbre Syncthing (règle en vigueur depuis la procédure Seedbox-Films) : le JSON versionné a ses champs username/password vides, et c'est Julien qui les renseigne, hors Syncthing.

Domaines routés par pays (télévisions publiques ; s'ajoutent dans la table du script) :

Pays Domaines
Italie rai.it, raiplay.it, raiplaysound.it, rainews.it
Royaume-Uni bbc.co.uk, bbc.com, bbci.co.uk, channel4.com, itv.com
Allemagne zdf.de, ardmediathek.de, ard.de, daserste.de, tagesschau.de
Espagne rtve.es — Portugal : rtp.pt — Belgique : rtbf.be, vrt.be
Pays-Bas npo.nl, npostart.nl, nos.nl — Irlande : rte.ie — Pologne : tvp.pl
Rép. Tchèque ceskatelevize.cz, ivysilani.cz — Finlande : yle.fi — Lituanie : lrt.lt

Les motifs sont des expressions régulières sur l'URL complète (^https?://([^/]+\.)?rai\.it(:\d+)?(/|$)) : le domaine nu et ses sous-domaines, mais ni boulevard.de pour ard.de, ni une URL qui ne ferait que citer rai.it dans son chemin. FoxyProxy évalue les proxys dans l'ordre et retient le premier dont un motif correspond : les pays sont en tête, la France (motif *) en dernier. Sans ce motif final, FoxyProxy enverrait tout le reste en direct — c'est son comportement par défaut en mode motifs.

5. Mise en place — pas à pas

  1. Installer FoxyProxy Standard dans Firefox (menu ⋮ → Extensions et thèmes → chercher « FoxyProxy Standard », éditeur eric.h.jung / foxyproxy). Épingler son icône dans la barre d'outils.
  2. Copier foxyproxy_seedbox.json hors de l'arbre Syncthing (par exemple D:\Seedbox\) et y mettre les identifiants dans un éditeur de texte : Remplacer tout "username": "" par "username": "<identifiant seedbox>", idem pour "password". Treize proxys, deux remplacements. Supprimer cette copie après l'import. Variante sans toucher au fichier : importer tel quel, puis saisir identifiant et mot de passe dans chacun des 13 proxys de la page d'options (FoxyProxy propose aussi un Bulk Edit).
  3. Importer : icône FoxyProxy → Options → onglet Import → choisir le fichier. L'import remplace la configuration existante.
  4. Vérifier que le sélecteur en haut de la page d'options est bien sur « Proxy by Patterns » (le fichier le pose, mais c'est ce réglage qui fait tout).
  5. Contrôle :
    • https://ifconfig.me doit afficher 87.98.174.34 (le proxy France) — et non l'IP Orange de la maison ;
    • ouvrir https://www.raiplay.it puis l'onglet Log des options de FoxyProxy : les requêtes raiplay.it doivent être marquées Italie, les autres France ;
    • lancer une vidéo RaiPlay.
  6. Compléter la liste d'exclusion (options → Global Exclude, ou la liste PASSTHROUGH du script) avec les sites sensibles : banque, assurance, santé. Voir §6, point 3.

Portmaster : rien à faire, le sortant est en permit par défaut. Firefox ouvrira des connexions vers proxy-*.seedbox.fr:3128, c'est tout.

6. Ce qu'il faut savoir — limites

  1. L'Adblock du proxy ne travaille qu'au niveau des domaines sur HTTPS. Un proxy ne lit pas l'intérieur d'une page chiffrée ; il ne peut que refuser les connexions vers les domaines publicitaires connus. Garder uBlock Origin dans Firefox — les deux se complètent, ils ne se remplacent pas.

  2. Les IP sont des adresses de datacenter OVH — et la Rai les refuse (constaté le 2026-09-16). Premier essai sur Diretta Rai 2 par le proxy Italie : « RAI detiene i diritti per lo streaming del contenuto esclusivamente per connessioni dall'Italia ». Géolocalisation des 13 IP (base ip-api) :

    Proxy annoncé IP Vu comme Hébergeur
    Italie 94.23.65.245 IT Milan OVH AS16276, hosting
    Espagne, Portugal, Belgique, Pologne, Tchéquie 87.98.225.34, 94.23.74.75, 91.121.216.35, 87.98.235.69, 94.23.168.27 pays annoncé OVH, hosting
    Royaume-Uni, Allemagne, Pays-Bas, Irlande, Finlande, Lituanie 178.32.60.249, 87.98.243.154, 94.23.144.159, 188.165.0.96, 188.165.136.66, 188.165.24.74 France (Paris, Strasbourg, Roubaix) OVH, hosting

    Toutes les machines sont physiquement chez OVH en France ; seule la géolocalisation déclarée change, et six « pays » sur treize ne sont même pas repris par cette base. La Rai diffuse via Akamai, dont la base (EdgeScape) place vraisemblablement 94.23.x à Roubaix. Conclusion : les proxys seedbox ne servent pas pour les télévisions étrangères — ils restent utiles pour la France/Adblock. Pour une vraie IP italienne : un Raspberry Pi chez un proche en Italie, raccordé au hub WireGuard du VPS comme peer 10.0.0.5 avec un petit Squid, déclaré dans FoxyProxy comme « Italie maison » ; à défaut, un VPN grand public avec extension Firefox dans un profil séparé (ses IP sont aussi en datacenter mais renouvelées contre les blocages). Les proxys résidentiels payants (facturés au Go, 10-30 € le film) et les listes gratuites (machines compromises) sont écartés.

  3. Le proxy voit passer tout le trafic HTTP en clair, et l'identifiant en Basic (encodé, pas chiffré, entre Firefox et le proxy). Le HTTPS reste chiffré de bout en bout, mais le proxy connaît les sites visités. D'où la liste d'exclusion — nos propres services et les sites sensibles n'ont aucune raison de transiter par un Squid OVH.

  4. Firefox seulement. VLC, Jellyfin, l'émulateur Android… ne sont pas concernés. C'est voulu.

  5. Une vidéo qui démarre puis échoue : le lecteur charge parfois son flux depuis un CDN sur un autre domaine que le site (Akamai, etc.), qui part alors par la France. Repérer ce domaine dans l'onglet Log de FoxyProxy (ou l'outil Réseau de Firefox, F12) et l'ajouter au pays concerné.

  6. Réimporter le JSON efface les identifiants saisis (l'import remplace tout). Pour ajouter un site durablement : modifier la table du script, regénérer, réimporter la copie avec identifiants. Pour un essai rapide : ajouter le motif directement dans le proxy, depuis les options.

  7. Squid 3.5.20 date de 2016 — c'est le choix de seedbox.fr, pas le nôtre. Sans conséquence pour l'usage.

7. Variante « proxy système » — seedbox.pac

Même routage, sans extension : un fichier PAC lu par le navigateur ou le système.

8. Voies écartées

9. Suite — la réponse pour la télévision : IPTV-Publiques (2026-09-16, le soir même)

Ni proxy ni VPN : les diffuseurs publics publient leurs flux HLS, le projet iptv-org les recense, et Jellyfin les joue via un tuner M3U testé toutes les 6 h. Rai 1/2/3, News 24, Storia, Scuola, Südtirol, TVE Internacional, Das Erste, Tagesschau 24, arte, RTP… — 21 chaînes vivantes au premier relevé. Page BookStack 323, dossier Jux-scripts/IPTV-Publiques/. Les proxys seedbox restent utiles pour la France/Adblock ; le VPN n'a pas été souscrit.

02_les petites procédures de Claude

260916-IPTV-Publiques — la télévision publique européenne dans Jellyfin

1. Le besoin, et pourquoi pas les proxys ni un VPN

Regarder les télévisions publiques européennes (Rai en tête) depuis la maison. La page 322 raconte les deux impasses de la journée : les proxys seedbox.fr sont des IP de datacenter OVH que la Rai refuse, et un VPN grand public aurait coûté un abonnement pour un résultat incertain.

La troisième voie est la bonne : les diffuseurs publics publient eux-mêmes leurs flux HLS, et le projet communautaire iptv-org les recense par pays. Un flux HLS est une simple URL .m3u8. Il n'y a rien à contourner — seulement à trier ce qui répond réellement depuis le VPS, et à le servir proprement.

Décision de Julien : c'est Jellyfin qui joue la TV. Le VPS porte déjà Jellyfin ; une liste M3U branchée en tuner y ajoute une section « TV en direct » visible sur la télé, la tablette et les téléphones de toute la famille, avec logos, numéros de chaînes et groupes par pays.

2. Ce que fait generer_playlist.py

Toutes les 6 heures sur le VPS (cron 15 */6 * * *), stdlib seule :

  1. lit les listes iptv-org des pays concernés ;
  2. n'en garde que les chaînes de la liste blanche config.json (regex sur le nom) ; ajoute les candidats supplémentaires connus hors liste (les flux CloudFront de Rai 1 et Rai 3, le flux officiel d'arte) ; écarte d'office les hôtes en adresse IP nue et streamhostingcdn (rediffusions pirates) ;
  3. teste chaque candidat : playlist HLS → variante la plus haute → téléchargement d'un vrai segment, avec mesure du débit. Un segment qui n'arrive pas, une playlist vide, un débit sous 3 Mbit/s = KO ;
  4. retient le candidat le plus rapide par chaîne, avec une préférence de stabilité pour celui de la fois précédente ;
  5. écrit tv_publiques.m3u (tvg-id, logo, tvg-chno, group-title = pays) dans /home/debian/jellyfin/config/ (= /config/ dans le conteneur, lu par le tuner) et dans /home/debian/Documents/IPTV/ (= D:\Syncthing\IPTV\, pour VLC depuis n'importe quelle machine) ;
  6. si la liste a changé, demande à Jellyfin de relire son guide (POST /ScheduledTasks/Running/{RefreshGuide}, clé API dédiée iptv-publiques dans /home/debian/.iptv_publiques.env, hors Syncthing) ;
  7. termine par la ligne que lit le canari : === BILAN: 21/41 chaînes vivantes, 0 perdue — absentes : … ===.

« Perdue » ≠ « absente ». Une chaîne géobloquée depuis toujours est absente et ne fait pas parler le canari ; une chaîne vivante au passage précédent et morte maintenant est perdue, et là le canari chante (attendu: "BILAN: .*0 perdue", journal iptv_publiques.log, cadence 8 h). Hystérésis : au premier échec la chaîne est conservée dans la M3U avec son flux précédent (? au journal) ; elle n'est déclarée perdue qu'au second passage raté. Sans cela, les flux RTP « Not 24/7 » faisaient chanter le canari pour rien — constaté dès le second passage.

--simulation teste et affiche sans rien écrire, --verbeux détaille chaque candidat. explorer.py it de … liste et teste toutes les chaînes publiques d'un pays : c'est l'outil pour enrichir la liste blanche.

3. Relevé du 2026-09-16 depuis le VPS — 21 chaînes vivantes sur 41 demandées

Pays Vivantes Absentes et pourquoi
Italie Rai 1, Rai 2, Rai 3, Rai News 24, Rai Storia, Rai Scuola (CloudFront tiers, 80-95 Mbit/s), Rai Südtirol (flux officiel wzstreaming.rai.it) Rai 4, Gulp, Sport : flux officiels géobloqués
Espagne TVE Internacional (le flux officiel RTVE pour l'Europe), Teledeporte, Clan La 1, La 2, 24 Horas : HTTP 451 — RTVE bloque les IP d'hébergeur (mais répond depuis la maison)
Allemagne Das Erste HD, Tagesschau 24, KiKA, hr-fernsehen, SR Fernsehen — tous flux officiels ARD, ouverts au monde ZDF, 3sat : n'existent que via antik.sk, trop lent ; Phoenix, ZDFinfo/neo : géobloqués ; BR, NDR, WDR, ARD-alpha, MDR : géoblocage doux (voir §4)
Arte arte (flux officiel Akamai, 140 Mbit/s) —
Belgique BX1 (Bruxelles) La Une, Tipik : uniquement via des IP nues (écartées) ; VRT absente des listes
Portugal RTP 1, RTP Notícias, RTP Açores (flux officiels) — intermittents, [Not 24/7] RTP 2
Danemark Folketinget (le parlement, Kaltura) DR1, DR2 : géobloqués
Suisse aucune SRF/RTS/RSI : absentes des listes ou géobloquées
Autriche aucune ORF 1/2 : IP nues ; ORF III : géoblocage doux
Luxembourg aucune RTL Télé Lëtzebuerg : géoblocage doux
Pays-Bas aucune NPO : géobloqués

Vérifié de bout en bout : tuner créé par l'API (POST /LiveTv/TunerHosts, type m3u, URL /config/tv_publiques.m3u, User-Agent navigateur), guide rafraîchi, 21 chaînes vues par Jellyfin, puis lecture de Rai 2 par le vrai enchaînement client (PlaybackInfo → LiveStreams/Open) : Jellyfin sonde le flux (hls, h264 1080p, aac) et répond SupportsDirectPlay: true — aucun transcodage, le VPS ne fait que relayer.

4. Pièges rencontrés

  1. Les listes iptv-org ne sont pas la Rai. Rai 1/2/3 y viennent de rediffuseurs tiers (un CloudFront anonyme, un opérateur slovaque). Ils peuvent disparaître : d'où le test à chaque passage et l'hystérésis, plutôt qu'une liste figée.
  2. Un flux « OK » n'est pas forcément jouable : dash2/dash4.antik.sk répond 200 mais sert ses segments au rythme du direct (~1 Mbit/s), mesuré depuis le VPS et depuis la maison. En lecture ça coupe. D'où la mesure de débit et le seuil debit_min_mbit: 3. ZDF et 3sat n'ont pas d'autre source : absentes.
  3. Géoblocage doux : ARD régionales, RTL.lu et ORF III resservent la playlist master à la place de la variante — HTTP 200, aucune erreur, et un lecteur naïf tourne en rond. Détecté par « la variante contient encore #EXT-X-STREAM-INF ».
  4. Le dernier segment d'un direct n'est pas toujours servi (404 fugace sur Das Erste) : le test prend l'avant-avant-dernier et réessaie une fois.
  5. La géographie n'est pas la même depuis la maison et depuis le VPS : RTVE La 2 joue depuis la Livebox (IP Orange) et répond 451 depuis OVH. Jellyfin étant sur le VPS, c'est le VPS qui fait foi — la M3U de Syncthing est la même, VLC à la maison n'aura pas RTVE La 2 même si elle marcherait.
  6. PlaybackInfo seul fait croire à un transcodage (ContainerNotSupported, VideoCodecNotSupported, ffmpeg à 170-290 % CPU) : Jellyfin ne sonde un tuner M3U qu'à l'ouverture (RequiresOpening: true → LiveStreams/Open). Après l'ouverture, direct play. Les ffmpeg de mes premiers essais ont tourné 2 min à 3 cœurs — tués à la main (pgrep -x ffmpeg).
  7. pkill -f 'motif' lancé par plink -m script tue la session elle-même : le motif figure dans la ligne de commande du bash qui l'exécute. Passer par pgrep -x sur le nom du processus.
  8. streaming-live.rtp.pt répond 204 No Content hors antenne ([Not 24/7]) : un 204 est traité comme vide, pas comme un succès.
  9. arte : l'entrée « arte » de la liste France est une IP nue ; le flux officiel est artesimulcast.akamaized.net/hls/live/2030993/artelive_de/index.m3u8 (celui de la liste allemande, marqué à tort [Geo-blocked] — il répond depuis la France). Le chemin artelive_fr n'existe pas sous cet identifiant : le flux français a le sien, 2031003/artelive_fr (trouvé le lendemain dans la liste belge de Free-TV, voir §7).

5. Utilisation et entretien

Pas encore fait — le guide des programmes (EPG). Les tvg-id iptv-org (Rai1.it, DasErste.de…) sont ceux du projet iptv-org/epg, qui sait produire un XMLTV par chaîne ; Jellyfin l'accepte en fournisseur de guide XMLTV. Un grabber Node à faire tourner, à évaluer si le « qu'est-ce qui passe ? » manque à l'usage.

6. Fichiers

Jux-scripts/IPTV-Publiques/ : generer_playlist.py (production), config.json (liste blanche, sorties, seuils), explorer.py (exploration), README.md, doc_bookstack.md (cette page). Sur le VPS : journal /home/debian/logs/iptv_publiques.log, état /home/debian/logs/iptv_publiques.etat.json, clé API dans /home/debian/.iptv_publiques.env (chmod 600). Canari : entrée IPTV-Publiques dans Etat-Infra/config.json.

7. Le 2026-09-17 — seconde source (Free-TV) et guide des programmes

Julien a signalé la liste Free-TV/IPTV (via l'article de Korben sur les chaînes IPTV gratuites, qui ne cite que ces deux listes). Elle est complémentaire d'iptv-org : un seul fichier de 2 080 chaînes, le pays dans group-title, des flux officiels plus souvent, des marqueurs Ⓖ (géobloquée), Ⓢ (pas 24/7), Ⓨ (YouTube) accolés aux noms, et surtout un en-tête x-tvg-url qui désigne les guides XMLTV d'epgshare01 par pays.

Le script lit désormais les deux sources (sources dans config.json, mode pays pour iptv-org, mode groupe pour Free-TV), fusionne les candidats d'une même chaîne et garde le plus rapide. Résultat depuis le VPS : 55 chaînes vivantes sur 87 demandées (21 la veille). Ce que Free-TV a apporté :

Pays Nouvelles chaînes vivantes
Italie Rai Italia Europa (le canal international de la Rai, fait pour l'étranger), Rai World Premium, La7 (flux officiel), Senato TV, Camera dei Deputati
Espagne régionales officielles : Telemadrid, Canal Sur, Canal Extremadura, Televisión Canaria, ETB 1/2, TV3 Catalunya, 3/24, À Punt
Allemagne NDR International, WDR Fernsehen
Arte le flux français (artelive_fr, id Akamai 2031003 — celui de la liste belge) remplace le flux allemand
Portugal RTP 2, RTP Mundo (international), RTP Madeira ; RTP 3/Notícias
Autriche W24 (la chaîne de la ville de Vienne — ORF reste géobloqué)
Danemark TV 2/Bornholm
Pays-Bas 13 régionales publiques (NH Nieuws, RTV Rijnmond, Utrecht, Omroep Brabant, Gelderland, RTV Noord, Oost, Drenthe, Omrop Fryslân, Flevoland, West, Zeeland, L1) — NPO reste géobloqué

Toujours rien pour la Suisse (SRF/RTS/RSI : IP nues ou géobloqués), le Luxembourg (RTL.lu en géoblocage doux) et les nationales RTVE, ZDF, ORF, DR, NPO, RTBF.

Guide des programmes — generer_guide.py (cron 5 3 * * *, 9 s) : lit en flux les guides epgshare01 des pays utiles (18 à 52 Mo de XML chacun, jusqu'à 751 chaînes), n'en garde que nos chaînes, réécrit leurs identifiants sur les nôtres et produit /config/guide.xml (5 Mo, ~7 500 programmes) pour le fournisseur XMLTV de Jellyfin (créé par POST /LiveTv/ListingProviders). 50 chaînes sur 55 ont un programme ; les 5 sans (Rai Italia, Rai World Premium, Rai Südtirol, Senato, Camera) n'existent dans aucun guide.

Pièges du jour :

  1. L'outil Bash abîme \b et \n dans un heredoc — un \b de regex est devenu un caractère backspace (0x08) dans explorer.py : la regex ^(Rai\b|…) ne trouvait plus une seule Rai, sans erreur. Éditer avec Edit/Write, jamais par heredoc (déjà noté en mémoire, re-mordu)
  2. Free-TV marque le géoblocage d'un Ⓖ dans le nom : sans le retirer, ^Rai 1$ ne matche pas « Rai 1 Ⓖ ». Et un flux marqué Ⓖ répond parfois depuis le VPS (arte, UniNettuno) : le marqueur trie les candidats, il ne les écarte pas
  3. Segments RTP aux noms hors ASCII → UnicodeEncodeError/InvalidURL : l'URL du segment est désormais encodée (urllib.parse.quote)
  4. antik.sk répond 200 mais sert au rythme du direct : ZDF et 3sat n'ont aucune autre source vivante, ils restent absents

8. État au 2026-09-17

55 chaînes dans Jellyfin, 50 avec guide, cron M3U toutes les 6 h et guide à 3h05 UTC, deux entrées canari (0 perdue, GUIDE: [1-9]). Ajouter une chaîne = python3 explorer.py <pays> puis une ligne dans chaines (motif sur le nom tel qu'il apparaît dans l'une des deux listes).

9. Le 2026-09-27 — l'Europe du Nord et de l'Est, et la Grèce

Julien demandait la télévision publique grecque, ERT 1 surtout, en donnant l'URL https://ertflix.s.llnwi.net/ertlive/ert1/clrdef24723b/playlist.m3u8.

Cette URL est morte : llnwi.net est le CDN Limelight, retiré du service — le nom ne résout plus du tout (NXDOMAIN, depuis le PC comme depuis le VPS). Le flux vivant d'ERT est ailleurs, et il fallait le trouver.

Ce que les deux listes donnaient, et pourquoi ça ne suffisait pas : iptv-org n'a que ERT 3, ERT News et ERT Cosmos ; Free-TV a bien ERT 1/2/3 mais en .mpd (DASH), que notre chaîne ne sait ni tester ni servir à Jellyfin. En remplaçant l'extension par index.m3u8 sur le même paquetiseur, tout ERT répond en HLS 1080p, audio grec et sous-titres inclus : https://ert-live.siliconweb.com/bpk-tv/{ERT1,ERT2,ERT3,ERTNews,ERTCosmos,ERTKids}/default/index.m3u8. Ces six URL sont posées en candidats dans config.json ; le script les préfère aux .mpd.

Exploration de 18 pays dans la foulée (explorer.py gr ie pl cz fi se no hr ro hu bg sk si cy is ee lv lt), 34 chaînes ajoutées à la liste blanche :

Pays Ajouté Source
Grèce ERT 1, ERT 2, ERT 3, ERT News, ERT Cosmos, ERT Kids, Vouli TV (le parlement) siliconweb, officiel
Irlande RTÉ One, RTÉ 2, RTÉ News, TG4 live.rte.ie, officiel
Roumanie TVR 1, 2, 3, International, Cultural, Info, Folclor CDN officiel mncdn
Finlande Yle TV1, Yle TV2, Yle Teema & Fem Akamai, officiel
Islande RÚV, RÚV 2 Akamai, officiel
Pays baltes ETV, ETV2, ETV+ (Estonie), LTV7 (Lettonie), LRT Lituanica, LRT Plius, LRT Klasika err.ee et lrt.lt, officiels
Chypre RIK Sat —
Slovaquie STVR Live, STVR :24 hôte tiers, intermittent
Pologne Belsat (la chaîne biélorusse d'opposition, émise depuis la Pologne) —

Écartées faute de source propre — à ne pas rechercher inutilement : les ČT tchèques, les M1/M2/Duna hongroises et Jednotka/Dvojka slovaques n'existent que derrière l'IP nue 88.212.15.19, un rediffuseur pirate que hotes_exclus refuse par principe. SVT (Suède), NRK (Norvège), HRT (Croatie), BNT (Bulgarie), RTV SLO (Slovénie) et TVP (Pologne) n'ont aucun flux vivant dans les deux listes.

Résultat : 83 chaînes vivantes sur 121, 65 avec programmes, 41 émissions en cours vues par Jellyfin au moment du contrôle.

Guide : onze guides epgshare01 ajoutés. Deux n'existent pas (IS1, EE1 renvoient une page HTML de 52 octets) — RÚV et ETV n'auront donc pas de programmes. ERT 1/2/3/News et Vouli sont absents du guide grec alors que ERT Cosmos y est : rien à corriger de notre côté. RIK Sat, lui, a été rattaché au guide grec et non chypriote (epg_pays: "gr"), et les irlandaises ont reçu leurs alias (RTE Two HD, RTE News Now).

Pièges du jour :

  1. Une URL de flux fournie de bonne foi peut pointer un CDN mort : vérifier la résolution DNS avant de chercher plus loin (host, ou un curl qui répond 000 en 0 s)
  2. .mpd ≠ .m3u8 : Free-TV donne du DASH pour certaines chaînes ; le même paquetiseur Broadpeak sert du HLS au même chemin, il suffit de changer l'extension
  3. Deux échecs passagers (ERT Kids, LRT Plius) ont été rattrapés par l'hystérésis puis se sont remis à répondre au passage suivant : c'est exactement ce pour quoi elle a été écrite
02_les petites procédures de Claude

261001-les playlistes de Claude sur Navidrome

En une phrase

AudioMuse-AI écoute réellement les morceaux (analyse sonore, pas les tags), les regroupe par parenté musicale, fait nommer les groupes par Gemini, et dépose le résultat en playlists dans Navidrome — où elles restent, même PC éteint.

1. Pourquoi sur le PC, et nulle part ailleurs

AudioMuse n'est pas un greffon : c'est une pile d'analyse (Flask + worker ONNX + PostgreSQL embarqué, 2,4 Go installés) qui exige AVX2 et 8 Go de RAM.

Machine AVX2 RAM disponible Verdict
NAS sasnexte non — Celeron J4025 0,6 Go éliminé, ne démarrera jamais
jux-debian non — même CPU hôte 3 Go éliminé, même raison
VPS Jux oui (Haswell, 6 cœurs) 2,5 Go, swap à 4,9/8 Go trop juste
PC julie oui — Ryzen 5 2600X, 12 threads 16 Go retenu

L'absence d'AVX2 sur le J4025 est définitive : ni le NAS ni la VM qui tourne dessus ne pourront héberger AudioMuse, quelle que soit la version.

2. Ce que le PC éteint change — et ne change pas

Point vérifié dans le code (tasks/mediaserver/navidrome.py) et non supposé : AudioMuse crée les playlists dans Navidrome, par l'API Subsonic (createPlaylist, puis updatePlaylist public=true). Elles vivent donc dans la base du VPS, comme si elles avaient été faites à la main.

PC allumé PC éteint
Écouter les playlists (web, Symfonium, Feishin) oui oui
Fabriquer / rafraîchir les playlists oui non
Instant Mix & Radio (greffon .ndp) oui non

Le greffon Navidrome audiomuseai.ndp n'a pas été installé : il interroge AudioMuse en direct à chaque clic, donc il exige un service permanent — ce que le PC n'est pas. Seules les playlists nous intéressent, et elles n'en ont pas besoin.

3. Emplacement, et les deux pièges du poste

D:\AudioMuse-AI\
├── app\                      le bundle (PostgreSQL embarqué compris), 2,4 Go
├── donnees\AudioMuse-AI\     base, audio temporaire, modèles, journaux, secrets
├── sauvegardes\              dumps produits par sauvegarder_base.py
├── Demarrer AudioMuse.cmd
├── Arreter AudioMuse.cmd
└── sauvegarder_base.py

Hors de l'arbre Syncthing, volontairement : 1,5 Go d'archive et plusieurs Go de données n'ont rien à faire sur les 7 appareils du maillage, dont un téléphone. Même raison que D:\Procedures photos\ et D:\Musique\.

⚠ Piège n°1 — MSIX

native-build/windows/paths.py construit les chemins de données à partir de la variable d'environnement LOCALAPPDATA. Or Claude Code tourne dans un conteneur MSIX : tout processus lancé depuis une session Claude voit son %LOCALAPPDATA% redirigé vers …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\. Lancé ainsi, AudioMuse installerait sa base dans un chemin fantôme — exactement l'incident Android Studio du 2026-08-26.

Demarrer AudioMuse.cmd force donc LOCALAPPDATA=D:\AudioMuse-AI\donnees avant d'appeler l'exécutable. Double bénéfice : hors périmètre de virtualisation, et hors du SSD système (95 Go libres, 146 arrêts brutaux au compteur, contre 596 Go sur D:).

C'est Julien qui lance, jamais Claude Code.

⚠ Piège n°2 — l'espace dans le chemin

Toujours dans paths.py : si le chemin de données contient une espace, AudioMuse bascule en silence vers %PROGRAMDATA%. Le lanceur vérifie et refuse de démarrer le cas échéant, plutôt que d'écrire ailleurs sans rien dire.

4. Mise en route

  1. Double-cliquer Demarrer AudioMuse.cmd. Au premier lancement, PostgreSQL s'initialise : compter 1 à 2 minutes. Le lanceur attend que le port 8000 réponde, puis ouvre le navigateur. Une icône apparaît dans la zone de notification (état, journal, arrêt).
  2. Dans l'assistant, serveur de musique : Navidrome, https://navidrome.juxjux.ovh, utilisateur julien, mot de passe Navidrome.
  3. Authentification AudioMuse : un identifiant, un mot de passe, un jeton d'API. Le jeton ne sert qu'au greffon (non installé) mais l'assistant l'exige.
  4. Première analyse — page Analysis and Clustering → Start Analysis.

Le coût de la première analyse

AudioMuse télécharge chaque morceau en entier par l'API Subsonic (download_track → stream), l'analyse, puis passe au suivant. Un seul fichier à la fois : rien ne s'accumule sur le disque. Mais au total ~133 Go transitent depuis le VPS (donc depuis kDrive), une seule fois.

Durée annoncée par le projet : « de quelques heures à plusieurs jours ». L'analyse est reprenable — les titres déjà traités sont en base, une interruption ne fait rien perdre — et incrémentale ensuite : un nouvel album ne coûte que sa propre taille.

5. Noms de playlists par Gemini

Il n'y a aucun greffon à installer : c'est de la configuration. Le modèle ne reçoit que des étiquettes de genre et d'humeur, jamais la musique ni les fichiers.

  1. Créer la clé (gratuite, sans facturation) sur aistudio.google.com → Clés API → Créer une clé API. C'est à Julien de le faire : Claude ne crée pas d'identifiants.
  2. AudioMuse → Administration → Configuration → Configuration avancée → Fournisseur d'IA & Nommage de playlist :
    • AI_MODEL_PROVIDER = GEMINI
    • GEMINI_API_KEY = la clé
    • GEMINI_MODEL_NAME = gemini-flash-latest — alias toujours à jour ; le défaut livré est gemini-2.5-pro, qui échoue souvent en version gratuite
  3. AI Prompt → Clustering Naming → style Titre complet de l'IA, et ajouter en fin de prompt la consigne de langue et de longueur (2 à 4 mots, sans underscore, jamais le mot « automatic »).
  4. Aperçu des titres teste sans rien enregistrer. Si les noms restent des étiquettes (no AI title so the tag name is kept), la clé ou le nom de modèle est faux.

Si Gemini cesse un jour de répondre, les playlists sont quand même créées, avec les anciens noms à base d'étiquettes.

6. ⚠ Le suffixe _automatic — à savoir avant de s'attacher à une playlist

Toute playlist produite se termine par _automatic. Au début de chaque clustering, AudioMuse appelle delete_automatic_playlists() qui supprime dans Navidrome toutes les playlists dont le nom finit par ce suffixe — y compris celles d'une exécution précédente. C'est voulu : il les recalcule.

Pour garder une playlist définitivement : la renommer dans Navidrome en retirant _automatic. Elle devient invisible de ce ménage et survit à tout, y compris à une réinstallation.

7. La base d'analyse, et sa sauvegarde sur kDrive

Son poids — calculé sur le schéma réel

Trois empreintes par titre, toutes en BYTEA float32 :

Empreinte Dimensions Octets/titre
MusiCNN (EMBEDDING_DIMENSION) 200 800
CLAP (CLAP_EMBEDDING_DIMENSION) 512 2 048
Paroles GTE (LYRICS_EMBEDDING_DIMENSION) 768 3 072
Métadonnées (score) — ~1 000

~7 Ko/titre × 16 069 ≈ 113 Mo de données brutes, que l'index de recherche (ivf_cell) double à peu près. Base vivante attendue : 250 à 350 Mo ; dump : 150 à 250 Mo.

⚠⚠ Pourquoi la base VIVANTE n'est pas sur kDrive

Demande initiale de Julien : « on mettra la base d'analyse dans le kDrive, on y a de la place, c'est pérenne ». L'objectif est le bon — cette base vaut des heures de calcul et 133 Go téléchargés — mais une base PostgreSQL vivante ne peut pas être posée sur kDrive : WebDAV n'offre ni fsync fiable, ni verrouillage de fichier, ni renommage atomique, et un fichier de base synchronisé pendant qu'il est ouvert se corrompt. C'est le mode de panne classique, pas une précaution théorique.

La pérennité s'obtient par un dump poussé sur kDrive — exactement le schéma de vps_backup.sh pour les 7 autres services. Restaurable sur n'importe quelle machine, et survit à un formatage.

Le script

py -3.12 D:\AudioMuse-AI\sauvegarder_base.py                 REM dump + envoi kDrive
py -3.12 D:\AudioMuse-AI\sauvegarder_base.py --simulation    REM dump local seulement
py -3.12 D:\AudioMuse-AI\sauvegarder_base.py --restaurer     REM recupere et reinjecte

8. Désinstallation

  1. Arreter AudioMuse.cmd
  2. Supprimer D:\AudioMuse-AI\

C'est tout : archive portable, rien dans Program Files, rien dans le registre, aucun service, aucun résidu dans %LOCALAPPDATA% puisque les données sont sur D:.

Les playlists déjà créées restent dans Navidrome — elles ne lui appartiennent pas. Seule disparaît la base d'analyse ; d'où le dump kDrive, qui permet de revenir sans refaire les 133 Go.

9. Repères

10. Mesures réelles du 2026-10-01 (première analyse)

Analyse lancée à 20h55 (heure de Paris) sur les 1 161 albums / 16 069 titres.

Grandeur Mesure
Durée par piste médiane 19,5 s, moyenne 20,6 s (min 4,8 — max 93,1)
dont étape paroles médiane 1,6 s, moyenne 3,1 s (max 78,7)
Part des paroles 15 % du temps
CPU pendant l'analyse 90 %, le worker à lui seul ~6 cœurs, 713 Mo
Durée totale projetée ~92 h, soit 3,8 jours

Trois méthodes indépendantes concordent sur ~90 h : comptage des lignes de score en base, horodatage du journal piste par piste, et la progression « Albums N/1161 ».

Le goulot est le CPU, pas le réseau : les 133 Go ne ralentissent rien, c'est l'inférence ONNX (CLAP + MusiCNN + GTE) qui limite.

Désactiver les paroles : mesuré, et non retenu

Question posée par Julien le 2026-10-01. Mesure faite sans rien désactiver, en horodatant l'étape dans le journal sur 216 pistes réelles : gain de 14 h sur 92 (92 h → 78 h, 3,8 → 3,2 jours).

Non retenu : 15 % de gain contre la perte du regroupement par le sens des textes (ce qui distingue AudioMuse d'un classeur purement acoustique), de la page Lyrics Search et de la fonction Album Creation (conditionnée à lyrics_enabled and clap_enabled). Comme l'analyse est suspendable, les 0,6 jour gagnés ne changent pas la nature du problème.

Détail : Whisper se déclenche bien (74 pistes sur 216 en échec d'API externe, repli whisper_small, timeout 300 s) mais seules 23 transcriptions aboutissent — le reste est reconnu instrumental avant. D'où une médiane basse avec quelques pointes à 78 s.

⚠ Suspendre et reprendre : sans perte

Vérifié dans le code, pas seulement dans la FAQ : tasks/analysis/main.py saute les albums entièrement analysés (Skipping album … all N tracks already analyzed) et album.py saute les étapes déjà faites piste par piste (SKIPPED MusiCNN … already analyzed).

Moyen Coût
Bouton Cancel Current Task (Analysis and Clustering) rien, la tâche passe en REVOKED
Arreter AudioMuse.cmd ou le menu de l'icône la piste en cours
Extinction du PC la piste en cours

Pour reprendre : relancer AudioMuse si besoin, puis Start Analysis — il repart où il s'était arrêté. Le PC n'a donc pas à rester immobilisé 3,8 jours d'affilée.

Et plus tard, l'analyse reste incrémentale : un nouvel album ne coûte que ses pistes (~5 min pour 15 titres). Le clustering, lui, recalcule toutes les playlists à chaque exécution, mais à partir des empreintes déjà en base — aucun téléchargement, aucune ré-analyse.

11. Deux corrections à la configuration documentée

12. ⚠⚠ Le choix du modèle Gemini — testé le 2026-10-01

Les deux modèles conseillés (par AudioMuse et par le billet Reddit d'origine) ne fonctionnent pas. Testé en appelant directement l'API Google avec la clé de Julien :

Modèle Résultat
gemini-2.5-pro — défaut livré par AudioMuse (config.py) 404 — « no longer available to new users »
gemini-flash-latest — conseillé par le billet Reddit 503 — « currently experiencing high demand », deux fois à 96 s d'écart, puis encore 3 min plus tard
gemini-2.5-flash ✅ 200, réponse réelle
gemini-2.5-flash-lite 404 — plus ouvert aux nouveaux comptes
gemini-2.0-flash 404 — retiré

Valeur à retenir : GEMINI_MODEL_NAME = gemini-2.5-flash. Son seul inconvénient face à un alias -latest est qu'il faudra le changer à la main le jour où Google sortira un Flash plus récent — bien moindre mal qu'un modèle qui ne répond jamais.

Comment distinguer les trois pannes

Le code HTTP dit tout, et évite de soupçonner la clé à tort :

Code Sens
401 / 403 la clé est mauvaise
404 le nom de modèle n'existe pas (ou plus) pour ce compte
429 quota dépassé
503 modèle surchargé chez Google — ni la clé ni le quota ne sont en cause

Méthode de diagnostic, sans rien modifier dans l'interface :

grep -E "generativelanguage" .../logs/audiomuse.log | head

Chaque ligne donne le modèle appelé et le code obtenu.

⚠ Aucune relance automatique sur erreur HTTP

tasks/ai/providers/gemini.py : les 3 tentatives de EMPTY_RESPONSE_RETRIES ne couvrent que les réponses vides. Sur une erreur SDK (503 comprise), la fonction renvoie directement "Error: AI service is currently unavailable." sans réessayer. Un délai de 7 s précède chaque appel (GEMINI_API_CALL_DELAY_SECONDS).

Conséquence le jour du clustering : si Google est surchargé à cet instant, les playlists concernées garderont leur nom d'étiquette (Electronic_Pop_Indie_Medium_Relaxed_Danceable). Ce n'est pas perdu : relancer le clustering suffit — il travaille sur les empreintes déjà en base, donc quelques minutes, sans téléchargement ni ré-analyse, et Gemini est réinterrogé.

Valider la clé sans attendre l'analyse complète

La page Instant Playlist appelle Gemini directement (app_chat.py → config.AI_MODEL_PROVIDER). C'est le test le plus rapide : une demande en langage naturel, et le journal dit si l'IA a planifié ou si AudioMuse est retombé sur rescue: matching your words directly (= l'IA n'a pas répondu).

Validé le 2026-10-01 à 22h29 : deux appels gemini-2.5-flash en 200, playlist de 50 titres cohérente, aucun repli.

13. ⚠ Pourquoi « Preview titles » échoue en début d'analyse

Message : « No playlist was large enough to keep. » Ce n'est ni Gemini ni une erreur de réglage, c'est de l'arithmétique :

Paramètre Valeur
NUM_CLUSTERS_MIN / MAX 40 à 100 grappes
MIN_PLAYLIST_SIZE_FOR_TOP_N 20 titres minimum pour qu'une playlist soit retenue
TOP_N_CLUSTERING_PLAYLIST 10 playlists conservées au final
CLUSTERING_MAX_PLAYLIST_SONGS 200 titres maximum
MAX_SONGS_PER_ARTIST 3 par playlist

Avec 237 titres analysés et 40 grappes au minimum, cela fait 6 titres par grappe au mieux. Le journal l'a confirmé au titre près : 5 playlists de 1, 4, 6, 9 et 16 titres, toutes écartées.

Il faut donc au moins ~800 titres pour que l'aperçu donne quelque chose, et en pratique davantage. Attendre ~2 000 titres (une dizaine d'heures d'analyse) avant de refaire l'essai.

Note sur le résultat final : seules 10 playlists seront conservées sur 40 à 100 grappes. Pour en avoir plus, augmenter TOP_N_CLUSTERING_PLAYLIST.

03_Claude et Ubuntu

03_Claude et Ubuntu

01_Installation de Claude dans le Ubuntu

Contexte

Installation et configuration de Claude Code sur la machine Ubuntu 25.10 (utilisateur julien), avec synchronisation du dossier de travail via Syncthing.

1. Installation de Syncthing

Date : 2026-05-31
Système : Ubuntu 25.10 (questing)

Étapes

  1. Vérification : Syncthing absent des paquets installés
  2. Installation via les dépôts Ubuntu : sudo apt install syncthing -y
  3. Activation au démarrage : systemctl --user enable --now syncthing
  4. Interface web disponible sur : http://127.0.0.1:8384

Résultat

Dossier synchronisé : /home/julien/Syncthing/

Contenu récupéré depuis le PC Windows (eliob) :

2. Configuration de Claude Code

Le fichier CLAUDE.md de référence a été localisé dans le dossier synchronisé :

/home/julien/Syncthing/Jux_univers/Claude-pcelio+jux/CLAUDE.md

Ce fichier centralise toute la configuration : MCPs, credentials VPS, préférences, projets en cours. Il a été lu en début de session pour initialiser le contexte.

Mémoire Claude Code initialisée

Répertoire : /home/julien/.claude/projects/-home-julien/memory/

3. Connexion BookStack depuis Ubuntu

Token API BookStack configuré manuellement pour permettre l écriture depuis Ubuntu (sans MCP npm disponible). Utilisation de l API REST directe via curl :

Authorization: Token TOKEN_ID:TOKEN_SECRET sur https://bookstack.juxjux.ovh/api/

03_Claude et Ubuntu

02_Diagnostic du Ubuntu par Claude

Diagnostic expert — Ubuntu julien-130430

Généré par Claude Code le 2026-05-31 à 19h57 — Ubuntu 25.10 questing — mis à jour 20h15


1. Système de base

OSUbuntu 25.10 (questing) — version non-LTS, support jusqu'à juillet 2026
Kernel6.17.0-19-generic (SMP PREEMPT_DYNAMIC — mars 2026)
Hostnamejulien-130430
Architecturex86_64
Uptime1h36 au moment du diagnostic
Languefr_FR.UTF-8 / shell bash

2. Matériel

CPU

ModèleAMD Ryzen 5 2600X Six-Core Processor
Cœurs / Threads6 cœurs / 12 threads (1 socket)
Fréquence2200–3600 MHz (scaling à 99%)
Charge (1/5/15 min)2,44 / 1,98 / 1,17 — charge en train de baisser, acceptable

RAM & Swap

RAM totale15 Gi
RAM utilisée4,9 Gi utilisé + 9 Gi cache/tampon — 10 Gi disponibles
Swap4 Gi (fichier /swap.img), 5,5 Mi utilisés — quasi vide, bonne santé

GPU

ModèleAMD Radeon RX 6400/6500 XT — Navi 24 (rev c1)
DriverAMDGPU (open-source, intégré au kernel)
Monitoringlm-sensors absent — pas de relevé de température possible

3. Stockage

DisqueModèleTaillePartitionFSPoint de montageUtiliséAlerte
sdaSanDisk 3.2Gen1 (USB)57,3 Gsda2ext4/ (racine)31G / 57G — 57%
sdbPatriot Burst (SSD)223,6 Gsdb3ntfs/media/julien/CE1C8DC545149G / 223G — 67%
sdcSeagate Backup Plus7,3 Tsdc2—/media/julien/Seagate…3,1T / 7,3T — 42%
sdd—932 Gsdd1—/media/julien/206897…827G / 932G — 89%⚠ Critique
sde—932 Gsde2—/media/julien/2ème disque dur294G / 932G — 32%

Point d'attention : Le disque sdd1 est à 89% de capacité (827G/932G). Seuil critique à surveiller.

Note : Le système racine est sur une clé USB SanDisk (sda). Performances limitées par rapport à un SSD SATA ou NVMe. Risque de défaillance à long terme supérieur à un disque interne.

4. Réseau

Interfaceenp37s0 (Ethernet)
IP locale192.168.1.26/24 (DHCP)
IPv62a01:cb1c:833b:d00:2ef0:5dff:feec:62e0/64
Passerelle192.168.1.1
DNS192.168.1.1 + IPv6 routeur (via systemd-resolved)
DNSSECDésactivé (unsupported)
mDNS / LLMNRDésactivés

Recommandation : L'IP est attribuée par DHCP. Envisager une réservation DHCP fixe sur le routeur pour la stabilité de 192.168.1.26.

5. Services et sécurité

Services systemd

SSH serveur

openssh-server absent — aucun accès SSH entrant possible sur cette machine. Si un accès distant est souhaité, installer openssh-server.

Pare-feu

ufw ne répond pas (non configuré ou inactif). La machine est probablement protégée par le NAT du routeur, mais aucune règle locale n'est en place.

Ports en écoute (accessibles depuis le réseau)

PortServiceRemarque
22000/tcp+udpSyncthing (PID 24179)Sync P2P — normal
53/tcp (127.0.0.53)systemd-resolvedDNS local uniquement
53/tcp (127.0.0.54)systemd-resolved stubDNS local uniquement

Surface d'attaque réseau réduite : seul Syncthing écoute sur l'interface externe.

Sudo

Julien est membre du groupe sudo. La commande sudo -l nécessite un terminal interactif (PAM conversation) — normal dans le contexte Claude Code non-interactif.

6. Syncthing

ProcessusEn cours d'exécution (PID 24179, port 22000 actif)
Service systemdsyncthing@julien.service : enabled / active ✓ (activé le 2026-05-31)
Dossiers synchronisésBillets, Jux_Obsidian, Jux_univers, Ouvrages, PDF temps, Suretés, Tutoriels videos

Fix 2026-05-31 : sudo systemctl enable --now syncthing@julien.service — service activé et démarré. Vérifié via API REST (HTTP 200, uptime ~17h).

7. Snaps

19 snaps installés. Plusieurs ont deux révisions montées simultanément (l'ancienne est conservée le temps du refresh par snapd) :

C'est le comportement normal de snapd (rollback possible). Les anciennes révisions sont supprimées automatiquement après quelques jours.

Nettoyage manuel possible : sudo snap set system refresh.retain=2 (déjà le défaut) ou snap list --all + sudo snap remove --revision=<rev> <snap>.

8. Environnements de développement

Python3.13.7 (/usr/bin/python3)
Venv global~/.venv — activé automatiquement via .bashrc (configuré le 2026-05-31)
Paquets venvpsycopg2-binary 2.9.12, requests 2.34.2, httpx 0.28.1, pip 26.1.2
Node.js24.16.0
npm11.13.0
Claude Codev2.1.158 — installé et opérationnel
DockerNon installé (ou non accessible sans sudo)

Installation venv : nécessitait sudo apt install python3.13-venv (paquet absent par défaut sur Ubuntu 25.10).

Activation manuelle : source ~/.venv/bin/activate

9. Connexion PostgreSQL — alteris_geo

Testée et validée depuis Ubuntu le 2026-05-31 via le venv ~/.venv.

Hôte79.137.14.202 (VPS Alteris)
Port5432 (accessible depuis l'extérieur)
Basealteris_geo
Utilisateuralteris_admin / Alteris2026
ServeurPostgreSQL 15.4 (Debian 15.4-1.pgdg110+1) — x86_64
Table recherches4 entrées au 2026-05-31 (2 FreshRSS, 2 kDrive — toutes du 2026-05-29)

Snippet de connexion Python (Ubuntu) :

import psycopg2
conn = psycopg2.connect(
    host="79.137.14.202", port=5432,
    dbname="alteris_geo", user="alteris_admin", password="Alteris2026"
)

10. Cron / tâches planifiées

11. Logs / erreurs récentes

Les seules erreurs journalctl (niveau err) sur 7 jours sont des échecs PAM sudo en mode non-interactif (générés par ce diagnostic) + des warnings udev ALSA sans conséquence. Aucune erreur critique applicative.


Synthèse — Points d'action

PrioritéProblèmeAction recommandéeStatut
Hautesdd1 à 89% (827G/932G)Libérer de l'espace ou déplacer des données vers sde (32% utilisé)En attente
MoyenneSyncthing non persistant au démarragesudo systemctl enable syncthing@julien.service✓ Résolu 2026-05-31
MoyenneSystème racine sur clé USB SanDiskEnvisager migration vers le SSD Patriot (sdb) pour fiabilitéEn attente
BassePare-feu inactifsudo ufw enable + règles minimales si accès SSH ajoutéEn attente
Basselm-sensors absentsudo apt install lm-sensors && sudo sensors-detectEn attente
BasseCUPS en double (paquet + snap)Supprimer l'un des deux selon usageEn attente
InfoUbuntu 25.10 non-LTSFin de support juillet 2026 — migration vers 26.04 LTS à lancerEn attente
InfoIP DHCP dynamiqueRéservation DHCP 192.168.1.26 sur le routeur recommandéeEn attente

Points positifs

03_Claude et Ubuntu

03_250531

1. Syncthing ne repartira pas automatiquement (service désactivé) — il faudra soit le lancer manuellement, soit profiter du redémarrage pour faire sudo systemctl enable syncthing@julien.service avant d'éteindre.
✓ Fix 2026-05-31 : sudo systemctl enable --now syncthing@julien.service — service activé et démarré. Vérifié via API REST (HTTP 200, uptime ~17h).

2. Le venv ~/.venv se réactivera automatiquement via .bashrc à l'ouverture du terminal.


En attente — après mise à jour Ubuntu 26.04

Mise à jour Ubuntu 26.04 LTS

Lancée le 2026-05-31 via screen -S upgrade + sudo do-release-upgrade.
✓ Terminée — Ubuntu 26.04 LTS opérationnel.

Montage NAS (192.168.1.17) — partages foxy et video

Le NAS a changé d'IP : était sur 192.168.1.22, maintenant sur 192.168.1.17 (MAC Synology 00:11:32:9c:8e:c9 — attribution DHCP).

Script exécuté : sudo bash /home/julien/setup_nas.sh
✓ Terminé — foxy et video montés sur /mnt/nas/foxy et /mnt/nas/video.
Credentials : /etc/samba/credentials_nas — entrées fstab ajoutées avec options nofail,_netdev,x-systemd.automount.

Note : entrée WebDAV sasnexte (https://82.66.244.248:5006) corrigée dans fstab (typos : un seul slash et lettre 'o' dans le port).

✓ Signets Nautilus ajoutés : smb://juxjux@192.168.1.17, /mnt/nas/foxy, /mnt/nas/video dans ~/.config/gtk-3.0/bookmarks.

rclone — sauvegarde vers kDrive

Configuration perdue lors de la mise à jour Ubuntu 26.04. La tâche sauvegardait vers kDrive (WebDAV). À reconfigurer :
rclone config → type webdav, URL https://connect.drive.infomaniak.com, credentials compte Infomaniak.

Son Bluetooth — Xiaomi 15T Pro

Tentative d'utiliser le Xiaomi 15T Pro comme enceinte Bluetooth depuis Ubuntu. Impossible : le téléphone n'expose pas le profil Audio Sink (UUID 0000110b) en Bluetooth classique — il est uniquement Audio Source. Limitation firmware Xiaomi, non contournable en BT.
Alternative WiFi (SoundWire) possible mais peu pratique.
→ À faire : acheter un casque ou une enceinte Bluetooth. N'importe quel périphérique BT standard exposant le profil Audio Sink fonctionnera directement avec Ubuntu/PipeWire.

Compétences Claude_QGIS

RAG de toutes les expériences de Claude dans l'utilisation de QGIS par MCP

Compétences Claude_QGIS

REX 06079

Contexte

Affichage des IRIS de Mandelieu-la-Napoule (06079) depuis PostGIS Alteris, avec population graduée, étiquettes, fond orthophoto IGN Géoplateforme et cadastre vecteur WFS — entièrement piloté depuis Claude Code via le MCP QGIS, sans interaction manuelle dans QGIS.


Données utilisées

Table / Source Schéma / Provider Contenu
contours_iris_2025 insee_raw (PostGIS Alteris) Géométries IRIS France entière
iris_2025_population insee_raw (PostGIS Alteris) Population 2022 par IRIS (recensement)
Orthophoto IGN Géoplateforme (WMTS → XYZ) HR.ORTHOIMAGERY.ORTHOPHOTOS — sans clé API
Cadastre parcelles Géoplateforme WFS CADASTRALPARCELS.PARCELLAIRE_EXPRESS:parcelle Parcelles cadastrales vecteur — OGR driver

Colonnes clés — pièges à retenir

contours_iris_2025 : colonnes standard sans espace — code_insee, code_iris, nom_iris, type_iris, geom

iris_2025_population : colonnes avec espace traînant (import INSEE brut) :


Résultats

9 IRIS pour 06079, population 2022 :

code_iris nom_iris population
060790101 Zone d'activités 24
060790102 IRIS 2 2 701
060790103 IRIS 3 2 000
060790104 IRIS 4 3 058
060790105 IRIS 5 2 197
060790106 IRIS 6 2 432
060790107 IRIS 7 3 188
060790108 IRIS 8 2 944
060790109 IRIS 9 2 656

Population min : 24 hab. (zone d'activités/naturelle) — max : 3 188 hab.

Cadastre : 26 439 parcelles après reprojection EPSG:4326 → EPSG:3857 (COUNT=2000 limite la requête WFS initiale à 2000 features, mais la reprojection en mémoire conserve toutes les géométries valides).


Procédure complète

Prérequis

Tunnel SSH paramiko actif (voir page 229 — Option 2). À relancer à chaque redémarrage de QGIS :

import sys
sys.path.insert(0, r'C:\Users\eliob\AppData\Roaming\Python\Python312\site-packages')
import paramiko
import socket, threading, select

class SSHTunnel(threading.Thread):
    def __init__(self, ssh_host, ssh_user, ssh_password,
                 remote_port, local_port=5433, remote_host='127.0.0.1'):
        super().__init__(daemon=True)
        self.ssh_host = ssh_host; self.ssh_user = ssh_user
        self.ssh_password = ssh_password; self.remote_host = remote_host
        self.remote_port = remote_port; self.local_port = local_port
        self._stop = threading.Event(); self.transport = None; self.server_sock = None

    def run(self):
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(self.ssh_host, username=self.ssh_user, password=self.ssh_password)
        self.transport = client.get_transport()
        self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_sock.bind(('127.0.0.1', self.local_port))
        self.server_sock.listen(5); self.server_sock.settimeout(1.0)
        while not self._stop.is_set():
            try:
                conn, _ = self.server_sock.accept()
                threading.Thread(target=self._forward, args=(conn,), daemon=True).start()
            except socket.timeout:
                continue
        self.server_sock.close(); client.close()

    def _forward(self, local_conn):
        try:
            chan = self.transport.open_channel('direct-tcpip',
                (self.remote_host, self.remote_port), local_conn.getpeername())
        except Exception:
            local_conn.close(); return
        while True:
            r, _, _ = select.select([local_conn, chan], [], [], 5)
            if local_conn in r:
                data = local_conn.recv(4096)
                if not data: break
                chan.send(data)
            if chan in r:
                data = chan.recv(4096)
                if not data: break
                local_conn.send(data)
        chan.close(); local_conn.close()

    def stop(self):
        self._stop.set()

tunnel = SSHTunnel('79.137.14.202', 'debian', 'RAW+NEXTE!', remote_port=5432, local_port=5433)
tunnel.start()

1. Charger l'orthophoto IGN (fond de carte)

Bug QGIS 4.0.3 : addMapLayer déclenche autoSelectAddedLayer → identifyMapTool → access violation quand une couche raster est ajoutée. Deux contournements obligatoires :

  1. Passer sur l'outil Pan avant d'ajouter la couche
  2. Utiliser addMapLayer(layer, False) + root.insertLayer() (sans auto-sélection)

Format URI : le provider WMTS natif de QGIS (crs=...&layers=...&url=...) échoue sur la Géoplateforme (pas de capabilities). Solution : encoder l'URL WMTS en XYZ tiles avec {z}/{y}/{x}.

from qgis.core import QgsProject, QgsRasterLayer
from qgis.gui import QgsMapToolPan
from qgis.utils import iface
import urllib.parse

# 1. Passer sur Pan AVANT d'ajouter la couche raster (évite le crash identifyMapTool)
pan_tool = QgsMapToolPan(iface.mapCanvas())
iface.mapCanvas().setMapTool(pan_tool)

# 2. URI XYZ (le provider WMTS natif échoue sur data.geopf.fr)
base_url = (
    "https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile"
    "&VERSION=1.0.0&LAYER=HR.ORTHOIMAGERY.ORTHOPHOTOS"
    "&STYLE=normal&FORMAT=image/jpeg"
    "&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}"
)
encoded = urllib.parse.quote(base_url, safe='')
uri = f"type=xyz&url={encoded}&zmin=0&zmax=19"

layer_ortho = QgsRasterLayer(uri, "Orthophoto IGN", "wms")
# 3. addToLegend=False + insertLayer manuel (évite autoSelectAddedLayer)
QgsProject.instance().addMapLayer(layer_ortho, False)
root = QgsProject.instance().layerTreeRoot()
root.insertLayer(-1, layer_ortho)  # en bas de la pile

2. Créer la vue PostGIS et charger les IRIS

import psycopg2
conn = psycopg2.connect(host='localhost', port=5433, dbname='alteris_geo',
                        user='alteris_admin', password='Alteris2026')
cur = conn.cursor()
cur.execute("""
    CREATE OR REPLACE VIEW insee_raw.v_iris_mandelieu_pop AS
    SELECT c.fid, c.geom, c.nom_iris, c.code_iris,
           ROUND(p."P22_POP "::numeric, 0)::integer AS population
    FROM insee_raw.contours_iris_2025 c
    LEFT JOIN insee_raw.iris_2025_population p ON p."IRIS " = c.code_iris
    WHERE c.code_insee = '06079'
""")
conn.commit(); conn.close()

from qgis.core import QgsVectorLayer
uri = (
    'host=localhost port=5433 dbname=alteris_geo '
    'user=alteris_admin password=Alteris2026 sslmode=disable '
    'table="insee_raw"."v_iris_mandelieu_pop" (geom) key=fid'
)
layer = QgsVectorLayer(uri, "IRIS Mandelieu-la-Napoule", "postgres")

3. Graduation par population (semi-transparent)

from qgis.core import QgsGraduatedSymbolRenderer, QgsRendererRange, QgsFillSymbol

colors = ['#EFF3FF', '#BDD7E7', '#6BAED6', '#2171B5', '#084594']
pmin, pmax = 24, 3188
step = (pmax - pmin) / 5
bounds = [pmin + i * step for i in range(6)]

ranges_def = []
for i in range(5):
    lo, hi = bounds[i], bounds[i+1]
    sym = QgsFillSymbol.createSimple({
        'color': colors[i], 'outline_color': '#555555', 'outline_width': '0.3'
    })
    sym.setOpacity(0.6)  # semi-transparent pour laisser voir l'ortho
    ranges_def.append(QgsRendererRange(lo, hi, sym,
        f"{int(lo):,}–{int(hi):,} hab.".replace(',', ' ')))

layer.setRenderer(QgsGraduatedSymbolRenderer('population', ranges_def))

4. Étiquettes + ajout dans le bon ordre

from qgis.core import (QgsPalLayerSettings, QgsTextFormat,
    QgsTextBufferSettings, QgsVectorLayerSimpleLabeling)
from qgis.PyQt.QtGui import QColor, QFont

pal = QgsPalLayerSettings()
pal.fieldName = "concat(nom_iris, '\n', population, ' hab.')"
pal.isExpression = True
pal.placement = QgsPalLayerSettings.Placement.OverPoint
fmt = QgsTextFormat()
fmt.setFont(QFont("Arial", 8)); fmt.setSize(8); fmt.setColor(QColor('#1a1a1a'))
buf = QgsTextBufferSettings()
buf.setEnabled(True); buf.setSize(1); buf.setColor(QColor('white'))
fmt.setBuffer(buf); pal.setFormat(fmt)
layer.setLabelsEnabled(True)
layer.setLabeling(QgsVectorLayerSimpleLabeling(pal))

# IRIS en haut de la pile (index 0), ortho déjà en bas
QgsProject.instance().addMapLayer(layer, False)
root = QgsProject.instance().layerTreeRoot()
root.insertLayer(0, layer)

5. Zoomer sur Mandelieu

from qgis.core import QgsRectangle, QgsCoordinateReferenceSystem, QgsCoordinateTransform

src_crs = QgsCoordinateReferenceSystem("EPSG:4326")
dst_crs = QgsCoordinateReferenceSystem("EPSG:3857")
transform = QgsCoordinateTransform(src_crs, dst_crs, QgsProject.instance())
pt_min = transform.transform(6.87, 43.51)
pt_max = transform.transform(6.99, 43.60)
extent = QgsRectangle(pt_min.x(), pt_min.y(), pt_max.x(), pt_max.y())
iface.mapCanvas().setExtent(extent)
iface.mapCanvas().refresh()

6. Charger le cadastre (WFS vecteur)

Pièges :

import processing
from qgis.core import (QgsVectorLayer, QgsCoordinateReferenceSystem,
                       QgsFillSymbol, QgsSingleSymbolRenderer, QgsProject)

# Driver OGR WFS avec BBOX en paramètre URL (le provider WFS natif QGIS échoue)
url = (
    "WFS:https://data.geopf.fr/wfs/ows?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature"
    "&TYPENAME=CADASTRALPARCELS.PARCELLAIRE_EXPRESS:parcelle"
    "&BBOX=6.87,43.51,6.99,43.60,EPSG:4326&COUNT=2000"
)
layer_wfs = QgsVectorLayer(url, "Cadastre Mandelieu", "ogr")
# → isValid() = True, 2000 features, EPSG:4326

# Reprojection en mémoire EPSG:3857 (sinon couche invisible dans le canevas)
result = processing.run("native:reprojectlayer", {
    'INPUT': layer_wfs,
    'TARGET_CRS': QgsCoordinateReferenceSystem('EPSG:3857'),
    'OUTPUT': 'memory:'
})
layer_cad = result['OUTPUT']
layer_cad.setName("Cadastre Mandelieu")
# → 26 439 features, EPSG:3857

# Symbologie : contour orange, remplissage quasi-transparent
sym = QgsFillSymbol.createSimple({
    'color': '204,68,0,30',      # orange très transparent (alpha 30/255)
    'outline_color': '#CC4400',
    'outline_width': '0.5'
})
layer_cad.setRenderer(QgsSingleSymbolRenderer(sym))

# Ajouter au-dessus des IRIS (index 0)
QgsProject.instance().addMapLayer(layer_cad, False)
root = QgsProject.instance().layerTreeRoot()
root.insertLayer(0, layer_cad)

Ordre final des couches (haut → bas) :

  1. Cadastre Mandelieu (vecteur WFS, EPSG:3857)
  2. IRIS Mandelieu-la-Napoule (PostGIS, gradué population)
  3. Orthophoto IGN (XYZ, fond)

Note cadastre : le BBOX rectangulaire déborde sur les communes voisines (Cannes à l'est, Pégomas au nord). Comportement attendu — pour restreindre au territoire communal strict, il faudrait une intersection post-chargement (pas de filtre code_commune disponible côté WFS Géoplateforme).


Points clés et pièges

Sujet Constat
Bug QGIS 4.0.3 — raster + identifyMapTool addMapLayer sur une couche raster → access violation si l'outil Identifier est actif. Fix : passer sur Pan + addMapLayer(layer, False) + insertLayer()
Ne pas cliquer sur la couche raster dans le panneau Même après ajout réussi, cliquer sur la couche raster dans le panneau des couches déclenche onActiveLayerChanged → crash. Rester sur l'outil Pan.
Provider WMTS natif QGIS invalide crs=...&layers=...&url=https://data.geopf.fr/wmts → couche invalide. Fix : encoder en XYZ avec type=xyz&url=...{z}/{y}/{x}
Canvas au zoom mondial au démarrage Les tuiles ne se chargent pas. Toujours zoomer sur la zone cible après ajout.
Provider WFS natif QGIS invalide QgsVectorLayer(url, name, "WFS") → couche invalide pour CADASTRALPARCELS.PARCELLAIRE_EXPRESS:parcelle. Fix : driver OGR WFS QgsVectorLayer("WFS:https://...", name, "ogr")
API Carto timeout geo.api.gouv.fr : appel HTTP synchrone dans le thread QGIS → 20 s de blocage puis timeout. Driver OGR WFS Géoplateforme préférable.
CRS mismatch WFS WFS retourne EPSG:4326, canevas EPSG:3857 → couche présente dans le panneau mais invisible sur la carte. Fix : processing.run("native:reprojectlayer", ...) vers EPSG:3857 en mémoire.
Colonnes INSEE avec espace "IRIS ", "COM ", "P22_POP " — espace traînant partout dans iris_2025_population
Types text Toutes les valeurs numériques INSEE sont en text — caster avec ::numeric
Sous-requête URI QGIS QgsDataSourceUri.setDataSource() sur-échappe les guillemets → couche invalide. Fix : créer une vue PostgreSQL
sys.executable QGIS Pointe sur qgis-bin.exe — pip via subprocess inutilisable. Fix : pip._internal.cli.main
sys.path paramiko QGIS n'inclut pas le dossier utilisateur Python. Ajouter sys.path.insert(0, ...) à chaque session

Généralisation à d'autres communes

code_insee = '06079'  # remplacer par le code cible
cur.execute(f"""
    CREATE OR REPLACE VIEW insee_raw.v_iris_pop AS
    SELECT c.fid, c.geom, c.nom_iris, c.code_iris, c.nom_commune,
           ROUND(p."P22_POP "::numeric, 0)::integer AS population
    FROM insee_raw.contours_iris_2025 c
    LEFT JOIN insee_raw.iris_2025_population p ON p."IRIS " = c.code_iris
    WHERE c.code_insee = '{code_insee}'
""")

Pour le cadastre, adapter le BBOX à l'emprise de la commune cible.


REX — 2026-06-21 (second run)

Résultat : 0 crash — procédure validée reproductible.

Run complet depuis un projet QGIS vide, piloté intégralement via MCP Claude Code → QGIS :

Étape Résultat
Tunnel SSH paramiko OK — PostGIS Alteris accessible localhost:5433
Orthophoto IGN (XYZ) Valide — rendu fond de carte immédiat
Vue PostGIS + couche IRIS 9 features, graduation 5 classes bleu, étiquettes population
Zoom sur Mandelieu Cadrage correct EPSG:3857
Cadastre WFS OGR + reprojection 26 439 parcelles EPSG:3857, symbologie orange

Conclusion : la procédure est stable et reproductible. Base solide pour une routine généralisable à n'importe quelle commune (code_insee + BBOX comme seuls paramètres variables). Potentiel : automatiser la production de fiches communales IRIS + cadastre + fond ortho à la demande depuis Claude Code.

Compétences Claude_QGIS

Expertises Topologie - Claude et Qgis

Contexte PLU

Pour une couche de zones PLU topologiquement correcte, trois règles sont non-négociables :

  1. Pas de gaps — tout le territoire communal doit être couvert, sans trou entre zones
  2. Pas d'overlaps — une parcelle n'appartient qu'à une seule zone
  3. Géométries valides — pas de self-intersection, pas de géométrie nulle

Ces trois vérifications + corrections sont pilotables intégralement depuis Claude Code via le MCP QGIS, sans manipulation manuelle.


Bloc 1 — Configuration du snapping avant saisie

À lancer en début de session d'édition sur une couche PLU. Configure l'environnement QGIS pour que la saisie soit topologiquement propre dès le départ.

from qgis.core import QgsSnappingConfig, QgsTolerance, QgsProject

proj = QgsProject.instance()
snap_cfg = proj.snappingConfig()

snap_cfg.setEnabled(True)
snap_cfg.setMode(QgsSnappingConfig.SnappingMode.AllLayers)
snap_cfg.setType(QgsSnappingConfig.SnappingType.VertexAndSegment)
snap_cfg.setTolerance(10.0)
snap_cfg.setUnits(QgsTolerance.UnitType.Pixels)
snap_cfg.setIntersectionSnapping(True)   # accrochage sur les intersections

proj.setSnappingConfig(snap_cfg)
proj.setTopologicalEditing(True)          # partage de noeuds entre couches
proj.setAvoidIntersectionsMode(
    QgsProject.AvoidIntersectionsMode.AvoidIntersectionsLayers
)  # évite automatiquement les overlaps lors de la saisie

Paramètres clés :

Paramètre Valeur Effet
AllLayers mode snap sur toutes les couches visibles
VertexAndSegment type accroche vertex ET bord
10 px tolérance adapté à la saisie courante PLU
TopologicalEditing True noeuds partagés entre polygones adjacents
AvoidIntersectionsLayers mode saisie d'un polygone qui "découpe" automatiquement ses voisins

Piège : setType() attend QgsSnappingConfig.SnappingType — pas Qgis.SnappingType ni Qgis.SnappingTypes.


Bloc 2 — Audit topologique

Routine complète : validité + overlaps + gaps sur n'importe quelle couche polygone.

import processing
from qgis.core import QgsProject

def audit_topo(layer, unique_id='fid', gap_threshold=0, min_overlap_area=0):
    """
    Audit topologique d'une couche polygone PLU.
    Retourne un dict avec les couches d'erreurs et un résumé.
    """
    rapport = {}

    # 1. Validité géométrique (GEOS)
    r_val = processing.run("native:checkvalidity", {
        'INPUT_LAYER': layer,   # NOTE : INPUT_LAYER, pas INPUT
        'METHOD': 2,            # GEOS
        'IGNORE_RING_SELF_INTERSECTION': False,
        'VALID_OUTPUT': 'memory:',
        'INVALID_OUTPUT': 'memory:',
        'ERROR_OUTPUT': 'memory:'
    })
    rapport['validite'] = {
        'valides': r_val['VALID_COUNT'],
        'invalides': r_val['INVALID_COUNT'],
        'erreurs': r_val['ERROR_COUNT'],
        'layer_invalides': r_val['INVALID_OUTPUT'],
        'layer_erreurs': r_val['ERROR_OUTPUT']
    }

    # 2. Overlaps
    r_ov = processing.run("native:checkgeometryoverlap", {
        'INPUT': layer,
        'UNIQUE_ID': unique_id,
        'MIN_OVERLAP_AREA': min_overlap_area,
        'TOLERANCE': 8,
        'ERRORS': 'memory:',
        'OUTPUT': 'memory:'
    })
    rapport['overlaps'] = {
        'count': r_ov['ERRORS'].featureCount(),
        'layer_errors': r_ov['ERRORS'],
        'layer_features': r_ov['OUTPUT']
    }

    # 3. Gaps
    r_gap = processing.run("native:checkgeometrygap", {
        'INPUT': layer,
        'UNIQUE_ID': unique_id,
        'GAP_THRESHOLD': gap_threshold,
        'TOLERANCE': 8,
        'NEIGHBORS': 'memory:',
        'ERRORS': 'memory:',
        'OUTPUT': 'memory:'
    })
    rapport['gaps'] = {
        'count': r_gap['OUTPUT'].featureCount(),
        'layer_gaps': r_gap['OUTPUT'],
        'layer_neighbors': r_gap['NEIGHBORS'],  # requis pour fixgeometrygap
        'layer_errors': r_gap['ERRORS']
    }

    # Résumé lisible
    print(f"=== Audit topo : {layer.name()} ({layer.featureCount()} features) ===")
    print(f"Validité  : {rapport['validite']['valides']} OK / "
          f"{rapport['validite']['invalides']} invalides")
    print(f"Overlaps  : {rapport['overlaps']['count']} erreur(s)")
    print(f"Gaps      : {rapport['gaps']['count']} trou(s)")
    ok = (rapport['validite']['invalides'] == 0 and
          rapport['overlaps']['count'] == 0 and
          rapport['gaps']['count'] == 0)
    print(f"Résultat  : {'PROPRE' if ok else 'ERREURS DETECTEES'}")

    return rapport

Usage :

from qgis.core import QgsProject
layer = QgsProject.instance().mapLayersByName("zones_plu")[0]
rapport = audit_topo(layer, unique_id='fid')

Piège critique : native:checkvalidity → paramètre INPUT_LAYER (pas INPUT). Erreur silencieuse sinon.


Bloc 3 — Correction automatique

S'appuie sur les couches d'erreurs produites par le Bloc 2.

3a. Corriger les overlaps

r_fix_ov = processing.run("native:fixgeometryoverlap", {
    'INPUT': layer,
    'ERRORS': rapport['overlaps']['layer_errors'],
    'UNIQUE_ID': 'fid',
    'OVERLAP_FEATURE_UNIQUE_IDX': 'gc_overlap_fid',  # champ produit par checkgeometryoverlap
    'ERROR_VALUE_ID': 'gc_error',
    'OUTPUT': 'memory:',
    'REPORT': 'memory:',
    'TOLERANCE': 8
})
layer_corrige = r_fix_ov['OUTPUT']
print(f"Overlaps corrigés : {r_fix_ov['REPORT'].featureCount()} opérations")

3b. Combler les gaps

3 méthodes disponibles :

Valeur Méthode Usage recommandé
0 Ajouter à la plus longue bordure en commun PLU — zone voisine qui partage le plus de frontière
1 Créer une nouvelle entité si le gap est une zone à part entière
2 Ajouter à la plus grande zone voisine quand la surface prime
r_fix_gap = processing.run("native:fixgeometrygap", {
    'INPUT': layer,
    'NEIGHBORS': rapport['gaps']['layer_neighbors'],  # issu de checkgeometrygap
    'GAPS': rapport['gaps']['layer_gaps'],
    'METHOD': 0,    # 0 = plus longue bordure (recommandé PLU)
    'UNIQUE_ID': 'fid',
    'ERROR_ID_IDX': 'gc_errorid',
    'OUTPUT': 'memory:',
    'REPORT': 'memory:',
    'TOLERANCE': 8
})
layer_sans_gap = r_fix_gap['OUTPUT']
print(f"Gaps comblés : {r_fix_gap['REPORT'].featureCount()} opérations")

3c. Corriger les géométries invalides (self-intersections, anneaux)

r_fix_val = processing.run("native:fixgeometries", {
    'INPUT': rapport['validite']['layer_invalides'],
    'METHOD': 1,    # 1 = structure linéaire (robuste)
    'OUTPUT': 'memory:'
})
layer_valide = r_fix_val['OUTPUT']

Bloc 4 — Accrochage post-saisie (snapgeometries)

Quand une couche a été saisie sans snapping actif, ou importée avec de micro-décalages entre polygones adjacents. Accroche les géométries d'une couche sur une couche de référence (ex : limites communales, autre zonage).

8 comportements disponibles :

Valeur Comportement Usage
0 Aligner les nœuds, ajoute sommets si besoin défaut recommandé
1 Point le plus proche, ajoute sommets si nœuds mal alignés
2 Aligner les nœuds, sans ajout de sommet quand on veut conserver la densité
4 Déplacer uniquement les extrémités (nœuds) micro-corrections de bord
6 Extrémités sur extrémités uniquement lignes/filaires
r_snap = processing.run("native:snapgeometries", {
    'INPUT': layer_a_corriger,
    'REFERENCE_LAYER': layer_reference,
    'TOLERANCE': 0.5,    # en unités de la couche (mètres si Lambert 93)
    'BEHAVIOR': 0,
    'OUTPUT': 'memory:'
})
layer_snapped = r_snap['OUTPUT']

Recommandation PLU : tolérance 0.1–0.5 m en EPSG:2154 (Lambert 93). Trop grande → déformation des géométries.


Bloc 5 — Reconstruction automatique depuis le cadastre

Quand une zone (ex : périmètre PLU, emprise de projet) a été saisie grossièrement et doit être recalée exactement sur les limites parcellaires cadastrales. Claude reconstruit le polygone par dissolution des parcelles qui chevauchent la zone rough ; l'opérateur complète ensuite manuellement les parties sans référence cadastrale (domaine public non-parcellaire : voiries, cours d'eau).

Validé le 2026-06-21 sur 06079-Minelle.gpkg (Mandelieu-la-Napoule) : 11 parcelles intersectantes → 2 retenues (overlap ≥ 50%) → 137 004 m², 31 nœuds, géométrie valide.

Principe

  1. Fixer les géométries du cadastre (WFS souvent invalide)
  2. Extraire les parcelles qui intersectent la zone rough
  3. Calculer le % de chevauchement pour chaque parcelle → garder celles à ≥ 50%
  4. Dissoudre → multiparttosingleparts → garder la plus grande part
  5. Écrire dans le GeoPackage en retirant d'abord les couches QGIS (file locking Windows)

Code complet

import processing
import urllib.parse
from qgis.core import (
    QgsProject, QgsVectorFileWriter, QgsWkbTypes,
    QgsFields, QgsMemoryProviderUtils
)

# Pré-requis : layer_cad (cadastre WFS reprojeté EPSG:3857)
#              layer_zone (zone rough à recaler)
#              gpkg_path (chemin du GeoPackage à écrire)

# 1. Fixer les géométries cadastrales (WFS Géoplateforme souvent invalide)
cad_fixed = processing.run("native:fixgeometries", {
    'INPUT': layer_cad,
    'METHOD': 1,    # structure linéaire, robuste
    'OUTPUT': 'memory:'
})['OUTPUT']

# 2. Extraire les parcelles qui intersectent la zone rough
parcelles_in = processing.run("native:extractbylocation", {
    'INPUT': cad_fixed,
    'PREDICATE': [0],   # intersects
    'INTERSECT': layer_zone,
    'OUTPUT': 'memory:'
})['OUTPUT']

# 3. Calculer le % de chevauchement et retenir celles ≥ 50%
geom_zone = next(layer_zone.getFeatures()).geometry()
a_inclure = []
for f in parcelles_in.getFeatures():
    inter = f.geometry().intersection(geom_zone)
    pct = inter.area() / f.geometry().area() * 100
    if pct >= 50:
        a_inclure.append(f['gid'])

print(f"{parcelles_in.featureCount()} parcelles intersectantes → "
      f"{len(a_inclure)} retenues (overlap ≥ 50%)")
print(f"GIDs retenus : {a_inclure}")

# 4. Sélectionner + dissoudre
ids_str = ', '.join(str(i) for i in a_inclure)
parcelles_sel = processing.run("native:extractbyexpression", {
    'INPUT': cad_fixed,
    'EXPRESSION': f'"gid" IN ({ids_str})',
    'OUTPUT': 'memory:'
})['OUTPUT']

dissolved = processing.run("native:dissolve", {
    'INPUT': parcelles_sel,
    'FIELD': [],
    'SEPARATE_DISJOINT': False,
    'OUTPUT': 'memory:'
})['OUTPUT']

# 5. Single part → garder la plus grande
single = processing.run("native:multiparttosingleparts", {
    'INPUT': dissolved,
    'OUTPUT': 'memory:'
})['OUTPUT']

largest = max(single.getFeatures(), key=lambda f: f.geometry().area())
print(f"Résultat : {largest.geometry().area():.0f} m², "
      f"{largest.geometry().constGet().nCoordinates()} nœuds")

layer_main = QgsMemoryProviderUtils.createMemoryLayer(
    "main", QgsFields(), QgsWkbTypes.Type.Polygon, single.crs()
)
layer_main.dataProvider().addFeature(largest)

# 6. Écrire dans le GeoPackage
# CRITIQUE : retirer toutes les couches QGIS référençant le fichier avant écriture
for name in ["06079-Minelle"]:
    for lyr in QgsProject.instance().mapLayersByName(name):
        QgsProject.instance().removeMapLayer(lyr)

options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "GPKG"
options.layerName = "06079-Minelle"
options.actionOnExistingFile = QgsVectorFileWriter.ActionOnExistingFile.CreateOrOverwriteLayer

# writeAsVectorFormatV3 retourne un tuple de 4 valeurs
res = QgsVectorFileWriter.writeAsVectorFormatV3(
    layer_main, gpkg_path, QgsCoordinateTransformContext(), options
)
# res = (error_code, error_message, filename, layername)
if res[0] == 0:
    print(f"Écrit : {gpkg_path} → couche '{options.layerName}'")
else:
    print(f"ERREUR {res[0]} : {res[1]}")

# 7. Recharger dans QGIS pour vérification
layer_reload = QgsVectorLayer(
    f"{gpkg_path}|layername={options.layerName}",
    options.layerName, "ogr"
)
QgsProject.instance().addMapLayer(layer_reload, False)
root = QgsProject.instance().layerTreeRoot()
root.insertLayer(0, layer_reload)
iface.mapCanvas().setExtent(layer_reload.extent())
iface.mapCanvas().refresh()
print("Couche rechargée et zoomée.")

Pièges spécifiques

Sujet Constat
writeAsVectorFormatV3 retourne 4 valeurs (error_code, error_message, filename, layername) — pas 2. Déstructurer en conséquence.
File locking Windows QGIS garde un handle sur le fichier GeoPackage. Retirer toutes les couches référençant le fichier avec removeMapLayer() avant d'écrire.
CreateOrOverwriteLayer pas CreateOrOverwriteFile CreateOrOverwriteFile supprime tout le fichier (détruisant les autres couches). CreateOrOverwriteLayer ne touche qu'à la couche cible.
native:savefeatures échoue si fichier existe "A file system object already exists" — utiliser writeAsVectorFormatV3 à la place.
MultiPolygon → asPolygon() fail Si les parcelles retenues ne sont pas adjacentes, le dissolve produit un MultiPolygon. Appliquer multiparttosingleparts + max(..., key=lambda f: f.geometry().area()) pour garder la plus grande part.
Cadastre WFS invalide La Géoplateforme retourne parfois des géométries invalides (ex : feature 15026). Toujours fixer avec native:fixgeometries METHOD=1 avant usage comme couche de référence.

Workflow collaboratif

Claude reconstruit le périmètre sur les limites parcellaires exactes. L'opérateur complète manuellement les parties manquantes non-parcellaires (domaine public : voiries, cours d'eau, espaces naturels non cadastrés). Les deux résultats sont complémentaires : la précision automatique sur le cadastre + le jugement humain sur le hors-cadastre.


Routine principale — Audit + Rapport

Fonction complète prête à l'emploi. Appeler par Claude en une seule commande.

import processing
from qgis.core import QgsProject, QgsSnappingConfig, QgsTolerance

def configurer_snapping_plu():
    proj = QgsProject.instance()
    snap_cfg = proj.snappingConfig()
    snap_cfg.setEnabled(True)
    snap_cfg.setMode(QgsSnappingConfig.SnappingMode.AllLayers)
    snap_cfg.setType(QgsSnappingConfig.SnappingType.VertexAndSegment)
    snap_cfg.setTolerance(10.0)
    snap_cfg.setUnits(QgsTolerance.UnitType.Pixels)
    snap_cfg.setIntersectionSnapping(True)
    proj.setSnappingConfig(snap_cfg)
    proj.setTopologicalEditing(True)
    proj.setAvoidIntersectionsMode(
        QgsProject.AvoidIntersectionsMode.AvoidIntersectionsLayers)
    print("Snapping PLU configuré")

def audit_topo(layer, unique_id='fid', gap_threshold=0, min_overlap_area=0):
    r_val = processing.run("native:checkvalidity", {
        'INPUT_LAYER': layer, 'METHOD': 2,
        'IGNORE_RING_SELF_INTERSECTION': False,
        'VALID_OUTPUT': 'memory:', 'INVALID_OUTPUT': 'memory:', 'ERROR_OUTPUT': 'memory:'
    })
    r_ov = processing.run("native:checkgeometryoverlap", {
        'INPUT': layer, 'UNIQUE_ID': unique_id,
        'MIN_OVERLAP_AREA': min_overlap_area, 'TOLERANCE': 8,
        'ERRORS': 'memory:', 'OUTPUT': 'memory:'
    })
    r_gap = processing.run("native:checkgeometrygap", {
        'INPUT': layer, 'UNIQUE_ID': unique_id,
        'GAP_THRESHOLD': gap_threshold, 'TOLERANCE': 8,
        'NEIGHBORS': 'memory:', 'ERRORS': 'memory:', 'OUTPUT': 'memory:'
    })
    rapport = {
        'layer': layer,
        'unique_id': unique_id,
        'validite': {
            'valides': r_val['VALID_COUNT'],
            'invalides': r_val['INVALID_COUNT'],
            'layer_invalides': r_val['INVALID_OUTPUT']
        },
        'overlaps': {
            'count': r_ov['ERRORS'].featureCount(),
            'layer_errors': r_ov['ERRORS'],
            'layer_features': r_ov['OUTPUT']
        },
        'gaps': {
            'count': r_gap['OUTPUT'].featureCount(),
            'layer_gaps': r_gap['OUTPUT'],
            'layer_neighbors': r_gap['NEIGHBORS'],
            'layer_errors': r_gap['ERRORS']
        }
    }
    ok = (r_val['INVALID_COUNT'] == 0 and
          r_ov['ERRORS'].featureCount() == 0 and
          r_gap['OUTPUT'].featureCount() == 0)
    print(f"\n=== Audit topo : {layer.name()} ===")
    print(f"  Géométries invalides : {r_val['INVALID_COUNT']}")
    print(f"  Overlaps             : {r_ov['ERRORS'].featureCount()}")
    print(f"  Gaps                 : {r_gap['OUTPUT'].featureCount()}")
    print(f"  => {'PROPRE' if ok else 'ERREURS — voir rapport'}")
    return rapport

# Usage type
# layer = QgsProject.instance().mapLayersByName("zones_plu")[0]
# configurer_snapping_plu()
# rapport = audit_topo(layer)

Pièges à retenir

Sujet Constat
INPUT_LAYER vs INPUT native:checkvalidity exige INPUT_LAYER, tous les autres utilisent INPUT. Erreur silencieuse sinon.
QgsSnappingConfig.SnappingType setType() attend ce type précis — pas Qgis.SnappingType ni Qgis.SnappingTypes.
NEIGHBORS obligatoire pour fixgeometrygap La couche NEIGHBORS produite par checkgeometrygap doit être conservée et passée à fixgeometrygap.
Tolérance snapgeometries en unités couche Si la couche est en Lambert 93 (mètres), 0.5 = 50 cm. Ne pas confondre avec la tolérance en pixels du snapping canvas.
METHOD 0 pour PLU gaps "Plus longue bordure en commun" est la méthode la plus cohérente pour les zonages PLU (le gap va à la zone avec laquelle il partage le plus de frontière).
AvoidIntersectionsLayers Mode le plus adapté PLU — évite les overlaps lors de la saisie mais uniquement sur les couches cochées dans les paramètres du projet.
writeAsVectorFormatV3 retourne 4 valeurs (error_code, error_message, filename, layername) — pas 2.
File locking GeoPackage Windows Retirer toutes les couches QGIS référençant le fichier avant écriture, utiliser CreateOrOverwriteLayer.

Statut

04_Claude et les dépannages informatiques

04_Claude et les dépannages informatiques

260803-suivi des logs de dysfonctionnement du PC - écrans bleus de la mort

Suivi des dysfonctionnements du PC eliob — écrans bleus

⚠ Mise à jour du 2026-08-25 — après réinstallation de Windows : les écrans bleus ont quasiment cessé, les coupures sèches non.

Deux précisions qui modifient la lecture de toute cette page :

1. eliob et julie sont la même machine. Le poste décrit ici n'a pas disparu : Windows y a été réinstallé le 2026-08-08 à 12:21, précisément à cause des plantages analysés dans cette page. Le compte eliob ayant perdu ses identifiants, un nouveau profil a été créé à 12:36 sous le nom julie (faute de frappe pour julien), adossé au compte Microsoft julien.bertrand@live.fr. C'est le seul profil de la machine. Matériel identique vérifié le 2026-08-25 : MSI A320M-A PRO (MS-7C51), BIOS 1.40 du 08/12/2020, Ryzen 5 2600X, une seule barrette 16 Go à 2400 MHz, RX 6500 XT.

2. Les deux populations ont divergé, et c'est le fait nouveau le plus important.

3. Les mesures du 2026-08-03 ont été effacées par la réinstallation — voir § 8 et § 10. Le démarrage rapide est de nouveau actif, la rétention des vidages est retombée à 5. À réappliquer.

Voir le journal (§ 12) et la révision du diagnostic (§ 9).

Machine : PC Windows eliob (pcelio) Analyse initiale : 2026-08-03 — Claude Code Fenêtre observée : 29/10/2025 → 03/08/2026 pour le journal d'événements (Windows réinstallé le 28/10/2025) — les compteurs SMART, eux, couvrent toute la vie des disques

En bref

Mise à jour du 2026-08-03, 08h30 — après élévation de privilèges, les rapports WER ont pu être lus et désignent nommément le module fautif : amdfendr.sys (AMD Crash Defender). Le pilote réseau VirtualBox, suspect n°1 de la première version de cette analyse, est disculpé comme cause des écrans bleus. Voir §6.

Mise à jour du 2026-08-03, 09h00 — WinDbg et smartmontools installés. Le vidage mémoire a été analysé : la pile d'appels confirme amdfendr.sys et donne le mécanisme exact du plantage (§6.1). Les données SMART complètes des 4 disques ont été relevées : aucun n'est défaillant, mais le compteur d'arrêts brutaux du SSD système révèle que l'instabilité est bien antérieure à la réinstallation de Windows (§7).


1. Configuration matérielle

Élément Valeur
Carte mère MSI A320M-A PRO (MS-7C51), BIOS AMI 1.40 du 08/12/2020
Processeur AMD Ryzen 5 2600X — 6 cœurs, 3,6 GHz
Carte graphique AMD Radeon RX 6500 XT (4 Go) — pilote 30.0.14023.3004 du 18/01/2022, soit 4 ans et demi de retard
Mémoire 1 seule barrette 16 Go TEAMGROUP UD4-2666 (DIMM 0, canal B) — cadencée à 2400 MHz (sous sa fréquence nominale de 2666)
Disque système SSD SATA Patriot Burst 240 Go (C: — 71 Go libres)
Disque secondaire HDD SATA Toshiba HDWD110 1 To (D:)
Périphériques USB ASMT 2115 1 To (E:), Seagate Backup+ Hub 8 To (F:), SanDisk 3.2Gen1 64 Go
OS Windows 10 Famille 22H2 — build 19045, installé le 28/10/2025
Boîtier / assemblage Megaport, modèle 130430

Remarque sur l'âge : Julien évalue le PC à 9 ans d'usage intensif. Le Ryzen 2600X date de 2018 et la carte A320M-A PRO de 2019-2020 — le cœur de la machine a donc plutôt 6-7 ans. Le boîtier, l'alimentation et les ventilateurs peuvent être plus anciens s'ils ont été repris d'une configuration précédente. L'alimentation n'a pas pu être identifiée par logiciel — c'est une information à relever physiquement (marque, modèle, wattage, année), elle est déterminante pour la suite du diagnostic.


2. Méthode

Sources exploitées

Sans privilèges particuliers :

Avec élévation (c'est ce qui a permis d'aboutir) :

Outils installés le 2026-08-03

Outil Version Usage
smartmontools 7.5 C:\Program Files\smartmontools\bin\smartctl.exe — SMART réel, à lancer en administrateur
Microsoft.WinDbg 1.2606 Expose de vrais alias console dans %LOCALAPPDATA%\Microsoft\WindowsApps : cdbX64.exe, kdX64.exe, WinDbgX.exe

Analyse d'un vidage en ligne de commande :

cdbX64.exe -z dump.dmp -y "srv*C:\symbols*https://msdl.microsoft.com/download/symbols" -c "!analyze -v; q" -logo sortie.txt

Trois points de méthode qui ont compté

  1. Les événements 41 et 1001 sont horodatés au redémarrage suivant, pas à l'instant du crash. Le redémarrage automatique étant activé (AutoReboot=1), les deux coïncident à la minute près pour les BSOD — mais il ne faut jamais lire ces horodatages comme « l'heure de la panne » sans cette vérification.
  2. Une corrélation temporelle, même serrée, ne vaut pas une preuve. Trois crashes à 12 secondes d'une erreur VBoxNetLwf m'ont fait désigner le mauvais coupable. Seule la lecture du vidage a tranché.
  3. Les preuves les plus utiles sont derrière une élévation de privilèges. Tant qu'on lit le journal en session standard, on tourne autour du problème.

3. Chiffres clés

Indicateur Valeur
Arrêts anormaux (Kernel-Power 41) 45 en 9 mois
dont écrans bleus réels (avec code bugcheck) 15 (33 %)
dont coupures sèches sans BSOD (BugcheckCode = 0) 30 (67 %)
Erreurs matérielles WHEA-Logger 0
Erreurs disque / NTFS critiques (90 j) 2 Ntfs 50, 3 volmgr 161 (échec d'écriture du dump)
Bouton d'alimentation maintenu (arrêt forcé manuel) 1 seul cas — 20/05/2026 20:35
Arrêt propre demandé (1074/13) juste avant le crash 0 cas sur 45
Arrêts brutaux au compteur SMART du SSD système 146 pour 1 066 mises sous tension (13,7 %)

Fréquence : environ 1 arrêt anormal tous les 6 jours en moyenne, avec des grappes (2 crashes le même jour à 5 reprises).

Écart entre les deux compteurs : 146 arrêts brutaux au SMART contre 45 dans le journal Windows. La centaine manquante est antérieure à la réinstallation du 28/10/2025 — voir §7.


4. Deux populations de pannes bien distinctes

Population A — 30 coupures sèches, sans écran bleu (67 %)

BugcheckCode = 0, PowerButtonTimestamp = 0 : le système s'est arrêté sans produire de vérification d'erreur, sans que le bouton d'alimentation ait été maintenu, et sans qu'un arrêt ait été demandé. Le dernier événement journalisé précède le redémarrage de moins d'une minute dans la quasi-totalité des cas.

C'est le profil d'une coupure d'alimentation, d'un reset matériel ou d'un gel total du noyau — Windows n'a pas eu le temps d'écrire quoi que ce soit.

Ces 30 événements sont répartis sur toute la période (octobre 2025 → juillet 2026), sans lien avec les vagues de BSOD. C'est la population la plus préoccupante pour une hypothèse matérielle, et c'est aussi celle sur laquelle les logs sont, par construction, muets.

Population B — 15 écrans bleus avec code d'erreur (33 %)

Code Nb Nom Signification
0x0000009F 10 DRIVER_POWER_STATE_FAILURE Un pilote bloque une requête de changement d'état d'alimentation (mise en veille, reprise, arrêt). Paramètre 1 = 0x3 dans les 10 cas : un objet de périphérique bloque une IRP trop longtemps.
0x00000050 3 PAGE_FAULT_IN_NONPAGED_AREA Accès à une adresse mémoire invalide. Paramètre 2 = 0 → il s'agit d'une lecture (confirmé par WinDbg : AV.Type = Read).
0x0000003B 1 SYSTEM_SERVICE_EXCEPTION Exception 0xC0000005 (violation d'accès) en mode noyau.
0x000000A0 1 INTERNAL_POWER_ERROR Erreur interne du gestionnaire d'alimentation.

12 des 15 BSOD (80 %) sont des erreurs liées à une transition d'alimentation (0x9F + 0xA0). Aucun n'est précédé d'une demande d'arrêt propre → il s'agit de transitions veille S3 / reprise / démarrage rapide, pas d'un arrêt lancé depuis le menu Démarrer.


5. Chronologie — trois régimes successifs

Période Régime dominant
29/10/2025 → 23/12/2025 Uniquement des coupures sèches (2 événements)
25/12/2025 → 29/03/2026 Vague de 10 × 0x9F — DRIVER_POWER_STATE_FAILURE, souvent 2 le même jour, entremêlée de coupures sèches
16/04/2026 → 19/05/2026 1 × 0xA0, 1 × 0x3B — puis les BSOD cessent
19/05/2026 → 28/07/2026 Retour aux seules coupures sèches (7 événements)
31/07/2026 → 03/08/2026 Nouvelle vague : 3 × 0x50 en 4 jours

Les BSOD ne sont donc pas un phénomène continu : ce sont des vagues qui apparaissent et disparaissent, ce qui est le comportement typique d'une cause logicielle (installation ou mise à jour d'un pilote). Les coupures sèches, elles, sont présentes en continu du premier au dernier jour — comportement typique d'une cause matérielle.


6. Cause de la vague en cours : amdfendr.sys (AMD Crash Defender)

6.1 — La preuve : l'analyse du vidage mémoire

!analyze -v sur C:\Windows\Minidump\073126-9718-01.dmp (crash du 31/07/2026 08:54) donne la pile d'appels complète :

nt!KeBugCheckEx
nt!MiSystemFault
nt!MmAccessFault
nt!KiPageFault
nt!LZNT1FindMatchStandard+0xce      <-- instruction fautive
nt!LZNT1CompressChunk+0xd7
nt!RtlCompressBufferLZNT1+0x80
nt!RtlCompressBuffer+0x6f
amdfendr+0x13e1b                    <-- L'APPELANT
MODULE_NAME:        amdfendr
IMAGE_NAME:         amdfendr.sys
FAILURE_BUCKET_ID:  AV_amdfendr!unknown_function
AV.Type:            Read
AV.Page.Virtual:    0xffff830288400000
Adresse fautive:    0xffff830288401000

Le mécanisme est limpide. amdfendr.sys appelle RtlCompressBuffer, la fonction de compression du noyau Windows, en lui passant un tampon dont la taille annoncée dépasse la taille réellement allouée. Le compresseur LZNT1 lit donc au-delà de la fin du tampon, tombe sur une page non mappée, et le noyau plante.

L'adresse fautive …88401000 est exactement à 0x1000 octets (une page mémoire) du début de la page valide …88400000. C'est la signature manuelle du dépassement de tampon : la lecture a franchi la frontière de page juste après la fin de la zone légitime.

Correction d'un point technique de la première version : le déplacement constant 0x3ae que j'avais relevé sur les trois écrans bleus se situe dans ntoskrnl (nt!LZNT1FindMatchStandard+0xce), pas dans amdfendr.sys. C'est pour cette raison qu'il est identique d'un crash à l'autre : c'est toujours la même fonction du noyau qui est mise en défaut. L'intuition — « le même chemin de code plante à chaque fois » — était juste ; son attribution à un pilote tiers ne l'était pas.

Notons enfin que l'horodatage réel du binaire est le 4 juin 2021 — encore plus ancien que sa date de fichier.

6.2 — Confirmation par les rapports WER

Après élévation de privilèges, les deux rapports d'erreur Windows du 31/07/2026 ont pu être lus. Ils contiennent le verdict de Microsoft :

EventType            = BlueScreen
Response.BucketId    = AV_amdfendr!unknown_function
Sig[0] Code          = 50
Sig[3] Paramètre 3   = fffff8031db903ae   /   fffff805091903ae
Sig[4] Paramètre 4   = 2

AV_amdfendr!unknown_function : Access Violation imputée au module amdfendr.sys. Les deux rapports du 31/07, produits indépendamment, aboutissent au même classement — et au même que l'analyse du vidage ci-dessus. Trois déterminations convergentes.

6.3 — Ce qu'est ce pilote

Fichier Description Version Date
amdfendr.sys AMD Crash Defender 21.30.0.9 07/02/2022
amdfendrmgr.sys AMD Crash Defender Manager Driver 21.30.0.9 07/02/2022

AMD Crash Defender est un composant des pilotes Radeon Adrenalin de la génération 21.30 / 22.x. Son rôle est d'intercepter les plantages du pilote graphique pour tenter de rétablir l'affichage sans redémarrer. Autrement dit : c'est le mécanisme censé éviter les écrans bleus qui les provoque.

Ce composant est connu pour être instable dans cette génération de pilotes. AMD l'a profondément remanié dans les versions ultérieures.

Le pilote graphique de cette machine date du 18/01/2022 (version 30.0.14023.3004) pour une Radeon RX 6500 XT — soit quatre ans et demi sans mise à jour, alors que la carte est toujours pleinement prise en charge par les pilotes Adrenalin actuels.

Le pilote graphique est également un candidat classique pour la famille 0x9F (DRIVER_POWER_STATE_FAILURE) : c'est typiquement lui qui bloque une transition de mise en veille ou de reprise. La vague de 10 × 0x9F de l'hiver 2025-2026 pourrait donc relever de la même origine — à confirmer par l'analyse des vidages.

6.4 — Anomalie secondaire : le pilote réseau VirtualBox

VBoxNetLwf — VirtualBox NDIS6 Bridged Networking Driver, version 7.2.14.174565

Le journal System contient 20 erreurs VBoxNetLwf (ID 12) : « Le pilote a détecté une erreur de pilote interne sur \Device\VBoxNetLwf ».

Toutes sont comprises entre le 24/07/2026 06:55 et le 03/08/2026 07:43 — soit exactement depuis l'installation d'Oracle VirtualBox 7.2.14 le 24/07/2026 (fichiers pilotes datés du 17/07/2026). Aucune avant.

Le rythme est de deux erreurs par jour — une le matin, une le soir :

Date Matin Soir
24/07 06:55 18:02
27/07 08:02 18:22
29/07 06:27 17:36
30/07 07:25 19:10
02/08 06:36 21:54

C'est-à-dire à chaque allumage et à chaque extinction — exactement le symptôme décrit par Julien.

Corrélation avec les 3 écrans bleus 0x50 :

Erreur VBoxNetLwf Écran bleu correspondant Écart
31/07/2026 06:27:21 BugCheck 0x50 à 06:27:34 13 s
31/07/2026 08:54:01 BugCheck 0x50 à 08:54:14 13 s
03/08/2026 07:43:26 BugCheck 0x50 à 07:43:37 11 s

Et le 28/07/2026 07:52:02, une erreur VBoxNetLwf coïncide à la seconde près avec une coupure sèche sans BSOD.

Verdict sur VBoxNetLwf : la corrélation temporelle est réelle, mais elle ne fait pas de lui la cause des écrans bleus. Les rapports WER placent le code fautif dans amdfendr.sys. L'explication cohérente est que les deux pilotes sont sollicités à la même seconde, lors de la même transition d'alimentation : VBoxNetLwf y journalise une erreur interne à chaque fois (20 fois), et amdfendr.sys y plante occasionnellement (3 fois).

VBoxNetLwf reste néanmoins un défaut logiciel réel à traiter : un filtre NDIS qui signale une erreur interne à chaque démarrage et à chaque extinction n'est pas un fonctionnement normal. Il a été désactivé (voir §10). Mais il faut être clair : ce n'est pas lui qui provoquait les écrans bleus.

Leçon de méthode : une corrélation temporelle à 12 secondes sur 3 événements, aussi frappante soit-elle, ne vaut pas une preuve. C'est la lecture du rapport WER — qui a nécessité une élévation de privilèges — qui a tranché. La constance du déplacement 0x3ae était bien la bonne piste ; c'est son attribution à VBoxNetLwf qui était fausse.

6.5 — Deux attributions antérieures invalidées

RustDesk — le fichier CLAUDE.md attribuait les écrans bleus 0x50 du 31/07/2026 aux pilotes RustDesk (écran virtuel usbmmidd_v2, imprimante virtuelle), désactivés le jour même. Cette explication ne tient pas : un troisième 0x50 s'est produit le 03/08 avec la même signature, alors que usbmmidd_v2 était désactivé depuis trois jours. Le dossier C:\Program Files\RustDesk\drivers — qui ne contenait déjà plus qu'un RustDeskPrinterDriver.disabled — a été renommé en drivers.disabled par sécurité.

VirtualBox — voir ci-dessus. Suspect n°1 de la première version de cette page, disculpé par les rapports WER.

Ces deux erreurs ont la même origine : trois logiciels installés dans la même fenêtre de temps (VirtualBox le 24/07, RustDesk le 31/07) ont capté l'attention, alors que le vrai coupable était un pilote présent depuis longtemps et sans rapport avec ces installations.


7. Ce que les logs ne permettent PAS d'accuser

Il faut être clair sur ce point : à ce stade, aucune donnée ne désigne un composant électronique défectueux.

Vérification Résultat Interprétation
WHEA-Logger (erreurs machine remontées par le firmware : CPU, mémoire, bus PCIe, cache) 0 événement sur 9 mois Aucune erreur matérielle corrigible ou fatale détectée par le processeur. C'est un signal négatif fort contre une défaillance CPU ou mémoire franche.
État de santé des 5 disques Tous Healthy / OK Aucune alerte
Erreurs disque / NTFS 2 Ntfs 50 + 3 volmgr 161 en 90 jours Les volmgr 161 sont des conséquences des crashes (échec d'écriture du fichier de vidage), pas des causes

Nuance importante sur WHEA : l'absence d'erreur WHEA ne disculpe pas le matériel pour la Population A. Une coupure d'alimentation brutale ou un gel total ne laisse par définition aucune trace, puisque le système n'a plus le temps d'écrire. WHEA ne couvre pas non plus les défaillances d'alimentation, de VRM ou de connectique.

SMART complet — relevé du 2026-08-03 via smartmontools 7.5

Windows n'exposait aucun compteur SMART sur ce chipset A320 (Get-StorageReliabilityCounter ne renvoie rien). smartctl a permis de lire directement les contrôleurs.

Disque Rôle Santé Heures Cycles Secteurs réalloués Erreurs CRC Temp. Usure
Patriot Burst 240 Go (SSD) Système (C:) PASSED 11 111 1 066 0 0 33 °C SSD_Life_Left = 88 % — 15 To écrits
Toshiba HDWD110 1 To (P300 CMR) Données (D:) PASSED 14 481 1 416 0 0 41 °C (max 49) —
Seagate/Samsung ST1000LM024 1 To Boîtier USB (E:) PASSED 60 187 5 800 0 0 39 °C (max 56) —
Seagate ST8000AS0002 8 To (SMR) Sauvegarde USB (F:) PASSED 19 823 2 166 0 0 46 °C (seuil 45 dépassé par le passé) —

Conclusion : aucun disque n'est défaillant. Zéro secteur réalloué, zéro secteur en attente, zéro erreur CRC, aucun journal d'erreurs SMART sur les quatre. Le SSD système conserve 88 % de sa durée de vie et n'a que 15 To d'écriture au compteur — il est hors de cause. L'hypothèse « SSD en fin de vie » est écartée.

Deux points annexes : le disque du boîtier USB affiche 60 187 heures, soit près de 7 ans d'allumage cumulé — sans le moindre défaut, mais il mérite une surveillance. Et le Seagate 8 To de sauvegarde a franchi son seuil de température de flux d'air (46 °C pour un seuil à 45 °C) : à surveiller, sans rapport avec les plantages.

⚠ Réglages du 2026-08-03 effacés par la réinstallation — à réappliquer

Constat du 2026-08-25 : la réinstallation de Windows du 08/08 a remis les valeurs par défaut. État actuel relevé au registre :

Réglage Voulu (03/08) État au 25/08 Effet
HiberbootEnabled (démarrage rapide) 0 1 — réactivé Amplificateur n°1 des 0x9F
MinidumpsCount 50 5 Moins d'historique de vidages
AlwaysKeepMemoryDump 1 absent MEMORY.DMP écrasé à chaque crash

Les deux derniers sont des réglages de diagnostic : sans eux, le prochain écran bleu laissera moins de traces exploitables. À réappliquer en session élevée.

En revanche, deux pilotes suspects ont bel et bien disparu et n'ont pas été réinstallés : VBoxNetLwf.sys (VirtualBox) et les pilotes RustDesk. Seul amdfendr.sys (07/02/2022) est revenu, avec le pilote AMD.

⚠ Le compteur qui change la perspective

Unsafe_Shutdown_Count du SSD système : 146 arrêts brutaux pour 1 066 mises sous tension — soit 13,7 % des extinctions qui se sont mal passées.

Or le journal d'événements ne recense que 45 arrêts anormaux depuis octobre 2025. Une centaine d'arrêts brutaux sont donc antérieurs à la réinstallation de Windows du 28/10/2025.

C'est une information importante : le problème n'est ni récent, ni né de la réinstallation. Il est installé de longue date, et la réinstallation de Windows ne l'a pas réglé — ce qui affaiblit d'autant les hypothèses purement logicielles pour la Population A, et renforce la piste matérielle.


8. Facteurs aggravants identifiés dans la configuration

Démarrage rapide — était activé, ✅ désactivé le 2026-08-03

Le démarrage rapide (Fast Startup, HiberbootEnabled = 1) était actif jusqu'au 03/08/2026. Avec ce réglage, « Arrêter » n'éteint pas réellement Windows : le noyau et les pilotes sont mis en hibernation dans un fichier, puis rechargés tels quels au démarrage suivant.

Conséquences sur ce cas :

  1. C'est la première cause connue des écrans bleus 0x9F — qui représentent 10 des 15 BSOD relevés ici.
  2. Cela explique qu'aucun crash ne soit précédé d'un arrêt propre dans les logs : les transitions concernées sont des hibernations/reprises, pas de vrais arrêts.
  3. Un état de pilote corrompu était réinjecté à chaque démarrage au lieu d'être réinitialisé — ce qui transforme un bug ponctuel en panne récurrente.

Depuis la désactivation, chaque arrêt réinitialise complètement l'état des pilotes. Effet de bord attendu : le démarrage est un peu plus lent — c'est normal et souhaitable ici.

Mémoire : une seule barrette, sous-cadencée

Un seul module de 16 Go occupant DIMM 0 (canal B) — donc pas de double canal, et la barrette tourne à 2400 MHz au lieu de 2666. Ce n'est pas une cause de panne en soi, mais c'est une configuration à connaître. Point positif pour le diagnostic : avec une seule barrette, un test mémoire est simple à interpréter et il n'y a pas de problème d'appairage possible.

BIOS de 2020

Version 1.40 datée du 08/12/2020, jamais mise à jour depuis. MSI a publié des révisions ultérieures pour l'A320M-A PRO, comportant des correctifs AGESA sur la gestion de l'alimentation et la compatibilité mémoire — directement pertinents pour des erreurs 0x9F et 0xA0.

Pilote graphique de 2022 — le facteur central

Pilote Radeon 30.0.14023.3004 du 18/01/2022 sur une RX 6500 XT, alors que la carte est toujours pleinement prise en charge par les Adrenalin actuels. C'est ce pilote qui embarque le amdfendr.sys fautif (binaire du 4 juin 2021). Plus qu'un facteur aggravant : c'est la cause identifiée des 0x50, et un suspect sérieux pour les 0x9F.

Espace disque système

71 Go libres sur 223 Go (C:) — suffisant, mais à surveiller : MEMORY.DMP occupe 2,4 Go, et sa copie de sauvegarde 2,31 Go de plus sur D:. Avec AlwaysKeepMemoryDump = 1 désormais actif, le vidage complet ne sera plus supprimé automatiquement par le nettoyage de disque — c'est voulu, mais cela demande de surveiller l'espace libre.


9. Diagnostic de synthèse

Il y a très probablement deux problèmes distincts, pas un seul.

Révision du 2026-08-25 — le test à variable unique a eu lieu, et il est négatif.

La réinstallation complète de Windows du 2026-08-08 constitue l'expérience que cette page appelait de ses vœux : logiciel intégralement remis à zéro, matériel inchangé. Résultat sur 17 jours de système neuf — 6 arrêts anormaux journalisés, dont 2 d'origine électrique externe établie : une coupure de courant Enedis le 24/08 à 06:24, et un débranchement volontaire face aux orages le 24/08 (journalisé au démarrage du 25/08 à 08:22).

Restent 4 épisodes inexpliqués : 2 coupures sèches sans code (12/08 05:49, 17/08 19:41) et 2 écrans bleus 0x9F (paramètre 0x3, 12/08 à 10:30 et 15:27).

Aucun écran bleu depuis le 12/08, soit 13 jours au 2026-08-25 — sans qu'aucune action n'ait été engagée entre-temps. Cohérent avec le régime par vagues décrit au § 5 : l'accalmie ne vaut pas correction, et ne dispense pas de la priorité 1.

Nuance importante sur les écrans bleus. Dire que « la réinstallation n'a rien réglé » serait faux pour cette population : le vécu est celui d'une amélioration franche, et les chiffres le corroborent — 2 BSOD dans les 4 jours suivant l'installation, puis 13 jours sans aucun. Trois raisons de rester prudent avant d'en conclure à une guérison :

Ce que la réinstallation établit en revanche sans ambiguïté :

La condition posée au § 10 — « ne pas engager d'intervention physique avant 2-3 semaines de relevés » — est remplie, et par la voie la plus radicale qui soit.

Problème 1 — logiciel, identifié formellement. amdfendr.sys (AMD Crash Defender, version 21.30.0.9 de février 2022) provoque les écrans bleus 0x50. Les rapports WER de Windows le désignent nommément, deux fois indépendamment (AV_amdfendr!unknown_function), et la signature d'adresse constante (0x3ae) confirme un défaut de code reproductible. Il est embarqué dans un pilote Radeon de janvier 2022, jamais mis à jour depuis. Le démarrage rapide amplifiait le phénomène. Ce même pilote est un candidat sérieux pour la vague de 0x9F de l'hiver. C'est traitable immédiatement et sans risque : il suffit d'installer un pilote AMD à jour.

Problème 2 — cause encore indéterminée, présent en continu depuis au moins octobre 2025. 30 coupures sèches réparties sur 9 mois, sans aucune trace exploitable. La vague de 10 × 0x9F de l'hiver 2025-2026 relève probablement aussi d'un pilote (autre que VirtualBox, installé bien plus tard), mais les coupures sèches restent inexpliquées. Les hypothèses ouvertes, par ordre de vraisemblance sur une machine de cet âge :

Le SMART apporte ici un élément décisif : avec 146 arrêts brutaux pour 1 066 démarrages, dont une centaine antérieurs à la réinstallation de Windows, le phénomène est ancien et a survécu à une remise à zéro complète du système. Hypothèses ouvertes, par ordre de vraisemblance :

  1. Qualité du secteur électrique — hypothèse ajoutée le 2026-08-25, désormais en tête. Micro-coupures et creux de tension venant du réseau, et non du bloc d'alimentation. Elle produit exactement la même signature que les hypothèses internes — coupure nette, aucune trace, insensible aux réinstallations de Windows — mais elle dispose de quelque chose qu'aucune autre n'a : des preuves directes.

Sur les 17 jours de suivi, 2 des 6 arrêts sont d'origine électrique externe établie : une coupure Enedis le 24/08 à 06:24, et un débranchement volontaire face aux orages. Autrement dit, le réseau électrique de ce logement a produit au moins un incident avéré en deux semaines et demie. Une installation qui subit des coupures franches subit aussi, statistiquement, des creux plus brefs — trop courts pour être remarqués, largement suffisants pour faire tomber un PC dont l'alimentation n'a plus de marge.

Cela réconcilie aussi les données anciennes : les 146 arrêts brutaux au compteur du SSD et les 30 coupures sèches sur 9 mois n'ont jamais eu d'explication interne convaincante. Un secteur instable les explique toutes, sans supposer de composant défectueux.

Effet de second ordre à ne pas négliger : chaque coupure franche est elle-même un stress pour le matériel — condensateurs, contrôleur du SSD, système de fichiers. Un secteur instable ne se contente pas de provoquer des arrêts, il use la machine et peut fabriquer, à terme, le défaut d'alimentation qu'on cherche par ailleurs.

Action : un onduleur. Il tranche l'hypothèse et la corrige d'un même geste — si les coupures sèches cessent, la cause était le secteur ; si elles persistent, elle est interne. Aucun démontage, aucun risque, matériel utile quoi qu'il arrive, et protection immédiate lors du prochain orage. C'est le test le moins invasif de la liste et il doit passer avant l'intervention physique du § 10 priorité 3.

  1. Alimentation vieillissante — condensateurs fatigués, tension instable sous charge. Hypothèse interne n°1 : composant le plus âgé et le plus sollicité, cohérente avec un problème qui traverse les réinstallations. À noter qu'elle n'est pas exclusive de la précédente — une alimentation fatiguée tient moins bien un creux de tension qu'une neuve, les deux causes se renforcent.
  2. Thermique — pâte thermique sèche après 6-7 ans, ventilateur de CPU encrassé, coupure de protection.
  3. Connectique / oxydation — barrette mémoire, connecteurs d'alimentation, câbles SATA.
  4. Mémoire — moins probable (aucune erreur WHEA), mais non écartée tant qu'un test complet n'a pas été passé.
  5. SSD système — écarté : SMART impeccable, 88 % de durée de vie restante, aucune erreur.

10. Actions recommandées, par ordre de priorité

✅ Déjà appliqué le 2026-08-03 à 08h29

# Action Résultat
1 Filtre VirtualBox NDIS6 Bridged Networking désactivé sur les cartes Ethernet et Ethernet 2 ✅ Enabled = False sur les deux
2 Démarrage rapide désactivé (HiberbootEnabled : 1 → 0) ✅
3 Mini-vidages portés à 50 (MinidumpsCount : 5 → 50) et AlwaysKeepMemoryDump = 1 ✅ Le vidage complet ne sera plus supprimé par le nettoyage de disque
4 C:\Program Files\RustDesk\drivers renommé en drivers.disabled ✅ (ne contenait déjà plus qu'un RustDeskPrinterDriver.disabled)
5 MEMORY.DMP du crash du 03/08 sauvegardé → D:\MEMORY_20260803_0743_bugcheck50.DMP (2,31 Go) ✅ La preuve est préservée du prochain écrasement

Priorité 1 — l'action décisive

# Action Objectif
6 Réinstaller proprement le pilote AMD Radeon. Télécharger l'Adrenalin actuel pour RX 6500 XT sur le site AMD, désinstaller l'ancien avec DDU (Display Driver Uninstaller) en mode sans échec, puis installer le nouveau. Choisir une installation minimale/personnalisée, sans les composants optionnels. Traite la cause identifiée. Remplace amdfendr.sys 21.30.0.9 (2022) par une version où AMD Crash Defender a été remanié. Susceptible de régler à la fois les 0x50 et les 0x9F.

Pourquoi DDU et pas une simple mise à jour : l'installateur AMD ne remplace pas systématiquement les pilotes de la génération 21.30 et peut laisser amdfendr.sys en place. DDU garantit une table rase.

Priorité 2 — confirmer et combler les angles morts

# Action Objectif
7 Installer WinDbg et analyser le vidage ✅ Fait le 03/08 à 09h00 — voir §6.1. Verdict confirmé et mécanisme établi
8 Installer smartmontools et relever le SMART ✅ Fait le 03/08 à 09h00 — voir §7. Aucun disque défaillant
9 Test mémoire complet : MemTest86 sur clé USB, au moins 4 passes complètes, de préférence une nuit entière. L'outil intégré à Windows est insuffisant. Écarte ou confirme la RAM de façon définitive. Simple ici : une seule barrette.
10 Mettre à jour le BIOS MSI A320M-A PRO (actuel : 1.40 de 2020). Correctifs AGESA sur la gestion d'alimentation, directement liés aux 0x9F/0xA0

Priorité 3 — intervention physique, pour la Population A

À n'engager qu'après avoir traité le pilote AMD et laissé passer deux ou trois semaines de relevés : si les coupures sèches s'arrêtent aussi, cette section devient inutile.

# Action Objectif
11 Relever les références de l'alimentation (marque, modèle, wattage, année). Information manquante et déterminante
12 Dépoussiérer : ventilateur et radiateur CPU, ventilateur de la carte graphique, ventilateurs de boîtier, filtres, bloc d'alimentation. Cause thermique
13 Réextraire et réinsérer la barrette mémoire et les connecteurs d'alimentation ATX 24 broches et EPS 8 broches. Nettoyer les contacts. Cause connectique / oxydation
14 Refaire la pâte thermique du processeur si elle n'a pas été changée depuis l'assemblage. Cause thermique
15 Surveiller les températures et les tensions en fonctionnement (HWiNFO64), en particulier les rails 12 V, 5 V et 3,3 V sous charge. Détecte une alimentation qui décroche
16 Si les coupures sèches persistent après tout ce qui précède : tester avec une autre alimentation. Test décisif de l'hypothèse n°1. À noter : la RX 6500 XT est peu gourmande (~107 W), mais une alimentation fatiguée décroche sur les pics de la carte graphique

11. Limites de cette analyse

À mentionner pour que les conclusions soient lues à leur juste valeur :


12. Journal des relevés

Un relevé toutes les 1 à 2 semaines suffit à mesurer l'effet des actions engagées. Le script ajoute automatiquement une ligne à ce tableau :

powershell -ExecutionPolicy Bypass -File "D:\Syncthing\Jux_univers\Jux-scripts\PC-Health\collect_bsod.ps1"

À lancer en administrateur pour que les compteurs SMART soient lus ; sinon la ligne est écrite sans eux. L'option -DryRun affiche le résultat sans rien écrire dans BookStack. Le script relève les arrêts anormaux, les codes bugcheck, les erreurs VBoxNetLwf, les erreurs WHEA, la version du pilote AMD (pour dater sa réinstallation), et signale tant que amdfendr 21.30 est en place.

La colonne « Actions faites depuis » est à compléter à la main.

Date du relevé Arrêts anormaux depuis le dernier relevé dont BSOD Codes rencontrés Erreurs VBoxNetLwf WHEA Actions faites depuis Observations
2026-08-03 45 (cumul 9 mois) 15 10×9F, 3×50, 1×3B, 1×A0 20 0 — (état initial) Analyse initiale. Deux populations distinctes. Cause des 0x50 établie par analyse du vidage : amdfendr.sys déborde un tampon sur RtlCompressBuffer. Actions 1 à 5 + 7 + 8 faites. SMART : 4 disques sains, mais 146 arrêts brutaux au compteur du SSD → problème antérieur à la réinstallation.
2026-08-25 4 inexpliqués / 6 journalisés (17 jours, système neuf) 2 2×9F (param. 0x3) n/c n/c Windows réinstallé le 2026-08-08 — profil eliob perdu, profil julie créé Relevé par Get-WinEvent (ID 41/6008/1001), session non élevée donc SMART non lu. Épisodes : 12/08 05:49, 12/08 10:30 (9F), 12/08 15:27 (9F), 17/08 19:41, puis deux épisodes d'origine électrique externe confirmée — 24/08 06:24 coupure de courant Enedis, et 25/08 08:22 qui journalise le débranchement volontaire du 24/08 (orages ; l'arrêt sale est écrit au démarrage suivant). Aucun BSOD depuis le 12/08. Système neuf sans effet sur les deux populations. Pilote AMD revenu en 30.0.14023.3004 (18/01/2022) par Windows Update, amdfendr.sys du 07/02/2022 réinstallé. Test à variable unique négatif → priorité déplacée vers le matériel (§ 9).

⚠ Attention au compteur SMART depuis le 2026-08-25 : Unsafe_Shutdown_Count est un compteur du SSD, pas de Windows — il n'a donc pas été remis à zéro par la réinstallation et reste directement comparable au relevé du 2026-08-03. C'est aujourd'hui le meilleur indicateur disponible pour la Population A : l'écart attendu depuis le 03/08 est d'environ 6. À relever en session élevée au prochain passage.

Référence — état au 2026-08-03 : SSD système 11 111 h / 1 066 cycles / 146 arrêts brutaux / 88 % de vie restante. Comparer Unsafe_Shutdown_Count d'un relevé à l'autre donne un compteur de coupures indépendant du journal Windows :

& 'C:\Program Files\smartmontools\bin\smartctl.exe' -A /dev/pd0

13. Indicateur de succès

Le suivi doit permettre de trancher entre les deux problèmes :

Point de vigilance sur la carte graphique : c'est le composant qui concentre désormais le plus de signaux. Si des artefacts visuels, des écrans noirs momentanés ou des gels pendant un jeu ou une vidéo apparaissent, il faut le noter dans le journal — ce serait l'indice d'un défaut matériel de la RX 6500 XT.

Deuxième indicateur, indépendant du journal Windows : l'écart de Unsafe_Shutdown_Count entre deux relevés. Il compte les coupures réelles même quand Windows n'a rien pu journaliser — donc il capte la Population A, celle qui est invisible autrement. C'est le chiffre à surveiller pour trancher la question matérielle.


14. Fichiers et emplacements

Quoi Où
Script de relevé D:\Syncthing\Jux_univers\Jux-scripts\PC-Health\collect_bsod.ps1 (Syncthing, disponible sur toutes les machines)
Vidage du crash du 03/08, sauvegardé D:\MEMORY_20260803_0743_bugcheck50.DMP (2,31 Go)
Mini-vidage exploitable du 31/07 C:\Windows\Minidump\073126-9718-01.dmp (1,1 Mo) — accès administrateur
Vidages suivants C:\Windows\Minidump\ — 50 conservés désormais (au lieu de 5)
smartctl C:\Program Files\smartmontools\bin\smartctl.exe
Débogueur console cdbX64.exe (dans le PATH via %LOCALAPPDATA%\Microsoft\WindowsApps)
Contexte projet CLAUDE.md du dépôt Claude-pcelio+jux, section « Stabilité du PC Windows (poste julie, ex-eliob) »

Page tenue à jour par Claude Code. Analyse initiale et investigation complète le 2026-08-03. Révision du 2026-08-25 : réinstallation de Windows sans effet, priorité déplacée vers le matériel.

Relevé du 2026-09-03 — pilote AMD mis à jour

L'action en attente depuis le 2026-08-03 est exécutée.

Avant Après
Pilote graphique 30.0.14023.3004 du 18/01/2022 32.0.21045.5002 du 17/08/2026
amdfendr.sys actif 21.30.0.9 (07/02/2022) 25.10.0.7 (25/02/2026)
amdpsp.sys 5.24.0.0 5.46.0.0

Méthode : AMD Software Adrenalin Edition 26.8.1 WHQL, paquet complet de 942 Mo depuis amd.com, Factory Reset coché, installation Driver Only (la suite Adrenalin, l'enregistrement vidéo et l'AI Bundle ont été écartés — ce dernier est un mode d'échec connu de l'installeur). Point de restauration 11 créé au préalable, non utilisé. Aucun incident pendant l'opération.

La cause établie des écrans bleus 0x50 est donc corrigée : amdfendr.sys (AMD Crash Defender) passe de la version de février 2022 à celle de février 2026.

⚠ Ne pas se fier au fichier dans System32\drivers

C:\Windows\System32\drivers\amdfendr.sys affiche toujours 21.30.0.9 du 07/02/2022 après la mise à jour. C'est un résidu inutilisé. Le pilote réellement chargé est celui que désigne le service :

(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\amdfendr').ImagePath
# -> ...\DriverStore\FileRepository\amdfendr.inf_amd64_bea53a1d416fbcfa\amdfendr.sys  (v25.10.0.7)

Le script collect_bsod.ps1 doit être corrigé sur ce point — fait le 2026-09-03 : s'il lit le fichier de System32\drivers, il continuera de signaler la version 21.30 à tort.

Ce que cette mise à jour ne traite pas

Les 30 coupures sèches (BugcheckCode = 0, aucune trace exploitable) restent hors périmètre. Elles sont réparties en continu sur toute la période, ont survécu à la réinstallation complète de Windows d'octobre 2025, et le compteur SMART du SSD en recense une centaine antérieures à celle-ci. Hypothèse en tête : qualité du secteur électrique, qu'un onduleur trancherait sans démontage.

Si des coupures sèches persistent dans les semaines qui viennent, ce n'est pas un échec de cette intervention — c'est au contraire l'élément qui isolerait définitivement les deux populations.

Suite

Relancer Jux-scripts\PC-Health\collect_bsod.ps1 (en élevé) dans deux à trois semaines. Attendu : plus aucun 0x50, et une réponse sur la persistance ou non des coupures sèches.

Détail complet de l'intervention : page 295. Effets sur l'émulateur Android : page 282.

Correction de collect_bsod.ps1 (2026-09-03)

Deux défauts corrigés, sauvegarde collect_bsod.ps1.bak-260903 :

1. Il lisait le mauvais fichier. C:\Windows\System32\drivers\amdfendr.sys reste périmé après une mise à jour de pilote. Le script lit désormais l'ImagePath du service, résout \SystemRoot\ et rapporte la version réellement chargée. Il affiche maintenant la version quelle qu'elle soit, au lieu de ne signaler que la 21.30.

2. Get-WinEvent faisait planter le script. Le fournisseur VBoxNetLwf n'existe plus depuis la réinstallation de Windows, et Get-WinEvent -FilterHashtable lève alors une erreur que -ErrorAction SilentlyContinue ne supprime pas. Les deux appels passent par une fonction Compter-Evenements avec try/catch et -ErrorAction Stop — le seul moyen fiable de rendre l'échec non fatal.

Premier relévé après correction

Periode : 2026-08-25 -> 2026-09-03
Arrets anormaux : 6 | BSOD : 0 | VBoxNetLwf : 0 | WHEA : 0
pilote AMD 32.0.21045.5002 ; amdfendr 25.10.0.7
demarrage rapide TOUJOURS actif

⚠ Ce relévé ne mesure PAS encore l'effet du nouveau pilote : la fenêtre couvre le 25/08 au 03/09, alors que la mise à jour date du 03/09 au matin. C'est une référence de départ, pas un résultat.

Deux points à relever tout de même :

04_Claude et les dépannages informatiques

260813 - solutions de page Internet pour transfert des epub sur la liseuse Kobo Aura 2

Transfert d'epub sur la Kobo Aura Edition 2 sans câble USB

Date : 2026-08-13 — Statut : en production, validé sur l'appareil Matériel : Kobo Aura Edition 2 (6 pouces, micro-USB) URL de service : juxjux.ovh/56ifciz — répond en HTTP et en HTTPS


1. Le problème

Le port USB de la liseuse ne permet plus aucun transfert. Le PC ne détecte rien du tout — pas même un périphérique en erreur.

Diagnostic mené sur le poste Windows julie :

Vérification Résultat
Périphérique VID_2237 (Kobo Inc.) présent absent
Périphérique inconnu ou en erreur (Status ≠ OK) aucun
Historique registre Enum\USB — trace d'un VID_2237 aucune
Historique USBSTOR un seul boîtier ASMT, jamais de Kobo
Disques vus Patriot (C:), Toshiba (D:), ASMT (E:), Seagate (F:) — rien de plus

Conclusion : Windows ne reçoit aucun handshake USB. Le problème est en amont du système — ce n'est ni un pilote, ni une lettre de lecteur, ni une base de registre à nettoyer. Aucune piste logicielle n'est exploitable.

Causes matérielles possibles, par probabilité décroissante :

  1. Câble charge seule — cause n°1 et de loin. Beaucoup de câbles micro-USB ne câblent que 2 fils sur 4
  2. Port de la liseuse encrassé — la micro-USB accumule peluches et poussière de poche
  3. Batterie profondément déchargée — une Kobo à plat ne s'énumère pas, même branchée. Il faut la laisser une heure sur un chargeur secteur avant de retenter
  4. Port physiquement HS

Le contournement décrit ci-dessous rend la liseuse pleinement utilisable, mais ne remplace pas un test câble. Voir § 7.

Commandes de diagnostic réutilisables (PowerShell) :

Get-PnpDevice -PresentOnly | Where-Object { $_.InstanceId -match 'USB' } |
    Select-Object Status,Class,FriendlyName,InstanceId | Sort-Object Class

Get-ChildItem 'HKLM:\SYSTEM\CurrentControlSet\Enum\USB' |
    Where-Object { $_.PSChildName -match 'VID_2237' }

2. Solutions écartées, et pourquoi

Ce tableau évite de refaire le tour des mêmes impasses.

Piste Verdict Raison
GUI Syncthing impossible Ne permet aucun téléchargement de fichier — Syncthing synchronise, il ne sert pas de fichiers. Et c'est une application JS moderne, illisible sur ce navigateur
FileBrowser (files.juxjux.ovh) impossible SPA + login JWT — injouable sur le WebKit de la liseuse
OPDS (Komga, Kavita, Ubooquity) impossible Le navigateur stock de la Kobo ne lit pas l'OPDS. Ne deviendrait pertinent qu'avec KOReader installé
Kobo Sync natif de Calibre-web bloqué C'est la bonne solution sur le papier : synchronisation native par Wi-Fi. Mais elle impose de modifier api_endpoint dans .kobo/Kobo/Kobo eReader.conf sur la liseuse — donc exige l'USB, précisément ce qui est en panne. À reconsidérer si le port refonctionne
Yourls pour raccourcir l'URL inutile juxjux.ovh/56ifciz est déjà court à taper au doigt, et éviter la redirection supprime un point de fragilité
Page HTML nue en autoindex retenu Pas de JavaScript, pas de session, pas de cookie. Le navigateur Kobo télécharge le fichier et l'ajoute à la bibliothèque

3. La solution retenue

Un location nginx en autoindex greffé sur le vhost juxjux.ovh existant, servant un dossier de l'arbre Syncthing.

Dépôt du fichier            Syncthing              nginx autoindex         Navigateur bêta
D:\Syncthing\Kobo\    →   (n'importe quelle   →   juxjux.ovh/56ifciz  →   de la liseuse
                           machine du maillage)     (port 80)                → bibliothèque

Aucun DNS ni certificat n'a été créé — la location est greffée sur un vhost déjà en place.

Élément Valeur
URL liseuse juxjux.ovh/56ifciz (HTTP, pas HTTPS)
Dossier VPS /home/debian/Documents/Kobo/
Équivalent Windows D:\Syncthing\Kobo\
Propriétaire debian:debian (Syncthing tourne sous cet utilisateur)
Vhost modifié /etc/nginx/sites-available/juxjux.ovh
Sauvegarde /etc/nginx/sites-available/juxjux.ovh.bak-260813

Mode d'emploi

Déposer un livre : le glisser dans D:\Syncthing\Kobo\ depuis n'importe quelle machine du maillage. Syncthing le pousse au VPS, il apparaît dans la page — aucune autre manipulation.

Le récupérer sur la liseuse : Menu → Plus → Navigateur bêta → taper juxjux.ovh/56ifciz → toucher le lien de l'epub. Téléchargement, puis ajout automatique à la bibliothèque.


4. Les quatre pièges, et leur correctif

Ce sont les points à ne pas défaire par inadvertance.

4.1 Le chemin doit exister dans les deux blocs — la liseuse force HTTPS

C'est le point qui a demandé une correction après coup, et l'hypothèse de départ était fausse.

Hypothèse initiale (erronée) : le navigateur de l'Aura Edition 2 étant un WebKit ancien, on a supposé qu'il échouerait sur la config TLS actuelle — soit par une version TLS trop vieille (options-ssl-nginx.conf impose TLS 1.2+), soit par un magasin de racines ignorant la chaîne Let's Encrypt (ISRG Root X2 → ISRG Root X1). La location n'a donc d'abord été posée que dans le bloc listen 80, en HTTP volontaire.

Ce que l'appareil a montré : le navigateur bêta force HTTPS. Avec la location absente du bloc 443, il tombait sur un 404. Et le magasin de racines de la liseuse connaît parfaitement ISRG Root X1 — le TLS n'a jamais été le problème.

Correctif appliqué le 2026-08-13 à 14:49 : la location /56ifciz/ a été dupliquée à l'identique dans le bloc listen 443 ssl, le bloc listen 80 étant conservé pour la robustesse. Les deux répondent aujourd'hui 200.

Aucun assouplissement TLS n'a été nécessaire ni appliqué — pas de TLS 1.0/1.1 réactivé, pas de ciphers CBC hérités. Ne pas en ajouter « au cas où » : ce serait dégrader la sécurité de tout le domaine pour un problème qui n'existe pas.

Sauvegarde avant cet ajout : /etc/nginx/sites-available/juxjux.ovh.bak-260813-https

Contrepartie : la liseuse passant par 443, le chemin et les fichiers ne circulent plus forcément en clair. Mais le bloc HTTP reste ouvert, et surtout le seul rempart demeure l'obscurité de l'URL (§ 7). Ne rien déposer de sensible dans ce dossier.

4.2 La redirection 80 → 443 devait être restructurée

Le vhost portait la redirection sous cette forme, posée par Certbot :

if ($host = juxjux.ovh) { return 301 https://$host$request_uri; }

Écrit au niveau serveur, ce if s'évalue en phase rewrite — c'est-à-dire avant le choix de la location. Il est donc impossible d'y soustraire un chemin : /56ifciz/ partait en redirection HTTPS comme tout le reste.

Correctif : remplacer le if par un location / explicite. Une location plus spécifique (/56ifciz/) l'emporte alors naturellement.

location / {
    return 301 https://$host$request_uri;
}

4.3 nginx ne connaît pas le type MIME epub

/etc/nginx/mime.types ne contient ni epub, ni mobi, ni azw. Sans déclaration, le fichier est servi en text/plain et la liseuse l'affiche au lieu de le télécharger.

Piège dans le piège : un bloc types { } placé dans une location remplace intégralement la table MIME pour cette location — il ne s'y ajoute pas. Tout type utile doit donc y figurer, d'où le default_type application/octet-stream en filet de sécurité.

4.4 Permissions — Syncthing dépose parfois en 640

www-data doit pouvoir lire les fichiers déposés. Or Syncthing crée parfois des fichiers en 640, ce qui produirait un 403 silencieux.

Correctif — une ACL par défaut sur le dossier, qui force la lisibilité des fichiers à venir :

setfacl -m  o::rx /home/debian/Documents/Kobo
setfacl -d -m o::r  /home/debian/Documents/Kobo
setfacl -d -m u::rw /home/debian/Documents/Kobo
setfacl -d -m g::r  /home/debian/Documents/Kobo

Attention : si le dossier est créé avec sudo, il appartient à root et Syncthing ne peut plus y écrire. Vérifier chown -R debian:debian après création.


5. Configuration nginx appliquée

Fichier /etc/nginx/sites-available/juxjux.ovh. Le bloc location /56ifciz/ est identique dans les deux server — c'est délibéré (§ 4.1) : la liseuse force HTTPS, le port 80 est conservé pour la robustesse.

server {
    server_name juxjux.ovh www.juxjux.ovh;

    root /var/www/juxjux.ovh/html;
    index index.html index.htm;

    # --- Acces liseuse Kobo Aura Edition 2 (ajout 2026-08-13, volet HTTPS)
    # Duplique le location du bloc :80. La liseuse impose HTTPS -> ce chemin
    # doit exister aussi en 443. Ne rien mettre de sensible dans Documents/Kobo.
    location /56ifciz/ {
        alias /home/debian/Documents/Kobo/;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        charset utf-8;
        add_header X-Robots-Tag "noindex, nofollow" always;

        types {
            application/epub+zip            epub;
            application/pdf                 pdf;
            application/x-mobipocket-ebook  mobi;
            application/vnd.amazon.ebook    azw3;
            application/vnd.comicbook+zip   cbz;
            text/plain                      txt;
        }
        default_type application/octet-stream;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate     /etc/letsencrypt/live/juxjux.ovh/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/juxjux.ovh/privkey.pem;   # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;   # managed by Certbot
}

server {
    listen 80;
    server_name juxjux.ovh www.juxjux.ovh;

    # --- Acces liseuse Kobo Aura Edition 2 (ajout 2026-08-13)
    location /56ifciz/ {
        # ... bloc strictement identique a celui du server 443 ...
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

En cas de modification, penser à reporter le changement dans les deux blocs. Une divergence entre les deux produirait un comportement dépendant du protocole, très déroutant à diagnostiquer depuis la liseuse.


6. Vérifications de bon fonctionnement

Depuis le VPS et depuis l'extérieur :

# Page d'index dans les deux protocoles — les deux doivent repondre 200
for u in http https; do
  curl -s -o /dev/null -w "$u : HTTP %{http_code}  type=%{content_type}\n" \
       $u://juxjux.ovh/56ifciz/
done

# Type MIME du fichier — doit repondre application/epub+zip
curl -s -o /dev/null -D - "https://juxjux.ovh/56ifciz/<fichier>.epub" | grep -iE 'HTTP/|content-type'

# La racine doit toujours rediriger en HTTPS
curl -s -o /dev/null -w 'HTTP %{http_code} -> %{redirect_url}\n' http://juxjux.ovh/

Résultats attendus, relevés le 2026-08-23 :

Test Attendu Obtenu
Index HTTP 200 / text/html; charset=utf-8 conforme
Index HTTPS 200 / text/html; charset=utf-8 conforme
Epub 200 / application/epub+zip conforme
Racine / en HTTP 301 vers https://juxjux.ovh/ conforme
Lecture par www-data autorisée conforme

Un 404 sur un seul des deux protocoles signifie que la location a disparu du bloc correspondant — c'est le symptôme exact de la panne corrigée le 13 août (§ 4.1).


7. Limites et suites

Sécurité

La seule protection est l'obscurité du chemin. Il n'y a aucune authentification — le navigateur Kobo gère mal les invites Basic Auth, ce qui l'excluait. Un X-Robots-Tag: noindex, nofollow évite l'indexation par les moteurs.

Le passage en HTTPS (§ 4.1) chiffre le transport, mais ne change rien à ce point : quiconque connaît l'URL accède à tout le dossier, et le bloc HTTP reste ouvert.

Conséquence pratique : ce dossier est à considérer comme public. Y déposer uniquement des livres, jamais un document personnel.

Nommage des fichiers

Éviter accents et espaces. L'autoindex les encode correctement (%20), mais le navigateur de la liseuse est capricieux sur les URL encodées.

À faire — tester le câble USB

Le contournement fonctionne, mais la panne USB reste non élucidée. Dans l'ordre :

  1. Tester un autre câble dont on sait qu'il transporte des données (celui d'un disque externe ou d'un téléphone déjà utilisé en transfert)
  2. Inspecter et nettoyer le port de la liseuse à la lampe, appareil éteint, avec un cure-dent en bois — jamais en force
  3. Laisser une heure sur chargeur secteur (pas le PC) avant de retenter
  4. Reset matériel : bouton d'alimentation maintenu 30 secondes
  5. Croiser les variables : ce câble sur un autre appareil, cette liseuse sur un autre PC

Si l'USB revient, basculer sur le Kobo Sync de Calibre-web — synchronisation native, bidirectionnelle, avec suivi de la position de lecture. Nettement supérieur à cette page. Il ne faut l'USB qu'une seule fois, pour écrire api_endpoint dans .kobo/Kobo/Kobo eReader.conf.


Voir aussi

04_Claude et les dépannages informatiques

260823-Le réglage du pare-feu Portmaster

Portmaster — la découverte réseau et le NAS maison

Poste julie (DESKTOP-B7J2KGP), Windows 10. Installation de Safing Portmaster 2.2.1 le 22/08/2026 à 10:58, réglage le 23/08/2026.

Portmaster est un pare-feu applicatif qui s'insère au niveau WFP via son pilote portmaster-kext.sys. Il double le pare-feu Windows et c'est lui qui tranche : inutile d'aller chercher du côté de Defender.

Élément Valeur
Version 2.2.1 (éditeur safing)
Service PortmasterCore, démarrage automatique
Binaires C:\Program Files\Portmaster
Données et journaux C:\ProgramData\Portmaster
API locale http://127.0.0.1:817

1. Le symptôme, et ce qui n'était pas en cause

Plus aucune découverte réseau sur le poste : le NAS Synology maison (192.168.1.17, \\NASMAISON) n'apparaissait plus dans le volet Réseau de l'Explorateur.

Le premier réflexe — soupçonner le réseau ou le NAS — était faux. Tout répondait :

Contrôle Résultat
Poste 192.168.1.26/24, passerelle et DNS 192.168.1.1
Ping 192.168.1.17 répond
MAC du NAS 00-11-32-9C-8E-C9 — OUI Synology
Ports TCP 445, 139, 22, 80 ouverts (5000/5001 fermés)
Résolution du nom NASMAISON → NASMAISON.local = 192.168.1.17, par mDNS
Lecteur A: → \\NASMAISON\foxy monté et lisible, 55 entrées

Leçon : l'accès n'a jamais été rompu, seule la découverte l'était. Distinguer les deux dès le départ fait gagner beaucoup de temps.

Détail annexe, non symptomatique : \\192.168.1.17\foxy échoue alors que \\NASMAISON\foxy fonctionne. L'identifiant Windows est enregistré sous la cible NASMAISON (utilisateur juxjux), pas sous l'adresse IP — comportement normal de cmdkey.


2. Le diagnostic

La preuve est dans le journal de Portmaster, C:\ProgramData\Portmaster\logs\2026-08-22_10-57-46.log :

2026-08-23 07:12:50  filter: connection AUTORITE NT\SERVICE LOCAL:
  C:\Windows\System32\svchost.exe:12184 <- 192.168.1.17
  dropped: inbound connections blocked

svchost.exe PID 12184 héberge le service SSDPSRV (Découverte SSDP) — identifié par Get-CimInstance Win32_Service -Filter "ProcessId=12184".

Cadence des rejets : 05:56, 06:11, 06:26, 06:42, 06:57, 07:12 — toutes les ~15 minutes, soit exactement le rythme des annonces SSDP périodiques du NAS.

Répartition des 1 802 blocages du même motif :

Source Occurrences Destinataire
92.184.113.225 441 syncthing.exe
192.168.1.26 (le poste lui-même) 421 —
192.168.1.1 (Livebox) 330 —
192.168.1.17 (NAS) 249 SSDPSRV
192.168.1.19 153 —
IPv6 globales 2a01:cb1c:… ~80 syncthing.exe, SSDPSRV

À noter : le trafic sortant passait bien (287 requêtes SSDP acceptées vers 239.255.255.250:1900). Le poste interrogeait, mais les annonces du NAS, qui arrivent en entrant non sollicité, étaient jetées.


3. La cause

Le réglage filter/blockInbound — « Force Block Incoming Connections » — activé par défaut à l'installation.

Sa propre description est sans ambiguïté : « Is stronger than Rules ». Aucune règle entrante ne peut le contourner, ce qui explique qu'aucun réglage fin ne suffisait tant qu'il restait coché.

État des réglages liés au moment du diagnostic :

Clé Valeur Rôle
filter/blockInbound True (défaut) la cause
filter/defaultAction permit (défaut) action si aucune règle ne correspond
filter/serviceEndpoints [] Incoming Rules, vides
filter/blockLAN False (défaut) non impliqué

4. La configuration retenue

Incoming Rules, dans cet ordre impératif :

Ordre Menu Champ
1 Allow Localhost
2 Allow LAN
3 Block *

puis décocher Force Block Incoming Connections.

Localhost, LAN et Internet sont des mots-clés de portée reconnus par Portmaster, au même titre qu'une adresse ou un CIDR. Les utiliser vaut mieux que d'écrire 192.168.1.0/24 : la portée suit le réseau, la règle ne devient jamais caduque.

Variante resserrée

Si l'on veut n'ouvrir que le strict nécessaire à la découverte, plutôt que tout le LAN — cela laisse notamment les partages administratifs C$, D$, E$ et le RPC fermés y compris depuis le réseau local :

Menu Champ Rôle
Allow Localhost boucle locale
Allow LAN UDP/1900 SSDP — les annonces du NAS
Allow LAN UDP/3702 WS-Discovery
Allow LAN TCP/5357 WSDAPI, l'échange qui construit l'icône
Block * tout le reste

Pour Syncthing en direct sur le LAN, ajouter avant le Block : LAN TCP/22000, LAN UDP/22000, LAN UDP/21027.


5. Les pièges — à ne pas redécouvrir

1. Incoming Rules est invisible en mode Simple. filter/serviceEndpoints est de niveau expert (ExpertiseLevel 1), tandis que filter/endpoints (Outgoing Rules) est de niveau user — d'où l'impression trompeuse que seules les règles sortantes existent. Basculer l'interface sur Advanced Interface : sélecteur en haut à droite de la fenêtre, ou Settings → User Interface → UI Mode. Les réglages masqués restent actifs.

2. Ne jamais taper le + ou le - dans le champ de la règle. Le menu Allow/Block fournit déjà le signe. Saisir + LAN produit + + LAN et déclenche :

Invalid Value: validation of filter/serviceEndpoints failed:
entry #1 did not match validation regex

La regex de validation est :

^(\+|\-) (! +)?[A-z0-9\.:\-*/]+( [A-z0-9*]+(/[A-z0-9]+(\-[A-z0-9]+)?)?)?( +#.*)?

Le + n'appartient pas à la classe de caractères qui suit le signe. La syntaxe + LAN / - * est celle du fichier de configuration, pas de l'interface graphique.

3. Block * sans Allow Localhost au-dessus casse la boucle locale. Constaté en direct :

07:43:31  firefox.exe    <- 127.0.0.1  dropped: denied by rule: matches *
07:43:18  syncthing.exe  <- 127.0.0.1  changed from accepted to dropped
07:43:18  steam.exe      <- 127.0.0.1  changed from accepted to dropped
07:43:18  dasHost.exe    <- ::1        changed from accepted to dropped

L'interface Syncthing sur 127.0.0.1:8384 est tombée en timeout. Portmaster ré-évalue les connexions déjà établies et les coupe à chaud. Sur une machine de travail, une grande part du trafic légitime passe par la boucle locale.

Piège dans le piège : l'API de Portmaster s'auto-exempte et continue de répondre — elle ne sert donc pas de témoin pour détecter la panne.

4. L'ordre des règles fait tout. Évaluation de haut en bas, la première correspondance l'emporte. Block * doit être la dernière ligne. Les flèches à gauche de chaque ligne permettent de réordonner.

5. filter/defaultAction vaut permit. Une liste de règles sans Block * final n'est pas restrictive : tout ce qui ne correspond à aucune règle est autorisé. Décocher Force Block Incoming sans poser ce garde-fou ouvre la machine — point critique compte tenu de l'IPv6 (section 6).

6. L'API locale ment par omission. GET http://127.0.0.1:817/api/v1/config/options répond à n'importe quel processus, mais ne renvoie que les définitions et les valeurs par défaut : le champ Value reste vide même pour un réglage effectivement modifié, ce qui fait croire à tort que rien n'a été enregistré. Les endpoints qui exposent l'état réel (/api/v1/sync/settings/export) répondent :

403 The requesting process is not authorized to access the Portmaster API.

Vérifier par le journal, jamais par l'API.

7. Le profil réseau Windows n'a pas eu à être modifié. Il est resté sur Public et la découverte fonctionne. L'hypothèse initiale — passer en Privé et redémarrer FDResPub et upnphost — s'est révélée inutile. Ne pas y consacrer de temps.


6. IPv6 — le point de sécurité

Ce poste possède des adresses IPv6 globales routables : 2a01:cb1c:833b:d00:4958:51b1:629a:a6b4 et 2a01:cb1c:833b:d00:28cb:cac8:3621:d7d0 (préfixe Orange, obtenu par Router Advertisement).

En IPv6 il n'y a pas de NAT. La Livebox ne fait pas écran comme en IPv4 : Portmaster est la seule barrière. Ce que le poste expose au réseau :

Port Processus
445 SMB — partages ADMIN$, C$, D$, E$, IPC$
135 + 49664-49675 RPC (lsass, wininit, spoolsv, services)
5357 WSDAPI
22000 Syncthing
27036 Steam

La portée LAN ne couvre pas ces adresses globales — elles sont classées Global, pas LAN. Le Block * les refuse donc, ce qui est le comportement voulu.

Conséquence assumée : les liens Syncthing directs en IPv6 restent bloqués. Sans impact aujourd'hui, la synchronisation passant par le hub VPS (syncthing-vps, tcp-client vers 51.77.141.54:22000). Pour les rétablir, ajouter 2a01:cb1c:833b:d00::/64 au-dessus du Block * — en sachant que ce préfixe peut changer au redémarrage de la Livebox et rendre la règle caduque sans le moindre signal.


7. Vérification

État constaté après réglage :

Portée Verdict
127.0.0.1 / ::1 accepté — scope matches Localhost
LAN (192.168.1.x, fe80::) accepté — scope matches LAN, 8 acceptations NAS, zéro rejet
IPv6 globales 2a01:cb1c:… rejeté — denied by rule: matches *

Commande de contrôle, à relancer si le NAS redisparaît :

grep "192.168.1.17" /c/ProgramData/Portmaster/logs/*.log | tail -20

Attendu :

svchost.exe:12184 <- 192.168.1.17  accepted: allowed by rule: scope matches LAN
dasHost.exe:3608  to nasmaison. (192.168.1.17)  accepted

dasHost.exe est le Device Association Host : le voir dialoguer avec nasmaison., c'est littéralement l'icône du NAS en train de se construire dans l'Explorateur.

Si l'on lit dropped: inbound connections blocked, c'est que Force Block Incoming Connections a été réactivé.


8. Chronologie

Horodatage Événement
22/08 10:58 Installation de Portmaster 2.2.1
22/08 → 23/08 Découverte réseau muette, ~1 800 blocages entrants silencieux
23/08 ~05:45 Diagnostic : NAS joignable, seule la découverte est cassée
23/08 ~07:30 Cause identifiée — filter/blockInbound et les annonces SSDP
23/08 07:41 Allow LAN posé, Force Block Incoming décoché → NAS visible
23/08 07:43 Block * ajouté → boucle locale coupée, Syncthing GUI en timeout
23/08 07:45 Allow Localhost ajouté en tête → état final correct
23/08 07:46 Vérification des trois niveaux, conforme

9. Références

04_Claude et les dépannages informatiques

260826-Secure Virtual Machine et Emulateur Android

Mise en place d'un émulateur Android sur le poste julie pour faire tourner des applications de presse (The Guardian, Le Monde) et d'autres APK. Séance du 2026-08-26.

Trois obstacles se sont enchaînés, chacun avec un diagnostic trompeur : la virtualisation matérielle absente, un pilote d'accélération dont l'installation échoue en silence, et un faux écran noir. Cette page retient surtout les pièges, parce que chacun a coûté plusieurs allers-retours.

Contexte et matériel

Élément Valeur
Poste julie — MSI A320M-A PRO (MS-7C51), BIOS E7C51AMS.140 du 12/08/2020
CPU AMD Ryzen 5 2600X, 6 cœurs / 12 threads
RAM 16 Go
GPU Radeon RX 6500 XT, pilote du 18/01/2022 (voir page 249)
Écran dalle 4K 3840x2160, bureau logique 2560x1440 (mise à l'échelle 150 %)
OS Windows 10 19045, firmware UEFI, démarrage rapide actif

1. Activer la virtualisation (SVM)

Le symptôme

systeminfo répondait Virtualisation activée dans le microprogramme : Non, alors que le CPU est parfaitement capable de SVM. Sans virtualisation, aucun émulateur Android ne fonctionne — BlueStacks, LDPlayer, MEmu, Nox, Genymotion et l'AVD d'Android Studio sont tous des machines virtuelles x86. Changer d'émulateur ne contourne pas le problème.

Vérification préalable qu'aucune cause logicielle n'était en jeu :

Get-CimInstance Win32_ComputerSystem | Select-Object HypervisorPresent          # False
(Get-CimInstance -Namespace root\Microsoft\Windows\DeviceGuard `
  -ClassName Win32_DeviceGuard).VirtualizationBasedSecurityStatus               # 0

Aucun hyperviseur actif, pas de VBS : ni Hyper-V ni l'isolation du noyau ne confisquaient la virtualisation. La cause était donc bien dans le firmware.

Le chemin dans le BIOS

Ce poste a l'ancienne interface MSI Click BIOS à onglets horizontaux, pas la version récente à tuiles. Donc ni EZ Mode, ni touche F7, ni OC Explore Mode à chercher — toutes indications que l'on trouve partout en ligne et qui ne s'appliquent pas ici.

Touche d'entrée dans le BIOS sur cette machine : F11. Plus fiable, le démarrage rapide étant actif : Paramètres → Mise à jour et sécurité → Récupération → Démarrage avancé → Redémarrer maintenant → Dépannage → Options avancées → Changer les paramètres du microprogramme UEFI.

Chemin réel du réglage :

Overclocking → (section Other Setting, tout en bas) → Caractéristique du CPU → SVM Mode

Caractéristique du CPU est la traduction française de CPU Features.

Piège n°1 — deux sous-menus qui se ressemblent

La section Other Setting du menu Overclocking contient trois entrées :

CPU Specifications        -> INFORMATIONS, lecture seule
MÉMOIRE-Z                 -> informations RAM
Caractéristique du CPU    -> LES RÉGLAGES

CPU Specifications → CPU Technology Support affiche une fiche technique :

Secure Virtual Machine        YES

Ce « YES » ne signifie pas que SVM est activé — seulement que le processeur en est capable. C'est une page de consultation.

Règle pour distinguer d'un coup d'œil : dans ce BIOS, un réglage modifiable est toujours entre crochets (A-XMP [Désactivé], NX Mode [Activé], SVM Mode [Activé]). Une valeur en texte nu (YES, N/A, 3.60GHz) est informative.

Piège n°2 — la vraie cause : il faut couper le secteur

Contenu réel de Overclocking\Caractéristique du CPU :

Simultaneous Multi-Threading   [AUTO]
Global C-state Control         [AUTO]
Opcache Control                [AUTO]
IOMMU                          [AUTO]
Spread Spectrum                [AUTO]
Relaxed EDC throttling         [AUTO]
AMD Cool'n'Quiet               [Activé]
NX Mode                        [Activé]
SVM Mode                       [Activé]   <-- déjà correct
Power Supply Idle Control      [AUTO]

Le réglage était déjà bon, et Windows répondait pourtant Non.

Ce qui a débloqué : le débranchement de la prise pendant 10 secondes. Après quoi :

Virtualisation activée dans le microprogramme : Oui
VirtualizationFirmwareEnabled                 : True

Sur cette carte, un SVM Mode correctement réglé peut rester invisible du système tant qu'il n'y a pas eu de vraie coupure secteur. Un redémarrage, et même un arrêt Windows normal, ne suffisent pas — le démarrage rapide maintient un état résiduel. Débrancher d'abord, diagnostiquer ensuite.

Ne pas toucher aux autres lignes, en particulier laisser IOMMU et Simultaneous Multi-Threading sur [AUTO].

Fiche pas-à-pas réutilisable : Jux-scripts/PC-Health/bios_svm_a320m.md.

2. Android Studio

winget install -e --id Google.AndroidStudio --accept-package-agreements --accept-source-agreements

Version installée : 2026.1.3.7, 3,29 Go dans C:\Program Files\Android\Android Studio.

Installation en mode Custom pour accéder aux composants. Composants retenus :

Composant Version Rôle
Android Emulator 37.1.11 l'émulateur
Android SDK Platform-Tools 37.0.1 adb
Android SDK Command-line Tools 23.0.0 avdmanager, diagnostics
Android Emulator hypervisor driver 2.2.0 accélération AMD — voir section suivante

Symptôme si le pilote manque : l'assistant marque Android Virtual Device comme indisponible, et n'installe ni l'émulateur ni les platform-tools. Ce n'est pas un échec du BIOS — il manque juste la couche d'accélération.

Note : sdkmanager est déprécié et son remplaçant android est encore incomplet (android sdk list ne liste que l'installé). Passer par l'interface pour tout ce qui touche aux images système.

3. Le pilote AEHD — installation manuelle

Pourquoi ce pilote

Sur un CPU AMD sous Windows, l'émulateur a besoin de l'un des deux mécanismes suivants :

Mécanisme Prérequis Retenu ?
AEHD (Android Emulator Hypervisor Driver) SVM activé, Hyper-V absent Oui — correspond à la configuration du poste
WHPX Hyper-V + Windows Hypervisor Platform installés Non — alourdirait le système

Piège n°3 — le SDK Manager échoue et efface ses traces

Sortie observée :

Installing Android Emulator hypervisor driver (installer) in ...\extras\google\Android_Emulator_Hypervisor_Driver
"Install Android Emulator hypervisor driver (installer) v.2.2.0" complete.
Failed to update status to COMPLETE
"Install Android Emulator hypervisor driver (installer) v.2.2.0" failed.

Le paquet se télécharge et s'extrait, puis l'étape d'installation du pilote échoue faute d'élévation, et le gestionnaire annule l'extraction : extras\google se retrouve vide. Il ne reste donc rien à réparer sur place — il faut repartir du paquet d'origine.

La réparation

New-Item -ItemType Directory -Force 'D:\temp_aehd' | Out-Null
Invoke-WebRequest -Uri 'https://dl.google.com/android/repository/aehd-windows_v2.2.zip' `
                  -OutFile 'D:\temp_aehd\aehd.zip'
Expand-Archive 'D:\temp_aehd\aehd.zip' -DestinationPath 'D:\temp_aehd\x' -Force
Start-Process -FilePath 'cmd.exe' -Verb RunAs -Wait -ArgumentList `
  '/c','"cd /d D:\temp_aehd\x && silent_install.bat > D:\temp_aehd\out.txt 2>&1"'

Piège MSIX — utiliser D: et non le dossier temporaire habituel. Claude Code tourne dans un conteneur MSIX : ce qu'il écrit sous %LOCALAPPDATA% atterrit en réalité dans …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\. Un installeur lancé en élevé sort du conteneur et ne verrait pas ces fichiers. Même famille de piège que le home Syncthing (voir la section « Poste Windows julie » du CLAUDE.md).

Contenu du paquet : aehd.Sys (403 Ko), aehd.cat, aehd.Inf, silent_install.bat. Le script installe via RUNDLL32 SETUPAPI.DLL,InstallHinfSection puis lance le service. Désinstallation : silent_install.bat -u.

Résultat :

SERVICE_NAME: aehd
        TYPE  : 1  KERNEL_DRIVER
        STATE : 4  RUNNING

Vérification

& 'D:\Android\Sdk\emulator\emulator.exe' -accel-check

Attendu : AEHD (version 2.2) is installed and usable. et code de retour 0.

4. L'AVD

Choix retenus

Profil Pixel Tablet en paysage : l'écran du PC est large, et Guardian comme Le Monde ont de vraies mises en page tablette (multi-colonnes). Un profil téléphone donnerait une colonne étroite au milieu d'un grand écran.

Ce qui déclenche la mise en page tablette, c'est la largeur en dp, pas en pixels : 1600 / (320/160) = 800 dp, au-delà du seuil de 600 dp.

Si aucun profil tablette ne porte l'icône Play Store, ne pas se rabattre sur un téléphone : prendre un profil téléphone avec Play Store, puis régler dans Edit une résolution de 1920x1200 en 240 dpi (soit 800 dp). On garde le Play Store et la mise en page large.

Image système

system-images\android-35\google_apis_playstore_tablet\x86_64
Android 15, API 35

La variante « Google Play » est indispensable pour installer les applications depuis le Store. C'est une build de production : adb root y est impossible, mais adb install fonctionne normalement.

Traduction ARM confirmée — point décisif pour les APK récupérés ailleurs :

ro.product.cpu.abilist = x86_64,arm64-v8a

Les images x86_64 en API 30 et plus traduisent l'ARM 64 bits à la volée. Sans cela, un APK ARM échoue sur INSTALL_FAILED_NO_MATCHING_ABIS.

Piège n°4 — les réglages avancés ne s'appliquent pas à la création

Valeurs demandées dans l'assistant, valeurs réellement écrites :

Réglage Demandé Obtenu Corrigé en
hw.ramSize 4096 2048 6144
vm.heapSize — 192 512
disk.dataPartition.size 16 Go 10 Go 10 Go (suffisant)
hw.cpu.ncore 4 4 4

Plus simple que de rechercher le Device Manager dans l'interface : éditer directement, émulateur arrêté (il réécrit son fichier en quittant).

C:\Users\julie\.android\avd\Pixel_Tablet.avd\config.ini

hw.ramSize=6144
vm.heapSize=512
hw.cpu.ncore=4
disk.dataPartition.size=10G
hw.gpu.mode=auto

vm.heapSize est le réglage sous-estimé : c'est le plafond mémoire par application, distinct de la RAM totale. À 192 Mo, une application de presse chargeant beaucoup d'images se fait tuer sans message. C'était le vrai goulet d'étranglement, davantage que les 2 Go de RAM.

Sauvegarde : config.ini.bak-260826. Vérification côté invité : MemTotal: 6072156 kB — l'écart avec 6144 Mo est la part réservée par le noyau, c'est normal.

Augmenter le stockage après coup impose un effacement des données. C'est le seul réglage à ne pas rater à la création.

5. Piège n°5 — le faux écran noir

Le symptôme

Après quelques minutes, écran entièrement noir. La capture prise depuis l'intérieur d'Android était noire elle aussi — ce qui semblait exclure un simple problème de fenêtre Windows et accusait la pile graphique, d'autant que le journal de l'émulateur contenait :

UpdateLayeredWindowIndirect failed ... (Un périphérique attaché au système ne fonctionne pas correctement)

avec un pilote AMD de janvier 2022 comme suspect tout désigné.

La vraie cause

mWakefulness=Dozing

L'écran s'était simplement mis en veille, comme sur une vraie tablette. Et le volet de notifications était resté déployé par-dessus (mCurrentFocus=NotificationShade), ce qui gardait l'affichage noir même après réveil.

Aucune erreur graphique dans logcat. Le pilote AMD était hors de cause.

Méthode de diagnostic, dans cet ordre

$adb = 'D:\Android\Sdk\platform-tools\adb.exe'
& $adb devices                                              # le système répond-il ?
& $adb shell getprop sys.boot_completed                     # 1 = démarrage fini
& $adb shell dumpsys power   | Select-String mWakefulness   # Dozing / Asleep / Awake
& $adb shell dumpsys window  | Select-String mCurrentFocus  # quelle fenêtre au premier plan

Réveil et retour à l'accueil :

& $adb shell input keyevent 224        # KEYCODE_WAKEUP
& $adb shell cmd statusbar collapse    # referme le volet de notifications
& $adb shell input keyevent 3          # HOME

BACK et HOME ne referment PAS le volet de notifications quand il reste bloqué ouvert après un réveil. Seul cmd statusbar collapse y parvient. Symptôme : mWakefulness=Awake mais mCurrentFocus=NotificationShade et une capture toujours à ~19 Ko.

Le piège de stay_on_while_plugged_in

Ce réglage n'agit que si l'appareil se déclare en charge. Après un -wipe-data, la batterie virtuelle repart sur AC powered: false — et l'écran se remet donc en veille malgré stay_on = 7. Il faut forcer l'alimentation secteur :

& $adb shell dumpsys battery set ac 1
& $adb shell dumpsys battery set status 2

Vérification :

& $adb shell dumpsys battery | Select-String 'AC powered|status'

Attendu : AC powered: true et status: 2. À refaire après chaque effacement des données, en même temps que les deux settings put.

Indice utile : le poids de la capture d'écran. 23 Ko = écran noir, ~3 Mo = interface réellement dessinée.

& $adb shell screencap -p /sdcard/s.png; & $adb pull /sdcard/s.png D:\s.png

Le correctif

& $adb shell settings put global stay_on_while_plugged_in 7
& $adb shell settings put system screen_off_timeout 1800000

stay_on_while_plugged_in = 7 couvre secteur + USB + sans-fil. L'émulateur se déclarant toujours « en charge », l'écran ne s'éteint plus jamais. Le réglage persiste au redémarrage (il vit sur la partition de données).

6. Piège n°6 — le plus coûteux : ne jamais lancer un installeur depuis Claude Code

Android Studio a été lancé par Claude Code via Start-Process. Un processus enfant hérite du conteneur MSIX du parent. Android Studio a donc tourné dans le conteneur, et tout ce qu'il a écrit sous %LOCALAPPDATA%\Android\Sdk est parti dans :

C:\Users\julie\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\Android\Sdk

Pourquoi c'est indétectable de l'intérieur

Le symptôme n'apparaît qu'en dehors de Claude : un double-clic sur le raccourci du bureau donnait

Windows ne trouve pas 'D:\Android\Sdk\emulator\emulator.exe'

Le même piège sur les raccourcis

Un .lnk créé par WScript.Shell depuis le conteneur résout et fige la cible en chemin virtualisé :

Target : C:\Users\julie\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\Android\Sdk\emulator\emulator.exe

Le raccourci ne fait alors rien du tout, sans message. Les arguments, eux, sont stockés littéralement — d'où un contournement possible : viser cmd.exe (dans System32, non virtualisé) et passer le vrai chemin en argument.

Correctif retenu

Le SDK a été sorti sur D:\Android\Sdk, hors de toute virtualisation :

robocopy 'C:\Users\julie\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\Android\Sdk' `
         'D:\Android\Sdk' /E /MT:8

Puis : skin.path corrigé dans config.ini, raccourci repointé sur D:\Android\Sdk\emulator\emulator.exe. L'émulateur retrouve seul sa racine SDK à partir de son propre emplacement (Found systemPath D:\Android\Sdk\system-images\...). Le dossier .android (les AVD) n'était pas concerné : il vit à la racine du profil, hors LocalAppData.

Preuve directe de la redirection de %APPDATA% (2026-08-26) : après que l'utilisateur a repointé le SDK, le fichier %APPDATA%\Google\AndroidStudio2026.1.3\options\android.sdk.path.xml affichait

Deux contenus différents pour un chemin identique. La redirection ne concerne donc pas que %LOCALAPPDATA% : %APPDATA% (Roaming) l'est aussi. Conséquence pratique : depuis une session Claude, on ne peut pas relire un réglage écrit par une application lancée hors conteneur — la vérification revient à l'utilisateur.

Règles à retenir

  1. Ne jamais faire lancer un installeur ou un IDE par Claude Code. L'utilisateur le lance lui-même depuis le menu Démarrer.
  2. Ne jamais installer sous %LOCALAPPDATA% sur ce poste — préférer D:.
  3. Un .lnk créé depuis Claude vers une cible sous %LOCALAPPDATA% est cassé par construction.
  4. Pour vérifier : comparer le chemin réel et …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\…. Deux tailles identiques = c'est le même dossier redirigé.

Même famille que le piège du home Syncthing (D:\SyncthingHome) documenté dans CLAUDE.md.

7. Piège n°7 — le multi-écrans casse l'AVD

Une configuration d'écrans multiples essayée depuis l'interface a rendu la tablette inutilisable. Elle laisse des lignes dans config.ini :

hw.display1.width = 2160
hw.display1.height = 3840
hw.display1.density = 640
hw.display1.flag = 1739

Un Wipe Data seul ne les enlève pas — elles vivent dans config.ini, pas dans les données invité. Remise en état, émulateur arrêté :

  1. supprimer toutes les lignes hw.displayN.* de config.ini
  2. redémarrer avec -wipe-data -no-snapshot-load
  3. réappliquer les réglages invités — stay_on_while_plugged_in et screen_off_timeout sont effacés par le wipe

Vérification du retour à un seul écran :

& 'D:\Android\Sdk\platform-tools\adb.exe' shell dumpsys SurfaceFlinger --display-id

Une seule ligne attendue.

8. Point de restauration de la tablette

Une fois la tablette configuree - langue francaise, compte Google connecte, Play Store fonctionnel - cet etat vaut la peine d'etre fige. Le reconstituer a la main prend une bonne demi-heure.

Ce qu'il ne faut PAS utiliser : l'instantane interne

L'emulateur sait enregistrer des instantanes (snapshots\\), mais ils sont a ecarter comme sauvegarde :

Ce sont des caches de demarrage rapide, pas des sauvegardes.

La bonne methode : copie froide du dossier AVD

Emulateur arrete - copier un qcow2 en cours d'ecriture donne une image incoherente.

& 'D:\Android\Sdk\platform-tools\adb.exe' -s emulator-5554 emu kill
Get-Process emulator,qemu-system-x86_64 -ErrorAction SilentlyContinue | Stop-Process -Force

$d = "D:\Android\Backups\Pixel_Tablet_$(Get-Date -Format 'yyMMdd')"
robocopy 'C:\Users\julie\.android\avd\Pixel_Tablet.avd' "$d\Pixel_Tablet.avd" /E /XD snapshots tmpAdbCmds /R:1 /W:1
Copy-Item 'C:\Users\julie\.android\avd\Pixel_Tablet.ini' "$d\Pixel_Tablet.ini" -Force
compact /c /s /i /f /exe:LZX "$d\*"

/XD snapshots tmpAdbCmds retire l'instantane : 9,06 Go -> 4,06 Go. Apres restauration, le premier demarrage sera simplement a froid.

Sur la compression

La compression NTFS LZX est transparente - rien a decompresser a la restauration. Mais le gain est faible : 4,06 Go -> 3,26 Go, soit 1,2 pour 1 seulement. Les donnees de userdata sont deja denses.

Ne pas chercher mieux avec une archive 7z : on gagnerait peut-etre 1 Go, au prix d'une etape de decompression au moment ou l'on est presse. Compter ~3,3 Go par point de restauration et faire le menage dans les anciens.

Repartition du volume

Fichier Taille
userdata-qemu.img.qcow2 2 430 Mo
sdcard.img 512 Mo
cache.img.qcow2 + cache.img 137 Mo
snapshots\\ ~6 Go - exclu

Restaurer

  1. arreter l'emulateur et verifier qu'aucun processus ne subsiste
  2. renommer l'AVD abime plutot que le supprimer (Pixel_Tablet.avd.casse-AAMMJJ)
  3. robocopy de la sauvegarde vers C:\Users\julie\.android\avd\Pixel_Tablet.avd, plus le .ini
  4. redemarrer avec -no-snapshot-load
  5. ecran noir eventuel = veille, voir la section 5

Ce que la sauvegarde ne contient PAS

Si le PC lui-meme est reinstalle, il faut d'abord remettre en place, dans cet ordre :

  1. SVM dans le BIOS - avec la coupure secteur (section 1)
  2. le pilote AEHD - sans lui l'emulateur ne demarre pas (section 3)
  3. le SDK sur D:\Android\Sdk - jamais sous %LOCALAPPDATA% (section 6)

Emplacement

D:\Android\Backups\Pixel_Tablet_260826\
    Pixel_Tablet.avd\
    Pixel_Tablet.ini
    RESTAURATION.md      <- procedure complete, sur place

Piege annexe

Une redirection > D:\dossier\fichier.log dans un cmd /c echoue silencieusement si le dossier n'existe pas - et l'emulateur n'est alors jamais lance. Symptome : aucun processus, journal de 0 octet. Verifier l'existence du dossier de log avant de conclure a une panne de l'emulateur.

9. Piège n°8 — l'horloge de la tablette dérive et casse les applications

Symptôme trompeur : une application (ici Le Monde) semble privée d'Internet alors que la tablette navigue normalement. Le pare-feu Portmaster affiche au même moment une notification Blocked Bypass Attempt by Netsimd qui n'est pas la cause et détourne tout le diagnostic. Son conseil — « désactiver Secure DNS dans Netsimd » — est de surcroît inapplicable : netsimd.exe est le démon réseau de l'émulateur, il n'a aucun réglage de DNS sécurisé.

Le vrai défaut

L'AVD reprend un instantané (Quick boot) : au réveil, l'horloge invitée repart de l'heure figée au moment de la sauvegarde et ne se recale pas sur celle du PC. Écart mesuré le 2026-08-31 : 4 jours et 18 heures de retard.

Les serveurs rejettent alors toute requête signée. La preuve tient en une ligne d'adb logcat :

[LOGGER] error sending logs to kinesis - Signature expired:
20260826T234130Z is now earlier than 20260831T182829Z

AWS SigV4 tolère 5 minutes d'écart, pas 5 jours. Tout ce qui repose sur une signature ou une expiration de jeton tombe : connexion, abonnement, contenus.

⚠ auto_time = 1 ne protège pas. Le réglage « heure automatique » était bien actif et n'a rien rattrapé — il ne couvre pas la reprise d'instantané. Le vérifier ne sert à rien.

Correctif

Device Manager → arrêter la tablette → menu ⋮ → Cold Boot.

⚠ L'option n'apparaît pas tant que la tablette tourne : le menu propose Stop à la place. C'est ce qui fait qu'on ne la trouve pas. Le libellé a par ailleurs perdu son « Now » dans les versions récentes.

Durablement, pour que la dérive ne revienne pas : Edit → Show Advanced Settings → Boot option → Cold boot. Équivalent dans %USERPROFILE%\.android\avd\Pixel_Tablet.avd\config.ini :

fastboot.forceColdBoot = yes
fastboot.forceFastBoot = no

⚠ Android Studio n'écrit config.ini qu'à sa fermeture. Après un changement dans l'interface, relire le fichier avant de conclure que le réglage est pris.

⚠ adb shell date -s ne marche pas : l'image google_apis_playstore n'est pas rootable. Le démarrage à froid est la seule voie.

⚠ Ce chemin n'est PAS redirigé par le conteneur MSIX. C:\Users\julie\.android\ n'est ni %LOCALAPPDATA% ni %APPDATA% — vérifié le 2026-08-31, aucun jumeau sous …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\. Une écriture y est donc réelle, contrairement au piège n°6.

Vérification

Comparer les époques, pas l'affichage : la tablette est en GMT, le PC en heure de Paris.

adb shell date +%s ; date +%s

Attendu : quelques secondes d'écart au plus. Après recalage le 2026-08-31 — écart 1 seconde, Signature expired disparu, application fonctionnelle.

Méthode de diagnostic, dans cet ordre

1. Écarter le pare-feu d'abord. Sa notification est bruyante et fausse la piste. Mesurer la connectivité réelle depuis l'invité :

adb shell ping -c 2 8.8.8.8
adb shell curl -s -o /dev/null -w '%{http_code}' http://connectivitycheck.gstatic.com/generate_204

HTTP 204 est la réponse qu'Android attend pour se déclarer connecté. Si elle arrive, Portmaster est hors de cause.

2. Comparer les horloges. Contrôle le moins cher et le plus rentable — il aurait fait gagner toute la séance.

3. Lire le journal de l'application, pas seulement celui du pare-feu :

adb logcat -d --pid $(adb shell pidof com.lemonde.androidapp)

C'est là, et nulle part ailleurs, que se trouvait Signature expired.

⚠ monkey affiche not connected dans ses statistiques réseau même quand tout va bien : c'est sa comptabilité interne, pas l'état de ConnectivityManager. Se fier à dumpsys connectivity, qui doit montrer IS_VALIDATED.

⚠ Un logcat peut être périmé sans le dire : le tampon affichait encore des lignes datées du 26/08 alors qu'on était le 31/08 — conséquence directe de la dérive. Vider (adb logcat -c) et relancer l'application avant de conclure.

⚠ Le TLS n'était PAS cassé malgré 5 jours d'écart : curl depuis l'invité rendait 200/301/404. Une horloge en retard ne casse que les certificats émis après elle. Ne pas s'arrêter à ce test pour disculper l'horloge.

Ce que Portmaster bloquait réellement

Un seul blocage légitime à lever : cmp.lemonde.fr, la plateforme de consentement du Monde, classée traceur par la liste TRAC. Bloquée, l'application reste sur son écran de consentement — ce qui ressemble à une panne de réseau. Règle posée dans Outgoing Rules → Allow.

⚠ Deux profils netsimd.exe coexistent dans Portmaster, séquelle du piège n°6 : l'ancien sous …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Local\Android\Sdk\ (mort depuis le 26/08) et le vrai sur D:\Android\Sdk\emulator\. Portmaster identifie les applications par chemin de binaire : une règle posée sur le mauvais profil ne fait rien, sans le moindre message.

⚠ Ne pas taper le + dans le champ de la règle — le menu Allow le pose lui-même, et + + cmp.lemonde.fr échoue sur la regex de validation. Même piège que les Incoming Rules (CLAUDE.md, section « Portmaster »). À noter : Outgoing Rules est de niveau user, donc visible en mode Simple, contrairement aux Incoming Rules.

Le reste est voulu : ws.batch.com, tracking.purchasely.io, logs13.xiti.com, firebase-settings.crashlytics.com sont des traceurs. ws.batch.com reboucle indéfiniment — 4 224 requêtes en une journée, toutes les 2 à 6 secondes — c'est bruyant dans le journal et sans effet sur l'application. Ne pas l'autoriser pour faire taire le journal.

Portmaster laisse passer NTP (time.google.com accepté) : il n'est pour rien dans la dérive d'horloge.

9. Piège n°8 — « auto » choisit le rendu LOGICIEL (lavapipe)

2026-09-02. Retours d'usage : tablette peu réactive, vidéo saccadée, son défaillant, « bord blanc inutile », écran trop petit. Tout venait d'une seule cause.

Le diagnostic décisif : comparer les DEUX fichiers

config.ini porte ce qu'on a demandé. hardware-qemu.ini porte ce que l'émulateur a réellement retenu au dernier lancement. C'est ce second fichier qu'il faut lire.

config.ini         hw.gpu.mode = auto
hardware-qemu.ini  hw.gpu.mode = lavapipe     <-- rasteriseur Vulkan LOGICIEL

lavapipe, c'est le processeur qui dessine tout. Le GPU ne fait rien. À 2560x1600, cela représente 4,1 millions de pixels par image à la charge du CPU — d'où la lenteur, les saccades vidéo, et le son qui décroche (l'audio est sous-alimenté quand le CPU sature).

Chaîne d'échecs visible dans le journal de l'émulateur :

Failed to load [...\qemu\windows-x86_64\lib64\vulkan\vulkan-1.dll]
[Vulkan Loader] Registry lookup failed to get layer manifest files
Critical: Failed to load opengl32sw
Warning: Software OpenGL failed. Falling back to system OpenGL.

Le chemin Vulkan échoue, et auto se rabat silencieusement sur le logiciel. Aucun message d'erreur visible dans l'interface.

Correctif

hw.gpu.mode = host

Vérification après relance — c'est le seul test qui compte :

Get-Content 'C:\Users\julie\.android\avd\Pixel_Tablet.avd\hardware-qemu.ini' | Select-String 'gpu.mode'

Doit répondre host. Si host donne des artefacts, essayer angle_indirect (OpenGL traduit en Direct3D 11) : un peu plus lent, nettement plus robuste sur pilote ancien.

Suite (2026-09-03). Le pilote a été mis à jour en Adrenalin 26.8.1 (voir page 295). Vulkan n'est toujours pas enregistré pour autant : HKLM\SOFTWARE\Khronos\Vulkan\Drivers reste absente, l'installation Driver Only n'ayant pas recréé l'ICD supprimée par le Factory Reset. Conserver hw.gpu.mode = host — repasser en auto ferait retomber en lavapipe.

Cause racine : le pilote AMD de janvier 2022 (voir page 249), qui expose mal Vulkan. host contourne le problème, il ne le corrige pas. Résultat après correction : vidéo fluide et tablette nettement plus réactive, confirmé par l'utilisateur.

Le faux « cadre blanc » et l'écran trop petit : même cause

Le bord clair n'était pas le skin de la tablette — hardware-qemu.ini ne contenait aucune ligne skin ni showDeviceFrame, l'émulateur ne l'appliquait déjà plus.

C'était du remplissage de fenêtre : l'AVD faisait 2560x1600 pour un bureau logique de 2560x1440. Impossible à afficher en entier, donc image réduite pour tenir, et le fond clair de l'émulateur comble le reste.

Règle : la définition de l'AVD doit tenir dans le bureau, sinon l'image est réduite en permanence et entourée de remplissage.

Correctif appliqué — 1920x1200 en densité 240 :

Avant Après
Définition 2560x1600 1920x1200
Densité 320 240
Largeur en dp 800 800 (inchangée)
Pixels à calculer 4,1 Mpx 2,3 Mpx (-44 %)

Les 800 dp sont conservés : les mises en page tablette sont identiques. Mais l'image tient dans l'écran sans réduction, la fenêtre peut être agrandie à la main, et le GPU travaille moins. Résultat confirmé : bord blanc disparu, écran nettement plus grand.

Retirer aussi skin.name et skin.path de config.ini (showDeviceFrame = no seul les rend inopérants, mais autant être net).

Le son

Mesurer avant de conclure :

& $adb shell cmd media_session volume --stream 3 --get

Le volume invité était déjà à 13/15 — il a été passé à 15.

Résolu, et la cause n'était pas l'audio. Les ratés de son étaient un symptôme de la saturation processeur : quand le CPU dessinait 4,1 Mpx par image en lavapipe, le flux audio n'était plus alimenté à temps et décrochait. Une fois le rendu basculé sur host et la définition ramenée à 1920x1200, le son est redevenu correct sans aucun réglage audio supplémentaire. Ne pas partir sur le mélangeur de volume Windows ni sur le périphérique de sortie tant que le rendu graphique n'est pas vérifié — c'est une fausse piste coûteuse.

Note : la commande media n'existe pas sur cette image, il faut cmd media_session.

Horloge : démarrage à froid obligatoire

La tablette affichait lundi 31 août alors que le PC était au mercredi 2 septembre. Cause déjà documentée sur ce poste : en Quick boot, l'horloge repart de l'heure figée dans l'instantané et ne se recale jamais.

fastboot.forceColdBoot = yes
fastboot.forceFastBoot = no

Après correction : Wed Sep 2 21:18 GMT côté tablette pour 23:18 côté PC — le même instant, l'écart n'étant que le fuseau. Le démarrage passe de ~20 s à 2-3 min : compromis accepté, une horloge fausse ayant déjà fait rejeter des requêtes signées et accuser Portmaster à tort.

Le fuseau se règle à la main dans la tablette (Paramètres → Système → Date et heure) : setprop persist.sys.timezone est refusé sur une image Google Play, qui est une build de production.

Deux conséquences du démarrage à froid

  1. La tablette arrive verrouillée. mCurrentFocus=NotificationShade désigne alors l'écran de verrouillage, pas le volet de notifications. Déverrouiller par un glissement : adb shell input swipe 960 1000 960 200 200.
  2. dumpsys battery set ac 1 ne persiste pas — c'est une valeur d'exécution. À chaque lancement la tablette repart sur batterie, donc stay_on_while_plugged_in ne s'applique pas. Seul screen_off_timeout (30 min) protège alors de la veille.

10. Dimensionner la mémoire — mesurer, ne pas deviner

2026-09-02. qemu-system-x86_64 consommait 7 Go sur les 16 de la machine. L'AVD avait été réglé à 6 Go « pour être tranquille ».

La bonne mesure : MemAvailable, pas MemFree

& 'D:\Android\Sdk\platform-tools\adb.exe' shell cat /proc/meminfo

Relevé à 6 Go :

MemTotal:        6 071 Mo
MemFree:         1 038 Mo
MemAvailable:    3 834 Mo     <-- 63 % reellement disponible
Cached:          3 429 Mo
SwapTotal / SwapFree : 4 554 / 4 111 Mo   -> 442 Mo utilises, aucune pression

MemFree est trompeur : Linux remplit toujours la mémoire inoccupée de cache disque, donc MemFree reste bas quoi qu'il arrive. C'est MemAvailable qui dit ce que le système peut réellement rendre — ici 63 %, plus 3,4 Go de cache purement opportuniste. Android n'utilisait qu'environ 2,2 Go de mémoire de travail.

Second indice : la partition d'échange de l'invité n'était sollicitée qu'à 442 Mo sur 4 554. Aucune contrainte mémoire.

Résultat après passage à 4 Go

hw.ramSize = 4096
6 Go 4 Go
Guest MemTotal 6 071 Mo 4 013 Mo
Guest MemAvailable 3 834 Mo (63 %) 2 596 Mo (65 %)
qemu working set 6 964 Mo 3 479 Mo
Hôte libre 3,1 Go 6,9 Go

La mémoire de qemu est divisée par deux et Android conserve exactement la même marge relative. 3,8 Go rendus à l'hôte sans contrepartie mesurable.

Repères

Ne pas toucher à vm.heapSize en même temps : c'est un plafond par application, pas une réservation. Le laisser à 512 Mo, c'est ce qui évite qu'une application de presse chargeant beaucoup d'images se fasse tuer sans message (voir section 4).

Méthode réutilisable

  1. laisser tourner la tablette en usage normal quelques minutes
  2. lire MemAvailable et l'état du swap invité
  3. si MemAvailable dépasse ~50 % et que le swap est quasi inutilisé, il y a de la marge à reprendre
  4. réduire par paliers de 1 Go, émulateur arrêté, et remesurer
  5. penser à recopier config.ini dans le point de restauration après chaque changement

11. Apres un deplacement du SDK : « Could not automatically detect an ADB binary »

2026-09-06. Boite de dialogue au demarrage de l'emulateur, apres la sortie du SDK vers D:\\Android\\Sdk (section 6).

L'emulateur ne cherche pas adb seulement a cote de lui : il consulte d'abord ANDROID_HOME, ANDROID_SDK_ROOT et le PATH, qui pointaient implicitement sur l'ancien emplacement disparu.

adb present       D:\Android\Sdk\platform-tools\adb.exe   OK
ANDROID_HOME      non defini
ANDROID_SDK_ROOT  non defini
platform-tools    absent du PATH

Ce n'est pas anodin : les fonctions de l'emulateur qui reposent sur adb tombent — installation d'un APK par glisser-deposer sur la fenetre, bouton de capture d'ecran des Extended Controls, envoi de fichiers. Les scripts qui appellent adb par un chemin absolu, eux, ne sont pas concernes.

Correctif — a taper par l'utilisateur dans sa propre console, non elevee :

[Environment]::SetEnvironmentVariable('ANDROID_HOME','D:\Android\Sdk','User')
[Environment]::SetEnvironmentVariable('ANDROID_SDK_ROOT','D:\Android\Sdk','User')
[Environment]::SetEnvironmentVariable('PATH',
  [Environment]::GetEnvironmentVariable('PATH','User') + ';D:\Android\Sdk\platform-tools', 'User')

Fermer puis rouvrir l'emulateur : les variables ne sont lues qu'au demarrage du processus. Benefice annexe, adb devient utilisable sans chemin dans n'importe quelle console.

Repli si l'on ne veut rien toucher au systeme : ... (Extended Controls) -> Settings -> onglet General -> decocher Use detected ADB location et indiquer le chemin. Reglage propre a l'emulateur, sans effet ailleurs.

Precision sur la redirection MSIX : le registre se lit, mais ne s'ecrit pas

Constate a cette occasion : les valeurs ecrites par l'utilisateur dans HKCU\\Environment sont immediatement visibles depuis une session Claude Code, contrairement aux fichiers sous %LOCALAPPDATA% et %APPDATA% (section 6).

C'est le comportement classique de MSIX pour le registre : lecture directe, ecriture redirigee.

Consequence pratique : une variable d'environnement utilisateur peut etre verifiee depuis Claude Code — ce qui n'est pas le cas d'un fichier de configuration. En revanche, presumer qu'une ecriture depuis Claude serait visible a l'exterieur reste faux. La regle « c'est l'utilisateur qui ecrit » ne change pas ; seule la verification devient possible.

Aide-mémoire

Chemins

Android Studio   C:\Program Files\Android\Android Studio
SDK              D:\Android\Sdk   (sorti du conteneur MSIX, voir section 6)
adb              ...\Sdk\platform-tools\adb.exe
emulator         ...\Sdk\emulator\emulator.exe
AVD              C:\Users\julie\.android\avd\Pixel_Tablet.avd
Raccourci        C:\Users\julie\Desktop\Tablette Android.lnk

Commandes

# Démarrer (le raccourci du bureau fait la même chose)
& '...\Sdk\emulator\emulator.exe' -avd Pixel_Tablet

# Démarrage propre, si un boot se passe mal
& '...\Sdk\emulator\emulator.exe' -avd Pixel_Tablet -no-snapshot-load

# Lister les AVD / arrêter proprement
& '...\Sdk\emulator\emulator.exe' -list-avds
& '...\adb.exe' -s emulator-5554 emu kill

# Installer un APK (ou glisser-déposer le fichier sur la fenêtre)
& '...\adb.exe' install monapp.apk
& '...\adb.exe' install-multiple base.apk split_config.arm64_v8a.apk split_config.xxhdpi.apk

Les dépôts type APKMirror servent souvent des .xapk / .apkm : ce sont des archives ZIP de plusieurs APK. adb install échoue dessus, il faut les décompresser et utiliser install-multiple.

Premier démarrage : 2 à 3 minutes, sans aucune fenêtre visible pendant une bonne partie du temps. Ne pas conclure trop vite que le raccourci ne marche pas — vérifier le processus :

Get-Process emulator,qemu-system-x86_64 -ErrorAction SilentlyContinue

Les démarrages suivants réutilisent l'instantané, environ 20 secondes.

Limites connues

Presse, lecture, productivité et utilitaires : sans problème.

Voies écartées

Option Raison
Émulateur sur le VPS juxjux La virtualisation imbriquée y est pourtant active (/dev/kvm, kvm_intel.nested=Y) — mais 2,7 Gio de RAM disponibles seulement, swap déjà à moitié plein, aucun GPU, et usage interactif à travers le réseau. Redroid exigerait en plus un changement de noyau : le noyau cloud n'a pas CONFIG_ANDROID_BINDER_IPC
BlueStacks / LDPlayer / MEmu / Nox Mêmes prérequis de virtualisation, plus publicité et télémétrie
Genymotion Dépend de VirtualBox, déjà impliqué dans le dossier écrans bleus (page 249)
Waydroid sur l'Ubuntu 25.10 Reste une bonne solution de repli : conteneur LXC, aucun besoin de VT-x/AMD-V. Aurait été retenu si SVM était resté inaccessible
scrcpy + tablette existante Écarté ici, mais pertinent : recopie l'écran d'une Lenovo Tab K11 ou d'une SM-T720 sur le PC, sans virtualisation ni émulateur

Points restés ouverts

Voir aussi

04_Claude et les dépannages informatiques

260903 - Mise à jour du pilote AMD

Procédure préparée le 2026-09-02, à exécuter le 2026-09-03 sur le poste julie.

Objectif : remplacer le pilote graphique AMD du 18 janvier 2022 par la version actuelle. Deux motifs indépendants, chacun suffisant à lui seul.

Pourquoi

1. C'est la cause établie des écrans bleus 0x50. L'analyse du vidage mémoire du 31/07/2026 désigne amdfendr.sys (AMD Crash Defender) v21.30.0.9 : le pilote appelle RtlCompressBuffer avec une taille supérieure à l'allocation réelle, LZNT1 lit au-delà et tombe sur une page non mappée. MODULE_NAME: amdfendr, confirmé par deux rapports WER. Analyse complète : page 249.

2. C'est aussi ce qui dégradait l'émulateur Android. Le support Vulkan de ce pilote est défaillant : le chargement de l'ICD échouait, et l'émulateur se rabattait silencieusement sur lavapipe, un rasteriseur purement logiciel. Détail : page 282, section 9.

État avant intervention

À relever pour pouvoir comparer après.

Élément Valeur au 2026-09-02
Carte AMD Radeon RX 6500 XT (Navi 24, 0x743F), 4 Go
Pilote 30.0.14023.3004
Date du pilote 18/01/2022
amdfendr.sys 21.30.0.9, fichier du 07/02/2022
amdfendrmgr.sys 21.30.0.9, fichier du 07/02/2022
OS Windows 10 19045, UEFI
Point de restauration 11 — 260903-maj pilotes carte grapphique, 03/09/2026 03:09

Précautions propres à cette machine

⚠ L'utilisateur lance l'installeur lui-même. Un processus démarré par Claude Code hérite de son conteneur MSIX et installe au mauvais endroit, de façon indétectable depuis la session. Voir page 282, section 6.

⚠ Pas par temps d'orage, ni en période de coupures. Ce poste compte 146 arrêts brutaux au compteur SMART du SSD et a subi des coupures secteur avérées (Enedis le 24/08). Un flash de pilote graphique interrompu par une coupure est l'un des rares moments où l'on casse réellement quelque chose.

⚠ Une seule opération à risque à la fois. Ne pas enchaîner avec une mise à jour du BIOS, même si l'occasion se présente. Le BIOS 1.40 de 2020 reste volontairement en place.

⚠ winget est inutile ici. Il ne propose que AMD.AMDSoftwareCloudEdition, destiné aux serveurs de jeu en nuage — à ne pas installer. Le téléchargement vient du site AMD.

Procédure

1. Poser le filet

Dans une console PowerShell en administrateur (la protection système était déjà active sur ce poste — trois points existaient déjà des 26, 27 et 28/08) :

⚠ Angle mort à connaître. Get-ComputerRestorePoint exige l'élévation : depuis une session Claude Code, non élevée, il renvoie une liste vide, ce qui fait conclure à tort que la protection système est désactivée. Erreur commise le 2026-09-02. La vérification revient à l'utilisateur, dans sa propre console élevée — même famille d'angle mort que la lecture de %APPDATA% (page 282, section 6).

Autre piège : Windows refuse de créer un second point dans les 24 h suivant le précédent. Checkpoint-Computer peut donc échouer en silence.

Enable-ComputerRestore -Drive 'C:\'
Checkpoint-Computer -Description 'Avant pilote AMD' -RestorePointType MODIFY_SETTINGS

Vérifier qu'il est bien créé :

Get-ComputerRestorePoint | Select-Object SequenceNumber,Description,CreationTime

2. Télécharger

amd.com/fr/support → Graphics → Radeon RX 6000 Series → Radeon RX 6500 XT → Windows 10 - 64-Bit

Prendre l'édition Recommended (WHQL), pas l'Optional : plus prudente sur une machine dont la stabilité est en cours d'investigation.

3. Installer

Deux choix à ne pas manquer dans l'installeur :

L'écran clignote et devient noir plusieurs secondes pendant l'opération : c'est normal.

4. Redémarrer et vérifier

Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | Format-List
(Get-Item 'C:\Windows\System32\drivers\amdfendr.sys').VersionInfo.FileVersion

Attendu : une date récente, et amdfendr.sys sorti de la 21.30.0.9.

5. Contrôles complémentaires

Côté émulateur Android — vérifier que l'accélération répond toujours :

& 'D:\Android\Sdk\emulator\emulator.exe' -accel-check

Puis, après un lancement de la tablette, que le rendu n'est pas retombé en logiciel :

Get-Content 'C:\Users\julie\.android\avd\Pixel_Tablet.avd\hardware-qemu.ini' | Select-String 'gpu.mode'

Laisser hw.gpu.mode = host. Même si Vulkan est réparé, un réglage explicite qui fonctionne vaut mieux qu'un auto susceptible de retomber en lavapipe sans le moindre message.

Côté stabilité — relancer le relevé après deux à trois semaines :

Jux-scripts\PC-Health\collect_bsod.ps1

Le script signale la version d'amdfendr.sys à chaque passage ; il doit cesser de la marquer comme problématique.

Retour arrière

Si l'affichage se dégrade ou si de nouveaux plantages apparaissent :

  1. Restauration système sur le point créé à l'étape 1
  2. À défaut : Gestionnaire de périphériques → carte graphique → Propriétés → onglet Pilote → Restaurer le pilote précédent
  3. En dernier recours : DDU en mode sans échec, puis réinstallation propre

Ce qu'il ne faut PAS en attendre

La page 249 distingue deux populations d'arrêts anormaux, et cette mise à jour n'en traite qu'une.

Population Traitée ?
15 écrans bleus (3× 0x50 attribués à amdfendr, 10× 0x9F, 1× 0x3B, 1× 0xA0) Oui, c'est l'objet de l'intervention
30 coupures sèches (BugcheckCode = 0, aucune trace) Non — hypothèse électrique externe, un onduleur trancherait

Les 146 arrêts brutaux du compteur SSD, dont une centaine antérieurs à la réinstallation d'octobre 2025, appartiennent à la seconde catégorie. Ne pas conclure à un échec de la mise à jour si des coupures sèches persistent.

Après l'intervention

Mettre à jour :

Résultats — intervention du 2026-09-03

Version installée : AMD Software: Adrenalin Edition 26.8.1 (WHQL Recommended), paquet de 942 Mo téléchargé depuis amd.com, avec Factory Reset coché et installation Driver Only.

Point de restauration préalable : 11 — 260903-maj pilotes carte grapphique, 03/09/2026 03:09. Non utilisé.

Avant / après

Avant Après
Pilote affiché 30.0.14023.3004 32.0.21045.5002
Date du pilote 18/01/2022 17/08/2026
amdfendr.sys actif 21.30.0.9 (07/02/2022) 25.10.0.7 (25/02/2026)
amdpsp.sys 5.24.0.0 5.46.0.0 (19/06/2026)

Quatre ans et sept mois rattrapés. La version d'amdfendr.sys identifiée comme cause des écrans bleus 0x50 est remplacée — c'était l'objet de l'intervention.

⚠ Piège de vérification : lire le service, pas le fichier

Le premier contrôle a fait croire à un échec :

C:\Windows\System32\drivers\amdfendr.sys    21.30.0.9    07/02/2022

Ce fichier est un résidu de l'installation de 2022 que Windows n'utilise pas. Le pilote réellement chargé est désigné par le service :

HKLM\SYSTEM\CurrentControlSet\Services\amdfendr
  ImagePath = \SystemRoot\System32\DriverStore\FileRepository\
              amdfendr.inf_amd64_bea53a1d416fbcfa\amdfendr.sys   -> v25.10.0.7, 25/02/2026

Les deux versions cohabitent dans le DriverStore (...9c52cee6bd9e4fb5 pour l'ancienne, ...bea53a1d416fbcfa pour la nouvelle) ; seule la seconde est enregistrée.

Règle : après une mise à jour de pilote, vérifier ImagePath du service, jamais le fichier dans System32\drivers. Ce dernier peut rester périmé indéfiniment sans que cela signifie quoi que ce soit.

Commande de contrôle :

(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\amdfendr').ImagePath

État du service : Start = 3 (démarrage manuel), actuellement arrêté.

⚠ Vulkan n'est TOUJOURS pas enregistré

C'est le point décevant de l'intervention.

HKLM\SOFTWARE\Khronos\Vulkan\Drivers             absente
HKLM\SOFTWARE\WOW6432Node\Khronos\Vulkan\Drivers absente
C:\Windows\System32\amdvlk64.dll                 absent

Les bibliothèques existent pourtant dans le DriverStore (amdvlk64.dll, amdxc64.dll dans deux paquets), mais aucune ICD n'est déclarée : Vulkan reste inutilisable. Le Factory Reset a vraisemblablement supprimé la clé sans que l'installation Driver Only la recrée.

Seules entrées présentes sous Khronos\Vulkan\ImplicitLayers : les deux couches de Steam.

Conséquence pour l'émulateur Android : garder hw.gpu.mode = host, ne pas repasser en auto — il retomberait en lavapipe (page 282, section 9). Le réglage explicite reste nécessaire.

Si Vulkan devient un besoin (jeux, applications tierces), il faudra relancer l'installeur sans Driver Only, en acceptant la suite Adrenalin complète.

Émulateur — non régressé

emulator -accel-check     AEHD (version 2.2) is installed and usable.   code 0
hardware-qemu.ini         hw.gpu.mode = host
Definition                1920x1200
MemTotal invite           4 013 Mo
Focus                     NexusLauncherActivity

Ce qui reste à surveiller

La page 249 distingue deux populations d'arrêts anormaux. Cette mise à jour n'en traite qu'une.

05_Claude et les MCP

05_Claude et les MCP

Quelles opportunités entre logiciels opensource et les IA

Voici une liste des logiciels open source dans les domaines de l’infographie, la PAO, la CAO et la géomatique qui, en juin 2026, bénéficient d’une connexion MCP (Model Context Protocol) ou pour lesquels des serveurs MCP existent ou sont en développement pour permettre à une IA de prendre la main sur la production de documents ou d’automatiser des tâches.


📌 Logiciels compatibles MCP (ou avec serveurs MCP disponibles)

🎨 Infographie & PAO

  • Scribus Logiciel de PAO open source pour la mise en page professionnelle (brochures, magazines, livres). Statut MCP : Des serveurs MCP communautaires permettent d’interagir avec les fichiers Scribus (lecture, modification, export) via des scripts Python ou des connecteurs dédiés. Cela permet à une IA de générer ou modifier des mises en page automatiquement.

  • Inkscape Éditeur de graphiques vectoriels (SVG) open source. Statut MCP : Des serveurs MCP existent pour manipuler des fichiers SVG (création, édition, export) via des outils comme Puppeteer ou des scripts Python. Une IA peut ainsi générer ou modifier des visuels vectoriels.

  • GIMP Logiciel de retouche photo et de création graphique open source. Statut MCP : Des connecteurs MCP permettent d’automatiser des tâches de retouche ou de génération d’images via des scripts (Python, Bash) ou des API externes.


🏗️ CAO (Conception Assistée par Ordinateur)

  • FreeCAD Logiciel de CAO 3D paramétrique open source. Statut MCP : Des serveurs MCP permettent d’interagir avec les fichiers FreeCAD (.FCStd) pour automatiser la création ou la modification de modèles 3D. Une IA peut ainsi générer des pièces ou des assemblages à partir de prompts textuels.

  • Blender Logiciel open source de modélisation 3D, animation et rendu. Statut MCP : Blender est explicitement cité comme compatible avec MCP dans la documentation officielle. Des serveurs MCP permettent de contrôler Blender via Python (API Blender + MCP), ce qui permet à une IA de créer, modifier ou rendre des scènes 3D, ou même d’automatiser des workflows complexes (ex : génération de visuels pour l’architecture ou le design industriel).

  • OpenSCAD Logiciel de CAO 3D open source basé sur un langage de script. Statut MCP : Des serveurs MCP permettent d’exécuter des scripts OpenSCAD et de récupérer les modèles 3D générés, ce qui facilite l’automatisation de la conception paramétrique.


🌍 Géomatique (SIG & Cartographie)

  • QGIS Système d’Information Géographique (SIG) open source le plus répandu. Statut MCP : Des serveurs MCP permettent d’interagir avec QGIS via PyQGIS (Python) ou des API REST. Une IA peut ainsi :

    • Charger des couches géospatiales (Shapefile, GeoJSON, etc.).
    • Effectuer des analyses spatiales (requêtes, calculs de distances, etc.).
    • Générer des cartes ou des rapports automatiques.
  • GRASS GIS SIG open source avancé pour l’analyse spatiale. Statut MCP : Compatible via des scripts Python ou des connecteurs MCP dédiés pour automatiser des traitements géomatiques (ex : classification d’images satellite, modélisation de terrains).

  • GDAL/OGR Bibliothèque open source pour la manipulation de données géospatiales (raster/vectoriel). Statut MCP : Des serveurs MCP permettent d’utiliser GDAL pour convertir, traiter ou analyser des données géospatiales (ex : transformation de formats, extraction de métadonnées).

  • PostGIS Extension spatiale pour PostgreSQL. Statut MCP : Des serveurs MCP permettent d’interroger des bases de données PostGIS en langage naturel (ex : "Trouve tous les bâtiments à moins de 500m d’une rivière") et de générer des rapports ou des cartes automatiques.


🔌 Comment ça marche ?

Le Model Context Protocol (MCP) est un standard ouvert créé par Anthropic et donné à la Linux Foundation en décembre 2025. Il permet à une IA (comme Claude, ChatGPT, ou des modèles locaux) de :

  • Lire/écrire des fichiers (ex : .svg, .fcstd, .qgs).
  • Exécuter des fonctions (ex : lancer un rendu dans Blender, une requête SQL dans PostGIS).
  • Interagir avec des API externes (ex : Google Drive, GitHub, etc.).

Exemples concrets en 2026 :

  • Un agent IA peut créer une carte thématique dans QGIS à partir d’une demande en langage naturel.
  • Une IA peut générer un modèle 3D dans FreeCAD en suivant un cahier des charges textuel.
  • Un workflow automatisé peut produire une affiche dans Scribus en combinant du texte généré par IA et des images retouchées via GIMP.

📂 Où trouver les serveurs MCP pour ces logiciels ?


💡 Cas d’usage avancés

  • Infographie : Génération automatique de visuels pour les réseaux sociaux (Inkscape + IA).
  • PAO : Création de catalogues produits à partir d’une base de données (Scribus + MCP + PostGIS).
  • CAO : Optimisation topologique de pièces mécaniques (FreeCAD + IA + MCP).
  • Géomatique : Analyse de risques naturels à partir de données ouvertes (QGIS + GDAL + MCP).

⚠️ Limites et précautions

  • Sécurité : MCP permet un accès profond aux outils. Il faut contrôler les permissions pour éviter des actions non désirées (ex : suppression de fichiers).
  • Maturity : Tous les logiciels n’ont pas encore de serveurs MCP officiels, mais la communauté développe activement des connecteurs.
  • Performances : Pour les logiciels lourds (Blender, QGIS), une machine puissante est recommandée pour éviter les lenteurs.

🔍 Pour aller plus loin

Question : Souhaites-tu que je te guide pour configurer un serveur MCP spécifique (ex : Blender ou QGIS) ou explorer un cas d’usage précis dans ton domaine ?

05_Claude et les MCP

Retours de Claude et propositions d'intégration

Contexte

Analyse rédigée par Claude Code (Sonnet 4.6) le 2026-06-20, à partir d'une session de travail sur le PC Windows (eliob).

Logiciels utilisés par Julien : QGIS, Inkscape, GIMP, Scribus. Ces quatre outils forment un workflow cohérent : QGIS pour la donnée géospatiale, Inkscape et Scribus pour la mise en page cartographique et la PAO, GIMP pour le traitement d'image.


Note critique sur la page 227

La page 227 ("Quelles opportunités entre logiciels opensource et les IA") a vraisemblablement été générée par une IA en mode chatbot. Les liens GitHub vers modelcontextprotocol/servers/tree/main/src/servers/blender, .../qgis, .../freecad, .../postgis sont probablement hallusinés — ces sous-dossiers n'existent pas dans le dépôt officiel MCP. À vérifier systématiquement avant d'agir sur ces références.


Analyse par logiciel

QGIS — Priorité 1 (le plus mature et le plus pertinent)

Ce qui existe réellement : Le projet qgis-mcp (disponible sur GitHub, maintenu par la communauté) expose QGIS comme un serveur MCP local. Il s'installe comme un plugin Python dans QGIS et ouvre un socket local sur lequel Claude peut envoyer des commandes PyQGIS.

Capacités concrètes :

Avantage spécifique à Julien : La base PostGIS alteris_geo sur le VPS Alteris (79.137.14.202:5432) est déjà accessible. Un workflow QGIS + MCP + PostGIS permettrait à Claude de : interroger la base en SQL spatial → charger le résultat dans QGIS → générer une carte thématique → exporter en PDF, le tout en langage naturel.

Contrainte : QGIS doit être ouvert sur la machine locale. Le MCP communique via socket local (pas de pilotage à distance).


Scribus — Priorité 2 (fort potentiel pour les rendus cartographiques)

Ce qui existe réellement : Scribus expose une API Python complète via son module scribus (accessible en mode headless : scribus --python-script myscript.py). Pas de serveur MCP publié, mais un MCP custom est trivial à écrire : un script Python qui reçoit des commandes MCP et les traduit en appels scribus.*.

Capacités concrètes via Python headless :

Cas d'usage concret pour Julien : Générer automatiquement une fiche de synthèse cartographique (titre, carte exportée depuis QGIS, texte de légende) en combinant la carte produite par QGIS MCP et un gabarit Scribus.

Contrainte : Scribus headless est instable sur certaines versions — à tester avec la version installée. La génération de gabarits .sla de référence est un prérequis.


Inkscape — Priorité 3 (manipulation SVG, pas contrôle UI)

Ce qui existe réellement : Pas de serveur MCP dédié pour contrôler l'interface Inkscape. En revanche, deux approches sont réalistes :

  1. Manipulation directe du SVG — le format natif d'Inkscape est du XML/SVG standard. Claude peut générer ou modifier des fichiers SVG avec Python (lxml, svgwrite) sans lancer Inkscape.
  2. Inkscape CLI — inkscape --actions="verb1;verb2" permet des opérations batch (export PNG/PDF, conversion de formats) pilotables depuis un MCP.

Cas d'usage concret pour Julien : Modifier programmatiquement une carte SVG exportée depuis QGIS (changer des couleurs, ajouter un texte, insérer un logo) avant intégration dans Scribus.

Contrainte : L'automatisation reste au niveau fichier, pas au niveau interactif. Pour un usage cartographique, QGIS couvre déjà la plupart des besoins de rendu.


GIMP — Priorité 4 (batch uniquement)

Ce qui existe réellement : GIMP peut être piloté en batch via gimp --no-interface --batch='(script-fu-batch-list ...)' ou via Python-Fu (gimp --batch). Un MCP custom est faisable.

Cas d'usage concret pour Julien : Traitement en masse d'images pour intégration dans des documents Scribus (redimensionnement, recadrage, conversion CMJN, compression). Moins critique si StirlingPDF couvre déjà les besoins de compression.

Contrainte : GIMP batch est lent au démarrage. Pour du traitement image simple, des alternatives Python (Pillow, ImageMagick) sont plus légères à wraper en MCP.


Proposition de workflow intégré

PostGIS (Alteris) ──→ QGIS MCP ──→ carte exportée (PNG/PDF)
                                         │
                                         ▼
                              Inkscape CLI (ajustements SVG)
                                         │
                                         ▼
                              Scribus headless (mise en page finale)
                                         │
                                         ▼
                              StirlingPDF (compression)

Claude pilote l'ensemble de la chaîne : de la requête spatiale jusqu'au document final, sans intervention manuelle.


Ordre de priorité pour une mise en œuvre

Priorité Outil Action Effort
1 QGIS Installer le plugin qgis-mcp, tester avec une couche PostGIS Faible
2 Scribus Écrire un MCP custom Python headless, créer un gabarit .sla de référence Moyen
3 Inkscape MCP de manipulation SVG via lxml + CLI export Faible
4 GIMP MCP batch Python-Fu Moyen (faible priorité)

Recommandation : commencer par QGIS. C'est le maillon central du workflow de Julien, le MCP existe déjà, et la base PostGIS Alteris est immédiatement exploitable.

05_Claude et les MCP

QGIS MCP

Références


Architecture

Claude Code ↔ Serveur MCP Python (uvx) ↔ socket TCP local ↔ Plugin QGIS (dock "QGIS MCP")

Le plugin QGIS crée un serveur TCP local. Le serveur MCP Python (lancé par Claude Code via uvx) s'y connecte. QGIS doit être ouvert et le serveur démarré avant de lancer Claude Code.


Prérequis

Installer uv (gestionnaire de paquets Python) si absent :

winget install astral-sh.uv

Installation

1. Plugin dans QGIS

Extensions > Installer/Gérer les extensions > chercher QGIS MCP > Installer.

Redémarrer QGIS, puis cliquer Start Server dans le dock QGIS MCP.

2. Enregistrer le MCP dans Claude Code

claude mcp add -s user qgis -- uvx --from https://github.com/nkarasiak/qgis-mcp/archive/refs/heads/main.zip qgis-mcp-server

-s user = enregistrement global (tous les projets Claude Code).

3. Vérifier

Dans une session Claude Code avec QGIS ouvert et le serveur démarré, demander diagnose — confirme la synchronisation plugin/serveur MCP.


Ordre de démarrage (à chaque session)

  1. Ouvrir QGIS
  2. Cliquer Start Server dans le dock QGIS MCP
  3. Lancer Claude Code

Authentification (optionnel, machines partagées)

Définir QGIS_MCP_TOKEN=votre-secret dans l'environnement QGIS, redémarrer le serveur, puis ajouter la même variable à la config MCP :

"env": { "QGIS_MCP_TOKEN": "votre-secret" }

Capacités principales

Catégorie Exemples
Couches Charger Shapefile, GeoJSON, WMS, PostGIS ; lister, supprimer
Traitements Buffer, intersection, statistiques zonales (1000+ algorithmes)
Symbologie Modifier couleurs, classification, étiquettes
Export PNG, PDF, carte mise en page
SQL cross-couches Requêtes spatiales directement depuis Claude
Mise en page/Atlas Créer et exporter des atlas cartographiques

Lien avec PostGIS Alteris

La base alteris_geo (79.137.14.202:5432, user alteris_admin) est directement utilisable depuis QGIS MCP : Claude peut interroger PostGIS en SQL spatial, charger le résultat comme couche QGIS, styliser et exporter en PDF — sans intervention manuelle.

Le port 5432 n'est pas exposé publiquement (pare-feu VPS). Connexion via tunnel SSH obligatoire (voir section Tunnel SSH).


Tunnel SSH vers PostGIS Alteris

Option 1 — Tunnel manuel (terminal externe)

Lancer avant QGIS/Claude Code :

ssh -L 5433:localhost:5432 debian@79.137.14.202 -N

Puis se connecter sur localhost:5433 au lieu de 79.137.14.202:5432.

Option 2 — Tunnel automatique via paramiko (PyQGIS) ✓ validé 2026-06-20

Ouvre le tunnel directement depuis la console Python QGIS, sans terminal externe.

Installation de paramiko (une seule fois)

sys.executable dans QGIS pointe sur qgis-bin.exe — subprocess est inutilisable. Utiliser pip en interne :

from pip._internal.cli.main import main as pip_main
pip_main(['install', 'paramiko'])

Paramiko s'installe dans C:\Users\eliob\AppData\Roaming\Python\Python312\site-packages (dossier utilisateur). QGIS ne l'inclut pas automatiquement dans sys.path — ajouter à chaque session :

import sys
sys.path.insert(0, r'C:\Users\eliob\AppData\Roaming\Python\Python312\site-packages')
import paramiko
print(paramiko.__version__)  # 5.0.0

Script du tunnel (à lancer après l'import paramiko)

import socket
import threading
import select

class SSHTunnel(threading.Thread):
    def __init__(self, ssh_host, ssh_user, ssh_password,
                 remote_port, local_port=5433, remote_host='127.0.0.1'):
        super().__init__(daemon=True)
        self.ssh_host = ssh_host
        self.ssh_user = ssh_user
        self.ssh_password = ssh_password
        self.remote_host = remote_host
        self.remote_port = remote_port
        self.local_port = local_port
        self._stop = threading.Event()
        self.transport = None
        self.server_sock = None

    def run(self):
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(self.ssh_host, username=self.ssh_user, password=self.ssh_password)
        self.transport = client.get_transport()
        self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_sock.bind(('127.0.0.1', self.local_port))
        self.server_sock.listen(5)
        self.server_sock.settimeout(1.0)
        print(f"[Tunnel] localhost:{self.local_port} → {self.ssh_host} → {self.remote_host}:{self.remote_port}")
        while not self._stop.is_set():
            try:
                conn, _ = self.server_sock.accept()
                threading.Thread(target=self._forward, args=(conn,), daemon=True).start()
            except socket.timeout:
                continue
        self.server_sock.close()
        client.close()
        print("[Tunnel] Arrêté.")

    def _forward(self, local_conn):
        try:
            chan = self.transport.open_channel(
                'direct-tcpip',
                (self.remote_host, self.remote_port),
                local_conn.getpeername()
            )
        except Exception as e:
            print(f"[Tunnel] Erreur canal : {e}")
            local_conn.close()
            return
        while True:
            r, _, _ = select.select([local_conn, chan], [], [], 5)
            if local_conn in r:
                data = local_conn.recv(4096)
                if not data:
                    break
                chan.send(data)
            if chan in r:
                data = chan.recv(4096)
                if not data:
                    break
                local_conn.send(data)
        chan.close()
        local_conn.close()

    def stop(self):
        self._stop.set()


tunnel = SSHTunnel('79.137.14.202', 'debian', 'RAW+NEXTE!', remote_port=5432, local_port=5433)
tunnel.start()

import time; time.sleep(1)
s = socket.socket(); s.settimeout(3)
try:
    s.connect(('127.0.0.1', 5433)); print("Tunnel OK")
except Exception as e:
    print(f"Tunnel KO : {e}")
finally:
    s.close()

Pour arrêter : tunnel.stop()

Les avertissements DEPRECATION: Unexpected import of 'paramiko.*' sont inoffensifs (pip qui se plaint d'imports tardifs dans la même session).


Connexion PostGIS depuis PyQGIS

Charger une couche PostGIS

from qgis.core import QgsProject, QgsVectorLayer

uri = (
    "host=localhost port=5433 dbname=alteris_geo "
    "user=alteris_admin password=Alteris2026 sslmode=disable "
    'table="altfoncier_28051"."28051_plu_zonage" (geom) sql='
)
layer = QgsVectorLayer(uri, "PLU Zonage 28051", "postgres")
QgsProject.instance().addMapLayer(layer)

Point clé — champ JSONB props

Les tables altfoncier ont leurs attributs métier dans un champ props de type JSONB. Dans PyQGIS, ce champ est un dict Python (pas une chaîne). Pour y accéder en expression QGIS :

map_get("props", 'typezone')   ✓ correct
"props" LIKE '%typezone%'      ✗ ne fonctionne pas (props n'est pas une chaîne)

Stylisation CNIG PLU (zonage)

Renderer catégorisé sur map_get("props", 'typezone') :

typezone Couleur remplissage Couleur bordure Label
U #FFFF73 #A3A300 Zones urbaines
AU #FFAA00 #CD6600 Zones à urbaniser
A #D3FFBE #267300 Zones agricoles
N #98E600 #267300 Zones naturelles et forestières
from qgis.core import QgsCategorizedSymbolRenderer, QgsRendererCategory, QgsFillSymbol

cnig = {
    'U':  ('#FFFF73', '#A3A300', 'Zones urbaines (U)'),
    'AU': ('#FFAA00', '#CD6600', 'Zones à urbaniser (AU)'),
    'A':  ('#D3FFBE', '#267300', 'Zones agricoles (A)'),
    'N':  ('#98E600', '#267300', 'Zones naturelles et forestières (N)'),
}
categories = []
for tz, (fill, border, label) in cnig.items():
    symbol = QgsFillSymbol.createSimple({
        'color': fill, 'outline_color': border, 'outline_width': '0.26'
    })
    categories.append(QgsRendererCategory(tz, symbol, label))

renderer = QgsCategorizedSymbolRenderer("map_get(\"props\", 'typezone')", categories)
layer.setRenderer(renderer)
layer.triggerRepaint()

Journal de session

2026-06-20 — Premier diagnostic validé

Première connexion réussie entre Claude Code et QGIS via MCP. Résultat du diagnose :

Vérification Résultat
QGIS 4.0.3-Norrköping
Python 3.12.13
Qt 6.11.0
Plugin MCP 0.5.0 (serveur et plugin synchronisés)
Clients connectés 1
Providers de traitement 3d, gdal, grass, model, native, pdal, project, qgis, quickosm, script
Projet ouvert Aucun (layer_count = 0)

Statut global : healthy. Stack complète et opérationnelle.

2026-06-20 — Connexion PostGIS Alteris + stylisation CNIG

2026-06-20 — Tunnel paramiko validé

Prochaine étape :

05_Claude et les MCP

Inkscape MCP

Vue d'ensemble

Inkscape est un éditeur de graphisme vectoriel open source basé sur le format SVG. À la différence de QGIS, il n'existe pas de plugin MCP officiel pour Inkscape en juin 2026 — mais plusieurs approches sont réalistes, avec des niveaux d'effort et de puissance différents.


Approches possibles

Approche Effort Puissance Statut
1. Manipulation SVG directe Aucun Élevée (structure du fichier) Fonctionne déjà
2. MCP wrapper CLI Inkscape Moyen (écrire un serveur MCP) Moyenne (opérations CLI) À construire
3. Extension Inkscape + serveur TCP Élevé (plugin Python Inkscape) Maximale (GUI + rendu live) À construire

Approche 1 — Manipulation SVG directe (disponible maintenant)

SVG est du XML texte. Claude peut lire, écrire et modifier des fichiers .svg directement avec ses outils natifs, sans aucune intégration supplémentaire.

Ce que Claude peut déjà faire

Limites de cette approche

Flux de travail type

Claude génère/modifie le .svg → tu recharges dans Inkscape (Ctrl+Z+rechargement) → ajustements manuels → boucle

Approche 2 — MCP wrapper CLI Inkscape

Inkscape expose une interface en ligne de commande (--actions) qui permet d'automatiser des opérations sans ouvrir l'interface graphique.

Commandes CLI Inkscape utiles

# Export PNG depuis SVG
inkscape --export-type=png --export-filename=sortie.png source.svg

# Export PDF
inkscape --export-type=pdf --export-filename=sortie.pdf source.svg

# Appliquer une transformation et exporter
inkscape --actions="select-all;object-set-attribute:transform,scale(2)" source.svg --export-type=svg --export-filename=sortie.svg

# Convertir texte en chemins
inkscape --actions="select-all;object-to-path" source.svg --export-type=svg --export-filename=sortie.svg

# Obtenir les dimensions du document
inkscape --query-all source.svg

Architecture d'un serveur MCP CLI

Claude Code ↔ Serveur MCP Python (stdio) ↔ subprocess inkscape CLI ↔ fichiers SVG/PNG/PDF

Un serveur MCP Python minimal exposerait des outils comme :

Prérequis

# Inkscape doit être dans le PATH
inkscape --version
# Inkscape 1.x.x (...)

Sur Windows, ajouter le dossier Inkscape au PATH système ou utiliser le chemin complet :

C:\Program Files\Inkscape\bin\inkscape.exe

Approche 3 — Extension Inkscape + serveur TCP (pattern QGIS)

La plus puissante mais la plus complexe à mettre en place. Inkscape supporte les extensions Python via le module inkex. Une extension pourrait ouvrir un socket TCP local et exposer des outils MCP (similaire au plugin QGIS MCP).

Architecture

Claude Code ↔ Serveur MCP Python (uvx) ↔ socket TCP local ↔ Extension Python Inkscape

Ce que ça permettrait

Obstacles techniques


Capacités envisageables selon l'approche

Capacité Approche 1 (SVG direct) Approche 2 (CLI) Approche 3 (Extension)
Créer des formes géométriques ✓ ✓ ✓
Modifier couleurs / styles ✓ ✓ ✓
Gérer les calques ✓ — ✓
Exporter PNG/PDF — ✓ ✓
Convertir texte en chemins — ✓ ✓
Boolean operations — ✓ (CLI) ✓
Lire sélection courante — — ✓
Appliquer filtres Inkscape — ✓ (partiel) ✓
Batch processing de fichiers ✓ ✓ —
Rendu live dans l'UI — — ✓

Cas d'usage concrets avec Inkscape

Avec l'approche 1 (maintenant)

Avec l'approche 2 (à construire, effort ~2h)


Lien avec le workflow cartographique

Inkscape est souvent utilisé en aval de QGIS pour l'habillage cartographique (polices, mise en page avancée, symboles non gérés par QGIS). Le flux naturel serait :

QGIS MCP → export SVG → Claude (habillage Inkscape SVG direct) → Inkscape (retouches manuelles) → export PDF final

QGIS peut exporter une mise en page en SVG via Projet > Imprimer la mise en page > Exporter en SVG. Claude peut ensuite enrichir ce SVG (légendes, encadrés, pictogrammes) avant ouverture dans Inkscape.


Prochaine étape proposée

Trois options pour explorer concrètement :

  1. Test SVG direct — Claude génère un SVG d'exemple (carte, diagramme, gabarit) et tu l'ouvres dans Inkscape pour voir le résultat
  2. Prototype CLI MCP — écrire un serveur MCP Python minimal (~50 lignes) wrappant les exports Inkscape CLI, l'enregistrer dans Claude Code
  3. Exploration API inkex — ouvrir la console Python d'Inkscape et tester quelques commandes inkex pour évaluer la faisabilité de l'approche 3

Mise en place réalisée (2026-07-21)

L'approche 2 (MCP wrapper CLI Inkscape) a été implémentée sur le PC Windows eliob.

Obstacle rencontré : version Microsoft Store (MSIX)

Le PC avait initialement Inkscape installé via le Microsoft Store, packagé en MSIX. Ce type de paquet s'est révélé inutilisable pour un pilotage CLI :

Conclusion : les versions Inkscape installées via le Microsoft Store ne conviennent pas à un usage MCP/CLI. Il faut la version standalone.

Fix — installation de la version standalone

winget install --id Inkscape.Inkscape --source winget --accept-package-agreements --accept-source-agreements

Important : si une version Store est déjà présente, la désinstaller d'abord (Paramètres > Applications, ou winget uninstall) pour éviter la confusion entre les deux installations.

Serveur MCP créé

Outils exposés :

Outil Rôle
get_version() Vérifie qu'Inkscape répond (smoke test)
get_document_dimensions(svg_path) Dimensions et bounding boxes de tous les objets (--query-all)
export_png(svg_path, output_path="", dpi=96) Export PNG
export_pdf(svg_path, output_path="") Export PDF
convert_text_to_paths(svg_path, output_path="") Convertit les textes en chemins vectoriels
apply_inkscape_action(svg_path, actions, output_path="") Échappatoire générique — chaîne d'actions Inkscape libre (; séparées)

Toutes les fonctions retournent {ok, returncode, stdout, stderr} (+ output_path pour les exports) — pas d'exception levée sur échec CLI, le code retour renseigne l'appelant.

Enregistrement MCP

Ajouté dans C:\Users\eliob\.mcp.json :

"inkscape": {
  "type": "stdio",
  "command": "python",
  "args": ["C:\\Users\\eliob\\.claude\\mcp_inkscape.py"],
  "env": {}
}

Nécessite un rechargement de session Claude Code pour que le nouveau serveur MCP soit détecté et ses outils exposés.

Test réalisé

SVG de test (rectangle bleu + texte) → export_png → PNG de 1974 octets généré avec succès. get_document_dimensions retourne correctement les bounding box (svg1,10,10,180,80 etc.) via --query-all.

À reproduire demain sur le PC Windows Alteris

  1. Vérifier si Inkscape est installé via le Store (Get-AppxPackage -Name "*Inkscape*") — si oui, désinstaller
  2. winget install --id Inkscape.Inkscape --source winget --accept-package-agreements --accept-source-agreements
  3. Vérifier C:\Program Files\Inkscape\bin\inkscape.exe --version
  4. Copier mcp_inkscape.py (script identique, chemin INKSCAPE_EXE à adapter si besoin)
  5. Ajouter l'entrée inkscape dans le .mcp.json de la machine Alteris
  6. Recharger la session Claude Code et tester get_version() + export_png() sur un SVG de test

Confirmation de fonctionnement (2026-07-21, session rechargée)

Après rechargement de la session Claude Code, le serveur MCP inkscape est bien détecté et ses 6 outils sont exposés. Tests effectués dans l'ordre :

Test Résultat
get_version() OK — Inkscape 1.4.4 (dcaf3e7, 2026-05-05)
get_document_dimensions(svg_path) sur un SVG de test (rect 80x80) OK — svg1,10,10,80,80 / rect1,10,10,80,80
export_png(svg_path) OK — PNG généré (389 octets), fichier vérifié sur disque

Conclusion : le protocole MCP Inkscape est pleinement opérationnel sur le PC Windows eliob, de bout en bout (Claude Code → serveur MCP Python → subprocess Inkscape CLI → fichier de sortie).

05_Claude et les MCP

LibreOffice MCP

État au 2026-10-02 : réinstallé sur le poste julie (le PC eliob après la réinstallation de Windows du 2026-08-08, qui avait emporté l'ancienne configuration). Extension Nelson MCP 0.14.3, serveur actif sur 127.0.0.1:8766 (process soffice.bin), MCP nelson inscrit en portée utilisateur dans C:\Users\julie\.claude.json — voir « Installation sur julie » ci-dessous.

État au 2026-08-05 : installé et opérationnel sur le PC Windows eliob. Extension Nelson MCP 0.7.1, LibreOffice 26.2.5.2, serveur HTTP actif sur 127.0.0.1:8766, 110 outils exposés, MCP nelson enregistré dans Claude Code pour le projet D:\Syncthing\Jux_univers\Claude-pcelio+jux.

Cette page a été réécrite le 2026-08-05 à partir de l'installation réelle. La version précédente reposait sur une recherche web et contenait plusieurs erreurs — voir la section « Erreurs de la version précédente » en fin de page.

Nelson MCP — piloter LibreOffice depuis Claude Code

Le principe

Nelson n'est pas un serveur MCP séparé qu'on lance à côté de LibreOffice. C'est une extension .oxt qui embarque un serveur HTTP dans le process soffice.bin. Claude Code s'y connecte en HTTP et pilote les documents ouverts dans la fenêtre LibreOffice, en direct, via l'API UNO.

Conséquences pratiques :


Installation

1. Extension

Outils → Gestionnaire des extensions → Ajouter → sélectionner nelson.oxt, puis redémarrer LibreOffice.

Emplacement après installation (Windows) :

%APPDATA%\LibreOffice\4\user\uno_packages\cache\uno_packages\<hash>.tmp_\nelson.oxt\

Le sous-dossier <hash>.tmp_ est généré par LibreOffice — sur eliob : lu3692afhf.tmp_. Ne pas le coder en dur dans un script, le retrouver par Get-ChildItem ...\uno_packages -Recurse -Filter nelson.oxt.

2. Démarrage du serveur

Menu Nelson → Start HTTP Server (le libellé bascule en « Stop HTTP Server » quand il tourne, avec icône d'état vert/orange/gris). Le serveur peut aussi démarrer automatiquement si http.enabled est coché dans les options.

Valeurs par défaut : host localhost, port 8766. Modifiables dans Outils → Options → Nelson, ainsi que TLS (use_ssl, ssl_cert, ssl_key).

Vérifier :

netstat -ano | Select-String ":8766"

Le PID retourné doit être celui de soffice.bin.

3. Enregistrement dans Claude Code

claude mcp add --transport http nelson http://127.0.0.1:8766/mcp

Écrit dans C:\Users\eliob\.claude.json, section projects > <projet> > mcpServers. Vérifier avec claude mcp list → nelson: ✔ Connected.

Relancer la session Claude Code : les outils d'un MCP ajouté en cours de session ne sont pas chargés.

3 bis. Installation sur le poste julie (2026-10-02)

Le CLI claude n'est pas dans le PATH de ce poste (application de bureau) : claude mcp add est impossible, l'entrée s'écrit à la main dans C:\Users\julie\.claude.json (sauvegarder d'abord), puis on ferme et rouvre l'application.

json mcpServers: { nelson: { type: http, url: http://127.0.0.1:8766/mcp } }

⚠ Piège : en portée projet, le MCP n'est pas chargé. Première inscription sous projects > D:\Syncthing\Jux_univers\Claude-pcelio+jux\.claude > mcpServers : après redémarrage, aucun outil Nelson — et pas davantage ceux de bookstack ou kdrive, inscrits au même endroit. Seul caldav, en portée utilisateur (mcpServers à la racine du fichier), était chargé. Nelson a donc été déplacé à la racine. Contrepartie : ses outils sont présents dans toutes les sessions, quel que soit le projet.

Nombre d'outils variable. Le tools/list interrogé en HTTP, LibreOffice ouvert sans document, n'a rendu que 26 outils (gestion de documents, images, formes, styles, jobs, batch_execute) au lieu des 110 relevés en août. Les outils Writer, Calc ou Draw n'apparaissent que si un document de ce type est actif — ouvrir le document avant de démarrer la session.


Endpoints HTTP

Méthode Chemin Rôle
POST/GET/DELETE /mcp MCP Streamable HTTP (transport actuel) — c'est celui à utiliser
POST/GET /sse, /messages ancien transport SSE, pour clients qui ne gèrent pas Streamable HTTP
GET /health état du serveur
GET /api/tools référence HTML de tous les outils
GET / page d'info
GET/POST /api/config lecture/écriture de la configuration — désactivé par défaut (http.enable_config_api)

Test de connexion en une commande :

curl -s -X POST http://127.0.0.1:8766/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}'

Réponse attendue : serverInfo: {"name":"Nelson MCP","version":"0.7.1"} + un en-tête Mcp-Session-Id.


Ce que ça permet réellement — 110 outils

Writer

Lecture et écriture par paragraphe (read_paragraphs, insert_at_paragraph, set_paragraph_text, delete_paragraph, duplicate_paragraph, insert_paragraphs_batch), styles, plan/outline, tableaux, images, cadres, hyperliens, commentaires, statistiques, recherche/remplacement, suivi des modifications (accept/reject), navigation (signets, titres, proximité), et un index plein texte avec stemming (33 langues embarquées via snowballstemmer, base SQLite embarquée).

Calc

Cellules, lignes, feuilles, formules, graphiques, formatage conditionnel, commentaires, navigation, recherche, et un détecteur d'erreurs de feuille.

Draw / Impress

Pages, formes, masques, notes, transitions, espaces réservés.

Transversal

execute_batch (plusieurs appels en une requête, avec chaînage de variables entre opérations), undo/redo, document_health_check (titres vides, sauts de niveau de titre, images orphelines…), ouverture/création/sauvegarde/export/impression, jobs asynchrones (list_jobs, get_job).

Galeries et images IA

Fonction =PROMPT() dans Calc

Fournie par XPromptFunction.rdb — interroge un fournisseur IA directement depuis une formule de feuille de calcul.


Deux garde-fous activés par défaut

Ce sont les réglages les plus importants de la page Options (core) :

Réglage Défaut Effet
force_track_changes activé active l'enregistrement des modifications avant toute mutation venant du MCP — toutes les modifications de l'IA sont visibles et réversibles
follow_activity activé fait défiler la vue vers l'endroit modifié, en temps réel

À ne pas désactiver sans raison : c'est ce qui rend une session d'édition par IA relisable.

Le panneau latéral Nelson (deck NelsonDeck, visible dans Writer et Calc) affiche le journal des actions MCP et les jobs en cours.


Presets — réduire la surface d'outils

110 outils, c'est beaucoup de contexte. Nelson permet de créer des endpoints filtrés : Options → Nelson → MCP → preset puis bouton de création. L'endpoint apparaît sur /mcp/<preset>.

Preset Contenu
minimal 8 outils — lister/ouvrir/créer/sauver, lire et insérer des paragraphes, insérer une image
writer-read 14 outils, lecture seule
writer-edit 24 outils d'édition Writer
calc 13 outils tableur
gallery 10 outils images/documents

Utile pour un modèle plus petit, ou pour interdire les mutations (writer-read).


Launchers intégrés — l'autre façon de faire

Nelson sait lancer lui-même Claude Code (aussi Gemini CLI et OpenCode), depuis LibreOffice. Le module launcher.claude crée alors un espace de travail dans :

~/.local/share/nelson/cli/claude

et y génère automatiquement :

puis lance claude --resume dans ce dossier.

Choix retenu sur eliob : ne pas utiliser le launcher, et brancher le MCP sur les projets existants. Raisons — l'espace de travail du launcher est isolé et perd le CLAUDE.md du Jux_univers ; et l'auto-approbation globale mcp__nelson__* inclut les outils de mutation et de sauvegarde de fichiers.


Tunnels — accès distant

Modules tunnel.cloudflare, tunnel.ngrok, tunnel.tailscale (Funnel), tunnel.bore : exposent le serveur HTTP local à l'extérieur, pour piloter LibreOffice depuis un client MCP distant (l'aide embarquée documente le cas ChatGPT via Tailscale).

À manier avec prudence : cela publie sur internet un endpoint qui peut lire, modifier et enregistrer des fichiers locaux. Le serveur écoute par défaut sur localhost uniquement — c'est le bon réglage. Voir l'incident du 2026-06-09 sur l'API RC rclone exposée en 0.0.0.0 (VPS Jux), même schéma de risque.


Aide embarquée

L'extension embarque sa propre documentation HTML, consultable directement :

<...>\nelson.oxt\help\index.html

Fichiers utiles : writer.html (33 Ko), calc.html (20 Ko), draw.html, batch.html, documents.html, ai_images.html, et des how-to (howto_connect-chatgpt-tailscale, howto_setup-ollama-indexation, howto_setup-image-gallery, howto_setup-forge-images).


Points de vigilance


Erreurs de la version précédente de cette page

La version antérieure de cette page avait été rédigée à partir d'une recherche web, avant installation. Corrections :

Ancienne affirmation Réalité vérifiée
Port 8765 Port 8766 (cfg.get("port") or 8766 dans modules/http/__init__.py)
python3 -m nelson_mcp --port 8765 Cette commande n'existe pas — le serveur est embarqué dans soffice.bin
Variante de configuration stdio Inexistante — HTTP uniquement
.oxt à télécharger « depuis lobehub » lobehub est un annuaire ; la source est le dépôt quazardous/nelson-mcp
LibreOffice ≥ 24.2 requis La dépendance déclarée est 4.1 ; LibreOffice 26.2.5.2 en place
Alternatives libreoffice-mcp (KeithCu) port 2083, OooDev Sans objet une fois Nelson en place
05_Claude et les MCP

Baikal MCP pour la gestion des agendas perso et NEXTE et de l'observatoire des tâches

1-l'infrastructure Baikal et Infcloud sur le vps personnel - juxjux.ovh


Cas à part de la gestion des contacts et du calendrier - 
Non pas sur alteris.ovh mais sur juxjux.ovh car primauté de l'infrastructure personnelle de JUlien pour la gestion des agendas et des contacts.

la solution contacts et calendrier


Solution d'unification des contacts et du calendrier de Julien.

État au 3 août 2026 — déployé et opérationnel de bout en bout. Seul vdirsyncer (agrégation Google/Infomaniak) reste à faire.


1. Objectif

Unifier la base de contacts et de calendriers, dispersée entre plusieurs sources (Google, Infomaniak, téléphone), autour d'un point central auto-hébergé sur le VPS juxjux.ovh, synchronisé vers tous les clients existants.

Baïkal est la source de vérité unique. Roundcube, InfCloud et DAVx5 en sont des clients ; vdirsyncer sera le seul composant qui écrit depuis l'extérieur vers Baïkal.

2. Architecture réellement déployée

Composant Rôle Emplacement État
Baïkal Serveur CardDAV + CalDAV, stockage central Docker, VPS juxjux En service
InfCloud Agenda et contacts web Statique, servi par nginx En service
Roundcube Interface web des contacts Docker, VPS juxjux En service
Nginx Reverse proxy HTTPS Hôte VPS En service
DAVx5 Pont de synchronisation vers Android Téléphone Opérationnel
Fossify Agenda Client calendrier Téléphone (via DAVx5) Opérationnel
vdirsyncer Agrège Google et Infomaniak vers Baïkal VPS, cron Non déployé
Thunderbird Client mail, indépendant de ce circuit Téléphone Inchangé

3. Accès

Service URL Identifiant
Agenda + contacts web https://baikal.juxjux.ovh/infcloud/ Julien (compte Baïkal)
Contacts web (Roundcube) https://secretariat.juxjux.ovh julien.bertrand@ik.me (compte mail Infomaniak)
Administration Baïkal https://baikal.juxjux.ovh/admin/ compte admin Baïkal
Découverte DAV (DAVx5) https://baikal.juxjux.ovh/dav.php/ Julien

Utilisateur Baïkal : Julien — avec un J majuscule. La casse compte dans les URLs DAV.

Certificats Let's Encrypt valides jusqu'au 1er novembre 2026 pour les deux domaines. Celui de baikal.juxjux.ovh existait déjà mais avait expiré le 8 février 2026 (vestige d'une tentative antérieure) ; il a été renouvelé le 3 août.

4. Déploiement

Stack sur le VPS : /home/debian/baikal/docker-compose.yml, projet compose baikal. Sources versionnées : Syncthing/Jux_univers/Jux-scripts/Baikal-Contacts/.

Fichier Rôle
docker-compose.yml Stack Baïkal + Roundcube
baikal.juxjux.ovh.conf Vhost Baïkal (.well-known forcés en HTTPS + service d'InfCloud)
secretariat.juxjux.ovh.conf Vhost Roundcube
infcloud-config.js Configuration InfCloud
finaliser_tls.sh Vérifie le DNS puis lance certbot
vps_backup.sh Script de sauvegarde complet, Baïkal inclus
push_bookstack.py Publication de cette page via l'API BookStack


1
cd /home/debian/baikal && sudo docker compose -p baikal up -d


Service Image Port local Base RAM
baikal ckulka/baikal:nginx 127.0.0.1:8088 SQLite ~38 Mo
roundcube roundcube/roundcubemail:latest (1.7.2) 127.0.0.1:8083 SQLite ~32 Mo
InfCloud fichiers statiques (13 Mo sur disque) — aucune 0

Les deux containers pèsent environ 70 Mo au total, contre environ 600 Mo avec l'architecture MariaDB initialement prévue. Ce choix était important : le VPS était en pression mémoire au moment du déploiement (swap à 3,8/4,0 Go).

5. Écarts avec le plan initial

Le plan préparé prévoyait une configuration qui ne pouvait pas fonctionner en l'état. Écarts constatés et corrigés :

Point Prévu Réel Raison
Port Baïkal 8081 8088 8081 est occupé par FreshRSS. 8088 correspond au vhost baikal.juxjux.ovh préexistant
Port Roundcube 8082 8083 8082 est ciblé par un vhost nextcloud mort
Domaine Roundcube mail.juxjux.ovh secretariat.juxjux.ovh Aucun DNS n'existait ; mail. prêtait à confusion avec les MX OVH du domaine
Base Roundcube MariaDB SQLite ~400 Mo de RAM économisés, suffisant en mono-utilisateur
Vhost Baïkal À créer Déjà présent Le fichier baikal.conf préparé n'a pas servi
Agenda web Plugin calendar Roundcube InfCloud Plugin inutilisable, voir §6.2

6. Pièges rencontrés

6.1 Les plugins carddav et calendar ne sont pas dans l'image Roundcube

L'image officielle ne fournit ni carddav ni calendar. Les déclarer dans ROUNDCUBEMAIL_PLUGINS ne fait que les activer — s'ils sont absents, Roundcube part en erreur fatale.

Il faut les faire installer par composer au démarrage, via ROUNDCUBEMAIL_COMPOSER_PLUGINS (et non ROUNDCUBEMAIL_INSTALL_PLUGINS, qui n'existe pas dans cette image) :



1
2
ROUNDCUBEMAIL_COMPOSER_PLUGINS: "roundcube/carddav"
ROUNDCUBEMAIL_PLUGINS: "carddav"


Le premier démarrage est alors plus long (téléchargement composer).

6.2 Le plugin calendar de Roundcube est une impasse

Trois obstacles successifs, testés le 3 août :

a) Il casse le tout premier démarrage. Le script d'initialisation de base de kolab/calendar s'exécute avant que l'entrypoint n'écrive la configuration Roundcube : il tombe sur le DSN MySQL par défaut et échoue en SQLSTATE[HY000] [2002] No such file or directory. Cette erreur fatale empêche la régénération de l'autoloader composer, ce qui casse aussi le plugin carddav :



1
2
3
PHP Fatal error: Uncaught Error: Interface
"MStilkerich\RCMCardDAV\Frontend\RcmInterface" not found
in /var/www/html/plugins/carddav/carddav.php:43


Symptôme : HTTP 500 permanent, alors que les fichiers du plugin sont bien présents sur le disque — c'est vendor/composer/autoload_psr4.php qui ne contient aucune entrée carddav.

b) Ce premier obstacle est contournable. Réinstallé après que Roundcube ait été initialisé une première fois, la configuration existe déjà dans le volume et l'initialisation aboutit (Creating database schema... [OK]). Vérifié.

c) Mais le plugin ne sait pas parler à Baïkal. La seule version installable, kolab/calendar 3.2.9.1, ne livre que les pilotes database, kolab et ldap — aucun pilote caldav. Il ne créerait qu'un agenda local dans Roundcube, sans lien avec Baïkal ni le téléphone : pire qu'inutile, on pourrait y saisir des rendez-vous en croyant qu'ils se synchronisent.

Les versions qui embarquent le pilote CalDAV (3.5.7, 3.6.1) dépendent de kolab/libkolab, qui réclame pear/http_request2 — paquet bloqué par composer pour faille de sécurité (PKSA-jrt3-xndd-g4sz). Ne pas contourner ce garde-fou sur un service exposé sur internet.

Conclusion : agenda web assuré par InfCloud (§7), plugin calendar définitivement écarté.

6.3 Baïkal ignore X-Forwarded-Proto — fuite HTTP sur la découverte

Baïkal ne tient pas compte de X-Forwarded-Proto et générait ses redirections de découverte en HTTP nu :



1
/.well-known/carddav -> http://baikal.juxjux.ovh/dav.php


C'est exactement le risque identifié dès la conception : CardDAV et CalDAV envoient les identifiants à chaque synchronisation. Un client suivant cette redirection part sur du HTTP.

Corrigé en court-circuitant Baïkal directement dans le vhost :



1
2
3
4
5
6
location = /.well-known/carddav {
return 301 https://$host/dav.php/;
}
location = /.well-known/caldav {
return 301 https://$host/dav.php/;
}


À vérifier après tout reload nginx : le rechargement n'est pas instantané, un test lancé dans la foulée peut encore montrer l'ancien comportement.

6.4 Roundcube exige un serveur IMAP pour authentifier

Roundcube n'a pas de base d'utilisateurs propre : son écran de login valide les identifiants contre le serveur IMAP configuré. Sans IMAP joignable, aucune connexion n'est possible — donc aucun accès aux contacts non plus.

L'idée d'un Roundcube « contacts et agenda seulement, sans IMAP » n'est pas réalisable. La configuration retenue pointe vers ssl://mail.infomaniak.com:993, ce qui couvre le compte julien.bertrand@ik.me (le domaine ik.me est servi par l'infrastructure Infomaniak).

Si un jour le compte passe en double authentification, il faudra générer un mot de passe d'application Infomaniak.

6.5 Baïkal doit être installé en SQLite

L'installeur Baïkal propose MySQL ou SQLite. Choisir SQLite : la stack ne contient aucun serveur MySQL, cocher « Enable MySQL » mène à une impasse. Base à /var/www/baikal/Specific/db/db.sqlite, dans le volume baikal-data.

7. InfCloud — l'agenda web

Client CalDAV/CardDAV entièrement côté navigateur : aucun backend, aucune base, du HTML/JS servi en statique par nginx. Affiche agenda et contacts.

Réserve assumée : projet figé depuis 2015, interface datée, embarque jQuery 2.1.4. Acceptable parce qu'il n'a aucun composant serveur : rien à maintenir, rien à patcher. La seule alternative maintenue serait SOGo, au prix d'environ 500 Mo de RAM et d'une base PostgreSQL.

7.1 Les trois pièges d'InfCloud

a) Le bloc regex du vhost avale tous les JS. Le vhost Baïkal contient déjà :



1
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { proxy_pass http://127.0.0.1:8088; }


En nginx, un bloc regex ~* a priorité sur un bloc préfixe ordinaire. Tous les fichiers JavaScript d'InfCloud auraient donc été proxifiés vers Baïkal. Comme InfCloud est presque intégralement du JavaScript, la page serait restée blanche — symptôme difficile à diagnostiquer. Il faut ^~, qui passe devant les regex :



1
2
3
4
5
location ^~ /infcloud/ {
alias /home/debian/baikal/infcloud/;
index index.html;
location ~ /\. { deny all; }
}


b) L'endpoint par défaut vise DAViCal. Le config.js livré pointe /caldav.php/ ; Baïkal expose /dav.php/.

c) Le href doit viser les principals, pas la racine DAV. InfCloud accole le nom d'utilisateur au href. Avec /dav.php/ il demandait /dav.php/Julien/ → 404. La documentation du fichier le précise : « globalNetworkCheckSettings : principal URL WITHOUT the USER/ part ». Chez Baïkal, la bonne valeur est donc :



1
'/dav.php/principals/',


Après toute modification de config.js, rechargement forcé du navigateur (Ctrl+Maj+R) : le fichier est mis en cache.

7.2 Digest → Basic : le blocage d'authentification

Baïkal était configuré en dav_auth_type: Digest et annonçait WWW-Authenticate: Digest realm="BaikalDAV".

InfCloud ne sait faire que du Basic. Ses requêtes partaient donc en 401 en boucle, alors que DAVx5 — qui gère Digest — fonctionnait parfaitement avec le même compte. Le symptôme prêtait à confusion : les identifiants étaient bons.

Diagnostic par les logs nginx, où le champ utilisateur est renseigné mais la réponse reste 401 :



1
83.195.45.93 - Julien "PROPFIND /dav.php/ HTTP/2.0" 401


Correctif : dav_auth_type: Basic dans /var/www/baikal/config/baikal.yaml, puis docker restart baikal.

Ce n'est pas un pis-aller. Digest repose sur MD5, est considéré comme obsolète, et impose au serveur de stocker une empreinte exploitable ; Basic sur TLS est aujourd'hui la recommandation, et tout est en HTTPS ici, y compris les redirections de découverte (§6.3).

Les mots de passe restent valides : Baïkal calcule la même empreinte md5(username:auth_realm:password) dans les deux modes (Baikal\Core\PDOBasicAuth::validateUserPass), avec auth_realm: BaikalDAV conservé en interne — même si le serveur annonce désormais realm="sabre/dav" côté client. Rien à redéfinir, DAVx5 bascule tout seul.

Sauvegarde : /var/www/baikal/config/baikal.yaml.bak-260803-digest (dans le container).

8. Sauvegarde

Baïkal a été ajouté à /opt/backups/vps_backup.sh le 3 août 2026 (cron quotidien à 2h UTC).

La fonction archive deux volumes, via un tar intermédiaire puis 7z :

Sans le second, la restauration est incomplète. Testée le 3 août : upload HTTP 200, aucun résidu temporaire.

InfCloud n'a pas besoin d'être sauvegardé (fichiers statiques réinstallables), mais son config.js est versionné dans Jux-scripts/Baikal-Contacts/.

9. Vérifications effectuées le 3 août 2026

Test Résultat
GET /dav.php/ HTTP 401 — authentification bien exigée
PROPFIND /dav.php/ HTTP 401 et non 405 — nginx laisse passer les méthodes DAV étendues
.well-known/carddav et caldav 301 vers HTTPS
Installation Baïkal Utilisateur Julien, carnet et calendrier default créés
Login Roundcube IMAP Infomaniak accepté
Découverte CardDAV Roundcube Carnet résolu à .../dav.php/addressbooks/Julien/default/
Écriture d'un contact vCard 3.0 écrite par RCMCardDAV v5.1.3, relue dans Baïkal, accents UTF-8 préservés
Synchronisation DAVx5 5 rendez-vous d'août écrits dans Baïkal par DAVx5/4.5.18-ose, synctoken du calendrier à 6
InfCloud 32 ressources servies en 200 ; PROPFIND sur principals, addressbooks et calendars tous en 207
Dotfiles InfCloud .htaccess bloqué en 403
Sauvegarde Baïkal Archive uploadée sur kDrive, HTTP 200

Note : dans la table carddav_addressbooks de Roundcube, une seconde ligne nommée %N avec une URL vide n'est pas une erreur — c'est le template de rcmcarddav v5, qui porte les réglages appliqués aux carnets découverts.

10. Reste à faire

10.1 vdirsyncer — agrégation Google et Infomaniak

Seule brique du plan initial encore absente. Objectif : faire remonter dans Baïkal les contacts existants sur Google et Infomaniak, pour que Baïkal devienne le point central réel et pas un silo de plus.

Décision à prendre avant déploiement :

Recommandation : démarrer en one-way le temps de vérifier que l'import est fidèle, puis basculer si besoin.

10.2 Nettoyage

Quatre vhosts morts traînent dans /etc/nginx/sites-enabled/, vestiges des tentatives précédentes : radicale, agendav, infcloud, nextcloud. Le dernier cible le port 8082, ce qui a contraint le choix du port de Roundcube. Attention : le vhost nommé radicale.juxjux.ovh sert en réalité Readeck — ne pas le supprimer sans vérifier.

11. Checklist sécurité

12. Commandes utiles



# État de la stack
sudo docker ps --filter name=baikal --filter name=roundcube

# Logs
sudo docker logs roundcube --tail 50
sudo docker logs baikal --tail 50

# Redéployer
cd /home/debian/baikal && sudo docker compose -p baikal up -d

# Inspecter la base Baïkal
sudo docker cp baikal:/var/www/baikal/Specific/db/db.sqlite /tmp/bk.sqlite
sudo sqlite3 /tmp/bk.sqlite "SELECT COUNT(*) FROM cards;"
sudo sqlite3 /tmp/bk.sqlite "SELECT COUNT(*) FROM calendarobjects;"
sudo sqlite3 /tmp/bk.sqlite "SELECT id, username FROM users;"

# Méthode d'authentification annoncée par Baïkal
curl -s -D - -o /dev/null -X PROPFIND -H 'Depth: 0' \
https://baikal.juxjux.ovh/dav.php/ | grep -i www-authenticate

# Suivre les requêtes DAV des clients (DAVx5, InfCloud, Roundcube)
sudo tail -f /var/log/nginx/access.log | grep dav.php

# Vérifier la découverte DAV
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" \
https://baikal.juxjux.ovh/.well-known/carddav


13. Choix d'architecture — pourquoi ces outils

Radicale écarté : stockage fichier brut, pas de vraie gestion. La stack Radicale/InfCloud initialement envisagée n'a pas été mise en place — seul InfCloud a finalement été retenu, en client de Baïkal.

Nextcloud écarté : trop lourd pour l'usage visé (PHP-FPM + base + Redis + écosystème complet), alors que le VPS fait déjà tourner PostGIS, Metabase, BookStack, FreshRSS.

Baïkal retenu : léger, CardDAV et CalDAV natifs, interface d'administration suffisante. Développé par des bénévoles sous l'organisation sabre-io (mainteneurs de SabreDAV, la librairie sous-jacente) — pas de société commerciale derrière, mais communauté active et outil robuste pour un usage personnel sur la durée.

Roundcube retenu comme interface de saisie des contacts, Baïkal n'ayant pas de vraie UI de consultation : léger, traduit en français, projet actif (version 1.7.2 en août 2026). A rejoint la famille Nextcloud en 2023 tout en restant indépendant, sous licence GPL. Réserves constatées à l'usage : il impose une authentification IMAP (§6.4) et ne couvre pas l'agenda (§6.2).

InfCloud retenu pour l'agenda web : sans backend, donc sans coût mémoire ni surface d'attaque serveur, et couvre agenda et contacts. Ancien mais fonctionnel.

SOGo envisagé et écarté : suite complète et maintenue, mais environ 500 Mo de RAM et une base PostgreSQL sur un VPS déjà en pression mémoire, et il aurait fait doublon avec Roundcube.

Thunderbird containerisé (VNC/noVNC) envisagé puis écarté : fonctionnel mais plus lourd et moins adapté au multi-accès qu'un vrai webmail.

2-MCP CalDAV pour Claude Code — un agenda Baïkal partagé par les deux PC


MCP CalDAV pour Claude Code

État au 16 septembre 2026 — opérationnel sur les deux PC. Cycle complet validé le 15/09 sur NEXTE : création de calendrier, écriture d'un événement, relecture, visibilité sur le téléphone (DAVx5 → Fossify) et dans InfCloud, suppression. Installé sur le PC perso le 16/09 (§7.8), avec un écart de méthode : venv Python sur D: au lieu de uv.

Prérequis : l'infrastructure Baïkal décrite en page 1 de ce chapitre (Baïkal en Docker sur juxjux.ovh, Basic auth sur TLS, utilisateur DAV Julien).


1. Décision d'architecture

Un seul Baïkal, sur juxjux.ovh, partagé par les deux Claude Code (PC perso et PC NEXTE). C'est la seule exception assumée à l'étanchéité entre l'univers Jux et l'univers Alteris/NEXTE.

Pourquoi ne pas dupliquer Baïkal sur le VPS Alteris :

Pourquoi l'exception est acceptable : l'étanchéité protège les fichiers et données de mission. Un agenda n'est pas une donnée de mission, c'est un service de la personne, comme le téléphone. Le PC NEXTE devient un client CalDAV de plus, au même titre que DAVx5 ; aucune donnée Jux n'entre sur NEXTE, aucune donnée Alteris ne sort vers juxjux. Seul l'identifiant Baïkal traverse — il est dans le Vault 2603.

2. Modèle : un utilisateur, deux calendriers

Calendrier URL Usage Couleur PC qui y écrit par défaut
Default calendar https://baikal.juxjux.ovh/dav.php/calendars/Julien/default/ Personnel (Julien) (installeur) PC perso
NEXTE https://baikal.juxjux.ovh/dav.php/calendars/Julien/nexte/ Professionnel NEXTE (pas Alteris) #1E88E5 bleu PC NEXTE

Même compte Julien pour les deux, donc les deux calendriers apparaissent ensemble dans DAVx5, Fossify et InfCloud, chacun avec sa couleur.

Règle de lecture/écriture du MCP : chaque PC écrit dans son calendrier par défaut (CALDAV_DEFAULT_CALENDAR) mais lit les deux — sinon Claude placerait un rendez-vous pro sur un créneau perso. L'écriture dans l'autre calendrier reste possible en le nommant explicitement (calendar="Default calendar").

Le calendrier NEXTE a été créé le 15/09/2026 par le MCP lui-même (MKCALENDAR, outil create_calendar). Dans DAVx5, il faut ensuite rafraîchir la liste des calendriers du compte et le cocher pour qu'il se synchronise. Dans InfCloud, il faut l'inscrire dans les réglages stockés sur le serveur — voir §5.7, c'est désormais fait automatiquement par create_calendar.

3. Le serveur MCP

Aucun serveur MCP CalDAV communautaire mûr : serveur maison, ~400 lignes de Python.

Variable Valeur NEXTE Rôle
CALDAV_URL https://baikal.juxjux.ovh/dav.php/ racine DAV de Baïkal
CALDAV_USER Julien utilisateur DAV — J majuscule, la casse compte
CALDAV_PASSWORD Vault 2603 mot de passe de l'utilisateur DAV (pas celui de l'admin Baïkal)
CALDAV_DEFAULT_CALENDAR NEXTE calendrier d'écriture par défaut (default sur le PC perso)
CALDAV_TZ Europe/Paris (défaut) fuseau des heures saisies sans fuseau, et fuseau posé sur les calendriers créés

Le script ne journalise jamais le mot de passe ; s'il manque, il le signale sur stderr sans en dire plus.

Outils exposés

Outil Rôle
list_calendars calendriers du compte, avec marquage du calendrier par défaut
create_calendar(name, cal_id, color) MKCALENDAR, puis pose calendar-color / calendar-order / calendar-timezone (palette par défaut) et inscrit le calendrier dans les réglages InfCloud (§5.7) ; refuse si le nom existe déjà
infcloud_sync_collections inscrit dans les réglages InfCloud tous les calendriers du compte qui n'y figurent pas — pour un calendrier créé ailleurs (DAVx5, admin Baïkal)
list_events(start, end, calendar, all_calendars) événements sur une période (défaut : aujourd'hui → +14 j), tous calendriers sauf si calendar est nommé ; occurrences récurrentes développées
search_events(text, calendar) recherche plein texte (résumé, lieu, description), fenêtre −6/+12 mois
get_event(uid, calendar) détail + iCalendar brut
create_event(summary, start, end, calendar, all_day, location, description, rrule) end absent → +1 h (ou +1 jour en journée entière) ; heures sans fuseau = Europe/Paris ; dates ISO ou jj/mm/aaaa, heures 16:00 ou 16h00
update_event(uid, …) ne modifie que les champs fournis ; incrémente SEQUENCE et LAST-MODIFIED
delete_event(uid, calendar) suppression définitive — uniquement après confirmation explicite de Julien
free_slots(start, end, duration_minutes, day_start, day_end, weekdays_only) créneaux libres tous calendriers confondus, dans la plage horaire quotidienne indiquée

4. Enregistrement dans Claude Code (PC NEXTE)

Portée utilisateur (-s user), comme le MCP QGIS. À lancer dans un terminal, en remplaçant <MDP> par le mot de passe de l'utilisateur DAV Julien (Vault 2603) :


1
claude mcp add -s user caldav -e CALDAV_URL=https://baikal.juxjux.ovh/dav.php/ -e CALDAV_USER=Julien -e CALDAV_DEFAULT_CALENDAR=NEXTE -e 'CALDAV_PASSWORD=<MDP>' -- "C:\Users\nexte\.local\bin\uv.exe" run --script "C:\Users\nexte\Nexte Claude\MCP CalDAV\260915-mcp_caldav_server.py"


Puis :


1
claude mcp list


qui doit afficher caldav: … - ✔ Connected.

Pour refaire l'enregistrement (mot de passe changé, mauvais calendrier par défaut) : claude mcp remove -s user caldav puis la commande add.

Où va le secret : claude mcp add l'écrit en clair dans C:\Users\nexte\.claude.json — même niveau de protection que le MCP postgres. Le mot de passe reste archivé dans le Vault 2603 ; il n'a pas à figurer dans une conversation ni dans BookStack.

5. Pièges rencontrés le 15/09/2026

5.1 Les chevrons du gabarit ne font pas partie du mot de passe

Une commande donnée avec CALDAV_PASSWORD=<MDP> a été lancée telle quelle, puis avec <vrai-mdp> chevrons compris. Dans les deux cas Baïkal répond 401. Vérification sans afficher le secret : longueur de la valeur stockée, premier caractère, présence des caractères spéciaux attendus.

5.2 Mot de passe admin ≠ mot de passe utilisateur DAV

Baïkal a deux comptes distincts : l'admin (/admin/) et l'utilisateur DAV (Julien). Le premier essai a été fait avec le mot de passe admin → 401 systématique, avec Julien comme avec julien, alors que le serveur annonçait bien Basic realm="sabre/dav". Le bon mot de passe est celui saisi dans DAVx5 et InfCloud. Test de référence qui distingue « serveur joignable » de « identifiants acceptés » :


1
curl -s -o /dev/null -w "%{http_code}\n" -X PROPFIND -H "Depth: 0" https://baikal.juxjux.ovh/dav.php/


401 sans identifiants = normal ; 401 avec identifiants = mauvais couple utilisateur/mot de passe.

5.3 Caractères spéciaux dans PowerShell

Le mot de passe contient % et @ : passer la variable entre apostrophes simples ('CALDAV_PASSWORD=…'), pas entre guillemets. Vérifié : la valeur stockée est intacte.

5.4 SDK mcp 2.x

La 2.x du SDK Python a renommé FastMCP en MCPServer et cassé l'import mcp.server.fastmcp. Le script épingle mcp<2. À revoir si on migre un jour vers la 2.x.

5.5 Reprise de session ≠ nouvelle session

Un serveur MCP est chargé au démarrage de la session. Après claude mcp add, une session reprise dans l'app ne voit pas le nouveau serveur alors que claude mcp list le donne connecté. Il faut une nouvelle session. Entre-temps, le script peut être piloté directement (import du module + lecture de l'env dans .claude.json) — c'est ainsi que le calendrier NEXTE et l'événement test ont été créés.

5.6 Rappels de la page 1 qui s'appliquent au MCP

5.7 Un calendrier créé hors InfCloud n'apparaît jamais dans InfCloud

Symptôme : NEXTE visible dans DAVx5 et Fossify, mais absent d'InfCloud, même après déconnexion, Ctrl+Maj+R et reconnexion.

Fausse piste écartée en premier : le calendrier créé par MKCALENDAR nu n'avait ni calendar-color, ni calendar-order, ni calendar-timezone (404 sur ces trois propriétés, alors que le calendrier de l'installeur les a). Elles ont été posées par PROPPATCH — nécessaire pour l'homogénéité, mais insuffisant.

Cause réelle : config.js d'InfCloud a settingsAccount: true. InfCloud stocke alors ses réglages sur le serveur, dans la propriété {http://inf-it.com/ns/dav/}settings du principal (/dav.php/principals/Julien/), sous forme de JSON. Ce JSON contient loadedcalendarcollections et activecalendarcollections (idem pour les tâches), figés à la première session — donc réduits à default/. InfCloud ne charge que les collections de cette liste ; un nouveau calendrier n'y entre jamais tout seul.

Diagnostic (avec identifiants) :


1
2
PROPFIND /dav.php/principals/Julien/ Depth: 0
<D:propfind xmlns:D="DAV:" xmlns:I="http://inf-it.com/ns/dav/"><D:prop><I:settings/></D:prop></D:propfind>


puis lire loadedcalendarcollections dans le JSON retourné.

Correctif : relire le JSON, ajouter l'URL du calendrier aux quatre listes (loadedcalendarcollections, activecalendarcollections, loadedtodocollections, activetodocollections), réécrire la propriété par PROPPATCH, puis déconnexion/reconnexion InfCloud (les réglages sont lus au login). Sauvegarde du JSON d'origine : MCP CalDAV\260915-infcloud_settings_backup.json.

Depuis le 15/09, create_calendar fait tout cela d'emblée, et infcloud_sync_collections rattrape un calendrier créé ailleurs. Le config.js lui-même n'est pas en cause (additionalResources: [], pas de liste figée).

5.8 Le parseur de dates lisait 2026-10-02 comme le 10 février

dateutil.parser.parse(..., dayfirst=True) — voulu pour accepter 02/10/2026 — inverse aussi jour et mois d'une date ISO quand les deux valeurs sont ≤ 12 : 2026-10-02 devient le 10 février, 2026-10-09 le 10 septembre, 2026-10-12 le 10 décembre. 2026-10-13 passe, ce qui rend le bug intermittent et sournois.

Constaté lors du premier blocage de créneaux (6 dates, 3 fausses). Correctif dans _parse_dt : datetime.fromisoformat d'abord, dateutil en jour-premier seulement en repli ; 16h00 / 14h sont normalisés en 16:00 / 14:00. Les trois événements erronés ont été supprimés et recréés.

Règle : toujours relire les dates renvoyées par create_event (le résultat affiche start/end en ISO avec fuseau) avant d'annoncer qu'un créneau est bloqué.

6. Vérifications effectuées le 15/09/2026

Test Résultat
PROPFIND /dav.php/ sans identifiants 401, Basic realm="sabre/dav"
list_calendars Default calendar visible
create_calendar("NEXTE", cal_id="nexte") créé, URL …/calendars/Julien/nexte/
list_events 14 jours, tous calendriers 1 événement perso lu
create_event dans NEXTE (16/09 10:00–10:30, Europe/Paris) écrit, relu par get_event avec fuseau +02:00
Synchronisation DAVx5 → Fossify événement visible sur le téléphone après avoir coché NEXTE
delete_event par UID supprimé, calendrier NEXTE vide
PROPPATCH couleur/ordre/fuseau sur NEXTE 200, relu
Inscription de NEXTE dans les réglages InfCloud 200 ; NEXTE visible dans InfCloud après reconnexion
infcloud_sync_collections après correction added: [] — idempotent
create_calendar("NEXTE") une seconde fois refusé, « existe déjà »
claude mcp list caldav … ✔ Connected
6 créneaux « Tourrettes PLU (validation en attente) » dans NEXTE (02→16/10) créés, relus aux bonnes dates après correctif §5.8 ; aucun conflit perso

7. Installation sur le PC perso

Objectif : que le Claude Code du PC perso lise les deux calendriers et écrive dans l'un ou l'autre, avec le même serveur Baïkal et le même compte Julien. Aucune configuration côté Baïkal : le compte voit déjà les deux calendriers. Tout se passe sur le PC perso.

7.1 Copier le script

Source (PC NEXTE) : C:\Users\nexte\Nexte Claude\MCP CalDAV\260915-mcp_caldav_server.py — prendre la version courante, elle contient les correctifs du 15/09 (§5.7 InfCloud, §5.8 dates).

Destination recommandée : Syncthing/Jux_univers/Jux-scripts/Baikal-Contacts/260915-mcp_caldav_server.py, à côté d'infcloud-config.js — c'est le dossier où sont déjà versionnés les fichiers Baïkal (page 1, §4). Le script est autonome : un seul fichier, pas de dépendance à copier.

Point d'attention : le fichier ne doit pas être dans un coffre Cryptomator — un MCP se lance au démarrage de Claude Code, coffre fermé ou non (règle « aucun script ne dépend d'un coffre déverrouillé »).

7.2 Vérifier uv


1
uv --version


Si absent :


1
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"


puis rouvrir le terminal. uv télécharge lui-même un Python et les dépendances au premier lancement (~50 paquets, une dizaine de secondes) ; aucune installation Python système n'est nécessaire.

Repérer le chemin complet de uv.exe ((Get-Command uv).Source en PowerShell) — l'utiliser en absolu dans la commande d'enregistrement, comme sur NEXTE, évite les surprises de PATH au lancement par Claude Code.

Fait autrement sur le PC perso (16/09) : pas d'uv, un venv sur D: — voir §7.8 pour la raison.

7.3 Choisir le calendrier par défaut

Choix CALDAV_DEFAULT_CALENDAR Comportement
Recommandé default le PC perso écrit dans le calendrier perso sauf mention contraire ; symétrique de NEXTE sur le PC pro
Variante NEXTE le PC perso se comporte exactement comme le PC NEXTE

Dans les deux cas, la lecture porte sur les deux calendriers, et l'écriture dans l'autre calendrier reste possible en le nommant (« ajoute ça dans NEXTE »).

7.4 Enregistrer le MCP

Dans un terminal (PowerShell), en remplaçant <MDP> par le mot de passe de l'utilisateur DAV Julien (Vault 2603) et <chemin> par le dossier de destination :


1
claude mcp add -s user caldav -e CALDAV_URL=https://baikal.juxjux.ovh/dav.php/ -e CALDAV_USER=Julien -e CALDAV_DEFAULT_CALENDAR=default -e 'CALDAV_PASSWORD=<MDP>' -- "<chemin complet de uv.exe>" run --script "<chemin>\260915-mcp_caldav_server.py"


Rappels des pièges §5 :

Vérifier :


1
claude mcp list


→ caldav: … - ✔ Connected. Si Failed to connect : lancer à la main uv run --script "<chemin>\260915-mcp_caldav_server.py" dans le terminal pour voir l'erreur (dépendance, chemin, Python).

Pour corriger une valeur : claude mcp remove -s user caldav puis relancer la commande add.

7.5 Nouvelle session et test

  1. Ouvrir une nouvelle session Claude Code — pas une reprise (§5.5).
  2. Demander list_calendars : les deux calendriers doivent apparaître, Default calendar marqué par défaut.
  3. Écrire un événement test dans NEXTE (« crée un test demain 10 h dans NEXTE »), le vérifier sur le téléphone ou dans InfCloud, puis le faire supprimer.

7.6 Ce qui n'est PAS à faire

7.7 Entretien à deux PC

Le script existe en deux exemplaires (NEXTE et perso). Toute correction faite sur l'un doit être recopiée sur l'autre — c'est le prix d'un serveur maison hors dépôt. Convention : le fichier daté reste 260915-… tant que l'API des outils ne change pas ; une refonte produit un nouveau fichier daté et une mise à jour des deux enregistrements MCP.

7.8 Installation effective sur le PC perso — 16/09/2026

Faite depuis une session Claude Code du poste julie, après dépôt du script par Julien. Vérifiée en session : list_calendars rend Default calendar (par défaut) et NEXTE, list_tasks lit les deux tâches ouvertes de NEXTE.

Élément Valeur sur le PC perso
Script D:\Syncthing\Jux_univers\Jux-scripts\Baikal-Contacts\260915-mcp_caldav_server.py — dans l'arbre Syncthing, hors coffre
Interpréteur D:\Python\venv-caldav-mcp\Scripts\python.exe (venv créé par py -3.12 -m venv, puis pip install "mcp>=1.2,<2" "caldav>=1.4" "icalendar>=6" python-dateutil — mcp 1.30, caldav 3.3, icalendar 7.3)
Enregistrement à la main dans C:\Users\julie\.claude.json, clé mcpServers.caldav (portée utilisateur, type: stdio, command = python du venv en absolu, args = chemin du script, env = les 4 variables). Sauvegarde : .claude.json.bak-260916-caldav
CALDAV_DEFAULT_CALENDAR default — le PC perso écrit dans le perso, lit les deux

Pourquoi pas uv ni pip dans le Python système. Sur ce poste, Claude Code tourne dans un conteneur MSIX : tout ce qu'une session écrit sous %LOCALAPPDATA% ou %APPDATA% est redirigé vers …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\, invisible du reste du système (page 282). Or le Python 3.12 du poste est installé sous %LOCALAPPDATA%\Programs\Python, et uv met son cache dans %LOCALAPPDATA%\uv : un pip install ou un premier uv run lancés depuis la session auraient produit une installation fantôme. Un venv sur D: est hors redirection, et cohérent avec les six autres MCP Python du poste (enregistrés avec un python.exe en chemin absolu, page 282). uv reste valable sur NEXTE, où Claude Code n'est pas dans un conteneur.

Pas de claude mcp add : le CLI claude n'est pas dans le PATH de ce poste (application de bureau). L'entrée est écrite directement dans .claude.json, comme pour Mealie le 13/09. Le mot de passe y est en clair, au même titre que sur NEXTE.

Correctif apporté au script (à recopier sur NEXTE, §7.7). list_calendars marquait le calendrier par défaut en comparant CALDAV_DEFAULT_CALENDAR au seul nom affiché. Avec default, le nom affiché est Default calendar : aucun calendrier n'était marqué (default: false partout), alors que l'écriture fonctionnait — _find_calendar, lui, se rabat sur le dernier segment d'URL. Invisible sur NEXTE parce que nom et segment coïncident (NEXTE/nexte). list_calendars applique désormais la même règle : nom affiché ou segment d'URL, insensible à la casse. Une ligne changée, même fichier daté 260915-… (l'API des outils ne bouge pas).

Chargement en session : après l'écriture dans .claude.json, l'application de bureau a dû être fermée et rouverte — une session reprise ne voit pas le nouveau serveur (§5.5). Au retour, les 17 outils mcp__caldav__* étaient présents et list_calendars a répondu par le MCP.

8. Règles d'usage pour Claude

3 - gestionnaires de tâches - Tasks.org sur Baikal - Infcloud et DAVx5


Gestionnaire de tâches — Tasks.org sur Baïkal, InfCloud et DAVx5

État au 15 septembre 2026 — opérationnel de bout en bout. Cycle validé dans les deux sens : une tâche créée par le MCP est apparue dans Tasks.org, y a été cochée, et le MCP l'a relue COMPLETED ; une tâche saisie dans Tasks.org a été lue par le MCP ; les deux sont visibles dans InfCloud (§6).

Décision : on valorise au maximum l'existant — Baïkal, InfCloud, DAVx5. Les tâches vivent dans les mêmes collections que les événements, aucun composant serveur n'est ajouté. Seul ajout : Tasks.org sur le téléphone, comme écran des tâches que DAVx5 lui dépose.


1. Ce que l'existant sait déjà faire

Composant Tâches (VTODO) Constat
Baïkal oui, nativement les deux collections default/ et nexte/ annoncent VEVENT et VTODO (vérifié par PROPFIND supported-calendar-component-set)
InfCloud oui, onglet Tâches les réglages serveur contiennent déjà loadedtodocollections / activetodocollections avec les deux calendriers (page 2, §5.7)
DAVx5 oui, synchronise les VTODO mais Android n'a pas de fournisseur de tâches natif : DAVx5 ne peut les déposer que dans une appli tierce — Tasks.org, jtx Board ou OpenTasks. Sans elle, l'option « Tâches » n'apparaît même pas dans le compte
MCP CalDAV oui depuis le 15/09 7 outils *_task ajoutés au script (§3)

2. Choix du client Android

Fossify Calendar — écarté

La fonction « Tâche » de Fossify est locale : c'est un événement d'un type particulier dans sa propre base, jamais écrit en VTODO, jamais synchronisé (héritage de Simple Calendar, dont la synchro CalDAV ne couvre que les événements). Une tâche saisie là n'atteint ni Baïkal, ni InfCloud, ni le MCP — et on croirait qu'elle est synchronisée. Même famille de piège que le plugin calendar de Roundcube (page 1, §6.2).

Fossify reste le client événements ; il n'affiche pas les tâches — chaque appli dans son rôle.

Tasks.org (F-Droid, 15.x) — retenu

  Avantages Inconvénients
Synchro VTODO complet : échéance, priorité, récurrence, rappels, sous-tâches, étiquettes ; CalDAV direct ou via DAVx5 deux chemins possibles → en choisir un seul (§4)
Fonctionnel vraie appli de tâches : listes = collections CalDAV, filtres, widgets, tri par échéance plus riche que nécessaire pour un usage simple — d'où le §5
Projet actif, GPL, version F-Droid sans services Google pas de synchro Google Tasks sur F-Droid — sans importance ici
Cohérence les tâches apparaissent dans InfCloud et sont lisibles/écrites par le MCP —

Alternative connue : jtx Board (bitfire, même éditeur que DAVx5) — tâches + journaux (VJOURNAL), intégration DAVx5 très propre, mais moins de fonctions de gestion de tâches. À garder en tête si les notes datées deviennent un besoin ; Baïkal gère VJOURNAL.

Branchement : via DAVx5, pas en CalDAV direct

Tasks.org sait parler CalDAV tout seul, mais on le branche comme fournisseur de tâches de DAVx5 : un seul compte Baïkal sur le téléphone, une seule planification de synchro, un seul mot de passe stocké. DAVx5 détecte Tasks.org à l'installation et fait apparaître « Tâches » dans le compte. Rien à saisir dans Tasks.org : ni compte, ni URL, ni mot de passe.

Emplacement des tâches : dans les calendriers existants

Pas de collection dédiée aux tâches. La séparation perso/pro est portée par la collection (Default calendar / NEXTE), InfCloud est déjà configuré ainsi, et Tasks.org montre deux listes portant ces noms. L'échéance d'une tâche reste visible à côté des rendez-vous dans InfCloud.

3. Outils tâches du MCP CalDAV

Ajoutés le 15/09/2026 au script 260915-mcp_caldav_server.py (page 2, §3). Même mécanique que les événements : écriture dans le calendrier par défaut du PC, lecture des deux.

Outil Rôle
list_tasks(calendar, include_completed, due_before) tâches ouvertes de tous les calendriers (ou d'un seul) ; include_completed ajoute terminées/annulées ; due_before filtre sur l'échéance ; tri échéance puis priorité
get_task(uid, calendar) détail + iCalendar brut
create_task(summary, due, calendar, priority, description, start, categories, rrule) due = date seule (journée) ou date-heure (Europe/Paris) ; priority 0 aucune / 1 haute / 5 moyenne / 9 basse (convention Tasks.org) ; rrule ex. FREQ=WEEKLY;BYDAY=MO
update_task(uid, …) ne modifie que les champs fournis ; due="" retire l'échéance ; status ∈ NEEDS-ACTION / IN-PROCESS / COMPLETED / CANCELLED ; percent_complete
complete_task(uid, calendar) STATUS COMPLETED, COMPLETED = maintenant, 100 % ; une tâche récurrente est close pour l'occurrence courante et la suivante est générée
reopen_task(uid, calendar) retour à NEEDS-ACTION, COMPLETED et pourcentage retirés
delete_task(uid, calendar) suppression définitive — uniquement après confirmation explicite de Julien

Champs renvoyés : calendar, uid, summary, status, due, start, priority, percent_complete, completed, description, categories, rrule, last_modified.

4. Configuration du téléphone — faite le 15/09

  1. Tasks.org installé depuis F-Droid.
  2. DAVx5 → compte Baïkal : calendriers et tâches activés pour NEXTE et Default calendar (DAVx5 récent les montre dans le même onglet, avec une icône différente — il faut cocher les deux entrées de chaque collection).
  3. Tasks.org → Paramètres → Synchronisation : le compte « DAVx5 » est actif. Aucun compte CalDAV ajouté dans Tasks.org lui-même — ce serait le second chemin de synchro qu'on a écarté.

5. Utiliser Tasks.org au quotidien

Tasks.org intimide parce qu'il s'ouvre sur un filtre (« Ma journée » ou « Boîte de réception »), pas sur les listes. Une tâche due demain n'y apparaît pas ; il faut aller la chercher dans sa liste ou dans « Toutes les tâches ». Le vocabulaire à connaître :

5.1 Listes et filtres

Notion Ce que c'est Où
Liste une collection CalDAV — ici NEXTE et Default calendar menu ≡ (icône en bas à gauche, ou balayage depuis le bord gauche), bloc au nom du compte DAVx5
Filtre une vue transversale sur toutes les listes menu ≡, en haut
« Toutes les tâches » l'ensemble des tâches ouvertes, perso + pro, dans une seule vue — la vue du quotidien filtre
« Ma journée » échues aujourd'hui ou en retard, tous calendriers — l'équivalent de list_tasks(due_before=aujourd'hui) filtre
« Récemment modifiées » ce qui a bougé, utile après une synchro filtre
Filtre personnalisé composition de critères : listes, étiquettes, priorité, échéance (« cette semaine »), état menu ≡ → Filtres → + ; devient une entrée du menu
Widget un widget d'écran d'accueil par liste ou par filtre — « Toutes les tâches » en widget montre donc les deux calendriers appui long sur l'écran d'accueil

Pour distinguer perso et pro dans la vue commune : Paramètres → Apparence → regrouper par liste (ou afficher le nom de la liste sous chaque tâche), et une couleur par liste (appui long sur la liste → couleur), affichée en pastille. La couleur est locale à Tasks.org ; celle d'InfCloud est la calendar-color de la collection (page 2, §5.7).

5.2 Le déclenchement — quand une tâche se rappelle à toi

C'est la partie à comprendre avant de s'en remettre à l'appli :

Situation Notification ?
Tâche sans échéance (ex. « reprendre des fruits ») jamais. Elle n'existe que dans les listes et « Toutes les tâches ». C'est un pense-bête, pas un rappel
Échéance date seule (DUE;VALUE=DATE) à l'heure d'échéance par défaut de Tasks.org (Paramètres → Échéances / Notifications → « heure par défaut », à régler — souvent 18 h d'origine)
Échéance date + heure à cette heure, si le rappel « à l'échéance » est actif dans les réglages de la tâche (il l'est par défaut pour les tâches créées dans Tasks.org ; pour une tâche créée par le MCP, voir §7.3)
Rappels supplémentaires (dans la tâche → Rappels) « au début », « à l'échéance », « aléatoire », « personnalisé » (x heures/jours avant ou après), et « quand dépassée » qui relance périodiquement tant que la tâche n'est pas cochée
Tâche cochée plus aucune notification, elle passe dans les terminées (masquées ou non selon Paramètres → Apparence → « afficher les terminées »)

Une notification peut être reportée (snooze) depuis la notification elle-même. Les rappels sont écrits en VALARM dans le VTODO et donc synchronisés vers Baïkal ; InfCloud les affiche, le MCP les lit dans get_task (iCalendar brut) mais ne les crée pas encore.

5.3 Ce que porte une tâche, et sa correspondance CalDAV

Dans Tasks.org Dans le VTODO Vu par le MCP
Titre SUMMARY summary
Échéance (date, ou date + heure) DUE due
Date de début (« masquer jusqu'à ») DTSTART start
Priorité (aucune / basse / moyenne / haute) PRIORITY 0 / 9 / 5 / 1 priority
Notes DESCRIPTION description
Étiquettes (tags) CATEGORIES categories
Répétition RRULE rrule
Sous-tâches RELATED-TO (tâche parente) non exposé — à ajouter si l'usage vient
Rappels VALARM iCalendar brut seulement
Coché STATUS:COMPLETED + COMPLETED + PERCENT-COMPLETE:100 status, completed, percent_complete
Pièces jointes, lieux, minuteur locaux, jamais synchronisés —

Piège constaté : une tâche saisie dans Tasks.org sans toucher à la priorité arrive avec PRIORITY:9 (basse), pas 0. Ne pas lire « basse » comme un choix de Julien.

5.4 Trois gestes utiles

6. Vérifications effectuées le 15/09/2026

6.1 MCP → Baïkal (script seul)

Test Résultat
PROPFIND supported-calendar-component-set sur default/ et nexte/ VEVENT, VTODO sur les deux
create_task échéance 18/09/2026, priorité 1, catégorie créée dans NEXTE, DUE;VALUE=DATE
create_task échéance 2026-09-20 17h00, priorité 5 créée, DUE horodaté +02:00
list_tasks(calendar="NEXTE") les deux, triées par échéance
list_tasks(due_before="19/09/2026") une seule (la première)
update_task IN-PROCESS, 50 %, échéance décalée au 19/09 relu conforme
complete_task COMPLETED, 100 %, horodatage COMPLETED posé
list_tasks sans / avec include_completed 0 / 1
reopen_task NEEDS-ACTION, 0 %, COMPLETED retiré
update_event (régression §7.1) description posée sur un créneau Tourrettes, date inchangée
delete_task ×2 NEXTE vide
claude mcp list après modification caldav … ✔ Connected

6.2 Bout en bout, avec le téléphone

Étape Résultat
create_task « TEST MCP → Tasks.org », échéance 16/09, priorité 5, dans NEXTE créée
Synchro DAVx5 → Tasks.org, liste NEXTE visible, avec échéance et priorité
Cochée dans Tasks.org, synchro list_tasks(include_completed=True) : COMPLETED 100 %, completed 15/09 17:02
Tâche « reprendre des fruits » saisie dans Tasks.org (liste NEXTE) lue par le MCP : NEEDS-ACTION, sans échéance, PRIORITY:9
InfCloud → onglet Tâches les deux visibles

Les deux tâches sont laissées en place à la demande de Julien, pour observer le comportement des rappels (§5.2).

7. Pièges rencontrés le 15/09/2026

7.1 icalendar.walk() renvoie une liste

Avec icalendar 6, Calendar.walk("VTODO") renvoie une liste, pas un itérateur : next(ic.walk(...)) échoue en TypeError. Le même code dormait dans update_event depuis la création du script — jamais exercé jusque-là. Corrigé aux deux endroits (ic.walk(...)[0]).

7.2 Todo.complete() ne pose pas le pourcentage

La bibliothèque caldav pose STATUS:COMPLETED et COMPLETED:<horodatage> mais laisse PERCENT-COMPLETE à sa valeur précédente (50 % dans le test). Certains clients affichent alors une tâche « terminée à 50 % ». complete_task force 100 %.

7.3 Une tâche créée par le MCP n'a pas de rappel

Le MCP écrit DUE mais aucun VALARM. Dans Tasks.org, la tâche a une échéance mais son rappel « à l'échéance » dépend du réglage par défaut de l'appli pour les tâches importées (Paramètres → Notifications). Si Julien veut être notifié des tâches créées depuis Claude, deux options : régler Tasks.org pour appliquer les rappels par défaut aux nouvelles tâches synchronisées, ou ajouter un VALARM côté MCP (paramètre reminder sur create_task). À trancher à l'usage.

7.4 Échéance : date seule vs date-heure

Une échéance 18/09/2026 doit produire DUE;VALUE=DATE:20260918 (journée entière), et 2026-09-20 17h00 un DUE horodaté en Europe/Paris. Les deux formes sont gérées ; due_before compare une date seule à la fin de journée, pour ne pas exclure une tâche échue le jour même.

7.5 Priorité 9 par défaut côté Tasks.org

Voir §5.3 : « basse » n'est pas un choix, c'est le défaut de l'appli.

8. Règles d'usage pour Claude

4 - intégration des contacts personnels et professionnels de Julien


Intégration des contacts personnels et professionnels de Julien

Statut au 15 septembre 2026 : en discussion. Rien n'est construit. Cette page contient le plan en trois actes posé par Julien, puis les retours de Claude. Les décisions prises seront consignées en §5 au fur et à mesure.


1. Le plan de Julien (15/09/2026)

Sources actuelles, dispersées :

Trois actes :

  1. Une base unificatrice simple (SQLite) pour tout rapatrier, trier, sérier, ancrer, archiver — lisible depuis Thunderbird sur le téléphone, depuis Synology Contacts, etc.
  2. Baïkal comme catalyseur de cette base : il la distribue, mais reçoit aussi les mises à jour depuis les foyers de création que sont Gmail, Infomaniak et le Xiaomi.
  3. InfCloud comme répertoire web (Roundcube : à quoi sert-il encore ?), pour rapprocher adresses et rendez-vous.

Procédure hébergée sur le VPS perso juxjux.ovh, comme le reste de la stack (page 1).

2. Retours de Claude

2.1 L'acte 1 existe déjà : Baïkal est la base SQLite

Baïkal stocke ses contacts dans une base SQLite (/var/www/baikal/Specific/db/db.sqlite, table cards, une vCard par ligne — page 1 §6.5 et §12). Construire une seconde SQLite « unificatrice » à côté, c'est créer deux sources de vérité pour le même objet, avec un synchroniseur maison entre les deux à écrire et à maintenir. C'est précisément le problème que Baïkal a été installé pour résoudre (page 1 §1 : « Baïkal est la source de vérité unique »).

Ce que le plan attend de la base « versatile dans sa lecture » — être vue par Thunderbird, par le téléphone, par un répertoire web — c'est exactement ce qu'un serveur CardDAV fournit. Une SQLite nue ne le fournit pas : il faudrait un connecteur par client. Baïkal est la SQLite plus la couche de lecture universelle.

Proposition : fusionner les actes 1 et 2. Baïkal est la base ET le catalyseur. Ce qui manque n'est pas une base, ce sont trois choses :

  1. un outil d'ingestion des sources (vivantes et mortes) ;
  2. un espace de tri dans Baïkal, avant que les contacts n'entrent dans le carnet de référence ;
  3. un outil de triage : détecter les doublons, fusionner, classer, archiver.

Le tri, le sériage, l'ancrage et l'archivage se font dans le vocabulaire vCard, pas dans un schéma SQL à inventer : CATEGORIES pour les étiquettes (mairie, bureau d'études, famille, …), NOTE ou un champ X-PROVENANCE pour l'origine, ORG/TITLE pour l'ancrage professionnel, et plusieurs carnets pour les grands compartiments. Tous les clients relisent ces champs.

2.2 Les sources ne sont pas de même nature

Le plan les traite comme quatre « foyers de création » équivalents. Elles ne le sont pas :

Source Nature Traitement proposé
Synology Contacts (hérités) source morte : un stock à vider, pas un flux export .vcf une fois, import dans un carnet de transit, puis triage. Synology Contacts n'est ensuite plus alimenté
Infomaniak (pro) source vivante, CardDAV natif vdirsyncer, prévu depuis août (page 1 §10.1), en sens unique vers Baïkal pour commencer
Gmail (perso) source vivante, CardDAV Google (mot de passe d'application, compte en 2FA) idem, vdirsyncer sens unique vers Baïkal
Xiaomi pas une source distante : ce sont des contacts dans le compte « Téléphone » ou « Mi Cloud » de l'appareil, invisibles de tout serveur export .vcf une fois depuis l'appli Contacts, import en transit, triage ; puis réglage du compte par défaut pour les nouveaux contacts = compte Baïkal de DAVx5, et désactivation de la synchro contacts Mi Cloud / Google pour tarir la fuite

Point important : une fois le compte DAVx5 défini comme compte par défaut sur le téléphone, le téléphone n'est plus un foyer de création à synchroniser — il écrit directement dans Baïkal. Même chose pour InfCloud, Roundcube et Claude (via le futur MCP CardDAV). Restent deux vrais flux entrants : Infomaniak et Gmail.

2.3 Sur le « reçoit les mises à jour » de l'acte 2 : le sens du flux est la décision structurante

Deux modèles possibles, à trancher avant de configurer vdirsyncer :

Modèle A — Baïkal devient l'unique foyer de création. Gmail et Infomaniak sont vidés dans Baïkal une fois (sens unique), puis on cesse d'y créer des contacts : nouveaux contacts saisis sur le téléphone (compte DAVx5), dans InfCloud, ou par Claude. Gmail et Infomaniak deviennent des vestiges, ou reçoivent une copie descendante (Baïkal → Google) si l'autocomplétion Gmail compte.

Modèle B — synchronisation bidirectionnelle permanente avec Gmail et Infomaniak.

Recommandation : modèle A, avec vdirsyncer en sens unique le temps de la migration, puis à l'arrêt. C'est aussi la recommandation déjà posée en page 1 §10.1. Si l'autocomplétion Gmail manque, ajouter plus tard un flux descendant Baïkal → Google (sens unique aussi) — pas de remontée.

2.4 Espace de tri : des carnets de transit dans Baïkal

Plutôt que de trier dans une base à part, créer dans Baïkal, sous le même utilisateur Julien :

Carnet Rôle Synchronisé vers le téléphone ?
default contacts personnels de référence oui
nexte contacts professionnels de référence (mairies, DDTM, bureaux d'études, …) oui
archive contacts conservés mais sortis de l'usage (anciens clients, personnes décédées, …) non — visible dans InfCloud seulement
transit-synology, transit-gmail, transit-infomaniak, transit-xiaomi chaque source importée telle quelle, sans modification non

Les carnets de transit sont éphémères : une fois vidés par le triage, on les supprime. Tout ce qui est décidé s'exprime par un déplacement d'un carnet à un autre — ce qui est tracé par Baïkal (horodatage, synctoken) et sauvegardé chaque nuit (page 1 §8).

Deux carnets de référence (default / nexte) plutôt qu'un seul : même logique que pour les calendriers (page 2 §1) — le PC NEXTE n'écrit que dans nexte, les contacts personnels ne transitent par une conversation Alteris que si Julien le demande, et DAVx5 permet de n'exposer que l'un des deux à une appli donnée. Une mairie qui est « les deux » va dans nexte avec une CATEGORIES explicite ; on ne duplique pas.

2.5 L'outil de triage : c'est là que Claude a une valeur

Le triage manuel de quatre sources est ce qui a fait échouer toutes les tentatives de rangement de contacts depuis vingt ans. Ce que le MCP CardDAV (à écrire, comme pour les tâches — page 3) permettrait :

Rien de tout cela ne demande une base à part : ce sont des opérations CardDAV (REPORT addressbook-query, PUT, DELETE, MOVE) sur des vCards 3.0 — le format que Roundcube écrit déjà et que tout le monde relit (page 1 §9).

2.6 Acte 3 — InfCloud, Roundcube, Thunderbird, Synology

2.7 Ordre de chantier proposé

Chaque étape est réversible et laisse la stack en état de marche. Rien n'est lancé sans validation de Julien.

# Étape Où Outil
0 Inventaire : nombre de contacts par source, présence d'e-mail/téléphone, date du dernier ajout chaque source exports .vcf, comptage
1 Gel des sources : arrêt de la création de contacts dans Gmail et le webmail Infomaniak ; compte DAVx5 par défaut sur le Xiaomi ; synchro contacts Mi Cloud/Google coupée téléphone, discipline réglages Android
2 Carnets : création de nexte, archive et des carnets de transit ; inscription dans InfCloud Baïkal admin Baïkal ou MCP
3 Imports morts : Synology et Xiaomi → carnets de transit VPS .vcf + PUT CardDAV
4 Imports vivants : vdirsyncer sens unique Gmail → transit, Infomaniak → transit ; cron le temps de la migration VPS vdirsyncer (page 1 §10.1)
5 Triage : inventaire, doublons, fusions validées, classement default/nexte/archive MCP CardDAV Claude + Julien
6 Vérification clients : téléphone (DAVx5), InfCloud, Thunderbird PC clients —
7 Fin de migration : suppression des carnets de transit, arrêt de vdirsyncer (modèle A), sort de Roundcube VPS —

Le MCP CardDAV (outils *_contact) est un préalable à l'étape 5 et sert dès l'étape 0 pour compter. Il se construit comme celui des tâches, dans le même script.

3. Ce que Claude ne recommande pas

4. Questions à trancher

  1. Modèle A (Baïkal seul foyer de création) ou modèle B (bidirectionnel) ? — §2.3
  2. Deux carnets de référence default/nexte, ou un seul avec catégories ? — §2.4
  3. Le pro, c'est NEXTE ou Alteris, ou les deux avec une catégorie ? (même question que pour le calendrier, tranchée « NEXTE » le 15/09)
  4. Roundcube : webmail utilisé, ou à arrêter ? — §2.6
  5. Synology Contacts : confirmer qu'il ne peut pas être client CardDAV ; sinon, souhaite-t-on qu'il reste alimenté ?
  6. L'autocomplétion Gmail manque-t-elle si Gmail cesse d'être alimenté ? (déclenche ou non un flux descendant Baïkal → Google)
  7. Ordre de grandeur : combien de contacts au total, toutes sources confondues ? (change la méthode de triage : 300 se font en une séance, 3 000 par lots)

# Note de déploiement — miroir contacts Baïkal → Infomaniak (VPS juxjux)

Rédigée le 22/09/2026 par l'instance Claude du **PC NEXTE**, à l'attention de l'instance Claude du **PC perso** qui a l'accès SSH au VPS juxjux. Documentation du chantier : BookStack Alteris page 499 (chapitre 486, livre 280).

---

## 1. Ce qui est déjà fait (sur le PC NEXTE, en production)

Le miroir tourne et a été validé de bout en bout. Il est **lancé à la main** depuis le PC NEXTE ; il faut maintenant le **planifier sur le VPS** pour qu'il vive sans ce PC.

État au 22/09 au soir :

| Paire | Identifiant court | Carnet Infomaniak | Baïkal | Infomaniak |
|---|---|---|---|---|
| **NEXTE** → `julien.bertrand@nexte.fr` | `JB08607` | `Baikal-NEXTE` | 1 584 fiches | 1 584, identiques |
| **Jux** → `julien.bertrand@ik.me` | `JB06766` | `Baikal-Jux` | 305 fiches | 305, identiques |

Les deux paires sont déclarées dans `PAIRES` en tête du script et tournent en production ; un passage à blanc ne trouve plus rien à faire des deux côtés.

Chaîne vérifiée : correction d'une fiche dans InfCloud → descend dans Infomaniak et sur le téléphone (DAVx5/Fossify). Création **et modification** dans le webmail Infomaniak → remontent dans Baïkal (§2).

## 2. Le script

`260922-miroir_infomaniak.py` (ce dossier Syncthing, `Jux-scripts/Baikal-Contacts/`). Autonome PEP 723, dépendance `vobject`, lancé par `uv run --script`.

**Principe** — Baïkal est le maître :

- **descente** : toute fiche Baïkal absente ou sémantiquement différente côté Infomaniak est écrite (PUT, même UID) ; toute fiche que le miroir avait déposée et qui a disparu de Baïkal est supprimée côté Infomaniak ;
- **remontée des créations** : une fiche présente côté Infomaniak dont l'UID n'a **jamais** été déposé par le miroir (donc créée dans le webmail) est recopiée dans Baïkal, avec une note de provenance ;
- **remontée des modifications** *(ajoutée le 22/09, avant déploiement)* : une fiche existante modifiée dans le webmail remonte dans Baïkal. L'arbitrage repose sur les **ETag mémorisés des deux côtés** : si seul Infomaniak a bougé, la fiche remonte ; si seul Baïkal a bougé, elle redescend ; si les deux ont bougé, le **`REV` le plus récent gagne** et le conflit est compté dans la sortie (`conflits_arbitres`) ;
- **aucune suppression ne remonte jamais** — une suppression dans le webmail est annulée au passage suivant. C'est voulu : protection contre les suppressions intempestives et contre une compromission de la boîte.

Deux propriétés vérifiées avant de coder l'arbitrage, à re-vérifier si Infomaniak change de moteur : leurs **ETag sont stables** entre deux lectures sans modification (1 585/1 585 testées) et le **`REV` de Baïkal est conservé à l'identique** au stockage.

Le fichier d'état `miroir_<paire>.json` (**version 2** : `{uid: {"ik": etag, "bk": etag}}`) est **ce qui distingue** « supprimée dans Baïkal » de « créée dans le webmail », et quel côté a bougé. **Ne pas le perdre** : sans lui, le passage suivant retombe sur le comportement « Baïkal gagne » et les modifications faites dans le webmail seraient écrasées. Il migre automatiquement depuis le format v1 (simple liste d'UID).

Comparaison **sémantique** (nom, N, e-mails, téléphones, organisation, fonction, catégories, note, adresses) et non octet à octet : Infomaniak réécrit les vCards au stockage, une comparaison stricte réécrirait tout à chaque passage.

## 3. Ce qu'il faut faire sur le VPS

### 3.1 Fichiers à déposer

| Fichier | Où | Contenu |
|---|---|---|
| `260922-miroir_infomaniak.py` | `/home/debian/baikal-miroir/` | le script (copie depuis Syncthing) |
| `260915-mcp_caldav_server.py` | `/home/debian/baikal-miroir/` | **requis** : le miroir l'importe comme bibliothèque (accès Baïkal) |
| `infomaniak.env` | `/home/debian/baikal-miroir/` | `NEXTE_FR_PASSWORD=…` et `IK_ME_PASSWORD=…` — mots de passe d'application Infomaniak (16 caractères chacun). `chmod 600`. **À consigner dans le Vault 2603** : le fichier a disparu une fois du PC NEXTE sans explication, le 22/09 |
| `~/.claude.json` **ou** variables d'environnement | — | le script serveur lit `CALDAV_URL`, `CALDAV_USER`, `CALDAV_PASSWORD` dans `~/.claude.json` → **à adapter** (voir §3.2) |

### 3.2 Adaptation à faire dans `load_server()`

Sur le PC NEXTE, les identifiants Baïkal viennent de `~/.claude.json` (config du MCP Claude Code). **Sur le VPS il n'y a pas de Claude Code** : remplacer, dans `260922-miroir_infomaniak.py` (et dans les autres scripts si tu les déploies), la fonction :

```python
def load_server():
    cfg = json.load(open(os.path.expanduser("~/.claude.json"), encoding="utf-8"))
    os.environ.update(cfg["mcpServers"]["caldav"]["env"])
    ...
```

par une lecture directe d'un fichier `baikal.env` (même dossier, `chmod 600`) :

```
CALDAV_URL=https://baikal.juxjux.ovh/dav.php/
CALDAV_USER=Julien
CALDAV_PASSWORD=<mot de passe DAV de l'utilisateur Julien — Vault 2603>
CALDAV_DEFAULT_CALENDAR=NEXTE
```

Remarque : le VPS juxjux héberge Baïkal lui-même ; le miroir peut donc taper sur `http://127.0.0.1:8088/dav.php/` plutôt que de ressortir par nginx. À toi de voir — l'URL publique fonctionne et évite de dépendre du port interne (page 487 §4).

### 3.3 Cron

```
*/15 * * * * cd /home/debian/baikal-miroir && /usr/local/bin/uv run --script 260922-miroir_infomaniak.py --env infomaniak.env --etat /home/debian/baikal-miroir/etat --real >> /var/log/baikal-miroir.log 2>&1
```

- `uv` à installer si absent (`curl -LsSf https://astral.sh/uv/install.sh | sh`) ; sinon un venv avec `vobject`, `caldav`, `icalendar`, `python-dateutil`, `mcp<2`.
- **Verrou** : ajouter `flock` pour qu'un passage lent ne chevauche pas le suivant :
  `flock -n /tmp/baikal-miroir.lock -c '…'`
- **Alerte** : en cas de sortie contenant `"echecs": [1-9]` ou d'un code de retour non nul, envoyer un e-mail comme le fait `vps_backup.sh` (même mécanisme, page 487 §8).

Durée observée d'un passage sans changement : quelques secondes. Un passage qui réécrit 1 500 fiches : ~5 minutes.

### 3.4 Export `.vcf` quotidien

Décision de Julien : **un seul fichier, toujours à jour, réécrit à chaque passage** — pas de rotation, le versionnage est assuré par la sauvegarde nocturne de Baïkal vers kDrive (page 487 §8). Destination : le dossier Syncthing `Jux_univers/jux_contacts/` (si le VPS est dans le maillage ; sinon `/home/debian/baikal-miroir/export/`).

Poids mesuré le 22/09 : **1,92 Mo** pour les deux carnets réunis (1 890 fiches), dont 62 % de photos (116 photos). À écrire une fois par nuit, pas à chaque passage du miroir.

Le code d'export existe déjà, dupliqué dans plusieurs scripts (`260921-restaurer_carnets.py`, `260921-fusion_lots.py`) :

```python
with open(dest, "w", encoding="utf-8", newline="") as f:
    for c in m._fetch_contacts(m._find_addressbook(book)):
        f.write(c["_raw"].rstrip("\r\n") + "\r\n")
```

## 4. Pièges rencontrés — à ne pas redécouvrir

1. **Identifiant CardDAV Infomaniak** : ce n'est **pas** l'adresse e-mail mais un **identifiant court** de synchronisation (`JB08607` pour `julien.bertrand@nexte.fr`), obtenu sur `https://config.infomaniak.com` → *Contacts & calendriers* → appareil **GNU/Linux**. Avec l'adresse e-mail, l'authentification passe (207 à la racine) mais toute requête répond `Principal with name … not found` — cherche-erreur garanti.
2. **Mots de passe d'application Infomaniak** : ils n'ont **pas** de périmètre par service (contrairement à ce que j'avais supposé) ; un seul mot de passe vaut pour IMAP, CalDAV, CardDAV. Ne pas confondre avec les mots de passe **de boîte mail** générés par `config.infomaniak.com` pour un appareil : ceux-là ne donnent pas accès au CardDAV.
3. **MKCOL interdit** : Infomaniak refuse la création d'un carnet par CardDAV (403 Forbidden). Le carnet cible doit être créé **à la main dans le webmail**, avec le nom exact attendu par `PAIRES` (`Baikal-NEXTE`, `Baikal-Jux`).
4. **Lignes pliées** : Infomaniak lit mal les vCards pliées à 75 caractères (RFC 6350 §3.2) — la catégorie `Important` devenait `Imp`. Le script **déplie** les vCards avant le PUT (`data.replace("\r\n ", "")`). Ne pas retirer cette ligne.
5. **Suivre `carnet_ik_cree`** dans la sortie JSON : `true` signifie que le carnet n'a pas été trouvé par son nom — souvent un carnet renommé ou une faute de frappe, pas une vraie création (elle est interdite, cf. 3).

 

## 5. Reste à faire

1. ~~Paire `Jux` → `ik.me`~~ — **faite le 22/09** : identifiant court `JB06766`, carnet `Baikal-Jux`, 305 fiches déposées, 0 échec.

   *Au passage, un piège à connaître* : le compte `ik.me` ne contenait qu'un seul carnet, « Julien BERTRAND », avec **1 664 fiches jamais triées** (ce compte ne faisait pas partie des cinq exports du 17/09). Julien les a jugées « doublon de doublon de doublon » et fait supprimer — sauvegarde préalable dans `jux_contacts/260922-1643-sauvegarde-ikme-JulienBERTRAND.vcf` (736 Ko). **Il ne fallait surtout pas renommer ce carnet en `Baikal-Jux` avant de le vider** : le miroir aurait pris ses 1 664 fiches pour des créations faites dans le webmail et les aurait remontées dans le carnet Jux de Baïkal, puis sur le téléphone. Vider d'abord, renommer ensuite.
2. ~~Remontée des modifications~~ — **faite le 22/09**, avant déploiement (voir §2). Testée deux fois : mise à jour substantielle d'une fiche dans le webmail (nom, organisation, fonction, note de 483 caractères) et **ajout d'une photo de 70 Ko** — remontées intactes dans Baïkal, base64 et attribut de recadrage compris.
3. **Surveiller le poids du carnet** (question posée par Julien le 22/09, laissée ouverte) : le miroir relit **l'intégralité** des deux carnets à chaque passage. À 2 Mo aujourd'hui c'est indolore ; mais les photos ajoutées par le webmail pèsent ~70 Ko chacune (contre 7 Ko pour les vignettes héritées), et le base64 ajoute 33 %. À 500 photos, le carnet ferait ~46 Mo, soit ~4 Go de trafic par jour à raison d'un passage tous les quarts d'heure. Deux parades, à préparer avant d'en arriver là : **lecture incrémentale** (`sync-collection` + `sync-token`, supportés par Baïkal et Infomaniak — vérifié) et/ou **redimensionnement des photos à l'entrée** (400 px, ~25 Ko). Julien a choisi de laisser tel quel pour l'instant et d'en discuter avec toi.
4. **Ne pas oublier** : le troisième compte `nexte@ik.me` (trash) **ne doit jamais être branché** — c'est une consigne explicite de Julien.

## 6. Contrat entre nos deux instances

Le script maître reste celui du **pivot Syncthing** `Jux-scripts/Baikal-Contacts/`. Si tu le modifies pour le VPS (notamment `load_server()`), garde la version VPS distincte et datée (`2609xx-miroir_infomaniak_vps.py`) plutôt que d'écraser le fichier commun — le PC NEXTE continue de s'en servir pour les opérations manuelles sur les carnets.

Renvoie-moi une note dans ce même dossier quand le cron tourne, avec : chemin d'installation, contenu exact de la crontab, emplacement du journal, et le premier passage observé (JSON de sortie). Je la consignerai en page 499.


06_Veille quotidienne FreshRSS

Veille RSS automatique — une page par jour, generee chaque matin depuis FreshRSS par veille_freshrss.py

06_Veille quotidienne FreshRSS

00_Configuration de la veille

Configuration de la veille quotidienne

Cette page pilote le script veille_freshrss.py (VPS, cron 6h00). Elle est relue à chaque exécution : toute modification est prise en compte dès le lendemain matin.

Ne pas renommer les titres de section ni les en-têtes de colonnes — le script s'appuie dessus.

Paramètres généraux

Paramètre Valeur
fenetre_heures 24
max_par_theme 12
categories_exclues Torrentage, Alertes WEB - overveille
afficher_reste oui

Thèmes

# Thème Mode Max Catégories FreshRSS Mots-clés Expire le
1 SIG & Cartographie tout   QGIS SIG, Cartographie    
2 OpenStreetMap tout   SOTM Europe 2025    
3 Urbanisme & Territoires tout et filtre 24 Veille Urbanisme, urbanisme PLU, SCOT, Evaluation Environnementale, Corse, Var, Alpes-Maritimes, Bouches-du-Rhône,   
4 Self-hosting & Infra filtre   Synoworld, Infrastructure Docker, Cloud Storage, Synchronisation, Notes et documentation, Gestion de fichiers, Médias, RSS Reader, Sécurité docker, portainer, immich, jellyfin, navidrome, komga, kavita, syncthing, rclone, nginx, bookstack, readeck, freshrss, mealie, audiobookshelf, joplin, sauvegarde, backup, nas, synology, self-host, selfhosted, faille, cve, vulnérabilité  
5 Libre & Linux tout   LINUX NOW !, claude_foss Inkscape, Libreoffice, Gimp,   
6 IA & Numérique filtre   Geekeries ia, llm, claude, anthropic, chatgpt, openai, mistral, souveraineté, rgpd, cnil, chiffrement, vie privée, surveillance, open source, logiciel libre  
7 Culture tout   Culture    
8 Signaux transverses transverse     qgis, postgis, lizmap, openstreetmap, osm, ign, géoplateforme, cadastre, dvf, gdal, plu, plui, scot, foncier, zan, mobilité, vélo  

Modes disponibles

Règles de fonctionnement

Journal des modifications

Date Modification
2026-08-05 Création de la configuration initiale
2026-09-15 Publication avancée de 7h30 à 6h00 (cron VPS 4h00 UTC).
2026-09-29 Colonne Max par thème ; Urbanisme & Territoires porté à 24 ; nouveau thème Culture (catégorie FreshRSS Culture, ~7 articles/jour).
06_Veille quotidienne FreshRSS

Veille 2026-08-05

Veille du mercredi 5 aout 2026

120 articles sur 24 h (147 avant regroupement des doublons et fils de discussion) — 56 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (14)

Self-hosting & Infra (8)

Libre & Linux (13)

IA & Numérique (18)

Signaux transverses (1)

Non retenu (64)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 57
Sans catégorie 4
Synoworld 3

Genere le 2026-08-05 a 06h36 par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-06

Veille du jeudi 6 aout 2026

106 articles sur 24 h (111 avant regroupement des doublons et fils de discussion) — 48 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (3)

Urbanisme & Territoires (8)

Self-hosting & Infra (7)

Libre & Linux (15)

IA & Numérique (14)

Signaux transverses (1)

Non retenu (57)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 48
Sans catégorie 6
Synoworld 2
Culture 1

Genere le 2026-08-06 a 08h31 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-07

Veille du vendredi 7 aout 2026

144 articles sur 24 h (148 avant regroupement des doublons et fils de discussion) — 55 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

Urbanisme & Territoires (14)

Self-hosting & Infra (4)

Libre & Linux (16)

IA & Numérique (19)

Non retenu (88)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 69
Sans catégorie 12
cuisine 3
Synoworld 2
Culture 2

Genere le 2026-08-07 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-08

Veille du samedi 8 aout 2026

131 articles sur 24 h (144 avant regroupement des doublons et fils de discussion) — 54 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (7)

Urbanisme & Territoires (8)

Self-hosting & Infra (4)

Libre & Linux (19)

IA & Numérique (16)

Non retenu (77)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 66
Sans catégorie 8
Culture 2
Synoworld 1

Genere le 2026-08-08 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-09

Veille du dimanche 9 aout 2026

69 articles sur 24 h (70 avant regroupement des doublons et fils de discussion) — 25 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (1)

Urbanisme & Territoires (6)

Self-hosting & Infra (4)

Libre & Linux (9)

IA & Numérique (4)

Non retenu (43)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 36
Sans catégorie 3
Synoworld 2
Culture 2

Genere le 2026-08-09 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-10

Veille du lundi 10 aout 2026

61 articles sur 24 h (65 avant regroupement des doublons et fils de discussion) — 30 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (4)

Urbanisme & Territoires (7)

Self-hosting & Infra (4)

Libre & Linux (10)

IA & Numérique (5)

Non retenu (31)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 25
Synoworld 4
Culture 2

Genere le 2026-08-10 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-11

Veille du mardi 11 aout 2026

135 articles sur 24 h (147 avant regroupement des doublons et fils de discussion) — 49 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (5)

Urbanisme & Territoires (11)

Self-hosting & Infra (4)

Libre & Linux (16)

IA & Numérique (11)

Signaux transverses (1)

Non retenu (85)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 73
Sans catégorie 6
Culture 3
cuisine 2
Synoworld 1

Genere le 2026-08-11 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-12

Veille du mercredi 12 aout 2026

154 articles sur 24 h (157 avant regroupement des doublons et fils de discussion) — 55 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (5)

Urbanisme & Territoires (7)

Self-hosting & Infra (5)

Libre & Linux (15)

IA & Numérique (20)

Signaux transverses (3)

Non retenu (98)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 80
Sans catégorie 12
Synoworld 4
cuisine 2

Genere le 2026-08-12 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-13

Veille du jeudi 13 aout 2026

155 articles sur 24 h (171 avant regroupement des doublons et fils de discussion) — 62 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (6)

Urbanisme & Territoires (11)

Self-hosting & Infra (11)

Libre & Linux (15)

IA & Numérique (19)

Non retenu (92)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 80
Sans catégorie 8
Culture 2
Infrastructure Docker 1
Synoworld 1

Genere le 2026-08-13 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-14

Veille du vendredi 14 aout 2026

111 articles sur 24 h (116 avant regroupement des doublons et fils de discussion) — 42 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

Urbanisme & Territoires (9)

Self-hosting & Infra (1)

Libre & Linux (13)

IA & Numérique (17)

Signaux transverses (1)

Non retenu (69)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 64
Synoworld 2
Sans catégorie 2
Culture 1

Genere le 2026-08-14 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-15

Veille du samedi 15 aout 2026

130 articles sur 24 h (131 avant regroupement des doublons et fils de discussion) — 51 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (1)

Urbanisme & Territoires (9)

Self-hosting & Infra (6)

Libre & Linux (12)

IA & Numérique (19)

Signaux transverses (2)

Non retenu (78)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 64
Sans catégorie 8
Culture 5
Synoworld 1

Genere le 2026-08-15 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-16

Veille du dimanche 16 aout 2026

60 articles sur 24 h — 21 retenus dans 4 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

Urbanisme & Territoires (3)

Self-hosting & Infra (5)

Libre & Linux (9)

IA & Numérique (4)

Non retenu (39)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 31
cuisine 4
Synoworld 2
Culture 2

Genere le 2026-08-16 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-17

Veille du lundi 17 aout 2026

67 articles sur 24 h (69 avant regroupement des doublons et fils de discussion) — 30 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (7)

Self-hosting & Infra (6)

Libre & Linux (10)

IA & Numérique (5)

Non retenu (36)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 31
Culture 3
Sans catégorie 1
Synoworld 1

Genere le 2026-08-17 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-18

Veille du mardi 18 aout 2026

167 articles sur 24 h (183 avant regroupement des doublons et fils de discussion) — 74 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

OpenStreetMap (1)

Urbanisme & Territoires (19)

Self-hosting & Infra (11)

Libre & Linux (20)

IA & Numérique (14)

Signaux transverses (6)

Non retenu (92)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 75
Sans catégorie 11
Synoworld 5
cuisine 1

Genere le 2026-08-18 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-19

Veille du mercredi 19 aout 2026

156 articles sur 24 h (159 avant regroupement des doublons et fils de discussion) — 63 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (3)

Urbanisme & Territoires (15)

Self-hosting & Infra (9)

Libre & Linux (14)

IA & Numérique (20)

Non retenu (92)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 79
Sans catégorie 8
Synoworld 2
Culture 2
cuisine 1

Genere le 2026-08-19 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-20

Veille du jeudi 20 aout 2026

146 articles sur 24 h (149 avant regroupement des doublons et fils de discussion) — 58 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (2)

Urbanisme & Territoires (12)

Self-hosting & Infra (6)

Libre & Linux (17)

IA & Numérique (18)

Signaux transverses (2)

Non retenu (88)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 70
Sans catégorie 7
Synoworld 6
Culture 3
cuisine 2

Genere le 2026-08-20 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-21

Veille du vendredi 21 aout 2026

162 articles sur 24 h (165 avant regroupement des doublons et fils de discussion) — 58 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (3)

Urbanisme & Territoires (15)

Self-hosting & Infra (7)

Libre & Linux (16)

IA & Numérique (17)

Non retenu (103)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 80
Sans catégorie 9
cuisine 8
Culture 4
Synoworld 2

Genere le 2026-08-21 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-22

Veille du samedi 22 aout 2026

148 articles sur 24 h (153 avant regroupement des doublons et fils de discussion) — 59 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (1)

Urbanisme & Territoires (11)

Self-hosting & Infra (7)

Libre & Linux (20)

IA & Numérique (18)

Non retenu (88)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 69
Sans catégorie 7
Culture 6
cuisine 5
Synoworld 1

Genere le 2026-08-22 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-23

Veille du dimanche 23 aout 2026

72 articles sur 24 h (75 avant regroupement des doublons et fils de discussion) — 31 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (1)

Urbanisme & Territoires (10)

Self-hosting & Infra (4)

Libre & Linux (13)

IA & Numérique (3)

Non retenu (41)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 25
cuisine 8
Culture 4
Sans catégorie 4

Genere le 2026-08-23 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-24

Veille du lundi 24 aout 2026

69 articles sur 24 h (74 avant regroupement des doublons et fils de discussion) — 44 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (5)

Urbanisme & Territoires (5)

Self-hosting & Infra (6)

Libre & Linux (13)

IA & Numérique (14)

Non retenu (24)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 16
Sans catégorie 4
Culture 3
Synoworld 1

Genere le 2026-08-24 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-25

Veille du mardi 25 aout 2026

172 articles sur 24 h (176 avant regroupement des doublons et fils de discussion) — 56 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (5)

Urbanisme & Territoires (16)

Self-hosting & Infra (1)

Libre & Linux (14)

IA & Numérique (19)

Signaux transverses (1)

Non retenu (115)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 68
cuisine 26
Synoworld 8
Sans catégorie 7
Culture 5
Social 1

Genere le 2026-08-25 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-26

Veille du mercredi 26 aout 2026

180 articles sur 24 h (187 avant regroupement des doublons et fils de discussion) — 58 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

OpenStreetMap (5)

Urbanisme & Territoires (13)

Self-hosting & Infra (4)

Libre & Linux (13)

IA & Numérique (19)

Signaux transverses (1)

Non retenu (121)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 93
cuisine 16
Sans catégorie 9
Culture 3

Genere le 2026-08-26 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-27

Veille du jeudi 27 aout 2026

172 articles sur 24 h (182 avant regroupement des doublons et fils de discussion) — 57 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (5)

OpenStreetMap (3)

Urbanisme & Territoires (8)

Self-hosting & Infra (4)

Libre & Linux (19)

IA & Numérique (18)

Non retenu (114)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 90
cuisine 12
Culture 6
Sans catégorie 6

Genere le 2026-08-27 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-28

Veille du vendredi 28 aout 2026

177 articles sur 24 h (186 avant regroupement des doublons et fils de discussion) — 69 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

OpenStreetMap (1)

Urbanisme & Territoires (15)

Self-hosting & Infra (7)

Libre & Linux (21)

IA & Numérique (22)

Non retenu (108)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 85
Sans catégorie 12
cuisine 8
Culture 2
Synoworld 1

Genere le 2026-08-28 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-29

Veille du samedi 29 aout 2026

159 articles sur 24 h (164 avant regroupement des doublons et fils de discussion) — 55 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (8)

Urbanisme & Territoires (13)

Self-hosting & Infra (3)

Libre & Linux (15)

IA & Numérique (16)

Non retenu (103)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 81
Sans catégorie 16
Culture 4
Synoworld 2

Genere le 2026-08-29 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-30

Veille du dimanche 30 aout 2026

69 articles sur 24 h (71 avant regroupement des doublons et fils de discussion) — 29 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (3)

Urbanisme & Territoires (5)

Self-hosting & Infra (3)

Libre & Linux (12)

IA & Numérique (6)

Non retenu (40)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 26
Culture 7
Sans catégorie 3
Synoworld 2
cuisine 1
Synchronisation 1

Genere le 2026-08-30 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-08-31

Veille du lundi 31 aout 2026

82 articles sur 24 h (83 avant regroupement des doublons et fils de discussion) — 38 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (3)

Urbanisme & Territoires (7)

Self-hosting & Infra (3)

Libre & Linux (12)

IA & Numérique (11)

Signaux transverses (2)

Non retenu (43)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 35
Culture 5
Synoworld 2
Sans catégorie 1

Genere le 2026-08-31 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-01

Veille du mardi 1 septembre 2026

174 articles sur 24 h (198 avant regroupement des doublons et fils de discussion) — 77 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (4)

Urbanisme & Territoires (16)

Self-hosting & Infra (12)

Libre & Linux (21)

IA & Numérique (24)

Non retenu (96)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 79
Culture 7
Sans catégorie 5
Synoworld 5

Genere le 2026-09-01 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-02

Veille du mercredi 2 septembre 2026

187 articles sur 24 h (188 avant regroupement des doublons et fils de discussion) — 82 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (6)

OpenStreetMap (5)

Urbanisme & Territoires (30)

Self-hosting & Infra (5)

Libre & Linux (14)

IA & Numérique (20)

Signaux transverses (2)

Non retenu (104)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 92
Sans catégorie 7
Culture 2
Synoworld 2
Arts and Co 1

Genere le 2026-09-02 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-03

Veille du jeudi 3 septembre 2026

176 articles sur 24 h (189 avant regroupement des doublons et fils de discussion) — 80 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (4)

OpenStreetMap (1)

Urbanisme & Territoires (24)

Self-hosting & Infra (6)

Libre & Linux (18)

IA & Numérique (24)

Signaux transverses (3)

Non retenu (95)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 82
Sans catégorie 11
Synoworld 1
Culture 1

Genere le 2026-09-03 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-04

Veille du vendredi 4 septembre 2026

195 articles sur 24 h (203 avant regroupement des doublons et fils de discussion) — 88 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (6)

Urbanisme & Territoires (26)

Self-hosting & Infra (3)

Libre & Linux (16)

IA & Numérique (31)

Signaux transverses (4)

Non retenu (107)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 98
Sans catégorie 3
Culture 2
Synoworld 2
cuisine 2

Genere le 2026-09-04 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-05

Veille du samedi 5 septembre 2026

175 articles sur 24 h (184 avant regroupement des doublons et fils de discussion) — 76 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

OpenStreetMap (2)

Urbanisme & Territoires (30)

Self-hosting & Infra (8)

Libre & Linux (16)

IA & Numérique (17)

Non retenu (97)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 82
Sans catégorie 11
Culture 2
Toulon 1
cuisine 1

Genere le 2026-09-05 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-06

Veille du dimanche 6 septembre 2026

70 articles sur 24 h — 31 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (16)

Self-hosting & Infra (1)

Libre & Linux (9)

IA & Numérique (2)

Signaux transverses (1)

Non retenu (38)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 28
Toulon 4
Culture 3
Sans catégorie 3

Genere le 2026-09-06 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-07

Veille du lundi 7 septembre 2026

77 articles sur 24 h (78 avant regroupement des doublons et fils de discussion) — 33 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (1)

Urbanisme & Territoires (7)

Self-hosting & Infra (3)

Libre & Linux (13)

IA & Numérique (7)

Signaux transverses (2)

Non retenu (41)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 37
Culture 2
Synoworld 1
Toulon 1

Genere le 2026-09-07 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-08

Veille du mardi 8 septembre 2026

167 articles sur 24 h (171 avant regroupement des doublons et fils de discussion) — 61 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (3)

Urbanisme & Territoires (22)

Self-hosting & Infra (3)

Libre & Linux (12)

IA & Numérique (18)

Signaux transverses (1)

Non retenu (104)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 84
Sans catégorie 12
Synoworld 4
Toulon 2
Culture 2

Genere le 2026-09-08 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-09

Veille du mercredi 9 septembre 2026

166 articles sur 24 h (175 avant regroupement des doublons et fils de discussion) — 72 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

Urbanisme & Territoires (27)

Self-hosting & Infra (5)

Libre & Linux (16)

IA & Numérique (19)

Signaux transverses (2)

Non retenu (92)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 76
Sans catégorie 12
Toulon 2
Synoworld 1
Culture 1

Genere le 2026-09-09 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-10

Veille du jeudi 10 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 4 appareils synchronisés.

187 articles sur 24 h — 65 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (3)

Urbanisme & Territoires (28)

Self-hosting & Infra (2)

Libre & Linux (15)

IA & Numérique (15)

Non retenu (118)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 107
Sans catégorie 9
Culture 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : joplin-nginx (il y a 13 h), joplin (il y a 13 h), joplin-db (il y a 13 h), Immich-SERVER (il y a 3 h), stirling-pdf (il y a 11 h).

Relevé du 10/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.


Genere le 2026-09-10 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-11

Veille du vendredi 11 septembre 2026

À regarder — WireGuard : pas de liaison avec NAS sasnexte depuis 114 min · NAS sasnexte : port(s) 22, 445 injoignable(s) par le tunnel. Le reste est en ordre.

178 articles sur 24 h (192 avant regroupement des doublons et fils de discussion) — 86 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (3)

OpenStreetMap (2)

Urbanisme & Territoires (37)

Self-hosting & Infra (7)

Libre & Linux (20)

IA & Numérique (15)

Signaux transverses (2)

Non retenu (90)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 72
Sans catégorie 10
Culture 3
Toulon 3
Synoworld 1
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : joplin-nginx (il y a 37 h), joplin (il y a 37 h), joplin-db (il y a 37 h), Immich-SERVER (il y a 3 h), stirling-pdf (il y a 35 h) ; monitor-rclone est intervenu 10 fois depuis hier (Recovery terminée pour /home/debian/photo).

Relevé du 11/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.


Genere le 2026-09-11 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-12

Veille du samedi 12 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 3 appareils synchronisés. Rétabli depuis hier : WireGuard, NAS sasnexte.

222 articles sur 24 h (232 avant regroupement des doublons et fils de discussion) — 77 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (1)

Urbanisme & Territoires (19)

Self-hosting & Infra (17)

Libre & Linux (19)

IA & Numérique (17)

Signaux transverses (2)

Non retenu (94)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 73
Sans catégorie 9
Toulon 7
Culture 3
Synchronisation 1
Synoworld 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 3 h) ; monitor-rclone est intervenu 5 fois depuis hier (Recovery terminée pour /home/debian/photo).

Rétabli depuis hier : WireGuard : pas de liaison avec NAS sasnexte depuis 114 min ; NAS sasnexte : port(s) 22, 445 injoignable(s) par le tunnel.

Relevé du 12/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.


Genere le 2026-09-12 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-13

Veille du dimanche 13 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 3 appareils synchronisés.

110 articles sur 24 h (112 avant regroupement des doublons et fils de discussion) — 32 retenus dans 4 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

Urbanisme & Territoires (8)

Self-hosting & Infra (7)

Libre & Linux (11)

IA & Numérique (6)

Non retenu (48)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 32
Culture 6
Toulon 6
cuisine 2
Social 1
Synoworld 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 3 h), navidrome-navidrome-1 (il y a 21 h).

Relevé du 13/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.


Genere le 2026-09-13 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-14

Veille du lundi 14 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 3 appareils synchronisés.

125 articles sur 24 h (126 avant regroupement des doublons et fils de discussion) — 47 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (3)

Urbanisme & Territoires (13)

Self-hosting & Infra (9)

Libre & Linux (13)

IA & Numérique (8)

Non retenu (40)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 28
Culture 7
Toulon 3
Synoworld 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 3 h), navidrome-navidrome-1 (il y a 2 h), mealie (il y a 20 h).

Relevé du 14/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h13 — 8/8 OK OK
Komga-PDF (compression des magazines) 09/09 20h27 — 1 compressé(s), 0 erreur(s) (Cuisine et Vins de France - 09-10.2026… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) aujourd'hui 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) aujourd'hui 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) aujourd'hui 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 396.5 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 11h30 — Page 314 creee — 13432 caracteres HTML OK
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 14/09, komga 14/09, music 14/09, photo 14/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : PC-Julien… OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-14 a 07h30 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-15

Veille du mardi 15 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 3 appareils synchronisés.

203 articles sur 24 h (204 avant regroupement des doublons et fils de discussion) — 73 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (1)

Urbanisme & Territoires (34)

Self-hosting & Infra (2)

Libre & Linux (14)

IA & Numérique (17)

Signaux transverses (3)

Non retenu (84)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 69
Sans catégorie 5
Culture 4
Synoworld 3
Toulon 3

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 3 h), navidrome-navidrome-1 (il y a 26 h), mealie (il y a 44 h).

Relevé du 15/09 à 07h15 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h14 — 8/8 OK OK
Komga-PDF (compression des magazines) hier 08h34 — 1 compressé(s), 0 erreur(s) (Urbanisme - Septembre-Octobre 2026.pdf… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) aujourd'hui 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) aujourd'hui 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) aujourd'hui 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 396.5 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 11h30 — Page 317 creee — 21169 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » hier 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 15/09, komga 15/09, music 15/09, photo 15/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : PC-Julien… OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-15 a 07h15 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-16

Veille du mercredi 16 septembre 2026

Rien à signaler — sauvegardes 8/8, 32 conteneurs, 3 appareils synchronisés.

229 articles sur 24 h (237 avant regroupement des doublons et fils de discussion) — 90 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (43)

Self-hosting & Infra (9)

Libre & Linux (17)

IA & Numérique (15)

Signaux transverses (4)

Non retenu (92)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 73
Sans catégorie 10
Toulon 4
Culture 4
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Relevé du 16/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h13 — 8/8 OK OK
Komga-PDF (compression des magazines) 14/09 08h34 — 1 compressé(s), 0 erreur(s) (Urbanisme - Septembre-Octobre 2026.pdf… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 396.5 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 11h15 — Page 319 creee — 21667 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 16/09, komga 16/09, music 16/09, photo 16/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-16 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-17

Veille du jeudi 17 septembre 2026

À regarder — Syncthing : XIAOMI15Pro non vu depuis 3 j. Le reste est en ordre. Rétabli depuis hier : Tâches nocturnes.

222 articles sur 24 h (230 avant regroupement des doublons et fils de discussion) — 76 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (38)

Self-hosting & Infra (3)

Libre & Linux (17)

IA & Numérique (15)

Signaux transverses (1)

Non retenu (91)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 70
Sans catégorie 12
Toulon 4
Culture 4
Synoworld 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Rétabli depuis hier : IPTV-Publiques : dernière ligne inattendue : « [2026-09-16 19:51:39] === BILAN: 19/41 chaînes vivantes, 2 perdues (RT ».

Relevé du 17/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 8/8 OK OK
Komga-PDF (compression des magazines) hier 21h59 — 1 compressé(s), 0 erreur(s) (L'Express - 17 Septembre 2026.pdf, 8.1… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 320 creee — 24634 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 17/09, komga 17/09, music 17/09, photo 17/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 1 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-17 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-18

Veille du vendredi 18 septembre 2026

À regarder — IPTV-Publiques : dernière ligne inattendue : « [2026-09-18 00:18:28] === BILAN: 55/87 chaînes vivantes, 1 perdue (RTP ». Le reste est en ordre. Rétabli depuis hier : Syncthing.

241 articles sur 24 h (243 avant regroupement des doublons et fils de discussion) — 84 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (1)

Urbanisme & Territoires (36)

Self-hosting & Infra (3)

Libre & Linux (24)

IA & Numérique (20)

Non retenu (102)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 87
Sans catégorie 8
Culture 5
cuisine 1
Toulon 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Rétabli depuis hier : Syncthing : XIAOMI15Pro non vu depuis 3 j.

Relevé du 18/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 8/8 OK OK
Komga-PDF (compression des magazines) 16/09 21h59 — 1 compressé(s), 0 erreur(s) (L'Express - 17 Septembre 2026.pdf, 8.1… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 324 creee — 21271 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 18/09, komga 18/09, music 18/09, photo 18/09 OK
Maillage Syncthing (8 appareils) 4 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-18 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-19

Veille du samedi 19 septembre 2026

À regarder — IPTV-Publiques : dernière ligne inattendue : « [2026-09-19 00:18:18] === BILAN: 53/87 chaînes vivantes, 1 perdue (ORF » (depuis 2 j). Le reste est en ordre.

245 articles sur 24 h (253 avant regroupement des doublons et fils de discussion) — 80 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (1)

Urbanisme & Territoires (31)

Self-hosting & Infra (7)

Libre & Linux (16)

IA & Numérique (21)

Signaux transverses (2)

Non retenu (83)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 65
Sans catégorie 8
Culture 6
Toulon 2
Synoworld 1
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Relevé du 19/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 8/8 OK OK
Komga-PDF (compression des magazines) 16/09 21h59 — 1 compressé(s), 0 erreur(s) (L'Express - 17 Septembre 2026.pdf, 8.1… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 325 creee — 20938 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 19/09, komga 19/09, music 19/09, photo 19/09 OK
Maillage Syncthing (8 appareils) 2 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-19 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-20

Veille du dimanche 20 septembre 2026

À regarder — IPTV-Publiques : dernière ligne inattendue : « [2026-09-20 00:19:22] === BILAN: 53/87 chaînes vivantes, 1 perdue (RTP » (depuis 3 j). Le reste est en ordre.

99 articles sur 24 h (103 avant regroupement des doublons et fils de discussion) — 30 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

OpenStreetMap (2)

Urbanisme & Territoires (13)

Self-hosting & Infra (3)

Libre & Linux (7)

IA & Numérique (5)

Non retenu (35)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 21
Culture 6
Toulon 4
Sans catégorie 3
Synoworld 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Relevé du 20/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 8/8 OK OK
Komga-PDF (compression des magazines) 16/09 21h59 — 1 compressé(s), 0 erreur(s) (L'Express - 17 Septembre 2026.pdf, 8.1… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 326 creee — 23051 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 20/09, komga 20/09, music 20/09, photo 20/09 OK
Maillage Syncthing (8 appareils) 2 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-20 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-21

Veille du lundi 21 septembre 2026

À regarder — Syncthing : XIAOMI15Pro non vu depuis 3 j · IPTV-Publiques : dernière ligne inattendue : « [2026-09-21 00:18:02] === BILAN: 50/87 chaînes vivantes, 1 perdue (ORF » (depuis 4 j). Le reste est en ordre.

Agenda —

114 articles sur 24 h (115 avant regroupement des doublons et fils de discussion) — 26 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (1)

Urbanisme & Territoires (8)

Self-hosting & Infra (3)

Libre & Linux (10)

IA & Numérique (3)

Non retenu (35)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 20
Toulon 7
Culture 7
Sans catégorie 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h), navidrome-navidrome-1 (il y a 29 min).

Relevé du 21/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h16 — 8/8 OK OK
Komga-PDF (compression des magazines) 16/09 21h59 — 1 compressé(s), 0 erreur(s) (L'Express - 17 Septembre 2026.pdf, 8.1… OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) aujourd'hui 07h00 — Container redémarré — full scan en cours OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 327 creee — 17113 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 21/09, komga 21/09, music 21/09, photo 21/09 OK
Maillage Syncthing (8 appareils) 2 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-21 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-22

Veille du mardi 22 septembre 2026

À regarder — Syncthing : XIAOMI15Pro non vu depuis 4 j (depuis 2 j) · IPTV-Publiques : dernière ligne inattendue : « [2026-09-22 00:18:14] === BILAN: 51/87 chaînes vivantes, 1 perdue (Tel » (depuis 5 j). Le reste est en ordre.

Agenda —

242 articles sur 24 h (252 avant regroupement des doublons et fils de discussion) — 89 retenus dans 5 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (5)

Urbanisme & Territoires (34)

Self-hosting & Infra (7)

Libre & Linux (23)

IA & Numérique (20)

Non retenu (99)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 82
Sans catégorie 8
Culture 4
Synoworld 3
Toulon 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h), navidrome-navidrome-1 (il y a 24 h).

Relevé du 22/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h16 — 8/8 OK OK
Komga-PDF (compression des magazines) hier 22h06 — 1 compressé(s), 0 erreur(s) (Austrian Cuisine.pdf, 99.8 Mio (-2 %)) OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 328 creee — 15793 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 22/09, komga 22/09, music 22/09, photo 22/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-22 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-23

Veille du mercredi 23 septembre 2026

À regarder — Syncthing : XIAOMI15Pro non vu depuis 5 j (depuis 3 j) · IPTV-Publiques : dernière ligne inattendue : « [2026-09-23 00:18:02] === BILAN: 53/87 chaînes vivantes, 1 perdue (RTP » (depuis 6 j). Le reste est en ordre.

Agenda —

241 articles sur 24 h (248 avant regroupement des doublons et fils de discussion) — 88 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (6)

Urbanisme & Territoires (36)

Self-hosting & Infra (6)

Libre & Linux (18)

IA & Numérique (19)

Signaux transverses (3)

Non retenu (98)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 75
Sans catégorie 18
Culture 4
Synoworld 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Relevé du 23/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 8/8 OK OK
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 329 creee — 23549 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 12/09 04h20 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 23/09, komga 23/09, music 23/09, photo 23/09 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-23 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-24

Veille du jeudi 24 septembre 2026

À regarder — Sauvegardes : 7/8 réussies cette nuit (Documents ===) · IPTV-Publiques : dernière ligne inattendue : « [2026-09-24 00:18:17] === BILAN: 51/87 chaînes vivantes, 3 perdues (OR » (depuis 7 j). Le reste est en ordre. Rétabli depuis hier : Syncthing.

Agenda —

277 articles sur 24 h (280 avant regroupement des doublons et fils de discussion) — 98 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (13)

OpenStreetMap (1)

Urbanisme & Territoires (46)

Self-hosting & Infra (6)

Libre & Linux (12)

IA & Numérique (19)

Signaux transverses (1)

Non retenu (102)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 79
Sans catégorie 14
Culture 4
cuisine 2
Libres et Ouverts 2
Toulon 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h) ; monitor-rclone est intervenu 5 fois depuis hier (Recovery terminée pour /home/debian/photo).

Rétabli depuis hier : Syncthing : XIAOMI15Pro non vu depuis 5 j.

Relevé du 24/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 7/8 OK À regarder
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 330 creee — 23866 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) hier 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent — monitor-rclone est intervenu 5 fois… OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 24/09, komga 24/09, music 24/09, photo 24/09 OK
Maillage Syncthing (8 appareils) 4 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 1 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-24 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-25

Veille du vendredi 25 septembre 2026

À regarder — Sauvegardes : 7/8 réussies cette nuit (Documents ===) (depuis 2 j) · IPTV-Publiques : dernière ligne inattendue : « [2026-09-25 00:18:10] === BILAN: 52/87 chaînes vivantes, 1 perdue (ORF » (depuis 8 j). Le reste est en ordre.

Agenda —

276 articles sur 24 h (282 avant regroupement des doublons et fils de discussion) — 100 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (7)

Urbanisme & Territoires (46)

Self-hosting & Infra (3)

Libre & Linux (17)

IA & Numérique (24)

Signaux transverses (3)

Non retenu (114)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 80
Sans catégorie 24
Culture 5
Libres et Ouverts 2
Synoworld 2
Médias 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Relevé du 25/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h15 — 7/8 OK À regarder
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 10h39 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 400.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 331 creee — 25732 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 25/09, komga 25/09, music 25/09, photo 25/09 OK
Maillage Syncthing (8 appareils) 2 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 1 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-25 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-26

Veille du samedi 26 septembre 2026

À regarder — Sauvegardes : 7/8 réussies cette nuit (Documents ===) (depuis 3 j) · Certificat de pdf.juxjux.ovh expire dans 29 j. Le reste est en ordre. Rétabli depuis hier : Tâches nocturnes.

307 articles sur 24 h (312 avant regroupement des doublons et fils de discussion) — 91 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (6)

OpenStreetMap (1)

Urbanisme & Territoires (35)

Self-hosting & Infra (9)

Libre & Linux (11)

IA & Numérique (27)

Signaux transverses (2)

Non retenu (161)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 91
Sans catégorie 53
Culture 8
Libres et Ouverts 4
Synoworld 3
Toulon 1
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Rétabli depuis hier : IPTV-Publiques : dernière ligne inattendue : « [2026-09-25 00:18:10] === BILAN: 52/87 chaînes vivantes, 1 perdue (ORF ».

Relevé du 26/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h17 — 7/8 OK À regarder
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 402.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 332 creee — 23801 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 26/09, komga 26/09, music 26/09, photo 26/09 OK
Maillage Syncthing (8 appareils) 1 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-26 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-27

Veille du dimanche 27 septembre 2026

À regarder — Sauvegardes : 7/8 réussies cette nuit (Documents ===) (depuis 4 j) · Syncthing : XIAOMI15Pro non vu depuis 3 j · IPTV-Publiques : dernière ligne inattendue : « [2026-09-27 00:18:20] === BILAN: 49/87 chaînes vivantes, 2 perdues (RT ». Le reste est en ordre. Rétabli depuis hier : Certificats.

Agenda —

107 articles sur 24 h (111 avant regroupement des doublons et fils de discussion) — 35 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (2)

OpenStreetMap (3)

Urbanisme & Territoires (17)

Self-hosting & Infra (1)

Libre & Linux (8)

IA & Numérique (3)

Signaux transverses (1)

Non retenu (32)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 24
Culture 5
Toulon 1
Sans catégorie 1
Libres et Ouverts 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h).

Rétabli depuis hier : Certificat de pdf.juxjux.ovh expire dans 29 j.

Relevé du 27/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h16 — 7/8 OK À regarder
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 402.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 333 creee — 24397 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 27/09, komga 27/09, music 27/09, photo 27/09 OK
Maillage Syncthing (8 appareils) 1 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 2 min, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-27 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-28

Veille du lundi 28 septembre 2026

À regarder — Certificat de spdf.juxjux.ovh expire dans 29 j · Syncthing : XIAOMI15Pro non vu depuis 4 j (depuis 2 j) · Syncthing : SM-T720 non vu depuis 30 j · IPTV-Publiques : dernière ligne inattendue : « [2026-09-28 00:19:03] === BILAN: 85/121 chaînes vivantes, 1 perdue (LR ». Le reste est en ordre. Rétabli depuis hier : Sauvegardes.

Agenda —

177 articles sur 24 h (180 avant regroupement des doublons et fils de discussion) — 42 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (3)

Urbanisme & Territoires (19)

Self-hosting & Infra (6)

Libre & Linux (8)

IA & Numérique (5)

Non retenu (55)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 33
Culture 7
Sans catégorie 6
Libres et Ouverts 4
Toulon 3
Synoworld 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h), navidrome-navidrome-1 (il y a 29 min).

Rétabli depuis hier : Sauvegardes : 7/8 réussies cette nuit (Documents).

Relevé du 28/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h17 — 8/8 OK OK
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) aujourd'hui 07h00 — Container redémarré — full scan en cours OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 402.2 Mo (77.6%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 334 creee — 17884 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 28/09, komga 28/09, music 28/09, photo 28/09 OK
Maillage Syncthing (8 appareils) 2 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-28 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-29

Veille du mardi 29 septembre 2026

À regarder — Syncthing : SM-T720 non vu depuis 31 j (depuis 2 j) · Inventaire photo du NAS : aucun journal — la tache ne tourne pas · IPTV-Publiques : dernière ligne inattendue : « [2026-09-29 00:19:02] === BILAN: 86/121 chaînes vivantes, 2 perdues (O » (depuis 2 j). Le reste est en ordre. Rétabli depuis hier : Certificats, Syncthing.

Agenda —

285 articles sur 24 h (292 avant regroupement des doublons et fils de discussion) — 83 retenus dans 7 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (6)

OpenStreetMap (2)

Urbanisme & Territoires (32)

Self-hosting & Infra (2)

Libre & Linux (13)

IA & Numérique (26)

Signaux transverses (2)

Non retenu (148)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 88
Sans catégorie 47
Culture 5
Libres et Ouverts 4
Synoworld 2
cuisine 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h), navidrome-navidrome-1 (il y a 24 h), homarr2026 (il y a 15 h).

Rétabli depuis hier : Certificat de spdf.juxjux.ovh expire dans 29 j ; Syncthing : XIAOMI15Pro non vu depuis 4 j.

Relevé du 29/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h17 — 8/8 OK OK
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 407.9 Mo (77.7%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 335 creee — 19572 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 29/09, komga 29/09, music 29/09, photo 29/09 OK
Maillage Syncthing (8 appareils) 4 appareil(s) vu(s) depuis hier, connecté(s) maintenant : jux-debian À regarder
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) hier 20h44 — 3 compresse(s), 0 recopie(s), 0 echec(s) - 13.1 Mo -> 5.1 Mo (61.3… OK — à la demande
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-29 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-09-30

Veille du mercredi 30 septembre 2026

À regarder — Inventaire photo du NAS : aucun journal — la tache ne tourne pas (depuis 2 j) · Komga-PDF : 2 erreurs depuis hier — ERREUR (1/3) : 400 Client Error: Bad Request for url: https://spdf.juxjux.ovh/api/v1/misc/ · IPTV-Publiques : dernière ligne inattendue : « [2026-09-30 00:19:04] === BILAN: 86/121 chaînes vivantes, 1 perdue (RT » (depuis 3 j). Le reste est en ordre. Rétabli depuis hier : Syncthing.

Agenda —

316 articles sur 24 h (323 avant regroupement des doublons et fils de discussion) — 102 retenus dans 6 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (5)

Urbanisme & Territoires (35)

Self-hosting & Infra (5)

Libre & Linux (18)

IA & Numérique (32)

Culture (7)

Non retenu (151)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 97
Sans catégorie 46
Libres et Ouverts 4
cuisine 2
Toulon 2

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 1 h), homarr2026 (il y a 39 h).

Rétabli depuis hier : Syncthing : SM-T720 non vu depuis 31 j.

Relevé du 30/09 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h19 — 8/8 OK OK
Komga-PDF (compression des magazines) hier 22h56 — 5 compressé(s), 0 erreur(s) (Saveurs Octobre-Novembre 2026.pdf, 23.… À regarder
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 407.9 Mo (77.7%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 336 creee — 23338 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 30/09, komga 30/09, music 30/09, photo 30/09 OK
Maillage Syncthing (8 appareils) 5 appareil(s) vu(s) depuis hier, connecté(s) maintenant : PC-Julien… OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte il y a 1 min, PC julie à l'… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) 28/09 20h44 — 3 compresse(s), 0 recopie(s), 0 echec(s) - 13.1 Mo -> 5.1 Mo (61.3… OK — à la demande
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-09-30 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-10-01

Veille du jeudi 1 octobre 2026

À regarder — Inventaire photo du NAS : aucun journal — la tache ne tourne pas (depuis 3 j) · IPTV-Publiques : dernière ligne inattendue : « [2026-10-01 00:19:02] === BILAN: 87/121 chaînes vivantes, 2 perdues (O » (depuis 4 j). Le reste est en ordre. Rétabli depuis hier : Komga-PDF.

Agenda —

280 articles sur 24 h (289 avant regroupement des doublons et fils de discussion) — 115 retenus dans 8 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (7)

OpenStreetMap (3)

Urbanisme & Territoires (56)

Self-hosting & Infra (5)

Libre & Linux (14)

IA & Numérique (24)

Culture (4)

Signaux transverses (2)

Non retenu (143)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 85
Sans catégorie 54
Libres et Ouverts 2
Synoworld 1
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 6 h).

Rétabli depuis hier : Komga-PDF : 2 erreurs depuis hier — ERREUR (1/3) : 400 Client Error: Bad Request for url: https://spdf.juxjux.ovh/api/v1/misc/.

Relevé du 01/10 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h22 — 8/8 OK OK
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 407.9 Mo (77.7%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 337 creee — 28486 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 01/10, komga 01/10, music 01/10, photo 01/10 OK
Maillage Syncthing (8 appareils) 4 appareil(s) vu(s) depuis hier, connecté(s) maintenant : SM-T720,… OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) hier 20h20 — 10 compresse(s), 0 recopie(s), 0 echec(s) - 33.3 Mo -> 12.4 Mo (62.… OK — à la demande
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-10-01 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

06_Veille quotidienne FreshRSS

Veille 2026-10-02

Veille du vendredi 2 octobre 2026

À regarder — Certificat de alteris.juxjux.ovh expire dans 29 j · Certificat de bookstack.juxjux.ovh expire dans 29 j · Inventaire photo du NAS : aucun journal — la tache ne tourne pas (depuis 4 j) · IPTV-Publiques : dernière ligne inattendue : « [2026-10-02 00:18:54] === BILAN: 88/121 chaînes vivantes, 1 perdue (OR » (depuis 5 j). Le reste est en ordre.

Agenda —

217 articles sur 24 h (229 avant regroupement des doublons et fils de discussion) — 91 retenus dans 8 themes.

Ouvrir FreshRSS · Modifier les criteres de veille

SIG & Cartographie (1)

OpenStreetMap (4)

Urbanisme & Territoires (41)

Self-hosting & Infra (5)

Libre & Linux (19)

IA & Numérique (16)

Culture (4)

Signaux transverses (1)

Non retenu (119)

Articles hors criteres, consultables dans FreshRSS.

Categorie Articles
Geekeries 93
Sans catégorie 20
Libres et Ouverts 3
Toulon 1
Arts and Co 1
cuisine 1

État de l'infrastructure

Changements depuis hier : conteneur(s) redémarré(s) depuis hier : Immich-SERVER (il y a 30 h).

Relevé du 02/10 à 05h30 (heure de Paris) par etat_infra.py — muet quand tout va bien ; les exceptions attendues sont dans Etat-Infra/config.json.

Procédures

Procédure Dernière utilisation Vérification
Sauvegardes VPS → kDrive aujourd'hui 04h16 — 8/8 OK OK
Komga-PDF (compression des magazines) — OK — à la demande
Komga-Cache (refresh kDrive + 23 scans) hier 07h45 — 23 scan(s) lance(s), aucun echec OK
Scan Navidrome (quick 4h30, complet lundi 3h) hier 08h30 — Scan Navidrome lancé OK OK
Scan Audiobookshelf (36 bibliothèques) hier 08h00 — SCAN OK 36/36 libs OK
Compression Joplin (images en base) aujourd'hui 07h00 — Economie : 407.9 Mo (77.7%) OK
Veille FreshRSS → BookStack hier 10h00 — Page 338 creee — 30318 caracteres HTML OK
Seedbox → kDrive movies → Jellyfin « Films récents » 14/09 23h37 — dernière copie : 5 fichier(s) copie(s) en 125s OK — à la demande
monitor-rclone (recovery des montages) 23/09 09h40 — dernière intervention : Recovery terminée pour /home/debian/photo OK — à la demande
Montages rclone kDrive (7, dont Jellyfin) 7/7 montages kDrive répondent OK
Synchro NAS sasnexte → kDrive (4 dossiers) aujourd'hui — audiobooks 02/10, komga 02/10, music 02/10, photo 02/10 OK
Maillage Syncthing (8 appareils) 3 appareil(s) vu(s) depuis hier, connecté(s) maintenant : PC-Julien… OK
Tunnel WireGuard (VPS ↔ NAS ↔ PC) dernière poignée de main — NAS sasnexte à l'instant, PC julie il y… OK
Kobo — dépôt d'epub (Documents/Kobo) 22/08 11h28 — 1 fichier(s), dernier : Geohistoire Une autre histoire - Christian… OK — à la demande
Photos-Caesium (PC, dépôt de photos) 30/09 20h20 — 10 compresse(s), 0 recopie(s), 0 echec(s) - 33.3 Mo -> 12.4 Mo (62.… OK — à la demande
Musique-FLAC (PC, FLAC → MP3 vérifié) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Livres-ISBN (PC, inventaire + résolution) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Mealie-Recettes (note Joplin → recette) aucun témoin reçu — pas encore tourné depuis l'ajout du témoin non observé
Canari Etat-Infra (ce relevé) relevé en cours OK

Récapitulatif complet des procédures (description, où ça tourne, comment vérifier) : page 316. Liste dans Etat-Infra/procedures.json.


Genere le 2026-10-02 a 06h00 (heure de Paris) par veille_freshrss.py (VPS, cron quotidien). Criteres : page 252.

07_Claude et la domotique de la maison

07_Claude et la domotique de la maison

Le système Blink de caméras et sonnettes connectées

Première identification réseau : 23 août 2026, depuis le poste Windows julie (192.168.1.26, Ethernet). Script de relevé : Jux-scripts/Reseau-LAN/scan_lan.py

Ce qui a été cherché

Question de départ : la sonnette Blink est-elle visible sur le réseau local ? Réponse : oui, un unique appareil au constructeur Amazon répond sur le LAN domestique.

Champ Valeur
Adresse IP 192.168.1.128 (bail DHCP Livebox)
Adresse MAC e8:4c:4a:62:8d:d9
OUI E8:4C:4A Amazon Technologies Inc.
Nom DHCP / DNS inverse device-19.home
Ports TCP ouverts 443 uniquement
Latence 3–6 ms, 0 % de perte

Le port 443 n'accepte aucun client anonyme. Handshake TLS rejeté dans toutes les configurations testées :

Tentative Résultat
TLS auto (jusqu'à 1.3), ALL:@SECLEVEL=0 SSLV3_ALERT_HANDSHAKE_FAILURE
TLS 1.2 forcé, ALL:@SECLEVEL=0 SSLV3_ALERT_HANDSHAKE_FAILURE
TLS 1.0 forcé TLSV1_ALERT_PROTOCOL_VERSION

L'appareil impose donc son propre jeu de suites cryptographiques, et exige vraisemblablement un certificat client (authentification mutuelle). Comportement attendu et sain : le point de contact local ne parle qu'à l'application Blink et au cloud Amazon. Il n'y a pas d'interface web, pas de flux RTSP, pas d'API locale exploitable — inutile de chercher à brancher Frigate, Scrypted ou Home Assistant dessus par cette voie.

Ce que le réseau ne dit pas

  1. Impossible de distinguer la sonnette du module Sync depuis le LAN. Les deux portent une OUI Amazon et le même profil de port. Pour trancher : application Blink → Paramètres de l'appareil → Informations, qui affiche l'adresse MAC de chaque appareil. À reporter ici une fois relevé.
  2. Un seul appareil Amazon répond. Si le foyer compte à la fois une sonnette et un module Sync, le second est en veille au moment du relevé. La Blink Video Doorbell sur batterie en mode standard dort entre deux événements et ne répond alors ni au ping ni à l'ARP ; elle n'est connectée en permanence qu'en câblage secteur (mode « enhanced »). Point à confirmer par un relevé déclenché juste après avoir sonné à la porte.

Inventaire complet du LAN — 192.168.1.0/24

Relevé du 2026-08-23 (balayage ping de .1 à .254, puis lecture de la table ARP) :

IP MAC Constructeur Nom DNS Ports TCP
.1 20:37:f0:a1:fa:dc Arcadyan Corporation lan.home 80, 443, 8883
.10 72:75:be:32:27:c4 [MAC aléatoire] lenovo-tab-k11.home aucun
.11 4e:16:10:cb:79:51 [MAC aléatoire] redmi-note-11-pro.home aucun
.17 00:11:32:9c:8e:c9 Synology Incorporated — 21, 22, 80, 139, 443, 445
.23 2e:a5:80:20:23:b8 [MAC aléatoire] s23-de-elio.home aucun
.128 e8:4c:4a:62:8d:d9 Amazon Technologies Inc. device-19.home 443
.129 d4:3a:2e:d8:c5:52 SHENZHEN MTC CO LTD — 80
.200 d4:3a:2e:d8:c5:52 SHENZHEN MTC CO LTD — 80

Points de méthode — à ne pas re-découvrir

  1. arp -a seul ne montre presque rien. Le cache ARP ne contient que les hôtes contactés récemment — 3 entrées au premier relevé, contre 8 après balayage. Toujours pinger le /24 avant de lire la table ARP.
  2. La sortie de arp -a est traduite sous Windows (dynamique et non dynamic). Ne jamais filtrer sur ce mot-clé : parser par expression régulière sur le couple IP + MAC. C'est ce que fait scan_lan.py.
  3. Une MAC dont le 2e bit du premier octet est posé est aléatoire, pas un vrai constructeur : 72:, 4e:, 2e:… Test : int(octet1, 16) & 0x02. C'est la randomisation MAC des OS modernes (Android, iOS, Windows) — inutile d'interroger une base OUI, elle ne renverra rien. Trois des huit appareils du LAN sont dans ce cas.
  4. Le DNS inverse de la Livebox est la source la plus riche. socket.gethostbyaddr() renvoie les noms d'hôte du domaine .home (redmi-note-11-pro.home, s23-de-elio.home) — bien plus parlant que l'OUI pour les téléphones à MAC aléatoire. Ne pas s'arrêter à l'OUI.
  5. api.macvendors.com limite à ~1 requête/seconde en accès gratuit. Le script temporise 1,5 s et met en cache dans oui_cache.json ; les relevés suivants peuvent tourner en --hors-ligne.
  6. curl.exe est absent du poste julie — tout passe par Python (urllib) ou Invoke-RestMethod.
  7. Un TTL de 64 dans la réponse ping indique une pile réseau Linux/BSD embarquée (Windows répondrait 128). Indice utile pour typer un objet connecté muet.

Commandes de vérification

Inventaire complet, avec sondage des ports :

py -3.12 D:\Syncthing\Jux_univers\Jux-scripts\Reseau-LAN\scan_lan.py --ports

Relevé rapide sans rien pinger ni interroger en ligne (lit le cache ARP et le cache OUI) :

py -3.12 scan_lan.py --sans-balayage --hors-ligne

Vérifier que l'appareil Blink est éveillé :

ping -n 4 192.168.1.128

Le script est en stdlib Python pure — aucune dépendance à installer, il tourne tel quel sur Windows, Ubuntu et le VPS. Il détecte le préfixe /24 tout seul et accepte --reseau pour le forcer.

Reste à faire


Le problème d'usage — caméras muettes après une période d'inactivité

Analysé le 30 août 2026, à la suite de l'ajout de la caméra rampe.

Le symptôme

Quand quelqu'un sonne au portail, tout fonctionne. En revanche, après un laps de temps sans utilisation, ni la caméra du portail ni la caméra rampe ne répondent lorsqu'on les interroge depuis l'application Blink.

Cette asymétrie est l'indice le plus précieux du dossier, et elle oriente tout le diagnostic. Deux chemins bien distincts sont en jeu :

Le défaut est donc dans la chaîne de réveil entrante, pas dans les caméras elles-mêmes ni dans leur liaison au cloud.

La chaîne de réveil, maillon par maillon

Une demande de vue en direct traverse tout ceci :

  1. Application → cloud Amazon (Internet, réseau mobile ou Wi-Fi du téléphone)
  2. Cloud → module Sync, via la connexion Internet de la maison — le module est le seul élément en permanence alimenté et associé au Wi-Fi
  3. Module Sync → caméra, par une liaison radio propriétaire basse fréquence (de l'ordre de 900 MHz). C'est le seul canal encore actif quand la caméra dort, et il est hors de portée du réseau IP
  4. La caméra allume sa radio Wi-Fi, se ré-associe au point d'accès et obtient un bail DHCP
  5. Elle ouvre sa connexion vers le cloud, puis le flux vidéo remonte

Les maillons 3, 4 et 5 sont les points fragiles. Ils ne sont sollicités que lors d'un réveil entrant — ce qui explique exactement pourquoi la sonnerie fonctionne et pas la vue en direct.

Pourquoi un « ping léger et permanent » ne peut pas fonctionner

L'idée de maintenir les appareils éveillés par un ping périodique est séduisante, mais elle se heurte à un fait établi par nos propres relevés.

Sur trois balayages complets du /24, la table ARP n'a jamais contenu qu'une seule adresse Amazon. Les caméras ne sont pas « silencieuses » : elles ne sont pas associées au Wi-Fi du tout. Leur radio est éteinte, elles n'ont aucune adresse IP.

Deux conséquences, l'une technique et l'autre pratique :

Il n'existe donc pas de solution réseau à ce problème. Ce qui suit agit sur les causes réelles.

Causes plausibles, par rendement décroissant

Le fait que les deux caméras échouent ensemble est significatif : deux appareils indépendants tombant en panne simultanément est peu probable. Cela désigne un élément commun — module Sync, Wi-Fi de la maison, ou Livebox — plutôt qu'un défaut propre à chaque caméra. À traiter dans cet ordre :

  1. Piles faibles. Cause n°1 des réveils manqués, et la plus trompeuse. L'allumage de la radio Wi-Fi demande une pointe de courant ; des piles fatiguées s'effondrent sous cette charge alors que l'application les affiche encore « correctes », car elle mesure une tension à vide. Symptôme caractéristique : la caméra répond quand elle vient d'être sollicitée, mais plus après un long repos. Exiger des piles lithium AA (type Energizer Ultimate Lithium) — les alcalines tiennent mal les pointes de courant par temps froid, et les rechargeables NiMH à 1,2 V n'atteignent pas la tension attendue.
  2. Signal Wi-Fi insuffisant à l'emplacement. Au réveil, la caméra doit se ré-associer de zéro : c'est bien plus exigeant que maintenir une liaison déjà établie. Un signal limite passe quand tout va bien et échoue au portail, en bout de portée. L'application Blink affiche deux indicateurs distincts par caméra — un pour le Wi-Fi, un pour la liaison au module Sync. Les relever tous les deux, sur les deux caméras : c'est la mesure la plus utile disponible, et elle est hors de ma portée depuis le réseau.
  3. Placement du module Sync. Il doit être à la fois dans la portée radio des deux caméras et bien couvert en Wi-Fi. Le rapprocher des caméras améliore le maillon 3 ; le rapprocher de la Livebox améliore le maillon 2. C'est un arbitrage, souvent mal réglé par défaut.
  4. Bail DHCP expiré pendant le sommeil. Après une longue absence, le bail a disparu de la Livebox : la caméra doit refaire une négociation complète, ce qui allonge le réveil et peut le faire échouer. Correctif : réserver une IP fixe pour le module Sync et pour chaque appareil Blink dans le DHCP de la Livebox.
  5. SSID unique 2,4 + 5 GHz avec orientation de bande. Les appareils Blink sont 2,4 GHz uniquement. Une Livebox qui diffuse un SSID unique et arbitre les bandes peut mal orienter une ré-association. Si le modèle le permet, exposer un SSID 2,4 GHz distinct et y fixer les appareils Blink.
  6. Programmation horaire du Wi-Fi. Les Livebox savent couper le Wi-Fi la nuit. Vérifier qu'aucune plage d'extinction n'est active.
  7. Firmware. Vérifier les mises à jour du module Sync et des caméras dans l'application.

Mesurer avant de conclure

Le module Sync est le seul élément observable depuis le réseau, et c'est justement le suspect n°1 en tant qu'élément commun. S'il décroche du Wi-Fi pendant les périodes creuses, tout le reste s'effondre — et cela se mesure.

Script : Jux-scripts/Reseau-LAN/surveiller_blink.py, stdlib seule.

py -3.12 D:\Syncthing\Jux_univers\Jux-scripts\Reseau-LAN\surveiller_blink.py --intervalle 30
py -3.12 surveiller_blink.py --resume

Il sonde toutes les 30 s, journalise en CSV dans D:\Logs\Blink\blink_AAAAMMJJ.csv et signale à la seconde près chaque apparition, perte, retour et disparition ARP. Ce n'est pas un maintien en éveil — la sonde ne réveille rien, elle constate.

⚠ Les journaux sont volontairement écrits hors de l'arbre Syncthing, dans D:\Logs\Blink\ (surchargeable par la variable d'environnement BLINK_LOGS). Le script sonde toutes les 30 s : rangé dans Jux-scripts/, chaque sonde aurait déclenché une propagation vers les 7 appareils du maillage — bruit de synchronisation permanent pour quelques octets de mesure. Le script est synchronisé, ses journaux ne le sont pas. Même raisonnement que pour les dossiers de la procédure Photos-Caesium.

Deux lectures possibles au bout de quelques jours :

Ce test coupe le problème en deux et évite d'agir au hasard. Référence relevée le 30 août 2026 : 30 sondes, 0 % de perte, latence 4 à 26 ms — le module Sync est irréprochable en journée. Reste à savoir ce qu'il fait la nuit et pendant les longues absences.

Un point à confirmer par l'application : lequel des appareils est 192.168.1.128. Sa disponibilité parfaite et permanente désigne le module Sync, mais tant que la MAC e8:4c:4a:62:8d:d9 n'a pas été relevée dans Paramètres de l'appareil → Informations, ce n'est qu'une déduction.

Relevé du 30 août 2026

Nouveau balayage après ajout de la caméra rampe. Toujours un seul appareil Amazon, en IPv4 comme en IPv6 (le voisinage IPv6 ne connaît que la Livebox et le NAS). Évolutions constatées, sans rapport avec Blink :

ÉvolutionAppareil
Apparu.12 — redmi-13c.home (MAC aléatoire)
Apparu.28 — pc-elio.home, Intel 08:b4:d2:6b:3b:63
Disparu.23 — s23-de-elio.home
Inchangé.128 — e8:4c:4a:62:8d:d9, seul appareil Amazon

Le NAS résout désormais en NASMAISON. Le doublon de bail .129/.200 persiste.

Ce que la sonde voit — et ses angles morts

Point clarifié le 30 août 2026, parce qu'il conditionne les décisions de placement.

Il n'y a pas un lien mais trois, et celui qui relie le module Sync aux caméras n'est pas du Wi-Fi.

LienNatureActif quandObservable par la sonde ?
Livebox ↔ module SyncWi-Fi 2,4 GHzen permanenceOui, c'est la mesure principale
Module Sync ↔ camérasradio propriétaire ~900 MHzen permanence (réveil, commandes)Non, hors du monde IP
Livebox ↔ camérasWi-Fi 2,4 GHzuniquement caméra réveilléeOui, par intermittence

Conséquence pratique, contre-intuitive : le Wi-Fi des caméras va vers la Livebox, pas vers le module Sync. Rapprocher le module Sync des caméras améliore la liaison radio de réveil, mais ne change rien à la portée Wi-Fi des caméras. Si le portail est loin de la Livebox, déplacer le module Sync ne corrigera pas ce problème-là. C'est précisément pour cela que l'application affiche deux indicateurs séparés par caméra.

On n'est donc pas aveugle aux caméras. La liaison radio de réveil est inobservable, mais son résultat l'est : une caméra qui se réveille s'associe à la Livebox et prend une adresse IP, donc elle apparaît. Si elle n'apparaît jamais, c'est que le réveil ou l'association Wi-Fi échoue — ce qui est exactement la question posée.

Angles morts assumés

Trois correctifs du 30 août 2026

  1. Balayage périodique du /24 — sans lui, les caméras seraient restées invisibles. La première version lisait la table ARP sans jamais l'alimenter : or arp -a ne montre que les hôtes déjà contactés. Une caméra qui se réveille n'y serait entrée que par hasard, et la détection d'apparition n'aurait probablement jamais fonctionné. Le script balaie désormais le /24 toutes les 5 min (option --balayage). Défaut de conception, pas de réglage : la fonctionnalité annoncée était inopérante.
  2. Le script ne meurt plus sur une erreur d'écriture. Une exception sur le journal faisait tomber toute la surveillance — une sonde perdue est sans conséquence, un script mort laisse un trou de plusieurs jours et fait croire à une panne réseau.
  3. Journal de repli blink_AAAAMMJJ_b.csv. Ouvrir le CSV dans LibreOffice Calc pose un verrou exclusif qui bloque toute écriture : consulter ses propres mesures suffisait à les interrompre. Constaté en conditions réelles le 30 août — le coupable a été identifié par le Restart Manager de Windows, seul moyen sans outil tiers :
    Add-Type -TypeDefinition $sig -Language CSharp   # binding rstrtmgr.dll
    [RM]::Who('D:\Logs\Blink\blink_20260830.csv')     # -> 10336 : LibreOffice
    --resume agrège tous les fichiers blink_*, les deux journaux sont donc relus ensemble. À retenir : ni arp -a, ni la liste des processus Python ne désignent le verrou — aucun processus Python ne subsistait, et le fichier restait bloqué.

Mise en service de la surveillance — méthode retenue le 30 août 2026

Voie retenue : le dossier Démarrage de Windows, sans élévation. Le planificateur de tâches a été écarté après deux échecs successifs, documentés ci-dessous.

Lanceur : Jux-scripts/Reseau-LAN/Surveillance Blink.cmd (fins de ligne CRLF, appelle pythonw.exe — donc aucune fenêtre visible).

& "D:\Syncthing\Jux_univers\Jux-scripts\Reseau-LAN\Surveillance Blink.cmd"
Copy-Item "D:\Syncthing\Jux_univers\Jux-scripts\Reseau-LAN\Surveillance Blink.cmd" "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\"

État au 30 août 2026, 08:54 — sonde active (PID 3724), journal alimenté toutes les 30 s, module Sync joignable à 4–6 ms.

Pièges de mise en service — à ne pas refaire

  1. La syntaxe schtasks /tr "\"chemin\" \"script\"" est du cmd.exe, pas du PowerShell. En PowerShell, \" n'est pas une séquence d'échappement : la commande échoue sur « Argument ou option non valide » avec les antislashs restés collés au chemin. Soit utiliser le jeton d'arrêt d'analyse --%, soit — mieux — se passer des guillemets internes, aucun des deux chemins en jeu ne comportant d'espace.
  2. Register-ScheduledTask exige l'élévation pour écrire dans le dossier racine du planificateur : Accès refusé, HRESULT 0x80070005. Ce n'est pas contournable par la syntaxe. Le dossier Démarrage, lui, ne demande aucun droit administrateur — c'est ce qui a tranché.
  3. Si l'on passe malgré tout par le planificateur en console élevée, préciser -User "julie" -RunLevel Limited : sans cela la tâche s'exécuterait avec les privilèges administrateur, ce qu'une simple sonde réseau n'a aucune raison d'obtenir. Ajouter -ExecutionTimeLimit ([TimeSpan]::Zero), faute de quoi la tâche est tuée au bout de 72 h (limite par défaut) — fatal pour une surveillance censée durer.
  4. La copie vers le dossier Démarrage doit être tapée par Julien, jamais lancée depuis Claude Code. %APPDATA% est redirigé par le conteneur MSIX : la copie atterrirait dans …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\…, invisible de Windows, sans le moindre message d'erreur. Piège général documenté page 282.
  5. Méthode de vérification, elle, exécutable depuis Claude Code — la liste des processus et les chemins réels ne sont pas virtualisés en lecture :
    Get-CimInstance Win32_Process -Filter "Name='pythonw.exe'" | Select-Object ProcessId, CommandLine
    Pour lever tout doute sur une écriture dans %APPDATA%, comparer le chemin réel et son équivalent …\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\… : le fichier présent uniquement dans le chemin réel prouve une écriture authentique ; présent dans les deux avec les mêmes taille et horodatage, c'est le même fichier redirigé.
  6. Coller un message d'erreur PowerShell dans PowerShell produit une cascade d'erreurs trompeuses. Les lignes de rappel commencent par +, que l'interpréteur lit comme un opérateur unaire : « Expression manquante après l'opérateur unaire + ». Symptôme sans rapport avec le problème d'origine — ne pas se lancer dans son diagnostic.

Contrepartie de la voie retenue : une fenêtre de console apparaît une fraction de seconde à l'ouverture de session, et le script n'est pas relancé automatiquement s'il s'interrompt. Le planificateur offrirait les deux, au prix d'une élévation.

À faire, dans l'ordre

07_Claude et la domotique de la maison

Xiaomi 15T comme micro du PC Windows

08_Claude et la sécurité digitale du jux's univers

08_Claude et la sécurité digitale du jux's univers

1 - la prise en main sur Bitwarden

Relevé et suivi des passkeys du Jux's univers. Cette page a deux fonctions : conserver l'état du coffre Bitwarden, et servir de fiche de relevé pour ce que chaque service a réellement enregistré de son côté. C'est la confrontation des deux qui fait apparaître les credentials orphelins.

Pourquoi les deux moitiés sont nécessaires. Il n'existe aucun registre central des passkeys. Le coffre ne connaît que ce qu'il stocke lui-même ; la liste qui fait autorité est détenue par chaque service. Supprimer une passkey dans Bitwarden ne la révoque pas côté serveur, et l'inverse est vrai aussi.

1. État du coffre — relevé du 2026-08-25

14 passkeys, obtenues par bw list items (voir § 4).

Domaine (rpId) Élément Identifiant Créée le
amazon.fr amazon.fr jubertrand@gmail.com 2025-02-14
auth.monidentifiant.sncf monidentifiant.sncf nexte@ik.me 2026-01-15
aws.amazon.com signin.aws.amazon.com arn:aws:iam::712353451166:root 2024-12-17
google.com accounts.google.com bertrand.dadone@gmail.com 2024-07-07
google.com accounts.google.com jubertrand@gmail.com 2024-03-15
google.com accounts.google.com nexte.urbanisme@gmail.com 2024-02-01
juxjux.synology.me juxjux.synology.me juxjux 2026-01-09
login.eau.veolia.fr login.eau.veolia.fr jubertrand@gmail.com 2024-09-18
login.microsoft.com outlook.live.com julien.bertrand@live.fr 2025-07-29
login.nvgs.nvidia.com login.nvgs.nvidia.com juxjux@yahoo.com 2026-08-19
nextcloud.juxjux.ovh nextcloud.juxjux.ovh julien 2025-12-10
vault.bitwarden.com vault.bitwarden.com julien.bertrand@ik.me 2024-01-16
www.dropbox.com dropbox.com nexte@ik.me 2026-01-16
www.paypal.com paypal.com julien.bertrand@laposte.net 2026-04-04

10 identités distinctes pour 14 passkeys. Les trois lignes google.com ne sont pas des doublons : ce sont trois comptes Google différents — le script les signale comme doublons, c'est un faux positif connu.

2. Fiche de relevé côté services

Tableau à compléter au fil des visites. Une ligne par domaine. La colonne Identifiants côté service se remplit avec ce que la page de sécurité du service affiche réellement, séparé par des virgules — c'est elle que le script compare au coffre. Laisser Relevé le vide tant que la vérification n'a pas été faite.

# Domaine (rpId) URL de vérification Identifiants côté service Relevé le Action
1 login.microsoft.com account.microsoft.com → Sécurité → Options de connexion avancées
2 aws.amazon.com Console AWS → IAM → Identifiants de sécurité (compte racine)
3 google.com passwords.google.com → Passkeys (les 3 comptes)
4 www.paypal.com paypal.com → Paramètres → Sécurité
5 www.dropbox.com dropbox.com → Paramètres → Sécurité
6 juxjux.synology.me DSM → Personnel → Compte → Sécurité
7 amazon.fr amazon.fr → Connexion et sécurité
8 auth.monidentifiant.sncf monidentifiant.sncf → Sécurité
9 login.eau.veolia.fr eau.veolia.fr → Mon compte
10 login.nvgs.nvidia.com nvidia.com → Mon compte → Sécurité
11 vault.bitwarden.com vault.bitwarden.com → Paramètres → Sécurité
12 nextcloud.juxjux.ovh service démonté — voir § 3 — 2026-08-25 Supprimer du coffre

Sources hors coffre, à ne pas oublier

Ces emplacements peuvent contenir des passkeys absentes du coffre — typiquement celles créées directement sur le téléphone.

Emplacement Où regarder Relevé le
Google Password Manager passwords.google.com → Passkeys (par compte)
Android — S23 / Xiaomi myaccount.google.com → Sécurité → Vos appareils
Windows Hello néant sur ce poste : aucun TPM, voir § 3 2026-08-25
Clés USB FIDO2 Windows → Paramètres → Comptes → Clés de sécurité

3. Points d'attention

Compte racine AWS — le plus critique. arn:aws:iam::712353451166:root, passkey du 17/12/2024. Un compte racine AWS peut tout faire, y compris fermer le compte et changer le moyen de paiement. Deux questions ouvertes : le compte est-il encore utilisé, et cette passkey est-elle son seul facteur MFA ? Si oui, sa perte coupe l'accès à un compte susceptible d'accumuler de la facturation. C'est le seul cas de la liste justifiant une clé USB FIDO2 de secours.

Dépendance circulaire Bitwarden. La passkey vault.bitwarden.com est stockée dans Bitwarden : elle sert à ouvrir le coffre qui la contient. Sans conséquence tant que la connexion par mot de passe maître reste active — mais un passage du coffre en « passkey uniquement » enfermerait dehors. À laisser en l'état en le sachant, ou à déplacer sur le téléphone.

nextcloud.juxjux.ovh — orphelin confirmé le 2026-08-25. Le vhost subsiste dans /etc/nginx/sites-enabled/ mais répond 502, et aucun container Nextcloud ne tourne sur le VPS. La passkey date du 10/12/2025 : le service a été démonté depuis. Sans usage possible, à supprimer du coffre. Le vhost mort est par ailleurs déjà listé au nettoyage, avec agendav et infcloud — mais pas radicale, qui sert en réalité Readeck.

Compte Microsoft et Mobile connecté. La passkey login.microsoft.com sur julien.bertrand@live.fr existe depuis le 29/07/2025. Un compte Microsoft doté d'une passkey bascule souvent en mode sans mot de passe : lors de l'appairage du téléphone du 2026-08-25, le mot de passe saisi n'était probablement pas « incorrect », il n'était simplement plus le facteur attendu.

Aucun service auto-hébergé ne figure au coffre, hormis le Nextcloud défunt. BookStack, Immich, Readeck, Komga, Gitea restent en mot de passe ou TOTP — le support WebAuthn demeure inégal côté logiciels self-hosted.

Ce poste ne peut pas créer de passkey localement. Aucun TPM détecté (MSI A320M-A PRO, BIOS 1.40 de 2020, Ryzen 5 2600X) : Windows Hello n'a nulle part où protéger une clé. Le fTPM AMD serait activable au BIOS, mais déconseillé ici — BIOS antérieur aux AGESA corrigeant les micro-freezes fTPM, sur une machine à l'historique d'instabilité chargé. Passer par le téléphone ou le coffre.

4. Mode opératoire

Prérequis : Node (présent) et la CLI Bitwarden. Le dossier des binaires npm globaux n'était pas dans le PATH — correctif du 2026-08-25 :

[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path','User') + ";$env:APPDATA\npm", 'User')

Relevé du coffre :

npm install -g @bitwarden/cli
bw login
$env:BW_SESSION = bw unlock --raw
bw list items | py -3.12 "D:\Syncthing\Jux_univers\Jux-scripts\Passkeys\inventaire_passkeys.py"

Le mot de passe maître se tape directement dans la console. Le script n'affiche aucun secret : seuls le nom de l'élément, le domaine, l'identifiant et la date de création.

5. Rapprochement automatique

bw list items | py -3.12 inventaire_passkeys.py --confronter

Le script relit le tableau du § 2 depuis cette page (via l'API BookStack) et le compare à la sortie du coffre. Il signale :

Comme pour la veille FreshRSS, le script parse le HTML de la page et non son markdown : la configuration continue de fonctionner si la page est un jour rééditée en WYSIWYG.


Script : Jux-scripts/Passkeys/inventaire_passkeys.py — stdlib seule, utilisable sur Windows, Ubuntu et le VPS.

08_Claude et la sécurité digitale du jux's univers

2 - sauvegarde et récupération de l'accès au coffre

Procédure de sauvegarde de l'accès au coffre Bitwarden. Complète la fiche de relevé des passkeys (page « 1 - la prise en main sur Bitwarden »). Aucun secret ne figure sur cette page, et aucun ne doit y être ajouté — voir § 5.

1. Ce qu'il faut sauvegarder, et pourquoi ce n'est pas la passkey

Une passkey stockée dans Bitwarden n'est pas sur un appareil : elle est dans le coffre, donc déjà répliquée sur chaque machine connectée et présente dans les sauvegardes serveur de Bitwarden. Elle n'est pas le maillon fragile.

Le maillon fragile est l'accès au coffre. Le scénario qui coupe l'accès à Bitwarden coupe aussi l'accès à une passkey Bitwarden, où qu'elle soit dupliquée. Sauvegarder la passkey elle-même ne protégerait donc de rien — et n'est de toute façon pas possible : les passkeys ne figurent pas dans les exports de coffre.

Corollaire : on ne duplique jamais une passkey, on en enregistre une seconde. Chaque authentificateur génère sa propre paire de clés, le service en tient la liste. La redondance se joue côté service, pas côté fichier.

À sauvegarder Où le récupérer Rôle
Code de récupération vault.bitwarden.com → Paramètres → Sécurité → Connexion en deux étapes → Voir le code de récupération Désactive tous les facteurs 2FA. Le document qui rouvre le coffre
Export chiffré du coffre bw export --format encrypted_json --password <phrase> Les identifiants survivent à une disparition de Bitwarden en tant que service
Graines TOTP Selon les comptes Non incluses dans les passkeys, régulièrement oubliées
Inventaire des passkeys Page 1 du chapitre, ou inventaire_passkeys.py --csv Savoir quoi reconstruire, compte par compte

2. Le code de récupération ne tourne pas tout seul

Point vérifié dans la documentation Bitwarden le 2026-08-25, et contre-intuitif : ni le changement de mot de passe maître, ni l'ajout ou le retrait de méthodes de connexion en deux étapes ne modifient le code de récupération. Il est permanent tant qu'il n'a pas servi.

Le seul mécanisme de rotation documenté est de l'utiliser : après usage, un nouveau code est généré. L'opération désactive au passage les méthodes de connexion en deux étapes, qu'il faut ensuite ré-enrôler — et vérifier si la passkey vault.bitwarden.com en fait partie, ou si elle relève de la connexion par passkey, qui est un mécanisme distinct.

Conséquence pratique : ce code se traite comme un document permanent, pas comme un jeton qu'on pourra régénérer à peu de frais s'il fuite. Sa compromission se répare, mais au prix d'un ré-enrôlement complet du 2FA.

3. Emplacements de conservation

Le vault Cryptomator est le bon réceptacle : chiffrement côté client, présent sur le PC julie et sur le PC Nexte, avec une copie sur kDrive. Infomaniak ne voit qu'un blob chiffré.

Support Contenu Remarque
Papier, rangé physiquement Code de récupération Le seul support qui résiste simultanément à la panne de disque, au rançongiciel et à la perte du téléphone
Vault Cryptomator (PC julie, PC Nexte) Code, export chiffré, graines TOTP, inventaire Second exemplaire, hors ligne au repos
Copie kDrive du vault Idem Exemplaire hors site. La phrase de passe est le seul rempart

Les deux dépendances circulaires à éviter

  1. La phrase de passe Cryptomator ne doit pas être dans Bitwarden. Sinon la sauvegarde devient inutilisable précisément le jour où elle servirait. Elle doit être mémorisée, ou écrite sur papier hors ligne.
  2. L'accès kDrive ne doit pas dépendre uniquement du coffre, pour la même raison.

Même logique que la passkey vault.bitwarden.com stockée dans Bitwarden, signalée en page 1 : une sauvegarde qui a besoin de ce qu'elle sauvegarde n'est pas une sauvegarde.

4. Si le code est noté sous forme masquée

Un code partiellement substitué — segments remplacés par des références mnémotechniques (dates, numéros de département, lieux liés à des personnes connues) — appelle deux précautions.

Sur la robustesse : masquer deux groupes sur huit laisse les trois quarts du code lisible, et l'espace résiduel se compte en milliers de combinaisons. Le procédé ralentit une lecture opportuniste, il ne résiste pas à quelqu'un qui cible et connaît l'entourage. Ne pas lui prêter plus de solidité qu'il n'en a.

Sur la récupérabilité — le point qui compte le plus : la règle de décodage devient un second secret à ne pas perdre. Le code servira probablement dans plusieurs années, en situation dégradée. Il faudra alors se rappeler quelles personnes, quels lieux, dans quel ordre, et quelle parenthèse est une date plutôt qu'un département. Un code de récupération qu'on ne sait plus décoder équivaut à ne pas en avoir.

D'où le principe à respecter : séparer le code masqué de sa règle de décodage. Le papier ne porte que la version masquée, la règle vit dans le vault Cryptomator. Les deux ensemble reconstituent, chacun seul ne dit rien — et aucune perte unique n'est fatale.

5. Où ne jamais écrire ces secrets

Pas dans BookStack, ni dans aucun service auto-hébergé. Une page BookStack finit dans la base MariaDB du VPS, dans la sauvegarde nocturne de 2 h, puis dans l'archive 7z uploadée sur kDrive : trois copies supplémentaires, sur des systèmes que le code de récupération est justement censé pouvoir contourner.

Attention aux formats d'export. N'utiliser que encrypted_json avec --password :

Transcripts Claude Code : ils résident dans C:\Users\julie\.claude\projects\D--Syncthing-Jux-univers-Claude-pcelio-jux--claude\*.jsonl, soit hors de l'arbre Syncthing — ils ne se propagent donc ni vers le VPS, ni vers le téléphone, ni vers kDrive. Ils restent néanmoins en clair sur le disque local : ne pas y coller de secret exploitable.

6. Ordre d'exécution

  1. Récupérer le code de récupération dans l'interface Bitwarden, le porter sur papier, en déposer un second exemplaire dans le vault Cryptomator. (Fait le 2026-08-25.)
  2. Enregistrer une seconde passkey Bitwarden sur le téléphone (Google Password Manager) — casse au passage la dépendance circulaire de la page 1.
  3. Produire l'export chiffré avec une phrase de passe distincte, le déposer dans le vault.
  4. Vérifier que la phrase Cryptomator n'est pas uniquement dans Bitwarden.

Seul le point 1 est urgent. Les trois autres peuvent être étalés.


Voir aussi : page 1 du chapitre pour l'inventaire des passkeys et la fiche de relevé côté services. Script : Jux-scripts/Passkeys/inventaire_passkeys.py.

09- Claude et la debian-jux

09- Claude et la debian-jux

09_01 - la création de la VM le 260909

VM Debian sur le NAS SasNexte — poste de l'univers Jux

Procédure établie le 09/09/2026. Machine installée et opérationnelle le jour même. V2 du 09/09/2026 — redémarrage éprouvé, réservation DHCP posée, correction de l'erreur sur le gestionnaire de connexion.

Ce qui change par rapport à la V1. Le §7 corrige une affirmation fausse : LightDM est installé, contrairement à ce que la V1 annonçait. Le §9 est neuf — la procédure de redémarrage et sa validation réelle. Le §4 insiste sur le démontage de l'ISO, qui avait été omis. Deux points du « reste à faire » sont clos : la réservation DHCP et la question ufw.


1. Raison d'être

Ce poste n'existe pas pour l'ubiquité, mais pour l'étanchéité. Il s'agit de cesser de mélanger deux univers sur une même machine.

PC NEXTE (Windows) VM Debian (NAS)
Univers Alteris / NEXTE — professionnel Jux — personnel
BookStack bookstack.alteris.ovh bookstack.juxjux.ovh
Serveur d'appui VPS Alteris 79.137.14.202 VPS Jux 51.77.141.54
Outils QGIS, LibreOffice, PostGIS, pièces de mission Firefox, Thunderbird, FileZilla, Calibre, Claude Code

Un seul MCP BookStack par machine. C'est ce qui rend structurellement impossible de publier une procédure Alteris dans le BookStack perso, ou l'inverse — au lieu d'une discipline à tenir à chaque page.

Règle à ne pas relâcher. Pas de partage de mission NEXTE monté dans la VM, pas de coffre Alteris, pas de clé SSH vers 79.137.14.202. Un « juste un petit accès » suffit à rendre la séparation décorative.


2. Prérequis matériels — le seul point bloquant

Le DS220+ embarque un Celeron J4025 (2 cœurs, 2 threads). Le facteur limitant est la RAM.

Valeur constatée
RAM totale 5776 Mo (2 Go soudés + barrette 4 Go ajoutée en 2023)
Consommé par DSM ~1160 Mo
Volume1 Btrfs — exigé par VMM — 1,4 To libres
DSM 7.4

VMM réserve la mémoire statiquement : les 3 Go sont retirés à DSM en permanence tant que la VM tourne, qu'elle travaille ou non. Il n'y a pas de ballooning dynamique. Le plafond utile est d'environ 3,5 Go, DSM gardant un socle incompressible de 1,5 à 2 Go. Au-delà, c'est DSM qui swappe — et comme le disque virtuel est sur ce même NAS, tout ralentit ensemble.

Sur 2 Go alloués la VM tiendrait aussi : à l'usage réel, elle consomme 360 Mo au repos, et 473 Mo avec le bureau XFCE ouvert. Le dimensionnement se fait sur le pic, pas sur la somme des applications — elles ne tournent jamais ensemble.


3. Création de la machine virtuelle

Virtual Machine Manager n'était pas installé : Centre de paquets → Virtual Machine Manager, puis créer un stockage sur volume1.

À la première ouverture, DSM propose d'ouvrir les ports 30200-30300 dans le pare-feu. Accepter, puis restreindre la règle au sous-réseau local (Panneau de configuration → Sécurité → Pare-feu, source 192.168.1.0 / 255.255.255.0). Ces ports n'ont aucune raison d'être joignables de l'extérieur.

Paramètres retenus

Écran Réglage
Nom debian-jux
Processeurs 2
Mémoire 3 Go
Carte vidéo vmvga (seul choix)
Type de machine PC (châssis i440fx, BIOS legacy)
Disque 40 Go, contrôleur VirtIO SCSI, réclamation d'espace cochée
Réseau Default VM Network, VirtIO
Micrologiciel Legacy BIOS, pas UEFI
Disposition clavier fr
Port série Désactiver — inutile, et il a brouillé le diagnostic
Contrôleur USB Désactivé
Autostart Oui
Démarrer depuis Disque virtuel

Réclamation d'espace : c'est le TRIM, à ne pas confondre avec l'allocation à la demande (que VMM applique déjà par défaut). Sans elle, le fichier disque croît au fil des apt et n'en redescend jamais.

VirtIO SCSI expose le disque en /dev/sda, pas /dev/vda.

Adresse MAC. VMM en génère une localement administrée — ici 02:11:32:25:c6:e8, reconnaissable à son préfixe 02:. Elle est stable tant que l'interface réseau existe, mais supprimer et recréer la carte réseau dans VMM la change — et rend caduque, en silence, la réservation DHCP du §8.


4. Installation de Debian 13

L'image

Téléchargée directement par le NAS, ce qui évite de faire transiter 755 Mo par le PC :

cd '/volume1/Iso VM'
wget -c -O debian-13.6.0-amd64-netinst.iso \
  https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.6.0-amd64-netinst.iso
sha256sum debian-13.6.0-amd64-netinst.iso
curl -s https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS | grep netinst

Les deux sommes doivent être identiques.

Le mode d'installation

Prendre « Graphical install », pas « Install ». Le mode texte impose de saisir des numéros dans des listes qui défilent hors écran, et la console noVNC de VMM gère mal le clavier. Le mode graphique donne la souris : tous les choix se font au clic.

« Graphical install » ne désigne que le mode d'affichage — le premier écran reste le choix de la langue, où l'on prend « French — Français ».

Les réponses qui comptent

Écran Réponse
Nom de machine jux-debian
Domaine vide
Mot de passe root (voir remarque ci-dessous)
Partitionnement Assisté – disque entier → sda → tout dans une seule partition
Miroir France, deb.debian.org, pas de mandataire
Sélection des logiciels décocher tout sauf serveur SSH et utilitaires usuels du système
GRUB Oui → /dev/sda

Pas de LVM : sur un disque virtuel il n'apporte rien, on agrandit le disque dans VMM. Pas de chiffrement : la VM démarre automatiquement au boot du NAS et réclamerait une passphrase en console à chaque fois.

Remarque sur le mot de passe root. Le laisser vide fait installer sudo et place l'utilisateur dans le groupe. En définissant un mot de passe root — ce qui a été fait ici — sudo n'est pas installé, et le script de post-installation doit être lancé via su - avec le nom d'utilisateur en argument. sudo reste ensuite protégé par mot de passe : aucune automatisation à distance ne peut l'utiliser.

🔴 Démonter l'ISO — l'étape qu'on oublie

Avant le redémarrage final : démonter l'ISO dans les paramètres de la VM (Action → Modifier → Autres → Fichier ISO pour le démarrage → Démonté).

Ça n'a pas été fait le 09/09 — l'ISO est restée montée toute la journée sans qu'on s'en aperçoive, parce que Démarrer depuis : Disque virtuel masque le symptôme : la VM démarre sur le disque et tout paraît normal.

Le danger n'est pas immédiat, il est différé. Le jour où le disque devient non amorçable — GRUB cassé, disque plein — la VM ne s'arrête pas sur une erreur : elle démarre l'installeur Debian. Sur une machine sans écran, avec autostart activé, c'est le scénario où l'on formate sans le voir.

Le vérifier fait partie de la mise en service, au même titre que le reste. Le démontage est accepté à chaud, VM allumée.


5. LE PIÈGE — la console meurt au démarrage

Symptôme. Après l'installation, l'écran se fige systématiquement sur :

/dev/sda1: clean, 40622/2485504 files, 552845/9938432 blocks
[  5.812838] systemd-ssh-generator[255]: Failed to query local AF_VSOCK CID
[  5.958389] systemd[1]: Finished modprobe@efi_pstore.service
[  6.941405] ACPI: bus type drm_connector registered

Plus rien ensuite. Aucune invite de connexion, Ctrl+Alt+F2 sans effet, et la machine n'apparaît pas sur le réseau.

Cause. Trente millisecondes après drm_connector registered, le pilote de la carte vidéo vmvga prend la main sur l'écran et tue la console. Le système, lui, démarre parfaitement : SSH répond, le réseau monte, l'invite de connexion existe — elle n'est simplement plus affichée nulle part.

Correctif — dans /etc/default/grub :

GRUB_CMDLINE_LINUX_DEFAULT="nomodeset"

puis update-grub. nomodeset interdit le kernel modesetting et garde la console en VGA texte de bout en bout.

Retirer quiet en même temps, et ne jamais le remettre. C'est lui qui rend le diagnostic impossible : entre les messages du noyau et l'invite de connexion, l'écran reste muet, et rien ne distingue un démarrage figé d'un démarrage silencieux.

nomodeset ne coûte rien à l'usage. Vérifié le 09/09 : le bureau XFCE s'affiche normalement dans la console VMM malgré nomodeset. Seule l'accélération graphique est perdue, dont on n'a de toute façon pas l'emploi ici.

Deux fausses pistes, pour ne pas les refaire

Comment atteindre GRUB

La console VMM n'existe que si la VM tourne — impossible de l'ouvrir « avant ». Il faut garder la fenêtre de console ouverte (bouton Connecter), démarrer la VM depuis DSM, cliquer Connecter aussitôt et maintenir Maj : GRUB affiche alors son menu et suspend le décompte (GRUB_TIMEOUT=5).

Sur la ligne « Debian GNU/Linux », appuyer sur e — pas Entrée — descendre jusqu'à la ligne linux /boot/vmlinuz…, aller en fin de ligne, ajouter nomodeset et supprimer quiet, puis Ctrl+X.

Une correction faite ainsi ne vaut que pour ce démarrage. Elle ne devient permanente qu'une fois écrite dans /etc/default/grub et suivie d'un update-grub — voir le §9, où cette distinction a failli passer inaperçue.

Les entrées « recovery mode » sont inutilisables si le compte root est verrouillé : le shell de secours refuse de s'ouvrir.


6. Post-installation

Script : 260909-postinstall_vm_debian_jux_v2.sh. Idempotent, environ 20 minutes et 1,5 Go de paquets.

su -
bash /home/julien/260909-postinstall_vm_debian_jux_v2.sh julien 2>&1 \
  | tee /home/julien/260909-postinstall.log

L'argument julien est nécessaire : sans sudo, le script ne peut pas deviner pour quel utilisateur il travaille.

Étape Contenu
0 GRUB : nomodeset ajouté, quiet retiré, fichier d'origine sauvegardé en .avant-nomodeset-260909
1 Locale fr_FR.UTF-8, clavier français, fuseau Europe/Paris
2-3 Mise à jour, socle (sudo, curl, git, ripgrep…)
4 XFCE
5 xrdp + xorgxrdp, ~/.xsession, règle polkit
6 Firefox ESR, Thunderbird, FileZilla, Calibre (+ paquets de langue)
7 Node.js, puis Claude Code via npm avec préfixe ~/.npm-global
8 Syncthing, ufw (22, 3389, 22000, 21027)

L'interface web de Syncthing n'écoute qu'en local (127.0.0.1:8384). L'exposer sur le réseau donnerait un accès sans mot de passe à tout le contenu synchronisé.


7. LightDM — ce qui est réellement installé

Correction de la V1. Elle affirmait « XFCE sans gestionnaire de connexion », en présentant comme un fait ce qui n'était qu'une intention de conception. C'est faux.

Constaté le 09/09 après redémarrage :

lightdm.service — active (running), enabled
Paquets : lightdm, lightdm-gtk-greeter, light-locker
Cible systemd par défaut : graphical.target

LightDM a été tiré comme dépendance par le méta-paquet XFCE. L'étape 4 du script ne l'a jamais empêché.

Décision retenue : on garde LightDM

Le raisonnement, contre-intuitif mais solide : la console VMM de DSM est du noVNC — c'est-à-dire un accès navigateur qui existe déjà, sans rien installer.

Ce que la console DSM affiche dans le navigateur
Avec LightDM (retenu) écran de connexion, puis le bureau XFCE complet
Sans LightDM jux-debian login: — un terminal texte

Garder LightDM donne donc « navigateur → bureau graphique » gratuitement. Coût : environ 150 Mo au repos, sans conséquence sur 3 Go.

⚠️ La contrainte qui vient avec : une seule session à la fois

C'est exactement le conflit que la V1 disait vouloir éviter, et il est réel.

xrdp fonctionne ici en backend Xorg. Si une session XFCE est déjà ouverte sur :0 (la console) et qu'on lance une session RDP avec le même utilisateur, on tombe sur « session déjà ouverte » : écran noir ou reprise erratique. light-locker ajoute sa part — la session RDP peut revenir verrouillée sans moyen commode de la déverrouiller.

Console ou RDP, jamais les deux. Se déconnecter proprement de XFCE (Déconnexion, pas seulement fermer la fenêtre VMM) avant de basculer d'un accès à l'autre.

Si l'on change d'avis

Revenir au design initialement prévu tient en une commande, réversible :

sudo systemctl disable --now lightdm && sudo systemctl set-default multi-user.target

8. Accès

Bureau à distance — RDP

mstsc /v:192.168.1.10

Accepter l'avertissement de certificat (auto-signé), puis sur l'écran xrdp : Session = Xorg, utilisateur julien. Depuis un mobile : Microsoft Remote Desktop, même adresse.

C'est l'accès le plus fluide pour travailler — nettement plus réactif que le noVNC de DSM.

Bureau dans le navigateur — console DSM

http://192.168.1.82:5000 → Virtual Machine Manager → debian-jux → Connecter.

Fonctionne depuis n'importe quel navigateur du réseau local, sans client à installer. Utile aussi quand le réseau de la VM est en panne : la console voit l'écran même si SSH et RDP ne répondent plus.

Ce n'est pas un lien direct — il faut passer par DSM. Pour un vrai signet vers le bureau, la piste est Apache Guacamole (passerelle RDP/VNC vers HTML5) sur le VPS Jux, mais seulement après WireGuard : exposé seul sur Internet, Guacamole devient la porte d'entrée de la VM.

Réservation DHCP — faite le 09/09

L'adresse est réservée sur la Freebox v8 (Ultra), passerelle 192.168.1.254 :

Paramètres de la Freebox → DHCP → Baux Statiques
  jux-debian   02:11:32:25:C6:E8   →   192.168.1.10

Éprouvée au redémarrage du §9 : la VM est revenue sur .10.

Si un jour la VM réapparaît sur une autre adresse sans raison, le premier réflexe est de comparer la MAC réelle (ip link show ens3) à celle du bail : la recréation de la carte réseau dans VMM en génère une nouvelle.

RustDesk — écarté

L'infrastructure existe pourtant sur le VPS Jux (hbbs/hbbr, client enregistré, diode verte) mais n'a jamais donné de session exploitable — il échoue silencieusement, sans rien laisser d'exploitable pour diagnostiquer.

Pour le nomadisme, la voie retenue reste WireGuard sur le VPS Jux + RDP : le diagnostic y est binaire (wg show affiche un handshake, ou rien), les clients sont natifs partout, aucun port n'est à ouvrir sur la box — c'est la VM qui monte le tunnel — et le même tunnel sert pour SSH et pour DSM.

Interface Syncthing

ssh -L 8385:127.0.0.1:8384 julien@192.168.1.10

puis http://127.0.0.1:8385.

Le port local est 8385 et non 8384 : le Syncthing du PC NEXTE occupe déjà 8384. Les deux interfaces sont identiques à l'écran — vérifier le nom de l'appareil en haut à droite (jux-debian) avant de déclarer un partage.


9. Redémarrage — procédure et validation

Pourquoi ça ne va pas de soi

Le 09/09, la VM a tourné toute la journée sur un démarrage de 14:51 obtenu par édition manuelle de GRUB (Ctrl+X). Tout ce qui devait survivre à un redémarrage — GRUB persistant, ufw, configuration xrdp — a été écrit après ce démarrage, entre 15:02 et 15:12.

Autrement dit : la machine fonctionnait, mais rien ne prouvait qu'elle refonctionnerait. Une VM qui marche n'est pas une VM qui redémarre.

La procédure

Avant — deux préalables, dans cet ordre :

  1. Réserver l'adresse dans le DHCP de la box (§8). Sans ça, on teste le redémarrage en gardant le seul facteur capable de faire perdre la machine.
  2. Vérifier Action → Modifier → Autres : Autostart = Oui, Démarrer depuis = Disque virtuel, et surtout ISO démontée (§4).

Pendant :

  1. Ouvrir la console (bouton Connecter) et la garder à l'écran.
  2. Action → **Éteindre** — c'est l'arrêt ACPI propre, l'équivalent d'un appui bref sur le bouton d'alimentation. Pas Forcer l'arrêt, qui est la coupure de courant brutale, à réserver aux machines qui ne répondent plus.
  3. Attendre le statut Arrêté, puis Action → **Mettre sous tension**.

Le point de contrôle à l'écran : les messages du noyau doivent défiler au-delà de ACPI: bus type drm_connector registered. S'ils s'arrêtent là, nomodeset n'a pas tenu — voir §5.

Un instantané préalable (Action → Prendre un instantané) est possible et se supprime ensuite sans toucher la VM. Il n'a pas été jugé utile ici : la machine n'avait qu'un jour et tout son contenu est reproductible par le script du §6. Il prendra son sens quand elle contiendra des comptes Thunderbird et des données Syncthing.

Le contrôle après redémarrage

Depuis le PC NEXTE, en PowerShell (voir la remarque sur ssh.exe au §11) :

who -b ; cat /proc/cmdline
for u in ssh xrdp xrdp-sesman syncthing@julien ufw; do \
  printf "%-18s %-10s %s\n" "$u" "$(systemctl is-active $u)" "$(systemctl is-enabled $u)"; done
systemctl --failed --no-pager
ip -4 addr show ens3 | grep inet
systemd-analyze

is-enabled compte autant que is-active. Un service active mais disabled fonctionne aujourd'hui et disparaît au prochain démarrage — c'est précisément le genre d'écart qu'un test de redémarrage existe pour révéler.

Vérifier que le pare-feu filtre vraiment

ufw status exige root. On peut s'en passer : depuis le PC, comparer un port autorisé et un port qui ne l'est pas.

Test-NetConnection 192.168.1.10 -Port 22
Test-NetConnection 192.168.1.10 -Port 12345

Mesuré le 09/09 : 16 ms sur le port 22, 21 501 ms sur le port 12345. Le pare-feu filtre.

Résultat du test — 09/09/2026, 16:43

Point de contrôle Constaté
/proc/cmdline ro nomodeset, pas de quiet — la config persistante tient
ssh, xrdp, xrdp-sesman, syncthing@julien active + enabled
ufw active + enabled, et filtre réellement
Unités en échec aucune
Erreurs prioritaires au journal aucune
Adresse 192.168.1.10 — via la réservation
Durée 19,7 s (5,7 s noyau + 13,9 s espace utilisateur)
RAM au repos 360 Mo sur 2978

La question ufw laissée ouverte par la V1 est close : il n'y avait aucun bug. Le service apparaissait inactive parce qu'il avait été installé après le démarrage en cours. Un redémarrage suffisait à le montrer.


10. Reste à faire

  1. MCP BookStack perso, à déclarer dans la VM — jeton à créer sur bookstack.juxjux.ovh (profil → Jetons d'API ; le secret n'est affiché qu'une fois) :
claude mcp add -s user bookstack-jux \
  -e BOOKSTACK_BASE_URL=https://bookstack.juxjux.ovh/api \
  -e BOOKSTACK_API_TOKEN=ID:SECRET \
  -e MCP_TRANSPORT=stdio -- npx -y bookstack-mcp-server

Le suffixe /api est obligatoire, le jeton s'écrit id:secret. Jamais sur le PC NEXTE — c'est ce que la VM existe pour empêcher.

  1. Comptes Thunderbird.
  2. WireGuard sur le VPS Jux 51.77.141.54.
  3. (différé) Apache Guacamole, après WireGuard, si le lien navigateur direct se confirme utile.
  4. Publier cette procédure dans bookstack.juxjux.ovh, depuis le Claude Code de la VM — donc après le point 1.

Points clos depuis la V1 : réservation DHCP (§8) et vérification ufw (§9).


11. À retenir pour toute future VM Linux sur ce NAS