# 0_Claude et le Jux_VPS

# A_liens entre Claude et le KDRIVE

---

## kDrive API REST — Infomaniak

<table id="bkmrk-param%C3%A8tre-valeur-dri"><thead><tr><th>Paramètre</th><th>Valeur</th></tr></thead><tbody><tr><td>Drive ID</td><td>`591617`</td></tr><tr><td>Token Bearer</td><td>`cnAZannhRpecgAfsQM7QiO4Vqh37g6Ht_hm4f0E6eDihMRaP2ZckKCmW959T5ST2Nv3qhGlqs0ltpNAb`</td></tr><tr><td>Base URL</td><td>`https://api.infomaniak.com/3/drive/591617`</td></tr></tbody></table>

## Endpoints fonctionnels

<table id="bkmrk-m%C3%A9thode-endpoint-usa"><thead><tr><th>Méthode</th><th>Endpoint</th><th>Usage</th></tr></thead><tbody><tr><td>`GET`</td><td>`/files/{dir_id}/files`</td><td>Lister le contenu d'un dossier</td></tr><tr><td>`GET`</td><td>`/files/{file_id}`</td><td>Métadonnées d'un fichier</td></tr><tr><td>`POST`</td><td>`/upload?directory_id={id}&file_name={name}&conflict=replace&total_size={bytes}`</td><td>Uploader un fichier. `conflict=replace` écrase le fichier existant de même nom. `conflict=version` crée une nouvelle version.</td></tr></tbody></table>

---

## 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/trash` avec body `{"file_ids":[id]}`
- `POST /files/trash` avec body `{"ids":[id]}`
- `POST /files/{file_id}/trash`
- `PUT /files/{file_id}` avec `{"deleted":true}`
- `DELETE /files` avec 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)

<table id="bkmrk-service-dossier-id-e"><thead><tr><th>Service</th><th>Dossier ID</th><th>Exemple de fichier</th></tr></thead><tbody><tr><td>BookStack</td><td>`1427916`</td><td>`bookstack_db_day1.7z`</td></tr><tr><td>Immich</td><td>`1427919`</td><td>`immich_db_day1.7z`</td></tr><tr><td>Joplin</td><td>`1427920`</td><td>`joplin_db_day1.7z` (~630 Mo)</td></tr><tr><td>Mealie</td><td>`1427921`</td><td>`mealie_db_day1.7z`</td></tr><tr><td>Readeck</td><td>`1427922`</td><td>`readeck_db_day1.7z`</td></tr></tbody></table>

# B_les procédures de Claude

1/ [la sauvegarde quotidienne de la base de données Joplin sur Kdrive (sans images) ](https://bookstack.juxjux.ovh/link/166#bkmrk-sauvegarde-bdd)

5/ 260611 - [Komga-PDF](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/260611-procedure-komga-pdf-par-claude-sur-stirlingpdf "260611_procédure Komga-PDF par Claude sur StirlingPDF")

6/ 260614 - [Joplin-Compression](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/260614-procedure-joplin-compression "260614 - procedure 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 :

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

Ajout du PATH dans `~/.bashrc` :

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

Version installée : **2.1.197**

## Authentification

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

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

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

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

## Usage depuis Android (Termux)

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

## Sécurité

- 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/debian` accepté 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.

```bash
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_status` sur le dossier `afltj-njyuy` renvoyait `state: idle`, `needBytes: 0`, `errors: 0` — en apparence tout va bien
- Mais `get_connections` / `get_devices` montrait `numConnections: 0` sur **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 à `/init` pour 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=always` type 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`.

<table id="bkmrk-serviceavantapresres"><tbody><tr><th style="width:150px;">Service</th><th>Avant</th><th>Apres</th><th>Resultat</th></tr><tr><td>**Komga** (stack 7)</td> <td>`-Xmx4g -Xms2g -XX:MaxRAMPercentage=70.0`  
limits 4500M / reservations 3000M  
707 Mio residents</td> <td>`-Xmx1g`  
limits 1500M / reservations 256M</td> <td>**415 Mio** (-292 Mio, -41 %)</td></tr><tr><td>**StirlingPDF** (stack 89)</td> <td>JVM sans limite  
722 Mio residents</td> <td>`-Xmx512m`  
limits 2g</td> <td>**785 Mio** — pas de reduction, mais consommation desormais bornee</td></tr></tbody></table>

**Bilan hote :** swap **3,7 Go -&gt; 2,2 Go** (-1,5 Go), memoire disponible 4,4 -&gt; 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.

<table id="bkmrk-pageurlmcp-claude-co"><thead><tr><th>Page</th><th>URL</th><th>MCP Claude Code</th><th>Statut integration</th></tr></thead><tbody><tr><td>[01\_Portainer](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/152)</td><td>[https://portainer.juxjux.ovh](https://portainer.juxjux.ovh)</td><td>`mcp__portainer__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[02\_Bookstack](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/153)</td><td>[https://bookstack.juxjux.ovh](https://bookstack.juxjux.ovh)</td><td>`bookstack-mcp-server (npm)`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[03\_Homarr](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/154)</td><td>[https://homarr.juxjux.ovh](https://homarr.juxjux.ovh)</td><td>`mcp__homarr__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[04\_Audiobookshelf](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/155)</td><td>[https://audiobookshelf.juxjux.ovh](https://audiobookshelf.juxjux.ovh)</td><td>`mcp__audiobookshelf__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[05\_BentoPDF](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/156)</td><td>-</td><td>-</td><td><span style="color:#ffa500;">API directe</span></td></tr><tr><td>[06\_Cadvisor](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/157)</td><td>-</td><td>-</td><td><span style="color:#808080;">via Prometheus</span></td></tr><tr><td>[07\_Calibre-web](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/158)</td><td>-</td><td>-</td><td><span style="color:#ffa500;">OPDS</span></td></tr><tr><td>[08\_Dozzle](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/159)</td><td>-</td><td>-</td><td><span style="color:#808080;">via Portainer MCP</span></td></tr><tr><td>[09\_FileBrowser](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/160)</td><td>[https://files.juxjux.ovh](https://files.juxjux.ovh)</td><td>`mcp__filebrowser__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[10\_FreshRSS](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/161)</td><td>[https://freshrss.juxjux.ovh](https://freshrss.juxjux.ovh)</td><td>`mcp__freshrss__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[11\_Gitea](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/162)</td><td>-</td><td>-</td><td><span style="color:#ffa500;">API REST directe</span></td></tr><tr><td>[12\_Grafana](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/163)</td><td>[https://grafana.juxjux.ovh](https://grafana.juxjux.ovh)</td><td>-</td><td><span style="color:#ffa500;">API REST directe</span></td></tr><tr><td>[13\_Immich](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/164)</td><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td><td>`mcp__immich__*`</td><td><span style="color:#008000;">MCP actif (5 containers)</span></td></tr><tr><td>[14\_Jellyfin](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/165)</td><td>[https://jellyfin.juxjux.ovh](https://jellyfin.juxjux.ovh)</td><td>`mcp__jellyfin__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[15\_Joplin](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/166)</td><td>-</td><td>-</td><td><span style="color:#808080;">sync server uniquement</span></td></tr><tr><td>[16\_Kavita](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/167)</td><td>[https://kavita.juxjux.ovh](https://kavita.juxjux.ovh)</td><td>`mcp__kavita__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[17\_Komga](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/168)</td><td>[https://komga.juxjux.ovh](https://komga.juxjux.ovh)</td><td>`mcp__komga__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[18\_Mealie](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/169)</td><td>[https://mealie.juxjux.ovh](https://mealie.juxjux.ovh)</td><td>`mcp__mealie__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[19\_Navidrome](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/170)</td><td>[https://navidrome.juxjux.ovh](https://navidrome.juxjux.ovh)</td><td>`mcp__navidrome__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[20\_NodeExporter](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/171)</td><td>-</td><td>-</td><td><span style="color:#808080;">via Prometheus</span></td></tr><tr><td>[21\_Prometheus](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/172)</td><td>-</td><td>-</td><td><span style="color:#ffa500;">API REST / PromQL</span></td></tr><tr><td>[22\_Readeck](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/173)</td><td>[https://readeck.juxjux.ovh](https://readeck.juxjux.ovh)</td><td>`mcp__readeck__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[23\_Syncthing](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/174)</td><td>[https://syncthing.juxjux.ovh](https://syncthing.juxjux.ovh)</td><td>`mcp__syncthing__*`</td><td><span style="color:#008000;">MCP actif</span></td></tr><tr><td>[24\_Yourls](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/175)</td><td>-</td><td>-</td><td><span style="color:#ffa500;">API REST directe</span></td></tr><tr><td>[25\_StirlingPDF](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/208)</td><td>[https://spdf.juxjux.ovh](https://spdf.juxjux.ovh)</td><td>-</td><td><span style="color:#ffa500;">API directe</span></td></tr><tr><td>[A\_liens entre Claude et le KDRIVE](https://bookstack.juxjux.ovh/books/le-livre-de-claude/page/176)</td><td>[kdrive.infomaniak.com](https://kdrive.infomaniak.com)</td><td>`@infomaniak/mcp-server-kdrive` + API REST</td><td><span style="color:#008000;">MCP actif (kdrive\_search) + API directe</span></td></tr></tbody></table>

## Scripts de maintenance

<table id="bkmrk-fill_bookstack_pages"><tbody><tr><th>fill\_bookstack\_pages.py</th><td>Remplit les pages avec les infos containers (image, ports, volumes)</td><td>`C:\Users\eliob\.claude\fill_bookstack_pages.py`</td></tr><tr><th>fill\_bookstack\_mcp.py</th><td>Ajoute la section integration Claude Code / MCP a chaque page</td><td>`C:\Users\eliob\.claude\fill_bookstack_mcp.py`</td></tr></tbody></table>

## 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

<table id="bkmrk-ram8.4-%2F-11.41-gb-%287"><tbody><tr><th>RAM</th><td>8.4 / 11.41 GB (73.6%)</td></tr><tr><th>Swap</th><td><span style="color:#cc0000;">3.99 / 4.0 GB (quasi plein)</span></td></tr><tr><th>CPU</th><td>5.2%</td></tr></tbody></table>

### Top consommateurs RAM (RSS)

<table id="bkmrk-containerram-rss-kom"><thead><tr><th>Container</th><th>RAM RSS</th></tr></thead><tbody><tr><td>komga</td><td>1059 MB</td></tr><tr><td>Immich-SERVER</td><td>1011 MB</td></tr><tr><td>Immich-MICROSERVICES</td><td>520 MB</td></tr><tr><td>stirling-pdf</td><td>442 MB</td></tr><tr><td>homarr2026</td><td>355 MB</td></tr><tr><td>jellyfin</td><td>272 MB</td></tr><tr><td>prometheus</td><td>259 MB</td></tr><tr><td>jdownloader</td><td>220 MB</td></tr><tr><td>Kavita</td><td>196 MB</td></tr><tr><td>joplin</td><td>179 MB</td></tr><tr><td>calibre-web-eyrolles</td><td>132 MB</td></tr><tr><td>mealie</td><td>129 MB</td></tr><tr><td>grafana</td><td>125 MB</td></tr><tr><td>cadvisor</td><td>91 MB</td></tr><tr><td>navidrome</td><td>86 MB</td></tr></tbody></table>

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

<table id="bkmrk-ram-8.2-%2F-11.41-gb-%28"><tbody><tr><th>RAM</th><td>8.2 / 11.41 GB (71.7%)</td></tr><tr><th>Swap</th><td><span style="color:#cc0000;">4.0 / 4.0 GB (sature a 100%)</span></td></tr><tr><th>CPU</th><td>28% (compression 7z du backup en cours)</td></tr></tbody></table>

### Top consommateurs RAM (RSS)

<table id="bkmrk-container-ram-rss-im"><thead><tr><th>Container</th><th>RAM RSS</th></tr></thead><tbody><tr><td>Immich-SERVER</td><td>1147 MB</td></tr><tr><td>komga</td><td>791 MB</td></tr><tr><td>Immich-MICROSERVICES</td><td>618 MB</td></tr><tr><td>stirling-pdf</td><td>566 MB</td></tr><tr><td>jellyfin</td><td>380 MB</td></tr><tr><td>homarr2026</td><td>313 MB</td></tr><tr><td>Immich-DB</td><td>310 MB</td></tr><tr><td>prometheus</td><td>282 MB</td></tr><tr><td>joplin</td><td>241 MB</td></tr><tr><td>Kavita</td><td>240 MB</td></tr><tr><td>cadvisor</td><td>195 MB</td></tr><tr><td>grafana</td><td>164 MB</td></tr><tr><td>joplin-db</td><td>158 MB</td></tr><tr><td>yourls-db</td><td>157 MB</td></tr><tr><td>audiobookshelf</td><td>140 MB</td></tr></tbody></table>

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)

<table id="bkmrk-action-detail-gain-f"><thead><tr><th>Action</th><th>Detail</th><th>Gain</th></tr></thead><tbody><tr><td>Fix backup Immich</td><td>`-d immich` ajoute dans `/opt/backups/vps_backup.sh` + run manuel complet 5/5 OK (archive 87 MB sur kDrive, premiere sauvegarde Immich valide)</td><td>donnees enfin sauvegardees</td></tr><tr><td>Fusion Immich</td><td>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`</td><td>~900 MB RAM</td></tr><tr><td>Arret cAdvisor</td><td>`docker update --restart=no cadvisor` + stop. Plus de metriques par container dans Prometheus/Grafana (node-exporter conserve le host)</td><td>~200 MB RAM + 4-8% CPU</td></tr><tr><td>GDM/GNOME desactive puis purge</td><td>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</td><td>~150 MB RAM + 3,5 GB disque</td></tr></tbody></table>

**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/`) :

<table id="bkmrk-service-avant-apres-"><thead><tr><th>Service</th><th>Avant</th><th>Apres</th><th>Gain attendu</th></tr></thead><tbody><tr><td>Komga (stack 7)</td><td>`-Xmx4g -Xms2g` (2 GB pre-alloues, ~760 MB en swap), limites 4500M/3000M</td><td>`-Xmx1g` sans Xms, limites 1500M/256M</td><td>~400-500 MB RAM + ~700 MB swap</td></tr><tr><td>StirlingPDF (stack 89)</td><td>JVM sans plafond (566-643 MB residents + ~406 MB swap)</td><td>`JAVA_TOOL_OPTIONS=-Xmx512m`, limite 1g</td><td>~300-400 MB RAM</td></tr></tbody></table>

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.*

<table id="bkmrk-imageportainer%2Fporta"><tbody><tr><th>Image</th><td>`portainer/portainer-ce:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Reseau</th><td>bridge</td></tr><tr><th>URL</th><td>[https://portainer.juxjux.ovh](https://portainer.juxjux.ovh)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip94439"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>9443</td><td>9443/tcp</td><td>0.0.0.0</td></tr><tr><td>9443</td><td>9443/tcp</td><td>::</td></tr><tr><td>8000</td><td>8000/tcp</td><td>0.0.0.0</td></tr><tr><td>8000</td><td>8000/tcp</td><td>::</td></tr><tr><td>9000</td><td>9000/tcp</td><td>0.0.0.0</td></tr><tr><td>9000</td><td>9000/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/lib/docker/volumes/portainer_data/_data`</td><td>`/data`</td><td>volume</td><td>rw</td></tr><tr><td>`/var/run/docker.sock`</td><td>`/var/run/docker.sock`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__portainer__`</td></tr><tr><th>Configuration</th><td>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</td></tr></tbody></table>

### Outils disponibles

- `list_endpoints`
- `list_stacks`
- `get_stack`
- `get_stack_file`
- `redeploy_stack`
- `list_containers`
- `get_container`
- `get_container_logs`
- `restart_container`
- `start_container`
- `stop_container`
- `list_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*

<table id="bkmrk-imagelscr.io%2Flinuxse"><tbody><tr><th>Image</th><td>`lscr.io/linuxserver/bookstack:latest`</td></tr><tr><th>Version</th><td>v26.03.3-ls256</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>bookstack</td></tr><tr><th>Reseau</th><td>bookstack\_default</td></tr><tr><th>URL</th><td>[https://bookstack.juxjux.ovh](https://bookstack.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/linuxserver/docker-bookstack](https://github.com/linuxserver/docker-bookstack)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip68758"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>6875</td><td>80/tcp</td><td>0.0.0.0</td></tr><tr><td>6875</td><td>80/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/bookstack/app`</td><td>`/config`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## bookstack\_db

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

<table id="bkmrk-imagelscr.io%2Flinuxse-1"><tbody><tr><th>Image</th><td>`lscr.io/linuxserver/mariadb:latest`</td></tr><tr><th>Version</th><td>11.4.9-r0-ls212</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>bookstack</td></tr><tr><th>Reseau</th><td>bookstack\_default</td></tr><tr><th>URL</th><td>[https://bookstack.juxjux.ovh](https://bookstack.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/linuxserver/docker-mariadb](https://github.com/linuxserver/docker-mariadb)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-1"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/bookstack/db`</td><td>`/config`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`bookstack MCP (npm bookstack-mcp-server)`</td></tr><tr><th>Configuration</th><td>npm via npx -y bookstack-mcp-server | Projet Claude Code : C:\\Users\\eliob | Auth : Token ID + Secret en variables d'environnement (.claude.json)</td></tr></tbody></table>

### Outils disponibles

- `list_books`
- `get_book`
- `list_chapters`
- `get_chapter`
- `list_pages`
- `get_page`
- `create_page`
- `update_page`
- `search`
- `get_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

<table id="bkmrk-script%2Fopt%2Fbackups%2Fb"><tbody><tr><th>Script</th><td>`/opt/backups/bookstack_backup.sh`</td></tr><tr><th>Cron</th><td>Tous les jours à 2h du matin (`0 2 * * *`)</td></tr><tr><th>Base sauvegardée</th><td>`bookstackapp` — container `bookstack_db` (MariaDB)</td></tr><tr><th>Taille base (disque)</th><td>~203 Mo</td></tr><tr><th>Format archive</th><td>.7z (compression niveau 5) — ~564 Ko</td></tr><tr><th>Destination</th><td>kDrive Infomaniak — `TOOJUX/jux_vps/bookstack` (dossier ID 1427916)</td></tr><tr><th>Rétention</th><td>7 jours glissants (purge automatique des anciens fichiers)</td></tr><tr><th>Log</th><td>`/opt/backups/backup.log`</td></tr><tr><th>Nommage fichier</th><td>`bookstack_db_YYYY-MM-DD.7z`</td></tr></tbody></table>

### Fonctionnement du script

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

### Consulter les logs

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

### Relancer manuellement

```
ssh debian@51.77.141.54 "bash /opt/backups/bookstack_backup.sh"
```

# 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.*

<table id="bkmrk-imageghcr.io%2Fhomarr-"><tbody><tr><th>Image</th><td>`ghcr.io/homarr-labs/homarr:latest`</td></tr><tr><th>Version</th><td>main</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>homarr</td></tr><tr><th>Reseau</th><td>homarr\_homarr\_network</td></tr><tr><th>URL</th><td>[https://homarr.juxjux.ovh](https://homarr.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/homarr-labs/homarr](https://github.com/homarr-labs/homarr)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip75753"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>7575</td><td>3000/tcp</td><td>0.0.0.0</td></tr><tr><td>7575</td><td>3000/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/etc/localtime`</td><td>`/etc/localtime`</td><td>bind</td><td>ro</td></tr><tr><td>`/var/run/docker.sock`</td><td>`/var/run/docker.sock`</td><td>bind</td><td>ro</td></tr><tr><td>`/home/debian/docker/homarr2026/icons`</td><td>`/app/public/icons`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/homarr2026/appdata`</td><td>`/appdata`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__homarr__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_homarr.py | Projet Claude Code : C:\\Users\\eliob | Auth : cookie NextAuth session (authjs.session-token)</td></tr></tbody></table>

### Outils disponibles

- `get_all_boards`
- `get_board_items`
- `get_home_board`
- `get_integrations`
- `trpc_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)

<table id="bkmrk-versions"><tbody><tr><th>Version installee</th><td>0.53</td></tr><tr><th>Derniere version</th><td>1.71.0 (2026-07-17)</td></tr><tr><th>Ecart</th><td>Traverse la refonte majeure 1.0 (reecriture complete, ete 2024) + ~70 releases mineures jusqu'a juillet 2026</td></tr></tbody></table>

### 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` -&gt; `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 -&gt; 1.0)

- Variables d'env renommees : `DATABASE_URL` -&gt; `DB_URL` (conditionnelle), `DOCKER_HOST` -&gt; `DOCKER_HOSTNAMES` + `DOCKER_PORTS`, `AUTH_PROVIDER` -&gt; `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)
- `/data` restructure et deplace vers `/appdata` (non retrocompatible)
- `/app/data/configs` (JSON) et `/app/public/icons` abandonnes -- 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

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

*Sources : [github.com/homarr-labs/homarr/releases](https://github.com/homarr-labs/homarr/releases), [homarr.dev/blog - Homarr 1.0](https://homarr.dev/blog/2024/09/23/version-1.0/)*

# 04_Audiobookshelf

## audiobookshelf

*Self-hosted audiobook and podcast server*

<table id="bkmrk-imageghcr"><tbody><tr><th>Image</th><td>`ghcr.io/advplyr/audiobookshelf:latest`</td></tr><tr><th>Version</th><td>2.35.0</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>audiobookshelf</td></tr><tr><th>Reseau</th><td>audiobookshelf\_audiobookshelf\_network</td></tr><tr><th>URL</th><td>[https://audiobookshelf.juxjux.ovh](https://audiobookshelf.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/advplyr/audiobookshelf](https://github.com/advplyr/audiobookshelf)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip13378"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>13378</td><td>80/tcp</td><td>127.0.0.1</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-hote-destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/audiobookshelf/config`</td><td>`/config`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/audiobookshelf/metadata`</td><td>`/metadata`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/audiobookshelf/podcasts`</td><td>`/podcasts`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/audiobookshelf/audiobooks`</td><td>`/audiobooks`</td><td>bind</td><td>rw, :shared</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__audiobookshelf__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_audiobookshelf.py | Auth : JWT Bearer via POST /login</td></tr></tbody></table>

### Outils disponibles

- `get_libraries`
- `get_library`
- `get_library_items`
- `get_library_personalized`
- `get_item`
- `get_item_progress`
- `get_podcast_episodes`
- `download_podcast_episodes`
- `get_listening_sessions`
- `get_listening_stats`
- `get_me`
- `search_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

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

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

Exemple de log :

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

---

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

### Contexte

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

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

### Cause

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

### Solution

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

# 05_BentoPDF

## bentopdf

*Unprivileged NGINX Dockerfiles*

<table id="bkmrk-imagebentopdfteam%2Fbe"><tbody><tr><th>Image</th><td>`bentopdfteam/bentopdf-simple:latest`</td></tr><tr><th>Version</th><td>1.28.0-alpine-slim</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>bentopdf</td></tr><tr><th>Reseau</th><td>bentopdf\_default</td></tr><tr><th>URL</th><td>[https://bento.juxjux.ovh](https://bento.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/alam00000/bentopdf](https://github.com/alam00000/bentopdf)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip80898"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8089</td><td>8080/tcp</td><td>0.0.0.0</td></tr><tr><td>8089</td><td>8080/tcp</td><td>::</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>API REST interne, pas de MCP configuré. Accessible via PowerShell/Python httpx.</td></tr></tbody></table>

### 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

<table id="bkmrk-imagegcr.io%2Fcadvisor"><tbody><tr><th>Image</th><td>`gcr.io/cadvisor/cadvisor:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>gemini\_grafana</td></tr><tr><th>Reseau</th><td>gemini\_grafana\_monitor\_net</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/run`</td><td>`/var/run`</td><td>bind</td><td>rw</td></tr><tr><td>`/`</td><td>`/root`</td><td>bind</td><td>ro</td></tr><tr><td>`/sys`</td><td>`/sys`</td><td>bind</td><td>ro</td></tr><tr><td>`/var/lib/docker`</td><td>`/var/lib/docker`</td><td>bind</td><td>ro</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>Endpoint Prometheus /metrics exposé à Prometheus (port 8080). Pas de MCP. Données lisibles via Prometheus MCP ou requêtes PromQL directes.</td></tr></tbody></table>

### 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.*

<table id="bkmrk-imagelscr.io%2Flinuxse"><tbody><tr><th>Image</th><td>`lscr.io/linuxserver/calibre-web:latest`</td></tr><tr><th>Version</th><td>0.6.26-ls383</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>calibreweb\_automated</td></tr><tr><th>Reseau</th><td>calibre\_network</td></tr><tr><th>Source</th><td>[https://github.com/linuxserver/docker-calibre-web](https://github.com/linuxserver/docker-calibre-web)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip82148"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8214</td><td>8083/tcp</td><td>0.0.0.0</td></tr><tr><td>8214</td><td>8083/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/livres/Eyrolles`</td><td>`/books`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/calibre-web-automated/config`</td><td>`/config`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>Interface OPDS disponible pour parcourir la bibliothèque. API REST limitée. Pas de MCP configuré.</td></tr></tbody></table>

### 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.*

<table id="bkmrk-imageamir20%2Fdozzle%3Al"><tbody><tr><th>Image</th><td>`amir20/dozzle:latest`</td></tr><tr><th>Version</th><td>v8.14.9</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>dozzle</td></tr><tr><th>Reseau</th><td>nginx\_npm-network</td></tr><tr><th>URL</th><td>[https://dozzle.juxjux.ovh](https://dozzle.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/amir20/dozzle](https://github.com/amir20/dozzle)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip90918"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>9091</td><td>8080/tcp</td><td>0.0.0.0</td></tr><tr><td>9091</td><td>8080/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/run/docker.sock`</td><td>`/var/run/docker.sock`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>Interface de visualisation de logs uniquement. Pas d'API publique exploitable. Les logs sont mieux accessibles via mcp\_\_portainer\_\_get\_container\_logs.</td></tr></tbody></table>

### Ce que nous pouvons faire ensemble

- Logs containers accessibles en alternative via le MCP Portainer

# 09_FileBrowser

## File-Browser

<table id="bkmrk-imagefilebrowser%2Ffil"><tbody><tr><th>Image</th><td>`filebrowser/filebrowser:latest`</td></tr><tr><th>Version</th><td>2.63.3</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>filebrowser</td></tr><tr><th>Reseau</th><td>filebrowser\_default</td></tr><tr><th>URL</th><td>[https://files.juxjux.ovh](https://files.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/filebrowser/filebrowser](https://github.com/filebrowser/filebrowser)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip81478"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8147</td><td>80/tcp</td><td>0.0.0.0</td></tr><tr><td>8147</td><td>80/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/filebrowser/database`</td><td>`/database`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian`</td><td>`/srv`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/filebrowser/config`</td><td>`/config`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__filebrowser__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_filebrowser.py | Auth : JWT via POST /api/login (admin)</td></tr></tbody></table>

### Outils disponibles

- `list_files`
- `read_text_file`
- `upload_text_file`
- `get_file_info`
- `search_files`
- `copy_file`
- `move_or_rename`
- `create_directory`
- `delete_path`

### Ce que nous pouvons faire ensemble

- Naviguer dans l'arborescence de fichiers du VPS
- Lire et écrire des fichiers texte (configs, scripts, logs)
- Rechercher des fichiers par nom ou contenu
- Copier, déplacer, renommer des fichiers et dossiers
- Déposer des fichiers de config ou des scripts directement sur le VPS

# 10_FreshRSS

## freshrss

*A free, self-hostable news aggregator…*

<table id="bkmrk-imagefreshrss%2Ffreshr"><tbody><tr><th>Image</th><td>`freshrss/freshrss:latest`</td></tr><tr><th>Version</th><td>1.28.1</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 26 minutes</span></td></tr><tr><th>Compose project</th><td>freshrss</td></tr><tr><th>Reseau</th><td>freshrss\_default</td></tr><tr><th>URL</th><td>[https://freshrss.juxjux.ovh](https://freshrss.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/FreshRSS/FreshRSS](https://github.com/FreshRSS/FreshRSS)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip80818"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8081</td><td>80/tcp</td><td>0.0.0.0</td></tr><tr><td>8081</td><td>80/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/freshrss/data`</td><td>`/var/www/FreshRSS/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__freshrss__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_freshrss.py | Auth : GReader API avec mot de passe API dédié (≠ mot de passe web)</td></tr></tbody></table>

### Outils disponibles

- `get_feeds`
- `get_categories`
- `get_articles`
- `get_unread_count`
- `get_starred_articles`
- `mark_as_read`
- `mark_feed_as_read`
- `star_article`
- `search_articles`
- `add_feed`
- `delete_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*

<table id="bkmrk-imagegitea%2Fgitea%3Alat"><tbody><tr><th>Image</th><td>`gitea/gitea:latest`</td></tr><tr><th>Version</th><td>1.25.4</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>gitea</td></tr><tr><th>Reseau</th><td>gitea\_default</td></tr><tr><th>URL</th><td>[https://gitea.juxjux.ovh](https://gitea.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/go-gitea/gitea](https://github.com/go-gitea/gitea)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip22222"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>2222</td><td>2222/tcp</td><td>0.0.0.0</td></tr><tr><td>2222</td><td>2222/tcp</td><td>::</td></tr><tr><td>3005</td><td>3000/tcp</td><td>0.0.0.0</td></tr><tr><td>3005</td><td>3000/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/lib/gitea_data`</td><td>`/data`</td><td>bind</td><td>rw</td></tr><tr><td>`/etc/localtime`</td><td>`/etc/localtime`</td><td>bind</td><td>ro</td></tr><tr><td>`/etc/timezone`</td><td>`/etc/timezone`</td><td>bind</td><td>ro</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>API REST Gitea complète disponible sur /api/v1. Auth : token Bearer ou Basic Auth. Pas de MCP configuré — appels directs via PowerShell/Python.</td></tr></tbody></table>

### 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-lifecycle` actif 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.*

<table id="bkmrk-imageghcr.io%2Fimmich-"><tbody><tr><th>Image</th><td>`ghcr.io/immich-app/immich-server:release`</td></tr><tr><th>Version</th><td>v2.7.5</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>immich</td></tr><tr><th>Reseau</th><td>immich\_immich-network</td></tr><tr><th>URL</th><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/immich-app/immich](https://github.com/immich-app/immich)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip-8212"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8212</td><td>2283/tcp</td><td>0.0.0.0</td></tr><tr><td>8212</td><td>2283/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/immich/upload`</td><td>`/data`</td><td>bind</td><td>rw</td></tr><tr><td>`/etc/localtime`</td><td>`/etc/localtime`</td><td>bind</td><td>ro</td></tr><tr><td>`/home/debian/docker/immich/upload/encoded-video`</td><td>`/mnt/media/encoded-video`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/photo`</td><td>`/mnt/media/photo`</td><td>bind</td><td>ro,shared</td></tr></tbody></table>

---

## Immich-MICROSERVICES

*High performance self-hosted photo and video management solution.*

<table id="bkmrk-imageghcr.io%2Fimmich--1"><tbody><tr><th>Image</th><td>`ghcr.io/immich-app/immich-server:release`</td></tr><tr><th>Version</th><td>v2.7.5</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>immich</td></tr><tr><th>Reseau</th><td>immich\_immich-network</td></tr><tr><th>URL</th><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/immich-app/immich](https://github.com/immich-app/immich)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-1"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/immich/upload`</td><td>`/data`</td><td>bind</td><td>rw</td></tr><tr><td>`/etc/localtime`</td><td>`/etc/localtime`</td><td>bind</td><td>ro</td></tr><tr><td>`/home/debian/docker/immich/upload/encoded-video`</td><td>`/mnt/media/encoded-video`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/photo`</td><td>`/mnt/media/photo`</td><td>bind</td><td>ro,shared</td></tr></tbody></table>

---

## Immich-LEARNING

*High performance self-hosted photo and video management solution.*

<table id="bkmrk-imageghcr.io%2Fimmich--2"><tbody><tr><th>Image</th><td>`ghcr.io/immich-app/immich-machine-learning:release`</td></tr><tr><th>Version</th><td>v2.7.5</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>immich</td></tr><tr><th>Reseau</th><td>immich\_immich-network</td></tr><tr><th>URL</th><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/immich-app/immich](https://github.com/immich-app/immich)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-2"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/immich/cache`</td><td>`/cache`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Immich-REDIS

<table id="bkmrk-imageredis%3A6.2-alpin"><tbody><tr><th>Image</th><td>`redis:6.2-alpine`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>immich</td></tr><tr><th>Reseau</th><td>immich\_immich-network</td></tr><tr><th>URL</th><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-3"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td> </td><td>`/data`</td><td>volume</td><td>rw</td></tr></tbody></table>

---

## Immich-DB

*Base images for Immich containers*

<table id="bkmrk-imageghcr.io%2Fimmich--3"><tbody><tr><th>Image</th><td>`ghcr.io/immich-app/postgres:16-vectorchord0.3.0-pgvectors0.2.0`</td></tr><tr><th>Version</th><td>16-vectorchord0.3.0-pgvector0.8.1-pgvectors0.2.0</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>immich</td></tr><tr><th>Reseau</th><td>immich\_immich-network</td></tr><tr><th>URL</th><td>[https://immich.juxjux.ovh](https://immich.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/immich-app/base-images](https://github.com/immich-app/base-images)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-4"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/immich/db`</td><td>`/var/lib/postgresql/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actif-"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__immich__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_immich.py | Auth : JWT via POST /api/auth/login</td></tr></tbody></table>

### Outils disponibles

- `get_assets`
- `get_asset`
- `search_assets`
- `update_asset`
- `get_albums`
- `get_album`
- `create_album`
- `get_people`
- `get_person_assets`
- `get_memories`
- `get_statistics`
- `get_my_user`
- `get_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

<table id="bkmrk-script%2Fopt%2Fbackups%2Fv"><tbody><tr><th>Script</th><td>`/opt/backups/vps_backup.sh`</td></tr><tr><th>Cron</th><td>Tous les jours à 2h du matin (`0 2 * * *`)</td></tr><tr><th>Container DB</th><td>`Immich-DB` (PostgreSQL 16)</td></tr><tr><th>Commande</th><td>`pg_dump -U postgres`</td></tr><tr><th>Taille base (disque)</th><td>~7.5 Mo (métadonnées uniquement — photos sur volume séparé)</td></tr><tr><th>Format archive</th><td>.7z (compression niveau 5)</td></tr><tr><th>Destination</th><td>kDrive Infomaniak — `TOOJUX/jux_vps/immich` (dossier ID 1427919)</td></tr><tr><th>Rétention</th><td>7 jours glissants</td></tr><tr><th>Nommage fichier</th><td>`immich_db_YYYY-MM-DD.7z`</td></tr></tbody></table>

### 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*

<table id="bkmrk-imagejellyfin%2Fjellyf"><tbody><tr><th>Image</th><td>`jellyfin/jellyfin:latest`</td></tr><tr><th>Version</th><td>10.10.7</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>jellyfin</td></tr><tr><th>Reseau</th><td>host</td></tr><tr><th>URL</th><td>[https://jellyfin.juxjux.ovh](https://jellyfin.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/jellyfin/jellyfin-packaging](https://github.com/jellyfin/jellyfin-packaging)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/mnt/nas_videos/movies`</td><td>`/data/movies`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/palettes`</td><td>`/data/palettes`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/jellyfin/config`</td><td>`/config`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/cinema_europe`</td><td>`/data/cinema_europe`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/cinema_UK`</td><td>`/data/cinema_uk`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/spectacles`</td><td>`/data/spectacles`</td><td>bind</td><td>rw</td></tr><tr><td>``</td><td>`/cache`</td><td>volume</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/animes`</td><td>`/data/animes`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/cinema_asie`</td><td>`/data/cinema_asie`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/cinema_realisateurs`</td><td>`/data/cinema_realisateurs`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/fantastique_et_SF`</td><td>`/data/fantastique_et_SF`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/historiques`</td><td>`/data/historiques`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/series`</td><td>`/data/series`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/cinema_italie`</td><td>`/data/cinema_italie`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/culture_cuisine`</td><td>`/data/culture_cuisine`</td><td>bind</td><td>rw</td></tr><tr><td>`/mnt/nas_videos/documentaires`</td><td>`/data/documentaires`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__jellyfin__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_jellyfin.py | Auth : JWT MediaBrowser Token via POST /Users/AuthenticateByName</td></tr></tbody></table>

### Outils disponibles

- `get_libraries`
- `get_items`
- `get_item`
- `get_recently_added`
- `get_resume_items`
- `get_sessions`
- `get_users`
- `get_server_info`
- `scan_library`
- `search_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

<table id="bkmrk-imagejoplin_to_obsid"><tbody><tr><th>Image</th><td>`joplin_to_obsidian-joplin_to_obsidian`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>joplin\_to\_obsidian</td></tr><tr><th>Reseau</th><td>joplin\_joplin\_network</td></tr><tr><th>URL</th><td>[https://joplin.juxjux.ovh](https://joplin.juxjux.ovh)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/Documents/Joplin_Obsidian`</td><td>`/home/debian/Documents/Joplin_Obsidian`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## joplin-nginx

<table id="bkmrk-imagenginx%3Aalpineeta"><tbody><tr><th>Image</th><td>`nginx:alpine`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>joplin</td></tr><tr><th>Reseau</th><td>joplin\_joplin\_network</td></tr><tr><th>URL</th><td>[https://joplin.juxjux.ovh](https://joplin.juxjux.ovh)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip22301"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>22301</td><td>80/tcp</td><td>0.0.0.0</td></tr><tr><td>22301</td><td>80/tcp</td><td>::</td></tr></tbody></table>

---

## joplin

*Docker image for Joplin Server*

<table id="bkmrk-imagejoplin%2Fserver%3Al"><tbody><tr><th>Image</th><td>`joplin/server:latest`</td></tr><tr><th>Version</th><td>3.4.3</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>joplin</td></tr><tr><th>Reseau</th><td>joplin\_joplin\_network</td></tr><tr><th>URL</th><td>[https://joplin.juxjux.ovh](https://joplin.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/laurent22/joplin.git](https://github.com/laurent22/joplin.git)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip22300"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>22300</td><td>22300/tcp</td><td>0.0.0.0</td></tr><tr><td>22300</td><td>22300/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-1"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/joplin-data`</td><td>`/home/joplin/.config/joplin`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## joplin-db

<table id="bkmrk-imagepostgres%3A15-alp"><tbody><tr><th>Image</th><td>`postgres:15-alpine`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>joplin</td></tr><tr><th>Reseau</th><td>joplin\_joplin\_network</td></tr><tr><th>URL</th><td>[https://joplin.juxjux.ovh](https://joplin.juxjux.ovh)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-2"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/joplin-db-data`</td><td>`/var/lib/postgresql/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:#FFA500;">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>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.</td></tr></tbody></table>

### 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

<table id="bkmrk-script%2Fopt%2Fbackups%2Fv"><tbody><tr><th>Script</th><td>`/opt/backups/vps_backup.sh`</td></tr><tr><th>Cron</th><td>Tous les jours à 2h du matin (`0 2 * * *`)</td></tr><tr><th>Container DB</th><td>`joplin-db` (PostgreSQL 15)</td></tr><tr><th>Commande</th><td>`pg_dump -U joplin -d joplin`</td></tr><tr><th>Taille base (disque)</th><td>~1.4 Go (notes + pièces jointes stockées en BLOB)</td></tr><tr><th>Format archive</th><td>.7z (compression niveau 5)</td></tr><tr><th>Destination</th><td>kDrive Infomaniak — `TOOJUX/jux_vps/joplin` (dossier ID 1427920)</td></tr><tr><th>Rétention</th><td>7 jours glissants</td></tr><tr><th>Nommage fichier</th><td>`joplin_db_YYYY-MM-DD.7z`</td></tr></tbody></table>

### 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

<table id="bkmrk-ressources-totales-%28"><tbody><tr><th>Ressources totales (actuelles)</th><td>736 fichiers</td></tr><tr><th>Poids total actuel</th><td>**119.7 Mo**</td></tr><tr><th>Ressources compress?es</th><td>424</td></tr><tr><th>Poids avant compression</th><td>451.5 Mo</td></tr><tr><th>?conomie r?alis?e</th><td><span style="color:#008000;">**356.3 Mo (-78.9%)**</span></td></tr><tr><th>Ignor?es (gain insuffisant)</th><td>212</td></tr><tr><th>Erreurs</th><td>0</td></tr></tbody></table>

### Top 15 ressources les plus lourdes (?tat actuel)

<table id="bkmrk-%23idformattaille-actu"><thead><tr><th>\#</th><th>ID</th><th>Format</th><th>Taille actuelle</th><th>Gain compression</th></tr></thead><tbody><tr><td>1</td><td>`vVO2ePdMvtty3sXZy5nY6M`</td><td>?</td><td>3146 KB</td><td></td></tr><tr><td>2</td><td>`0xh87pWrRt82z0DbO9n3yQ`</td><td>ZIP</td><td>2250 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>3</td><td>`VasIoF2e9EGuNQt38aOFMx`</td><td>JPEG</td><td>1633 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>4</td><td>`TzWK21r4n0yvbEtJh02DGB`</td><td>JPEG</td><td>1529 KB</td><td><span style="color:#008000;">-63%</span></td></tr><tr><td>5</td><td>`M0C32hKC2hMqPAxpRGiVgp`</td><td>JPEG</td><td>937 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>6</td><td>`Hn6z6lvvbJzRsX0KGM8FNW`</td><td>JPEG</td><td>928 KB</td><td><span style="color:#008000;">-53%</span></td></tr><tr><td>7</td><td>`7EyAL9NNysJzWke6NT4ttJ`</td><td>JPEG</td><td>803 KB</td><td><span style="color:#008000;">-76%</span></td></tr><tr><td>8</td><td>`bz9Twmb2F5lj0mPIQi48IB`</td><td>JPEG</td><td>798 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>9</td><td>`UbAqQY3cEbH62vioIHU6Pj`</td><td>JPEG</td><td>776 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>10</td><td>`SrJi1UyeNGf8OhaRsaOCGq`</td><td>JPEG</td><td>745 KB</td><td><span style="color:#008000;">-79%</span></td></tr><tr><td>11</td><td>`87mV49tXupZcpt2wplcGjU`</td><td>JPEG</td><td>685 KB</td><td><span style="color:#008000;">-59%</span></td></tr><tr><td>12</td><td>`JsJFO6dIzqMKLA7clqW8nG`</td><td>JPEG</td><td>683 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>13</td><td>`VSyNmO0uN1fNNeqN6XZucO`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-19%</span></td></tr><tr><td>14</td><td>`hExoJEEWT2tHz1demE5Nhm`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-84%</span></td></tr><tr><td>15</td><td>`slTzAxAQ4xi0pMvzsLIDez`</td><td>?</td><td>670 KB</td><td></td></tr></tbody></table>

---

## Observatoire Joplin-Compression

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

### Bilan global

<table id="bkmrk-ressources-totales-%28-1"><tbody><tr><th>Ressources totales (actuelles)</th><td>736 fichiers</td></tr><tr><th>Poids total actuel</th><td>**119.9 Mo**</td></tr><tr><th>Ressources compress?es</th><td>425</td></tr><tr><th>Poids avant compression</th><td>452.0 Mo</td></tr><tr><th>?conomie r?alis?e</th><td><span style="color:#008000;">**356.4 Mo (-78.8%)**</span></td></tr><tr><th>Ignor?es (gain insuffisant)</th><td>212</td></tr><tr><th>Erreurs</th><td>0</td></tr></tbody></table>

### Top 15 ressources les plus lourdes (?tat actuel)

<table id="bkmrk-%23idformattaille-actu-1"><thead><tr><th>\#</th><th>ID</th><th>Format</th><th>Taille actuelle</th><th>Gain compression</th></tr></thead><tbody><tr><td>1</td><td>`vVO2ePdMvtty3sXZy5nY6M`</td><td>?</td><td>3146 KB</td><td></td></tr><tr><td>2</td><td>`0xh87pWrRt82z0DbO9n3yQ`</td><td>ZIP</td><td>2250 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>3</td><td>`VasIoF2e9EGuNQt38aOFMx`</td><td>JPEG</td><td>1633 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>4</td><td>`TzWK21r4n0yvbEtJh02DGB`</td><td>JPEG</td><td>1529 KB</td><td><span style="color:#008000;">-63%</span></td></tr><tr><td>5</td><td>`M0C32hKC2hMqPAxpRGiVgp`</td><td>JPEG</td><td>937 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>6</td><td>`Hn6z6lvvbJzRsX0KGM8FNW`</td><td>JPEG</td><td>928 KB</td><td><span style="color:#008000;">-53%</span></td></tr><tr><td>7</td><td>`7EyAL9NNysJzWke6NT4ttJ`</td><td>JPEG</td><td>803 KB</td><td><span style="color:#008000;">-76%</span></td></tr><tr><td>8</td><td>`bz9Twmb2F5lj0mPIQi48IB`</td><td>JPEG</td><td>798 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>9</td><td>`UbAqQY3cEbH62vioIHU6Pj`</td><td>JPEG</td><td>776 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>10</td><td>`SrJi1UyeNGf8OhaRsaOCGq`</td><td>JPEG</td><td>745 KB</td><td><span style="color:#008000;">-79%</span></td></tr><tr><td>11</td><td>`87mV49tXupZcpt2wplcGjU`</td><td>JPEG</td><td>685 KB</td><td><span style="color:#008000;">-59%</span></td></tr><tr><td>12</td><td>`JsJFO6dIzqMKLA7clqW8nG`</td><td>JPEG</td><td>683 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>13</td><td>`VSyNmO0uN1fNNeqN6XZucO`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-19%</span></td></tr><tr><td>14</td><td>`hExoJEEWT2tHz1demE5Nhm`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-84%</span></td></tr><tr><td>15</td><td>`slTzAxAQ4xi0pMvzsLIDez`</td><td>?</td><td>670 KB</td><td></td></tr></tbody></table>

---

## Observatoire Joplin-Compression

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

### Bilan global

<table id="bkmrk-ressources-totales-%28-2"><tbody><tr><th>Ressources totales (actuelles)</th><td>736 fichiers</td></tr><tr><th>Poids total actuel</th><td>**119.9 Mo**</td></tr><tr><th>Ressources compress?es</th><td>425</td></tr><tr><th>Poids avant compression</th><td>452.0 Mo</td></tr><tr><th>?conomie r?alis?e</th><td><span style="color:#008000;">**356.4 Mo (-78.8%)**</span></td></tr><tr><th>Ignor?es (gain insuffisant)</th><td>212</td></tr><tr><th>Erreurs</th><td>0</td></tr></tbody></table>

### Top 15 ressources les plus lourdes (?tat actuel)

<table id="bkmrk-%23idformattaille-actu-2"><thead><tr><th>\#</th><th>ID</th><th>Format</th><th>Taille actuelle</th><th>Gain compression</th></tr></thead><tbody><tr><td>1</td><td>`vVO2ePdMvtty3sXZy5nY6M`</td><td>?</td><td>3146 KB</td><td></td></tr><tr><td>2</td><td>`0xh87pWrRt82z0DbO9n3yQ`</td><td>ZIP</td><td>2250 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>3</td><td>`VasIoF2e9EGuNQt38aOFMx`</td><td>JPEG</td><td>1633 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>4</td><td>`TzWK21r4n0yvbEtJh02DGB`</td><td>JPEG</td><td>1529 KB</td><td><span style="color:#008000;">-63%</span></td></tr><tr><td>5</td><td>`M0C32hKC2hMqPAxpRGiVgp`</td><td>JPEG</td><td>937 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>6</td><td>`Hn6z6lvvbJzRsX0KGM8FNW`</td><td>JPEG</td><td>928 KB</td><td><span style="color:#008000;">-53%</span></td></tr><tr><td>7</td><td>`7EyAL9NNysJzWke6NT4ttJ`</td><td>JPEG</td><td>803 KB</td><td><span style="color:#008000;">-76%</span></td></tr><tr><td>8</td><td>`bz9Twmb2F5lj0mPIQi48IB`</td><td>JPEG</td><td>798 KB</td><td><span style="color:#008000;">-81%</span></td></tr><tr><td>9</td><td>`UbAqQY3cEbH62vioIHU6Pj`</td><td>JPEG</td><td>776 KB</td><td><span style="color:#008000;">-87%</span></td></tr><tr><td>10</td><td>`SrJi1UyeNGf8OhaRsaOCGq`</td><td>JPEG</td><td>745 KB</td><td><span style="color:#008000;">-79%</span></td></tr><tr><td>11</td><td>`87mV49tXupZcpt2wplcGjU`</td><td>JPEG</td><td>685 KB</td><td><span style="color:#008000;">-59%</span></td></tr><tr><td>12</td><td>`JsJFO6dIzqMKLA7clqW8nG`</td><td>JPEG</td><td>683 KB</td><td><span style="color:#008000;">-66%</span></td></tr><tr><td>13</td><td>`VSyNmO0uN1fNNeqN6XZucO`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-19%</span></td></tr><tr><td>14</td><td>`hExoJEEWT2tHz1demE5Nhm`</td><td>JPEG</td><td>674 KB</td><td><span style="color:#008000;">-84%</span></td></tr><tr><td>15</td><td>`slTzAxAQ4xi0pMvzsLIDez`</td><td>?</td><td>670 KB</td><td></td></tr></tbody></table>

# 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èques
- `get_series` — liste les séries (filtre library_id non fonctionnel : retourne toutes les bibliothèques)
- `get_series_detail`
- `get_series_metadata` — retourne genres, auteurs, éditeur, résumé, année
- `get_series_volumes`
- `get_recently_added`
- `get_on_deck` — séries en cours de lecture
- `get_server_stats`
- `search` — recherche full-text sur noms de séries, genres, fichiers, chapitres
- `get_collections` — corrigé 2026-06-25
- `get_reading_lists` — corrigé 2026-06-25
- `get_want_to_read` — corrigé 2026-06-25
- `add_to_want_to_read`
- `remove_from_want_to_read`
- `get_user_stats` — corrigé 2026-06-25
- `get_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_id` de `get_series` ne filtre pas : retourne toutes les bibliothèques triées alphabétiquement
- Pour filtrer par genre, utiliser l'API directe : `POST /api/Series/all-v2` avec 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

<table id="bkmrk-imagegotson%2Fkomgaver"><tbody><tr><th>Image</th><td>`gotson/komga`</td></tr><tr><th>Version</th><td>24.10</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>komga</td></tr><tr><th>Reseau</th><td>komga\_default</td></tr><tr><th>URL</th><td>[https://komga.juxjux.ovh](https://komga.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/gotson/komga](https://github.com/gotson/komga)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip25600"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>25600</td><td>25600/tcp</td><td>0.0.0.0</td></tr><tr><td>25600</td><td>25600/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/komga/config`</td><td>`/config`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/komga`</td><td>`/data`</td><td>bind</td><td>rw</td></tr><tr><td>`/etc/timezone`</td><td>`/etc/timezone`</td><td>bind</td><td>ro</td></tr><tr><td>``</td><td>`/tmp`</td><td>volume</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__komga__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_komga.py | Auth : Basic Auth (Base64 login:password)</td></tr></tbody></table>

### Outils disponibles

- `get_libraries`
- `get_series`
- `get_series_detail`
- `get_series_books`
- `get_book`
- `get_book_metadata`
- `get_books`
- `get_latest_books`
- `get_new_series`
- `get_updated_series`
- `get_on_deck`
- `get_read_lists`
- `get_read_list`
- `get_collections`
- `get_collection`
- `search`
- `mark_series_read`
- `update_book_progress`
- `get_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*

<table id="bkmrk-imageghcr.io%2Fmealie-"><tbody><tr><th>Image</th><td>`ghcr.io/mealie-recipes/mealie:latest`</td></tr><tr><th>Version</th><td>v3.16.0</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>mealie2</td></tr><tr><th>Reseau</th><td>mealie2\_default</td></tr><tr><th>URL</th><td>[https://mealie.juxjux.ovh](https://mealie.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/mealie-recipes/mealie](https://github.com/mealie-recipes/mealie)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip99259"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>9925</td><td>9000/tcp</td><td>0.0.0.0</td></tr><tr><td>9925</td><td>9000/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/docker/mealie/backups`</td><td>`/app/backups`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/mealie/config`</td><td>`/app/config`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/mealie/data`</td><td>`/app/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__mealie__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_mealie.py | Auth : OAuth2 Bearer Token via POST /api/auth/token</td></tr></tbody></table>

### Outils disponibles

- `get_recipes`
- `get_recipe`
- `create_recipe`
- `create_recipe_from_url`
- `delete_recipe`
- `get_categories`
- `get_tags`
- `get_cookbooks`
- `get_cookbook`
- `get_meal_plan`
- `add_meal_plan_entry`
- `get_shopping_lists`
- `get_shopping_list`
- `add_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

<table id="bkmrk-script%2Fopt%2Fbackups%2Fv"><tbody><tr><th>Script</th><td>`/opt/backups/vps_backup.sh`</td></tr><tr><th>Cron</th><td>Tous les jours à 2h du matin (`0 2 * * *`)</td></tr><tr><th>Type base</th><td>SQLite — `/app/data/mealie.db` (dans le container)</td></tr><tr><th>Méthode</th><td>`docker cp mealie:/app/data/mealie.db`</td></tr><tr><th>Taille base</th><td>~2.9 Mo</td></tr><tr><th>Format archive</th><td>.7z (compression niveau 5)</td></tr><tr><th>Destination</th><td>kDrive Infomaniak — `TOOJUX/jux_vps/mealie` (dossier ID 1427921)</td></tr><tr><th>Rétention</th><td>7 jours glissants</td></tr><tr><th>Nommage fichier</th><td>`mealie_db_YYYY-MM-DD.7z`</td></tr></tbody></table>

# 19_Navidrome

## navidrome-navidrome-1

*🎧 Your Personal Streaming Service*

<table id="bkmrk-imagedeluan%2Fnavidrom"><tbody><tr><th>Image</th><td>`deluan/navidrome:latest`</td></tr><tr><th>Version</th><td>0.61.2</td></tr><tr><th>Etat</th><td><span style="color: #008000;">Up</span></td></tr><tr><th>Compose project</th><td>navidrome</td></tr><tr><th>Reseau</th><td>navidrome\_default</td></tr><tr><th>URL</th><td>[https://navidrome.juxjux.ovh](https://navidrome.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/navidrome/navidrome](https://github.com/navidrome/navidrome)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip45334"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>4533</td><td>4533/tcp</td><td>0.0.0.0</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/music`</td><td>`/music`</td><td>bind</td><td>rw, :shared</td></tr><tr><td>`/home/debian/docker/navidrome/data`</td><td>`/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color: #008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__navidrome__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_navidrome.py | Auth : Subsonic API avec hachage MD5 (user + token + sel)</td></tr></tbody></table>

### Outils disponibles

- `ping`
- `get_artists`
- `get_artist`
- `get_albums`
- `get_album`
- `get_song`
- `get_genres`
- `get_random_songs`
- `get_playlists`
- `get_playlist`
- `create_playlist`
- `get_starred`
- `star`
- `unstar`
- `search`
- `get_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 :

<table id="bkmrk-cronscripttyper%C3%B4le-%2A"><thead><tr><th>Cron</th><th>Script</th><th>Type</th><th>Rôle</th></tr></thead><tbody><tr><td>`*/5 * * * *`</td><td>`/home/debian/monitor-rclone.sh`</td><td>Watchdog</td><td>Détecte FUSE mort → restart service + restart container (recovery auto)</td></tr><tr><td>`30 4 * * *`</td><td>`/home/debian/navidrome_scan.sh`</td><td>Quick scan</td><td>vfs/refresh + scan quotidien (MAJ des titres existants)</td></tr><tr><td>`0 3 * * 1`</td><td>`/home/debian/navidrome_fullscan.sh`</td><td>Full scan</td><td>vfs/refresh + restart container → full scan hebdomadaire (détecte nouveaux albums/artistes)</td></tr></tbody></table>

Log commun : `/var/log/navidrome_scan.log`

### Quick scan vs Full scan

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

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

### Auth RC sur kdrive-music.service

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

Commande de refresh manuel :

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

---

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

### Contexte

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

### Cause

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

### Solution mise en place

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

### Procédure manuelle si besoin

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

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

---

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

### Contexte

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

### Cause

Double problème :

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

### Solution immédiate

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

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

### Solution pérenne

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

---

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

### Contexte

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

### Symptômes

- Symfonium (Subsonic) : erreur "trop d'erreurs, arrêt de lecture" sur tous les appareils portables
- Logs Navidrome : `transport endpoint is not connected` sur 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

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

### Notes

- La propagation `:shared` ne 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érer `vfs/refresh` (avec auth RC) au restart quand le FUSE n'est pas corrompu.

# 20_NodeExporter

## node-exporter

<table id="bkmrk-imageprom%2Fnode-expor"><tbody><tr><th>Image</th><td>`prom/node-exporter:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>gemini\_grafana</td></tr><tr><th>Reseau</th><td>gemini\_grafana\_monitor\_net</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip91009"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>9100</td><td>9100/tcp</td><td>0.0.0.0</td></tr><tr><td>9100</td><td>9100/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/proc`</td><td>`/host/proc`</td><td>bind</td><td>ro</td></tr><tr><td>`/sys`</td><td>`/host/sys`</td><td>bind</td><td>ro</td></tr><tr><td>`/`</td><td>`/rootfs`</td><td>bind</td><td>ro</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>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.</td></tr></tbody></table>

### 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

<table id="bkmrk-imageprom%2Fprometheus"><tbody><tr><th>Image</th><td>`prom/prometheus:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>gemini\_grafana</td></tr><tr><th>Reseau</th><td>gemini\_grafana\_monitor\_net</td></tr><tr><th>Source</th><td>[https://github.com/prometheus/prometheus](https://github.com/prometheus/prometheus)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip90909"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>9090</td><td>9090/tcp</td><td>0.0.0.0</td></tr><tr><td>9090</td><td>9090/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/opt/monitoring/prometheus.yml`</td><td>`/etc/prometheus/prometheus.yml`</td><td>bind</td><td>ro</td></tr><tr><td>`/opt/monitoring/prometheus_data`</td><td>`/prometheus`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>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.</td></tr></tbody></table>

### 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

<table id="bkmrk-imagecodeberg.org%2Fre"><tbody><tr><th>Image</th><td>`codeberg.org/readeck/readeck:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>readeck</td></tr><tr><th>Reseau</th><td>readeck\_default</td></tr><tr><th>URL</th><td>[https://readeck.juxjux.ovh](https://readeck.juxjux.ovh)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip45678"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>4567</td><td>8000/tcp</td><td>0.0.0.0</td></tr><tr><td>4567</td><td>8000/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/home/debian/readeck/exports`</td><td>`/exports`</td><td>bind</td><td>rw</td></tr><tr><td>``</td><td>`/readeck`</td><td>volume</td><td>rw</td></tr><tr><td>`/home/debian/readeck/data`</td><td>`/readeck/data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:#008000;">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__readeck__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_readeck.py | Auth : token API Bearer (MFA actif sur le compte web)</td></tr></tbody></table>

### Outils disponibles

- `get_bookmarks`
- `get_bookmark`
- `create_bookmark`
- `update_bookmark`
- `delete_bookmark`
- `get_labels`
- `get_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

<table id="bkmrk-script%2Fopt%2Fbackups%2Fv"><tbody><tr><th>Script</th><td>`/opt/backups/vps_backup.sh`</td></tr><tr><th>Cron</th><td>Tous les jours à 2h du matin (`0 2 * * *`)</td></tr><tr><th>Type base</th><td>SQLite — `/readeck/data/db.sqlite3` (dans le container)</td></tr><tr><th>Méthode</th><td>`docker cp readeck:/readeck/data/db.sqlite3`</td></tr><tr><th>Taille base</th><td>~8.5 Mo</td></tr><tr><th>Format archive</th><td>.7z (compression niveau 5)</td></tr><tr><th>Destination</th><td>kDrive Infomaniak — `TOOJUX/jux_vps/readeck` (dossier ID 1427922)</td></tr><tr><th>Rétention</th><td>7 jours glissants</td></tr><tr><th>Nommage fichier</th><td>`readeck_db_YYYY-MM-DD.7z`</td></tr></tbody></table>

### 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

<table id="bkmrk-imagesyncthing%2Fsynct"><tbody><tr><th>Image</th><td>`syncthing/syncthing:latest`</td></tr><tr><th>Version</th><td>v2.0.14</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>syncthing</td></tr><tr><th>Reseau</th><td>syncthing\_syncthing\_net</td></tr><tr><th>URL</th><td>[https://syncthing.juxjux.ovh](https://syncthing.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/syncthing/syncthing](https://github.com/syncthing/syncthing)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip21027"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>21027</td><td>21027/udp</td><td>0.0.0.0</td></tr><tr><td>21027</td><td>21027/udp</td><td>::</td></tr><tr><td>22000</td><td>22000/tcp</td><td>0.0.0.0</td></tr><tr><td>22000</td><td>22000/tcp</td><td>::</td></tr><tr><td>22000</td><td>22000/udp</td><td>0.0.0.0</td></tr><tr><td>22000</td><td>22000/udp</td><td>::</td></tr><tr><td>8384</td><td>8384/tcp</td><td>0.0.0.0</td></tr><tr><td>8384</td><td>8384/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>``</td><td>`/var/syncthing`</td><td>volume</td><td>rw</td></tr><tr><td>`/home/debian/Documents`</td><td>`/var/syncthing/Documents`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/Public`</td><td>`/var/syncthing/Public`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/syncthing/config`</td><td>`/var/syncthing/config`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/syncthing/data1`</td><td>`/var/syncthing/data1`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/syncthing/data2`</td><td>`/var/syncthing/data2`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/joplin-data`</td><td>`/var/syncthing/joplin-data`</td><td>bind</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — MCP

<table id="bkmrk-statut-mcpmcp-actifo"><tbody><tr><th>Statut MCP</th><td><span style="color:green">MCP actif</span></td></tr><tr><th>Outils (prefix)</th><td>`mcp__syncthing__`</td></tr><tr><th>Configuration</th><td>Script Python : C:\\Users\\eliob\\.claude\\mcp\_syncthing.py | Auth : clé API dans header X-API-Key</td></tr></tbody></table>

### Outils disponibles

- `ping`
- `get_status`
- `get_version`
- `get_devices`
- `get_device_stats`
- `get_folders`
- `get_folder_status`
- `get_folder_stats`
- `get_folder_errors`
- `get_connections`
- `get_completion`
- `pause_device`
- `resume_device`
- `scan_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

<table id="bkmrk-imageyourls%3Alatestet"><tbody><tr><th>Image</th><td>`yourls:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours</span></td></tr><tr><th>Compose project</th><td>yourls</td></tr><tr><th>Reseau</th><td>yourls\_default</td></tr><tr><th>URL</th><td>[https://yourls.juxjux.ovh](https://yourls.juxjux.ovh)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip80858"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8085</td><td>80/tcp</td><td>0.0.0.0</td></tr><tr><td>8085</td><td>80/tcp</td><td>::</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/lib/docker/volumes/yourls_yourls_plugins/_data`</td><td>`/var/www/html/user/plugins`</td><td>volume</td><td>rw</td></tr><tr><td>`/home/debian/docker/yourls/ports.conf`</td><td>`/etc/apache2/ports.conf`</td><td>bind</td><td>rw</td></tr><tr><td>`/home/debian/docker/yourls/000-default.conf`</td><td>`/etc/apache2/sites-available/000-default.conf`</td><td>bind</td><td>rw</td></tr><tr><td>`/var/lib/docker/volumes/yourls_yourls_html/_data`</td><td>`/var/www/html`</td><td>volume</td><td>rw</td></tr><tr><td>`/var/lib/docker/volumes/yourls_yourls_user/_data`</td><td>`/var/www/html/user`</td><td>volume</td><td>rw</td></tr></tbody></table>

---

## yourls-db

<table id="bkmrk-imagemysql%3A8.0etatup"><tbody><tr><th>Image</th><td>`mysql:8.0`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up 9 hours (healthy)</span></td></tr><tr><th>Compose project</th><td>yourls</td></tr><tr><th>Reseau</th><td>yourls\_default</td></tr><tr><th>URL</th><td>[https://yourls.juxjux.ovh](https://yourls.juxjux.ovh)</td></tr></tbody></table>

### Volumes

<table id="bkmrk-source-%28hote%29destina-1"><thead><tr><th>Source (hote)</th><th>Destination</th><th>Type</th><th>Mode</th></tr></thead><tbody><tr><td>`/var/lib/docker/volumes/yourls_yourls_mysql_data/_data`</td><td>`/var/lib/mysql`</td><td>volume</td><td>rw</td></tr></tbody></table>

---

## Integration Claude Code — API directe

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:orange">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>API REST Yourls sur /yourls-api.php. Auth : signature HMAC ou token. Pas de MCP configuré — appels directs possibles.</td></tr></tbody></table>

### 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*

<table id="bkmrk-imagestirlingtools%2Fs"><tbody><tr><th>Image</th><td>`stirlingtools/stirling-pdf:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (healthy)</span></td></tr><tr><th>Compose project</th><td>stirlingpdf</td></tr><tr><th>Reseau</th><td>stirlingpdf\_default</td></tr><tr><th>URL</th><td>[https://spdf.juxjux.ovh](https://spdf.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/Stirling-Tools/Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip80908"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>8090</td><td>8080/tcp</td><td>0.0.0.0</td></tr></tbody></table>

### Variables

<table id="bkmrk-variablevaleurdocker"><thead><tr><th>Variable</th><th>Valeur</th></tr></thead><tbody><tr><td>DOCKER\_ENABLE\_SECURITY</td><td>false</td></tr><tr><td>LANGS</td><td>fr\_FR</td></tr></tbody></table>

### Volumes

<table id="bkmrk-hotecontainer%2Fopt%2Fst"><thead><tr><th>Hote</th><th>Container</th></tr></thead><tbody><tr><td>/opt/stirling-pdf/configs</td><td>/configs</td></tr><tr><td>/opt/stirling-pdf/logs</td><td>/logs</td></tr></tbody></table>

---

## 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

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:#FFA500;">Pas de MCP — API directe possible</span></td></tr><tr><th>Note technique</th><td>API REST sur /api — scriptable via PowerShell/Python httpx.</td></tr></tbody></table>

### 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*

<table id="bkmrk-imagejlesage-jdownlo"><tbody><tr><th>Image</th><td>`jlesage/jdownloader-2:latest`</td></tr><tr><th>Etat</th><td><span style="color:#008000;">Up (running)</span></td></tr><tr><th>Compose project</th><td>jdownloader</td></tr><tr><th>Reseau</th><td>jdownloader\_default</td></tr><tr><th>URL</th><td>[https://jdownloader.juxjux.ovh](https://jdownloader.juxjux.ovh)</td></tr><tr><th>Source</th><td>[https://github.com/jlesage/docker-jdownloader-2](https://github.com/jlesage/docker-jdownloader-2)</td></tr></tbody></table>

### Ports

<table id="bkmrk-hotecontainerip58005"><thead><tr><th>Hote</th><th>Container</th><th>IP</th></tr></thead><tbody><tr><td>5800</td><td>5800/tcp</td><td>127.0.0.1</td></tr></tbody></table>

### Variables

<table id="bkmrk-variablevaleuruser-i"><thead><tr><th>Variable</th><th>Valeur</th></tr></thead><tbody><tr><td>USER\_ID</td><td>1000</td></tr><tr><td>GROUP\_ID</td><td>1000</td></tr><tr><td>TZ</td><td>Europe/Paris</td></tr></tbody></table>

### Volumes

<table id="bkmrk-hotecontaineropt-jd"><thead><tr><th>Hote</th><th>Container</th></tr></thead><tbody><tr><td>/opt/jdownloader/config</td><td>/config</td></tr><tr><td>/home/debian/downloads</td><td>/output</td></tr></tbody></table>

---

## Notes

- Interface noVNC accessible via navigateur — pas besoin de client VNC
- Port 5800 lié à `127.0.0.1` uniquement — 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

<table id="bkmrk-statut-mcppas-de-mcp"><tbody><tr><th>Statut MCP</th><td><span style="color:#FFA500;">Pas de MCP — interface web uniquement (noVNC)</span></td></tr><tr><th>Note technique</th><td>Pas d'API REST publique documentée. Pilotage uniquement via l'interface graphique.</td></tr></tbody></table>

### 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/downloads` via 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)

```yaml
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: host` est 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) :

```yaml
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 fichier **`id_ed25519.pub`** contient 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.ovh` ou l'IP directe)
  - **Relay Server** : peut rester vide (déduit automatiquement, sinon `IP:21117`)
  - **Key** : contenu de `id_ed25519.pub`
- 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 bugcheck **`0x50` (PAGE_FAULT_IN_NONPAGED_AREA)**, dump complet dans `C:\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 driver `usbmmidd` (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-Power` event 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) :

```powershell
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.exe` actif, 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 |

```bash
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) :

```yaml
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 :

```nginx
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 base `db.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é

- [x] Aucun mot de passe `CHANGE_ME_...` en production — la bascule vers SQLite a supprimé les identifiants MariaDB du compose
- [x] HTTPS forcé sur les deux vhosts (redirection 80 vers 443)
- [x] Certificats Let's Encrypt valides, renouvellement automatique certbot en place
- [x] Découverte DAV forcée en HTTPS (§6.3)
- [x] Les deux containers n'écoutent que sur `127.0.0.1` — seul nginx les expose
- [x] 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

```bash
# É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

```bash
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 :

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

Swap par processus :

```bash
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/libraries` renvoie bien les bibliothèques
- StirlingPDF : `compress-pdf` OK (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.

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

---

## 3. OCR StirlingPDF impossible sur les images PNG

### Symptôme

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

### Deux refus cumulés d'ocrmypdf 17.4.0

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

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

### Solution sans outil (interface web)

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

### Solution scriptée

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

```bash
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` — multipart `fileInput`, champs `languages` (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** :

```bash
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_postgis` tourne et `pg_isready` ré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 :

```bash
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 base `recherches` sur Alteris)
- Page **208** — 25_StirlingPDF
- `CLAUDE.md` du projet : sections « Swap », « Alléger Komga », « Alléger StirlingPDF », StirlingPDF/OCR