0_Claude et le Jux_VPS
- A_liens entre Claude et le KDRIVE
- B_les procédures de Claude
- C_ installation de Claude Code dans le VPS juxjux
- 00_Recapitulatif
- 01_Portainer
- 02_Bookstack
- 03_Homarr
- 04_Audiobookshelf
- 05_BentoPDF
- 06_Cadvisor
- 07_Calibre-web
- 08_Dozzle
- 09_FileBrowser
- 10_FreshRSS
- 11_Gitea
- 12_Grafana
- 13_Immich
- 14_Jellyfin
- 15_Joplin
- 16_Kavita
- 17_Komga
- 18_Mealie
- 19_Navidrome
- 20_NodeExporter
- 21_Prometheus
- 22_Readeck
- 23_Syncthing
- 24_Yourls
- 25_StirlingPDF
- 26_JDownloader
- 27 - Rustdesk
- D_la solution contacts et calendrier
- E_la gestion du SWAP du VPS par Claude
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 écrase le fichier existant de même nom. 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"}} :
DELETE /files/{file_id}POST /files/trashavec body{"file_ids":[id]}POST /files/trashavec body{"ids":[id]}POST /files/{file_id}/trashPUT /files/{file_id}avec{"deleted":true}DELETE /filesavec body{"ids":[id]}
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=replace. 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 |
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
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)
- Node.js : v20.20.2 déjà présent sur le VPS (Debian) — aucune installation nécessaire
- npm : v10.8.2
- tmux : absent, installé via
sudo apt-get install -y tmux(v3.3a-3)
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) :
- Lancer
claudedans une session tmux dédiée (tmux new-session -d -s claude) pour que la session survive à une déconnexion SSH - Choisir "Claude account with subscription" au login
- Le CLI affiche une URL
https://claude.com/cai/oauth/authorize?...— impossible à ouvrir depuis le VPS, donc récupérée viatmux capture-paneet ouverte manuellement sur un navigateur (PC ou mobile) - Après connexion sur claude.ai, un code
xxxx#yyyyest retourné — collé dans le promptPaste code here if prompted >viatmux send-keys - 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)
- Installer Termux depuis F-Droid (pas le Play Store, version obsolète)
- Se connecter en SSH au VPS :
ssh debian@51.77.141.54 - Rattacher ou créer la session tmux :
tmux attach -t claude # si la session existe déjà tmux new -s claude # sinon - Lancer
claude(ou il tourne déjà si la session persiste) - Détacher sans tuer la session :
Ctrl+bpuisd— permet de couper la connexion mobile sans interrompre Claude Code
Sécurité
- Le VPS a déjà subi un incident de sécurité (CVE rclone RC, 2026-06-09 — voir page correspondante) : rester vigilant sur toute nouvelle surface d'exposition
- Claude Code tourne en utilisateur
debian(non-root), scope de travail/home/debianaccepté comme dossier de confiance - Authentification liée au compte personnel Julien (Claude Pro) — pas de clé API partagée à protéger séparément
- Accès à la session Claude Code = accès SSH au VPS (mot de passe
debian) — aucune surface réseau supplémentaire ouverte (pas de port exposé, tout passe par SSH existant)
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 :
get_folder_statussur le dossierafltj-njyuyrenvoyaitstate: idle,needBytes: 0,errors: 0— en apparence tout va bien- Mais
get_connections/get_devicesmontraitnumConnections: 0sur tous les appareils — le VPS n'avait aucune connexion active vers ses pairs, y compris PC-Elio+Jux
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
- Penser à
/initpour générer un CLAUDE.md propre au contexte VPS si l'usage se confirme - Vérifier que la session tmux ne meurt pas silencieusement (pas de
Restart=alwaystype systemd ici, contrairement aux services rclone)
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.
| Service | Avant | Apres | Resultat |
|---|---|---|---|
| Komga (stack 7) | -Xmx4g -Xms2g -XX:MaxRAMPercentage=70.0limits 4500M / reservations 3000M 707 Mio residents |
-Xmx1glimits 1500M / reservations 256M |
415 Mio (-292 Mio, -41 %) |
| StirlingPDF (stack 89) | JVM sans limite 722 Mio residents |
-Xmx512mlimits 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).
01_Portainer
portainer
Docker container management made simple, with the world’s most popular GUI-based container management platform.
| Image | portainer/portainer-ce:latest |
|---|---|
| Etat | Up 9 hours |
| Reseau | bridge |
| URL | https://portainer.juxjux.ovh |
Ports
| Hote | Container | IP |
|---|---|---|
| 9443 | 9443/tcp | 0.0.0.0 |
| 9443 | 9443/tcp | :: |
| 8000 | 8000/tcp | 0.0.0.0 |
| 8000 | 8000/tcp | :: |
| 9000 | 9000/tcp | 0.0.0.0 |
| 9000 | 9000/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/lib/docker/volumes/portainer_data/_data | /data | volume | rw |
/var/run/docker.sock | /var/run/docker.sock | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__portainer__ |
| Configuration | Script 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
list_endpointslist_stacksget_stackget_stack_fileredeploy_stacklist_containersget_containerget_container_logsrestart_containerstart_containerstop_containerlist_images
Ce que nous pouvons faire ensemble
- Lister et inspecter tous les containers et leurs états
- Consulter les logs d'un container en temps réel
- Redémarrer, démarrer ou arrêter un container à la demande
- Lire le fichier docker-compose.yml d'une stack
- Redéployer une stack après modification
- Lister toutes les images Docker disponibles sur le 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
| Image | lscr.io/linuxserver/bookstack:latest |
|---|---|
| Version | v26.03.3-ls256 |
| Etat | Up 9 hours |
| Compose project | bookstack |
| Reseau | bookstack_default |
| URL | https://bookstack.juxjux.ovh |
| Source | https://github.com/linuxserver/docker-bookstack |
Ports
| Hote | Container | IP |
|---|---|---|
| 6875 | 80/tcp | 0.0.0.0 |
| 6875 | 80/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/bookstack/app | /config | bind | rw |
bookstack_db
[Mariadb](https://mariadb.org/) is one of the most popular database servers. Made by the original developers of MySQL.
| Image | lscr.io/linuxserver/mariadb:latest |
|---|---|
| Version | 11.4.9-r0-ls212 |
| Etat | Up 9 hours |
| Compose project | bookstack |
| Reseau | bookstack_default |
| URL | https://bookstack.juxjux.ovh |
| Source | https://github.com/linuxserver/docker-mariadb |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/bookstack/db | /config | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | bookstack MCP (npm bookstack-mcp-server) |
| Configuration | npm via npx -y bookstack-mcp-server | Projet Claude Code : C:\Users\eliob | Auth : Token ID + Secret en variables d'environnement (.claude.json) |
Outils disponibles
list_booksget_booklist_chaptersget_chapterlist_pagesget_pagecreate_pageupdate_pagesearchget_shelves
Ce que nous pouvons faire ensemble
- Lire et écrire des pages de documentation directement depuis Claude Code
- Créer et organiser des livres, chapitres et pages
- Rechercher du contenu dans toute la base de connaissance
- Auto-documenter des projets ou des sessions de travail
- Mettre à jour cette page et les autres pages containers automatiquement
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 |
|---|---|
| Cron | Tous les jours à 2h du matin (0 2 * * *) |
| Base sauvegardée | bookstackapp — container bookstack_db (MariaDB) |
| Taille base (disque) | ~203 Mo |
| Format archive | .7z (compression niveau 5) — ~564 Ko |
| Destination | kDrive Infomaniak — TOOJUX/jux_vps/bookstack (dossier ID 1427916) |
| Rétention | 7 jours glissants (purge automatique des anciens fichiers) |
| Log | /opt/backups/backup.log |
| Nommage fichier | bookstack_db_YYYY-MM-DD.7z |
Fonctionnement du script
- Exécute
mysqldumpdepuis le containerbookstack_dbvers/tmp/ - Compresse en
.7zavec7z(déjà installé sur le VPS) - Upload sur kDrive via l'API REST Infomaniak (
POST /3/drive/{id}/upload) avec le paramètretotal_size - Supprime le fichier temporaire local
- 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"
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.
| Image | ghcr.io/homarr-labs/homarr:latest |
|---|---|
| Version | main |
| Etat | Up 9 hours |
| Compose project | homarr |
| Reseau | homarr_homarr_network |
| URL | https://homarr.juxjux.ovh |
| Source | https://github.com/homarr-labs/homarr |
Ports
| Hote | Container | IP |
|---|---|---|
| 7575 | 3000/tcp | 0.0.0.0 |
| 7575 | 3000/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/etc/localtime | /etc/localtime | bind | ro |
/var/run/docker.sock | /var/run/docker.sock | bind | ro |
/home/debian/docker/homarr2026/icons | /app/public/icons | bind | rw |
/home/debian/docker/homarr2026/appdata | /appdata | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__homarr__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_homarr.py | Projet Claude Code : C:\Users\eliob | Auth : cookie NextAuth session (authjs.session-token) |
Outils disponibles
get_all_boardsget_board_itemsget_home_boardget_integrationstrpc_call
Ce que nous pouvons faire ensemble
- Lire la configuration du tableau de bord principal
- Lister les services et widgets configurés
- Consulter les intégrations actives (Jellyfin, Sonarr, etc.)
- Appeler des procédures tRPC personnalisées
Mise a jour disponible (verifie le 2026-07-19)
| Version installee | 0.53 |
|---|---|
| Derniere version | 1.71.0 (2026-07-17) |
| Ecart | Traverse 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)
- Variables d'env renommees :
DATABASE_URL->DB_URL(conditionnelle),DOCKER_HOST->DOCKER_HOSTNAMES+DOCKER_PORTS,AUTH_PROVIDER->AUTH_PROVIDERS - Nouvelle variable requise :
SECRET_ENCRYPTION_KEY - Variables supprimees :
DISABLE_ANALYTICS,AUTH_OIDC_TIMEOUT,AUTH_LDAP_ADMIN_GROUP,AUTH_LDAP_OWNER_GROUP,AUTH_OIDC_ADMIN_GROUP,AUTH_OIDC_OWNER_GROUP(gestion des groupes/permissions passee dans l'UI) /datarestructure et deplace vers/appdata(non retrocompatible)/app/data/configs(JSON) et/app/public/iconsabandonnes -- gestion des icones et des configs via l'UI- Support ARM v7 supprime
- Tous les widgets reecrits ; systeme d'integrations passe en asynchrone (fetch en arriere-plan + WebSockets/bus de messages)
- Test de connexion desormais obligatoire avant d'activer une integration
Nouveautes notables depuis la 1.0 (jusqu'a 1.71.0)
- v1.65.0 -- support MCP (integration IA), nouvelles integrations Beszel, Technitium DNS, Uptime Kuma, Audiobookshelf, Paperless-ngx, Navidrome ; widgets personnalises ; sauvegarde/restauration SQLite avec apercu WASM ; cache Redis global
- v1.66.1 -- support des groupes locaux OIDC
- v1.68.0 -- ameliorations de l'interface Beszel (stats en direct)
- v1.69.0 -- menu contextuel (clic droit) sur les widgets avec actions auto-generees, evenements calendrier au survol avec epinglage au clic, stockage de secrets par widget
- v1.70.0 -- integrations Traefik (widget dedie), Bazarr, PatchMon, et monitoring systeme Synology ; widgets media manquants/en file d'attente pour Radarr et Sonarr
- v1.71.0 -- support direction de texte pour le widget notes, bouton de rafraichissement compact sur le widget Docker, tri ameliore des torrents qBittorrent
Etapes de migration recommandees
- Sauvegarder
/home/debian/docker/homarr2026/appdataavant toute action - Exporter la config du dashboard depuis l'UI (fonction export/backup SQLite)
- Verifier les variables d'environnement du compose homarr2026 contre la liste des breaking changes ci-dessus (notamment
SECRET_ENCRYPTION_KEY,DOCKER_HOSTNAMES/DOCKER_PORTS) - Redeployer le stack, puis retester chaque integration (Jellyfin, Sonarr, etc.) -- test de connexion obligatoire en 1.x
- Reimporter la sauvegarde SQLite si necessaire
Sources : github.com/homarr-labs/homarr/releases, homarr.dev/blog - Homarr 1.0
04_Audiobookshelf
audiobookshelf
Self-hosted audiobook and podcast server
| Image | ghcr.io/advplyr/audiobookshelf:latest |
|---|---|
| Version | 2.35.0 |
| Etat | Up (healthy) |
| Compose project | audiobookshelf |
| Reseau | audiobookshelf_audiobookshelf_network |
| URL | https://audiobookshelf.juxjux.ovh |
| Source | https://github.com/advplyr/audiobookshelf |
Ports
| Hote | Container | IP |
|---|---|---|
| 13378 | 80/tcp | 127.0.0.1 |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/audiobookshelf/config | /config | bind | rw |
/home/debian/audiobookshelf/metadata | /metadata | bind | rw |
/home/debian/audiobookshelf/podcasts | /podcasts | bind | rw |
/home/debian/audiobookshelf/audiobooks | /audiobooks | bind | rw, :shared |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__audiobookshelf__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_audiobookshelf.py | Auth : JWT Bearer via POST /login |
Outils disponibles
get_librariesget_libraryget_library_itemsget_library_personalizedget_itemget_item_progressget_podcast_episodesdownload_podcast_episodesget_listening_sessionsget_listening_statsget_mesearch_library
Ce que nous pouvons faire ensemble
- Parcourir la bibliothèque d'audiobooks et de podcasts
- Suivre la progression d'écoute d'un livre ou épisode
- Rechercher un titre, auteur ou podcast
- Consulter les statistiques d'écoute (temps total, sessions)
- Télécharger des épisodes de podcast
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
- Authentification via
POST /loginpour obtenir un token JWT frais - Récupération de toutes les bibliothèques via
GET /api/libraries - 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.
05_BentoPDF
bentopdf
Unprivileged NGINX Dockerfiles
| Image | bentopdfteam/bentopdf-simple:latest |
|---|---|
| Version | 1.28.0-alpine-slim |
| Etat | Up 9 hours |
| Compose project | bentopdf |
| Reseau | bentopdf_default |
| URL | https://bento.juxjux.ovh |
| Source | https://github.com/alam00000/bentopdf |
Ports
| Hote | Container | IP |
|---|---|---|
| 8089 | 8080/tcp | 0.0.0.0 |
| 8089 | 8080/tcp | :: |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | API REST interne, pas de MCP configuré. Accessible via PowerShell/Python httpx. |
Ce que nous pouvons faire ensemble
- Manipulation de PDF via l'API REST (fusion, découpage, conversion)
- Automatisation de traitements PDF dans des scripts Claude Code
06_Cadvisor
cadvisor
| Image | gcr.io/cadvisor/cadvisor:latest |
|---|---|
| Etat | Up 9 hours (healthy) |
| Compose project | gemini_grafana |
| Reseau | gemini_grafana_monitor_net |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/run | /var/run | bind | rw |
/ | /root | bind | ro |
/sys | /sys | bind | ro |
/var/lib/docker | /var/lib/docker | bind | ro |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | Endpoint 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
- Métriques CPU/RAM/réseau/disque par container (via Prometheus)
- Surveillance des performances en temps réel de chaque service
- Détection de containers consommant trop de ressources
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.
| Image | lscr.io/linuxserver/calibre-web:latest |
|---|---|
| Version | 0.6.26-ls383 |
| Etat | Up 9 hours (healthy) |
| Compose project | calibreweb_automated |
| Reseau | calibre_network |
| Source | https://github.com/linuxserver/docker-calibre-web |
Ports
| Hote | Container | IP |
|---|---|---|
| 8214 | 8083/tcp | 0.0.0.0 |
| 8214 | 8083/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/livres/Eyrolles | /books | bind | rw |
/home/debian/docker/calibre-web-automated/config | /config | bind | rw |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | Interface OPDS disponible pour parcourir la bibliothèque. API REST limitée. Pas de MCP configuré. |
Ce que nous pouvons faire ensemble
- Parcourir la bibliothèque Eyrolles via le catalogue OPDS
- Potentielle automatisation d'ajout/export de livres via l'API
08_Dozzle
dozzle
Realtime log viewer for containers. Supports Docker, Swarm and K8s.
| Image | amir20/dozzle:latest |
|---|---|
| Version | v8.14.9 |
| Etat | Up 9 hours |
| Compose project | dozzle |
| Reseau | nginx_npm-network |
| URL | https://dozzle.juxjux.ovh |
| Source | https://github.com/amir20/dozzle |
Ports
| Hote | Container | IP |
|---|---|---|
| 9091 | 8080/tcp | 0.0.0.0 |
| 9091 | 8080/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/run/docker.sock | /var/run/docker.sock | bind | rw |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | Interface 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
- Logs containers accessibles en alternative via le MCP Portainer
09_FileBrowser
File-Browser
| Image | filebrowser/filebrowser:latest |
|---|---|
| Version | 2.63.3 |
| Etat | Up 9 hours (healthy) |
| Compose project | filebrowser |
| Reseau | filebrowser_default |
| URL | https://files.juxjux.ovh |
| Source | https://github.com/filebrowser/filebrowser |
Ports
| Hote | Container | IP |
|---|---|---|
| 8147 | 80/tcp | 0.0.0.0 |
| 8147 | 80/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/filebrowser/database | /database | bind | rw |
/home/debian | /srv | bind | rw |
/home/debian/docker/filebrowser/config | /config | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__filebrowser__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_filebrowser.py | Auth : JWT via POST /api/login (admin) |
Outils disponibles
list_filesread_text_fileupload_text_fileget_file_infosearch_filescopy_filemove_or_renamecreate_directorydelete_path
Ce que nous pouvons faire ensemble
10_FreshRSS
freshrss
A free, self-hostable news aggregator…
| Image | freshrss/freshrss:latest |
|---|---|
| Version | 1.28.1 |
| Etat | Up 26 minutes |
| Compose project | freshrss |
| Reseau | freshrss_default |
| URL | https://freshrss.juxjux.ovh |
| Source | https://github.com/FreshRSS/FreshRSS |
Ports
| Hote | Container | IP |
|---|---|---|
| 8081 | 80/tcp | 0.0.0.0 |
| 8081 | 80/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/freshrss/data | /var/www/FreshRSS/data | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__freshrss__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_freshrss.py | Auth : GReader API avec mot de passe API dédié (≠ mot de passe web) |
Outils disponibles
get_feedsget_categoriesget_articlesget_unread_countget_starred_articlesmark_as_readmark_feed_as_readstar_articlesearch_articlesadd_feeddelete_feed
Ce que nous pouvons faire ensemble
- Lire les derniers articles de tous les flux RSS
- Rechercher des articles par mots-clés dans toute la veille
- Marquer des articles comme lus ou les étoiler
- Ajouter ou supprimer des flux
- Faire une synthèse de veille thématique à partir des non-lus
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
| Image | gitea/gitea:latest |
|---|---|
| Version | 1.25.4 |
| Etat | Up 9 hours (healthy) |
| Compose project | gitea |
| Reseau | gitea_default |
| URL | https://gitea.juxjux.ovh |
| Source | https://github.com/go-gitea/gitea |
Ports
| Hote | Container | IP |
|---|---|---|
| 2222 | 2222/tcp | 0.0.0.0 |
| 2222 | 2222/tcp | :: |
| 3005 | 3000/tcp | 0.0.0.0 |
| 3005 | 3000/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/lib/gitea_data | /data | bind | rw |
/etc/localtime | /etc/localtime | bind | ro |
/etc/timezone | /etc/timezone | bind | ro |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | API 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
- Lister repositories, branches, commits via l'API REST
- Lire/écrire des fichiers dans les repos (contenu base64)
- Gérer issues, pull requests, tags et releases
- Automatiser des workflows de versionning depuis Claude Code
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
- Lister les dashboards et leur état
- Interroger des datasources Prometheus via l'API (PromQL)
- Créer ou modifier des annotations sur les graphiques
- Exporter des dashboards en JSON pour sauvegarde/versioning
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
- Stack ID Portainer : 63 — compose sur
/data/compose/63/docker-compose.yml - Config Prometheus :
/opt/monitoring/prometheus.yml| Data :/opt/monitoring/prometheus_data --web.enable-lifecycleactif sur Prometheus (reload API disponible sur:9090/-/reload)- cadvisor port 8080 non exposé publiquement (aucun mapping IP externe)
- grafana.juxjux.ovh : DNS non résolu depuis l'extérieur — pas de vhost nginx configuré, accès direct via port 3000
- Ports 3000, 9090, 9100 exposés sur
0.0.0.0— à vérifier dans ufw
13_Immich
Immich-SERVER
High performance self-hosted photo and video management solution.
| Image | ghcr.io/immich-app/immich-server:release |
|---|---|
| Version | v2.7.5 |
| Etat | Up (healthy) |
| Compose project | immich |
| Reseau | immich_immich-network |
| URL | https://immich.juxjux.ovh |
| Source | https://github.com/immich-app/immich |
Ports
| Hote | Container | IP |
|---|---|---|
| 8212 | 2283/tcp | 0.0.0.0 |
| 8212 | 2283/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/immich/upload | /data | bind | rw |
/etc/localtime | /etc/localtime | bind | ro |
/home/debian/docker/immich/upload/encoded-video | /mnt/media/encoded-video | bind | rw |
/home/debian/photo | /mnt/media/photo | bind | ro,shared |
Immich-MICROSERVICES
High performance self-hosted photo and video management solution.
| Image | ghcr.io/immich-app/immich-server:release |
|---|---|
| Version | v2.7.5 |
| Etat | Up (healthy) |
| Compose project | immich |
| Reseau | immich_immich-network |
| URL | https://immich.juxjux.ovh |
| Source | https://github.com/immich-app/immich |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/immich/upload | /data | bind | rw |
/etc/localtime | /etc/localtime | bind | ro |
/home/debian/docker/immich/upload/encoded-video | /mnt/media/encoded-video | bind | rw |
/home/debian/photo | /mnt/media/photo | bind | ro,shared |
Immich-LEARNING
High performance self-hosted photo and video management solution.
| Image | ghcr.io/immich-app/immich-machine-learning:release |
|---|---|
| Version | v2.7.5 |
| Etat | Up (healthy) |
| Compose project | immich |
| Reseau | immich_immich-network |
| URL | https://immich.juxjux.ovh |
| Source | https://github.com/immich-app/immich |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/immich/cache | /cache | bind | rw |
Immich-REDIS
| Image | redis:6.2-alpine |
|---|---|
| Etat | Up (healthy) |
| Compose project | immich |
| Reseau | immich_immich-network |
| URL | https://immich.juxjux.ovh |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/data | volume | rw |
Immich-DB
Base images for Immich containers
| Image | ghcr.io/immich-app/postgres:16-vectorchord0.3.0-pgvectors0.2.0 |
|---|---|
| Version | 16-vectorchord0.3.0-pgvector0.8.1-pgvectors0.2.0 |
| Etat | Up (healthy) |
| Compose project | immich |
| Reseau | immich_immich-network |
| URL | https://immich.juxjux.ovh |
| Source | https://github.com/immich-app/base-images |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/immich/db | /var/lib/postgresql/data | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__immich__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_immich.py | Auth : JWT via POST /api/auth/login |
Outils disponibles
get_assetsget_assetsearch_assetsupdate_assetget_albumsget_albumcreate_albumget_peopleget_person_assetsget_memoriesget_statisticsget_my_userget_server_info
Ce que nous pouvons faire ensemble
- Rechercher des photos par date, lieu, contenu ou personne reconnue
- Parcourir les albums et les souvenirs générés automatiquement
- Consulter les statistiques de la photothèque (nb photos, vidéos, taille)
- Créer un album et y regrouper des assets
- Mettre à jour les métadonnées d'un asset (description, date, lieu)
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 |
|---|---|
| Cron | Tous les jours à 2h du matin (0 2 * * *) |
| Container DB | Immich-DB (PostgreSQL 16) |
| Commande | pg_dump -U postgres |
| Taille base (disque) | ~7.5 Mo (métadonnées uniquement — photos sur volume séparé) |
| Format archive | .7z (compression niveau 5) |
| Destination | kDrive Infomaniak — TOOJUX/jux_vps/immich (dossier ID 1427919) |
| Rétention | 7 jours glissants |
| Nommage fichier | immich_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
14_Jellyfin
jellyfin
The Free Software Media System
| Image | jellyfin/jellyfin:latest |
|---|---|
| Version | 10.10.7 |
| Etat | Up 9 hours (healthy) |
| Compose project | jellyfin |
| Reseau | host |
| URL | https://jellyfin.juxjux.ovh |
| Source | https://github.com/jellyfin/jellyfin-packaging |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/mnt/nas_videos/movies | /data/movies | bind | rw |
/mnt/nas_videos/palettes | /data/palettes | bind | rw |
/home/debian/jellyfin/config | /config | bind | rw |
/mnt/nas_videos/cinema_europe | /data/cinema_europe | bind | rw |
/mnt/nas_videos/cinema_UK | /data/cinema_uk | bind | rw |
/mnt/nas_videos/spectacles | /data/spectacles | bind | rw |
| /cache | volume | rw |
/mnt/nas_videos/animes | /data/animes | bind | rw |
/mnt/nas_videos/cinema_asie | /data/cinema_asie | bind | rw |
/mnt/nas_videos/cinema_realisateurs | /data/cinema_realisateurs | bind | rw |
/mnt/nas_videos/fantastique_et_SF | /data/fantastique_et_SF | bind | rw |
/mnt/nas_videos/historiques | /data/historiques | bind | rw |
/mnt/nas_videos/series | /data/series | bind | rw |
/mnt/nas_videos/cinema_italie | /data/cinema_italie | bind | rw |
/mnt/nas_videos/culture_cuisine | /data/culture_cuisine | bind | rw |
/mnt/nas_videos/documentaires | /data/documentaires | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__jellyfin__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_jellyfin.py | Auth : JWT MediaBrowser Token via POST /Users/AuthenticateByName |
Outils disponibles
get_librariesget_itemsget_itemget_recently_addedget_resume_itemsget_sessionsget_usersget_server_infoscan_librarysearch_items
Ce que nous pouvons faire ensemble
- Parcourir films, séries et musiques de la médiathèque
- Voir les ajouts récents et les éléments en cours de lecture
- Surveiller les sessions actives (qui lit quoi en ce moment)
- Déclencher un scan de bibliothèque après ajout de contenu
- Rechercher un titre dans toute la médiathèque
15_Joplin
joplin_to_obsidian
| Image | joplin_to_obsidian-joplin_to_obsidian |
|---|---|
| Etat | Up 9 hours |
| Compose project | joplin_to_obsidian |
| Reseau | joplin_joplin_network |
| URL | https://joplin.juxjux.ovh |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/Documents/Joplin_Obsidian | /home/debian/Documents/Joplin_Obsidian | bind | rw |
joplin-nginx
| Image | nginx:alpine |
|---|---|
| Etat | Up 9 hours |
| Compose project | joplin |
| Reseau | joplin_joplin_network |
| URL | https://joplin.juxjux.ovh |
Ports
| Hote | Container | IP |
|---|---|---|
| 22301 | 80/tcp | 0.0.0.0 |
| 22301 | 80/tcp | :: |
joplin
Docker image for Joplin Server
| Image | joplin/server:latest |
|---|---|
| Version | 3.4.3 |
| Etat | Up 9 hours |
| Compose project | joplin |
| Reseau | joplin_joplin_network |
| URL | https://joplin.juxjux.ovh |
| Source | https://github.com/laurent22/joplin.git |
Ports
| Hote | Container | IP |
|---|---|---|
| 22300 | 22300/tcp | 0.0.0.0 |
| 22300 | 22300/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/joplin-data | /home/joplin/.config/joplin | bind | rw |
joplin-db
| Image | postgres:15-alpine |
|---|---|
| Etat | Up 9 hours |
| Compose project | joplin |
| Reseau | joplin_joplin_network |
| URL | https://joplin.juxjux.ovh |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/joplin-db-data | /var/lib/postgresql/data | bind | rw |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | Le 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
- Synchronisation des notes entre appareils (via le client Joplin)
- Migration Joplin → Obsidian via le script joplin_to_obsidian (ponctuel)
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 |
|---|---|
| Cron | Tous les jours à 2h du matin (0 2 * * *) |
| Container DB | joplin-db (PostgreSQL 15) |
| Commande | pg_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) |
| Destination | kDrive Infomaniak — TOOJUX/jux_vps/joplin (dossier ID 1427920) |
| Rétention | 7 jours glissants |
| Nommage fichier | joplin_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 actuel | 119.7 Mo |
| Ressources compress?es | 424 |
| Poids avant compression | 451.5 Mo |
| ?conomie r?alis?e | 356.3 Mo (-78.9%) |
| Ignor?es (gain insuffisant) | 212 |
| Erreurs | 0 |
Top 15 ressources les plus lourdes (?tat actuel)
| # | ID | Format | Taille actuelle | Gain compression |
|---|---|---|---|---|
| 1 | vVO2ePdMvtty3sXZy5nY6M | ? | 3146 KB | |
| 2 | 0xh87pWrRt82z0DbO9n3yQ | ZIP | 2250 KB | -81% |
| 3 | VasIoF2e9EGuNQt38aOFMx | JPEG | 1633 KB | -66% |
| 4 | TzWK21r4n0yvbEtJh02DGB | JPEG | 1529 KB | -63% |
| 5 | M0C32hKC2hMqPAxpRGiVgp | JPEG | 937 KB | -87% |
| 6 | Hn6z6lvvbJzRsX0KGM8FNW | JPEG | 928 KB | -53% |
| 7 | 7EyAL9NNysJzWke6NT4ttJ | JPEG | 803 KB | -76% |
| 8 | bz9Twmb2F5lj0mPIQi48IB | JPEG | 798 KB | -81% |
| 9 | UbAqQY3cEbH62vioIHU6Pj | JPEG | 776 KB | -87% |
| 10 | SrJi1UyeNGf8OhaRsaOCGq | JPEG | 745 KB | -79% |
| 11 | 87mV49tXupZcpt2wplcGjU | JPEG | 685 KB | -59% |
| 12 | JsJFO6dIzqMKLA7clqW8nG | JPEG | 683 KB | -66% |
| 13 | VSyNmO0uN1fNNeqN6XZucO | JPEG | 674 KB | -19% |
| 14 | hExoJEEWT2tHz1demE5Nhm | JPEG | 674 KB | -84% |
| 15 | slTzAxAQ4xi0pMvzsLIDez | ? | 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 actuel | 119.9 Mo |
| Ressources compress?es | 425 |
| Poids avant compression | 452.0 Mo |
| ?conomie r?alis?e | 356.4 Mo (-78.8%) |
| Ignor?es (gain insuffisant) | 212 |
| Erreurs | 0 |
Top 15 ressources les plus lourdes (?tat actuel)
| # | ID | Format | Taille actuelle | Gain compression |
|---|---|---|---|---|
| 1 | vVO2ePdMvtty3sXZy5nY6M | ? | 3146 KB | |
| 2 | 0xh87pWrRt82z0DbO9n3yQ | ZIP | 2250 KB | -81% |
| 3 | VasIoF2e9EGuNQt38aOFMx | JPEG | 1633 KB | -66% |
| 4 | TzWK21r4n0yvbEtJh02DGB | JPEG | 1529 KB | -63% |
| 5 | M0C32hKC2hMqPAxpRGiVgp | JPEG | 937 KB | -87% |
| 6 | Hn6z6lvvbJzRsX0KGM8FNW | JPEG | 928 KB | -53% |
| 7 | 7EyAL9NNysJzWke6NT4ttJ | JPEG | 803 KB | -76% |
| 8 | bz9Twmb2F5lj0mPIQi48IB | JPEG | 798 KB | -81% |
| 9 | UbAqQY3cEbH62vioIHU6Pj | JPEG | 776 KB | -87% |
| 10 | SrJi1UyeNGf8OhaRsaOCGq | JPEG | 745 KB | -79% |
| 11 | 87mV49tXupZcpt2wplcGjU | JPEG | 685 KB | -59% |
| 12 | JsJFO6dIzqMKLA7clqW8nG | JPEG | 683 KB | -66% |
| 13 | VSyNmO0uN1fNNeqN6XZucO | JPEG | 674 KB | -19% |
| 14 | hExoJEEWT2tHz1demE5Nhm | JPEG | 674 KB | -84% |
| 15 | slTzAxAQ4xi0pMvzsLIDez | ? | 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 actuel | 119.9 Mo |
| Ressources compress?es | 425 |
| Poids avant compression | 452.0 Mo |
| ?conomie r?alis?e | 356.4 Mo (-78.8%) |
| Ignor?es (gain insuffisant) | 212 |
| Erreurs | 0 |
Top 15 ressources les plus lourdes (?tat actuel)
| # | ID | Format | Taille actuelle | Gain compression |
|---|---|---|---|---|
| 1 | vVO2ePdMvtty3sXZy5nY6M | ? | 3146 KB | |
| 2 | 0xh87pWrRt82z0DbO9n3yQ | ZIP | 2250 KB | -81% |
| 3 | VasIoF2e9EGuNQt38aOFMx | JPEG | 1633 KB | -66% |
| 4 | TzWK21r4n0yvbEtJh02DGB | JPEG | 1529 KB | -63% |
| 5 | M0C32hKC2hMqPAxpRGiVgp | JPEG | 937 KB | -87% |
| 6 | Hn6z6lvvbJzRsX0KGM8FNW | JPEG | 928 KB | -53% |
| 7 | 7EyAL9NNysJzWke6NT4ttJ | JPEG | 803 KB | -76% |
| 8 | bz9Twmb2F5lj0mPIQi48IB | JPEG | 798 KB | -81% |
| 9 | UbAqQY3cEbH62vioIHU6Pj | JPEG | 776 KB | -87% |
| 10 | SrJi1UyeNGf8OhaRsaOCGq | JPEG | 745 KB | -79% |
| 11 | 87mV49tXupZcpt2wplcGjU | JPEG | 685 KB | -59% |
| 12 | JsJFO6dIzqMKLA7clqW8nG | JPEG | 683 KB | -66% |
| 13 | VSyNmO0uN1fNNeqN6XZucO | JPEG | 674 KB | -19% |
| 14 | hExoJEEWT2tHz1demE5Nhm | JPEG | 674 KB | -84% |
| 15 | slTzAxAQ4xi0pMvzsLIDez | ? | 670 KB |
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)
get_libraries— liste les 53 bibliothèquesget_series— liste les séries (filtre library_id non fonctionnel : retourne toutes les bibliothèques)get_series_detailget_series_metadata— retourne genres, auteurs, éditeur, résumé, annéeget_series_volumesget_recently_addedget_on_deck— séries en cours de lectureget_server_statssearch— recherche full-text sur noms de séries, genres, fichiers, chapitresget_collections— corrigé 2026-06-25get_reading_lists— corrigé 2026-06-25get_want_to_read— corrigé 2026-06-25add_to_want_to_readremove_from_want_to_readget_user_stats— corrigé 2026-06-25get_reading_list
Ce que nous pouvons faire ensemble
- Parcourir la bibliothèque par série, volume ou bibliothèque thématique
- Rechercher un titre, auteur ou genre
- Consulter les séries récemment ajoutées ou en cours de lecture
- Gérer la liste "À lire" (ajout/suppression)
- Consulter les collections et listes de lecture
- Appeler l'API directement via PowerShell pour filtrer par genre (
/api/Series/all-v2)
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) :
- genres :
Actualités,Philosophie,Politique,2020-2025
Conditions pour que ça fonctionne :
- Le fichier epub doit avoir été re-sauvegardé depuis Calibre après ajout des étiquettes (Préférences > Sauvegarde des métadonnées → writeback activé)
- La bibliothèque Kavita doit avoir
enableMetadata: true(c'est le cas pour Actualités) - Les PDFs ne portent généralement pas les métadonnées Calibre → genres vides
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
- Le paramètre
library_iddeget_seriesne filtre pas : retourne toutes les bibliothèques triées alphabétiquement - Pour filtrer par genre, utiliser l'API directe :
POST /api/Series/all-v2avec filtre JSON (hors MCP, via PowerShell)
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 :
- Où est la bibliothèque Calibre (Windows, NAS Maison, autre) ?
- Le dossier source Kavita et le dossier d'import Calibre sont-ils le même, ou séparés ?
- Calibre est-il en mode copie (défaut) ou lien vers fichier original ?
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.
17_Komga
komga
| Image | gotson/komga |
|---|---|
| Version | 24.10 |
| Etat | Up 9 hours |
| Compose project | komga |
| Reseau | komga_default |
| URL | https://komga.juxjux.ovh |
| Source | https://github.com/gotson/komga |
Ports
| Hote | Container | IP |
|---|---|---|
| 25600 | 25600/tcp | 0.0.0.0 |
| 25600 | 25600/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/komga/config | /config | bind | rw |
/home/debian/komga | /data | bind | rw |
/etc/timezone | /etc/timezone | bind | ro |
| /tmp | volume | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__komga__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_komga.py | Auth : Basic Auth (Base64 login:password) |
Outils disponibles
get_librariesget_seriesget_series_detailget_series_booksget_bookget_book_metadataget_booksget_latest_booksget_new_seriesget_updated_seriesget_on_deckget_read_listsget_read_listget_collectionsget_collectionsearchmark_series_readupdate_book_progressget_recently_added
Ce que nous pouvons faire ensemble
- Parcourir la bibliothèque comics/manga par série et tome
- Voir les dernières acquisitions et séries mises à jour
- Marquer une série comme lue ou mettre à jour la progression
- Gérer les listes de lecture et collections
- Rechercher dans toute la bibliothèque
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
| Image | ghcr.io/mealie-recipes/mealie:latest |
|---|---|
| Version | v3.16.0 |
| Etat | Up 9 hours (healthy) |
| Compose project | mealie2 |
| Reseau | mealie2_default |
| URL | https://mealie.juxjux.ovh |
| Source | https://github.com/mealie-recipes/mealie |
Ports
| Hote | Container | IP |
|---|---|---|
| 9925 | 9000/tcp | 0.0.0.0 |
| 9925 | 9000/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/docker/mealie/backups | /app/backups | bind | rw |
/home/debian/docker/mealie/config | /app/config | bind | rw |
/home/debian/docker/mealie/data | /app/data | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__mealie__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_mealie.py | Auth : OAuth2 Bearer Token via POST /api/auth/token |
Outils disponibles
get_recipesget_recipecreate_recipecreate_recipe_from_urldelete_recipeget_categoriesget_tagsget_cookbooksget_cookbookget_meal_planadd_meal_plan_entryget_shopping_listsget_shopping_listadd_shopping_item
Ce que nous pouvons faire ensemble
- Parcourir et rechercher des recettes par catégorie ou tag
- Importer automatiquement une recette depuis une URL
- Planifier les repas de la semaine
- Gérer les listes de courses (ajout d'ingrédients)
- Créer une recette depuis une description ou un texte fourni
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 |
|---|---|
| Cron | Tous les jours à 2h du matin (0 2 * * *) |
| Type base | SQLite — /app/data/mealie.db (dans le container) |
| Méthode | docker cp mealie:/app/data/mealie.db |
| Taille base | ~2.9 Mo |
| Format archive | .7z (compression niveau 5) |
| Destination | kDrive Infomaniak — TOOJUX/jux_vps/mealie (dossier ID 1427921) |
| Rétention | 7 jours glissants |
| Nommage fichier | mealie_db_YYYY-MM-DD.7z |
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
pingget_artistsget_artistget_albumsget_albumget_songget_genresget_random_songsget_playlistsget_playlistcreate_playlistget_starredstarunstarsearchget_now_playing
Ce que nous pouvons faire ensemble
- Parcourir artistes, albums et pistes de la médiathèque musicale
- Rechercher un titre, artiste ou album
- Voir ce qui est en cours de lecture (now playing)
- Gérer les playlists (création, lecture)
- Étoiler/désigner des favoris
- Générer une sélection aléatoire par genre
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 :
- Cache VFS 72h :
--dir-cache-time 72hsurkdrive-music.service— les nouveaux dossiers kDrive ne sont pas visibles dans le mount avant expiration ouvfs/refresh. - Quick scan insuffisant : le scan quotidien (
startScanAPI) 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
- Symfonium (Subsonic) : erreur "trop d'erreurs, arrêt de lecture" sur tous les appareils portables
- Logs Navidrome :
transport endpoint is not connectedsur tous les fichiers audio systemctl status kdrive-music.service: active (running) depuis 3 jours — aucune indication du problème
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
- Redémarrer le service rclone :
sudo systemctl restart kdrive-music.service - Vérifier que le mount répond :
ls /home/debian/music | head -5 - Redémarrer le container Navidrome — nécessaire même avec
:shared, car le container garde l'ancienne référence FUSE corrompue - Sur les appareils : force-fermer Symfonium et relancer
Notes
- La propagation
:sharedne suffit pas à propager un nouveau mount FUSE à un container déjà démarré — le container doit être redémarré. - Attention spool /tmp : un restart du service rclone peut créer un fichier
/tmp/rclone-spool*de plusieurs Go si des fichiers cachés sont marqués "dirty". Préférervfs/refresh(avec auth RC) au restart quand le FUSE n'est pas corrompu.
20_NodeExporter
node-exporter
| Image | prom/node-exporter:latest |
|---|---|
| Etat | Up 9 hours |
| Compose project | gemini_grafana |
| Reseau | gemini_grafana_monitor_net |
Ports
| Hote | Container | IP |
|---|---|---|
| 9100 | 9100/tcp | 0.0.0.0 |
| 9100 | 9100/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/proc | /host/proc | bind | ro |
/sys | /host/sys | bind | ro |
/ | /rootfs | bind | ro |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | Exporte 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
- Métriques système VPS (CPU load, RAM libre, espace disque, I/O)
- Accessible via requêtes PromQL sur Prometheus ou via l'API Grafana
21_Prometheus
prometheus
| Image | prom/prometheus:latest |
|---|---|
| Etat | Up 9 hours |
| Compose project | gemini_grafana |
| Reseau | gemini_grafana_monitor_net |
| Source | https://github.com/prometheus/prometheus |
Ports
| Hote | Container | IP |
|---|---|---|
| 9090 | 9090/tcp | 0.0.0.0 |
| 9090 | 9090/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/opt/monitoring/prometheus.yml | /etc/prometheus/prometheus.yml | bind | ro |
/opt/monitoring/prometheus_data | /prometheus | bind | rw |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | API 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
- Requêtes PromQL pour métriques CPU, RAM, réseau, containers
- Interroger l'historique d'un container ou du système sur une période
- Détecter des anomalies ou pics de consommation
- Lister les targets et leurs états (up/down)
22_Readeck
readeck
| Image | codeberg.org/readeck/readeck:latest |
|---|---|
| Etat | Up 9 hours |
| Compose project | readeck |
| Reseau | readeck_default |
| URL | https://readeck.juxjux.ovh |
Ports
| Hote | Container | IP |
|---|---|---|
| 4567 | 8000/tcp | 0.0.0.0 |
| 4567 | 8000/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/home/debian/readeck/exports | /exports | bind | rw |
| /readeck | volume | rw |
/home/debian/readeck/data | /readeck/data | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__readeck__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_readeck.py | Auth : token API Bearer (MFA actif sur le compte web) |
Outils disponibles
get_bookmarksget_bookmarkcreate_bookmarkupdate_bookmarkdelete_bookmarkget_labelsget_profile
Ce que nous pouvons faire ensemble
- Sauvegarder un article ou une page web depuis Claude Code
- Parcourir et rechercher les articles enregistrés
- Organiser les bookmarks avec des labels
- Mettre à jour le statut (lu/archivé) d'un article
- Supprimer des bookmarks obsolètes
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 |
|---|---|
| Cron | Tous les jours à 2h du matin (0 2 * * *) |
| Type base | SQLite — /readeck/data/db.sqlite3 (dans le container) |
| Méthode | docker cp readeck:/readeck/data/db.sqlite3 |
| Taille base | ~8.5 Mo |
| Format archive | .7z (compression niveau 5) |
| Destination | kDrive Infomaniak — TOOJUX/jux_vps/readeck (dossier ID 1427922) |
| Rétention | 7 jours glissants |
| Nommage fichier | readeck_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.
23_Syncthing
syncthing
| Image | syncthing/syncthing:latest |
|---|---|
| Version | v2.0.14 |
| Etat | Up 9 hours (healthy) |
| Compose project | syncthing |
| Reseau | syncthing_syncthing_net |
| URL | https://syncthing.juxjux.ovh |
| Source | https://github.com/syncthing/syncthing |
Ports
| Hote | Container | IP |
|---|---|---|
| 21027 | 21027/udp | 0.0.0.0 |
| 21027 | 21027/udp | :: |
| 22000 | 22000/tcp | 0.0.0.0 |
| 22000 | 22000/tcp | :: |
| 22000 | 22000/udp | 0.0.0.0 |
| 22000 | 22000/udp | :: |
| 8384 | 8384/tcp | 0.0.0.0 |
| 8384 | 8384/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
| /var/syncthing | volume | rw |
/home/debian/Documents | /var/syncthing/Documents | bind | rw |
/home/debian/Public | /var/syncthing/Public | bind | rw |
/home/debian/docker/syncthing/config | /var/syncthing/config | bind | rw |
/home/debian/docker/syncthing/data1 | /var/syncthing/data1 | bind | rw |
/home/debian/docker/syncthing/data2 | /var/syncthing/data2 | bind | rw |
/home/debian/joplin-data | /var/syncthing/joplin-data | bind | rw |
Integration Claude Code — MCP
| Statut MCP | MCP actif |
|---|---|
| Outils (prefix) | mcp__syncthing__ |
| Configuration | Script Python : C:\Users\eliob\.claude\mcp_syncthing.py | Auth : clé API dans header X-API-Key |
Outils disponibles
pingget_statusget_versionget_devicesget_device_statsget_foldersget_folder_statusget_folder_statsget_folder_errorsget_connectionsget_completionpause_deviceresume_devicescan_folder
Ce que nous pouvons faire ensemble
- Vérifier l'état de synchronisation de chaque dossier
- Voir la progression de sync entre appareils (PC ↔ VPS)
- Détecter des erreurs de synchronisation
- Déclencher un scan d'un dossier manuellement
- Mettre en pause ou reprendre la sync avec un appareil
- Consulter les statistiques de transfert par device
24_Yourls
yourls
| Image | yourls:latest |
|---|---|
| Etat | Up 9 hours |
| Compose project | yourls |
| Reseau | yourls_default |
| URL | https://yourls.juxjux.ovh |
Ports
| Hote | Container | IP |
|---|---|---|
| 8085 | 80/tcp | 0.0.0.0 |
| 8085 | 80/tcp | :: |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/lib/docker/volumes/yourls_yourls_plugins/_data | /var/www/html/user/plugins | volume | rw |
/home/debian/docker/yourls/ports.conf | /etc/apache2/ports.conf | bind | rw |
/home/debian/docker/yourls/000-default.conf | /etc/apache2/sites-available/000-default.conf | bind | rw |
/var/lib/docker/volumes/yourls_yourls_html/_data | /var/www/html | volume | rw |
/var/lib/docker/volumes/yourls_yourls_user/_data | /var/www/html/user | volume | rw |
yourls-db
| Image | mysql:8.0 |
|---|---|
| Etat | Up 9 hours (healthy) |
| Compose project | yourls |
| Reseau | yourls_default |
| URL | https://yourls.juxjux.ovh |
Volumes
| Source (hote) | Destination | Type | Mode |
|---|---|---|---|
/var/lib/docker/volumes/yourls_yourls_mysql_data/_data | /var/lib/mysql | volume | rw |
Integration Claude Code — API directe
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | API REST Yourls sur /yourls-api.php. Auth : signature HMAC ou token. Pas de MCP configuré — appels directs possibles. |
Ce que nous pouvons faire ensemble
- Créer des URLs courtes personnalisées depuis Claude Code
- Lister et gérer les liens raccourcis existants
- Consulter les statistiques de clics sur un lien
25_StirlingPDF
stirling-pdf
Suite complète de manipulation de PDF — open source, auto-hébergée
| Image | stirlingtools/stirling-pdf:latest |
|---|---|
| Etat | Up (healthy) |
| Compose project | stirlingpdf |
| Reseau | stirlingpdf_default |
| URL | https://spdf.juxjux.ovh |
| Source | https://github.com/Stirling-Tools/Stirling-PDF |
Ports
| Hote | Container | IP |
|---|---|---|
| 8090 | 8080/tcp | 0.0.0.0 |
Variables
| Variable | Valeur |
|---|---|
| DOCKER_ENABLE_SECURITY | false |
| LANGS | fr_FR |
Volumes
| Hote | Container |
|---|---|
| /opt/stirling-pdf/configs | /configs |
| /opt/stirling-pdf/logs | /logs |
Notes
- Remplacera BentoPDF (bento.juxjux.ovh / port 8089) quand la transition sera faite
- A terme : récupérer le domaine pdf.juxjux.ovh et désactiver la stack bentopdf
- Sécurité désactivée (DOCKER_ENABLE_SECURITY=false)
Integration Claude Code
| Statut MCP | Pas de MCP — API directe possible |
|---|---|
| Note technique | API REST sur /api — scriptable via PowerShell/Python httpx. |
Ce que nous pouvons faire ensemble
- Fusion, découpage, compression, conversion PDF via API REST
- OCR, extraction de texte, filigrane, rotation
- Automatisation dans des scripts Claude Code
26_JDownloader
jdownloader
Gestionnaire de téléchargements avancé — interface web noVNC, supporte hôtes premium et lien direct
| Image | jlesage/jdownloader-2:latest |
|---|---|
| Etat | Up (running) |
| Compose project | jdownloader |
| Reseau | jdownloader_default |
| URL | https://jdownloader.juxjux.ovh |
| Source | https://github.com/jlesage/docker-jdownloader-2 |
Ports
| Hote | Container | IP |
|---|---|---|
| 5800 | 5800/tcp | 127.0.0.1 |
Variables
| Variable | Valeur |
|---|---|
| USER_ID | 1000 |
| GROUP_ID | 1000 |
| TZ | Europe/Paris |
Volumes
| Hote | Container |
|---|---|
| /opt/jdownloader/config | /config |
| /home/debian/downloads | /output |
Notes
- Interface noVNC accessible via navigateur — pas besoin de client VNC
- Port 5800 lié à
127.0.0.1uniquement — non exposé directement à l'internet - Au 1er lancement, JDownloader télécharge ses composants (~1 min) avant d'afficher l'UI
- Cert SSL Let's Encrypt valide jusqu'au 2026-08-31 (renouvellement automatique certbot)
- Installé le 2026-06-02 via stack Portainer (ID 90)
Integration Claude Code
| Statut MCP | Pas de MCP — interface web uniquement (noVNC) |
|---|---|
| Note technique | Pas d'API REST publique documentée. Pilotage uniquement via l'interface graphique. |
Ce que nous pouvons faire ensemble
- Vérifier l'état du container via l'API Portainer
- Redémarrer le container si l'interface ne répond plus
- Lister les fichiers téléchargés dans
/home/debian/downloadsvia SSH
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 :
- hbbs (ID/rendezvous server) — enregistre les IDs des clients, gère le heartbeat, tente d'établir une connexion P2P directe.
- hbbr (relay server) — relaie le flux quand le P2P direct échoue (NAT symétrique, pare-feu strict, etc.).
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
network_mode: hostest la méthode recommandée sous Linux : hbbs/hbbr voient l'IP réelle du client au lieu de l'IP interne du container. Fonctionne uniquement sur Linux (donc OK sur le VPS Debian, pas sur un NAS DSM qui a ses propres contraintes réseau — voir plus bas).- Alternative sans host networking (mapping de ports classique, pour Portainer/stack isolée) :
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
- Au premier démarrage, hbbs génère une paire de clés dans le volume
./data: le fichierid_ed25519.pubcontient la clé publique à distribuer aux clients. - Configuration côté client RustDesk (menu ⋮ → Réseau, déverrouiller) :
- ID Server : IP ou domaine du VPS (ex.
vps.juxjux.ovhou l'IP directe) - Relay Server : peut rester vide (déduit automatiquement, sinon
IP:21117) - Key : contenu de
id_ed25519.pub
- ID Server : IP ou domaine du VPS (ex.
- Export/import de config possible entre clients (bouton "Export Server Config"), pratique pour déployer sur plusieurs machines (PC Windows, Ubuntu, etc.) sans ressaisir.
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
- Analyse de l'Observateur d'événements (
Microsoft-Windows-WER-SystemErrorReporting) : crash à 06:27:20 avec bugcheck0x50(PAGE_FAULT_IN_NONPAGED_AREA), dump complet dansC:\WINDOWS\MEMORY.DMP(2,4 Go). - Corrélation temporelle exacte avec l'extraction de deux composants pilotes bundlés par le client RustDesk :
C:\Program Files\RustDesk\usbmmidd_v2— pilote d'écran virtuel USBMMIDD (permet le contrôle à distance sans moniteur physique branché)C:\Program Files\RustDesk\drivers\RustDeskPrinterDriver— pilote d'imprimante virtuelle (impression à distance)
- Vérification : ni l'un ni l'autre n'était enregistré comme périphérique actif (
Get-PnpDevice,pnputil /enum-drivers) après coup → l'installation du driver a fait planter le noyau avant de s'enregistrer. Un problème connu et documenté côté communauté RustDesk : le driverusbmmidd(ancien, non WHQL sur les builds récentes de Windows 10) provoque des BSOD à l'installation sur certaines configs. - Point distinct identifié en passant : la machine a un historique chronique de BSOD
0x9f(DRIVER_POWER_STATE_FAILURE) récurrent environ une fois par mois depuis janvier 2026 (Kernel-Powerevent 41), sans lien avec RustDesk — probablement un driver qui répond mal à la mise en veille. Non résolu, à creuser séparément si besoin.
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
- Service
RustDesk Service:Running - Contrôle à distance classique opérationnel (vérifié : process
RustDesk.exeactif, service démarré) - Écran virtuel et impression à distance désactivés (fonctionnalités non utilisées) — évite que RustDesk retente d'installer ces drivers automatiquement
- Mot de passe permanent + 2FA activés par Julien le 2026-07-31 (menu Sécurité de RustDesk) → accès non attendu opérationnel : ce PC est joignable via RustDesk sans présence devant l'écran, ID + mot de passe permanent (2FA en complément).
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.
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 fonctionnel, à l'exception de vdirsyncer (agrégation Google/Infomaniak) et du calendrier web.
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 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 |
| Roundcube | Interface web de saisie/lecture des contacts | Docker, VPS juxjux | En service |
| Nginx | Reverse proxy HTTPS des deux services | Hôte VPS | En service |
| DAVx5 | Pont de synchronisation vers Android | Téléphone | À configurer |
| Fossify Agenda | Client calendrier | Téléphone (via DAVx5) | À configurer |
| 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 |
|---|---|---|
| Baïkal (admin) | https://baikal.juxjux.ovh/admin/ | compte admin Baïkal |
| Roundcube | https://secretariat.juxjux.ovh | julien.bertrand@ik.me (compte mail Infomaniak) |
| Découverte DAV | https://baikal.juxjux.ovh/dav.php/ |
Julien |
Utilisateur Baïkal : Julien — avec un J majuscule. La casse compte dans les URLs DAV.
- Contacts :
https://baikal.juxjux.ovh/dav.php/addressbooks/Julien/default/ - Calendrier :
https://baikal.juxjux.ovh/dav.php/calendars/Julien/default/
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 (avec le correctif .well-known) |
secretariat.juxjux.ovh.conf |
Vhost Roundcube |
finaliser_tls.sh |
Vérifie le DNS puis lance certbot |
vps_backup.sh |
Script de sauvegarde complet, Baïkal inclus |
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 | ~30 Mo |
| roundcube | roundcube/roundcubemail:latest (1.7.2) |
127.0.0.1:8083 | SQLite | ~41 Mo |
Les deux services pèsent 71 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 |
| Plugin calendar | Activé | Non déployé | Incompatible, voir §6 |
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 casse tout le démarrage
La seule version résolvable est kolab/calendar 3.3.3 (ancienne, alors que libcalendaring monte en 3.6.1). Son script d'initialisation de base s'exécute avant que l'entrypoint n'écrive la configuration Roundcube : il tombe donc 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.
Le plugin calendar a donc été retiré. Conséquence : Roundcube gère les contacts, pas l'agenda. Ce n'est pas bloquant, DAVx5 couvre l'agenda sur le téléphone. Pour un agenda web, la piste est InfCloud (un vhost infcloud.conf traîne déjà sur le VPS).
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 en Basic Auth à chaque synchronisation (DAVx5 notamment). 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. Sauvegarde
Baïkal a été ajouté à /opt/backups/vps_backup.sh le 3 août 2026 (cron quotidien à 2h UTC).
- Dossier kDrive de destination : 1467771 (
SYNC-pour_VPS/backups/baikal) - Le bilan de fin de log passe de 5 à 6 services (le total est calculé dynamiquement, pas codé en dur)
- Sauvegarde de l'ancien script :
/opt/backups/vps_backup.sh.bak-260803
La fonction archive deux volumes, via un tar intermédiaire puis 7z :
Specific/— la basedb.sqlite(contacts et calendriers)config/—baikal.yaml(paramètres et hash du mot de passe admin)
Sans le second, la restauration est incomplète. Testée le 3 août : upload HTTP 200, aucun résidu temporaire.
8. 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 | 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 incrémentale | sync_token à http://sabre.io/ns/sync/2 |
| 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.
9. Reste à faire
9.1 DAVx5 sur le téléphone
Ajouter un compte avec l'URL de base https://baikal.juxjux.ovh/dav.php/ et l'utilisateur Julien. DAVx5 découvre seul le carnet et le calendrier ; router ensuite la synchronisation vers l'app Contacts Android et Fossify Agenda.
9.2 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.
- Google Contacts : CardDAV via
https://www.google.com/carddav/v1/principals/EMAIL/— nécessite un mot de passe d'application (compte en 2FA) - Infomaniak : CardDAV natif, identifiants standards du compte mail
- vdirsyncer : outil CLI léger, une paire de synchronisation par source, exécuté par cron sur le VPS
Décision à prendre avant déploiement :
- one-way (Google/Infomaniak → Baïkal, lecture seule) : sans risque, mais les modifications faites dans Baïkal ne remontent pas vers Google
- two-way : tout reste aligné, mais un conflit ou une erreur de configuration peut propager des suppressions dans les deux sens
Recommandation : démarrer en one-way le temps de vérifier que l'import est fidèle, puis basculer si besoin.
9.3 Agenda web
Roundcube n'affiche pas le calendrier (§6.2). Piste : déployer InfCloud, dont le vhost existe déjà.
9.4 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.
10. Checklist sécurité
- Aucun mot de passe
CHANGE_ME_...en production — la bascule vers SQLite a supprimé les identifiants MariaDB du compose - HTTPS forcé sur les deux vhosts (redirection 80 vers 443)
- Certificats Let's Encrypt valides, renouvellement automatique certbot en place
- Découverte DAV forcée en HTTPS (§6.3)
- Les deux containers n'écoutent que sur
127.0.0.1— seul nginx les expose - Sauvegarde quotidienne des volumes Baïkal vers kDrive
- Mot de passe d'application dédié pour l'accès CardDAV Google — à faire au moment de vdirsyncer
11. 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 (contacts, carnets, utilisateurs)
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 id, uri, displayname FROM addressbooks;"
# Vérifier la découverte DAV
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" \
https://baikal.juxjux.ovh/.well-known/carddav
# Tester la sauvegarde Baïkal seule (sans relancer les 14 min du run complet)
# voir /tmp/test_baikal.sh — filtre les autres run_service et loggue dans /tmp
12. 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.
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/lecture, 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, mises à jour de sécurité régulières). A rejoint la famille Nextcloud en 2023 tout en restant indépendant, sous licence GPL. Réserve constatée à l'usage : il impose une authentification IMAP (§6.4) et ne couvre pas l'agenda (§6.2).
Thunderbird containerisé (VNC/noVNC) envisagé puis écarté : fonctionnel mais plus lourd et moins adapté au multi-accès qu'un vrai webmail.
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
- Komga répond 200, API
/api/v1/librariesrenvoie bien les bibliothèques - StirlingPDF :
compress-pdfOK (workflows komga-pdf et nas_geo_compress) et OCR OK (page A4 300 dpi, pic 969 Mio, aucun OOM kill, aucun redémarrage)
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
UnsupportedImageFormatError: The input image has an alpha channel.— tout PNG avec transparence- 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
- Endpoint :
POST /api/v1/misc/ocr-pdf— multipartfileInput, champslanguages(liste),ocrType(Force-OCR/skip-text),outputType - Langues tesseract installées (6) :
fra,eng,deu,por,chi_sim,osd - Versions : ocrmypdf 17.4.0, tesseract 5.3.4
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).
- ufw est actif sur Alteris sans règle pour 5432
- Le container
alteris_postgistourne etpg_isreadyrépond en local - Vérifié : le port est injoignable depuis le PC et depuis le VPS Jux
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
- Page 177 — 00_Récapitulatif : section « 260802 - Allègement JVM Komga + StirlingPDF »
- Page 211 — REX StirlingPDF : entrée
RCH-20260802-0001(également en baserecherchessur Alteris) - Page 208 — 25_StirlingPDF
CLAUDE.mddu projet : sections « Swap », « Alléger Komga », « Alléger StirlingPDF », StirlingPDF/OCR