La partie 1 s’arrêtait sur un NAS monté, instrumenté, et vide. Voici la suite : la stack media complète — Jellyfin, la suite *arr, qBittorrent, Nextcloud — a déménagé de l’ancien i5 (84 W, 2014) vers gbnas (6 W). Au moment où j’écris, 12 conteneurs tournent depuis plus d’une semaine sans un incident.
données media + appdata media data + appdata
Les configs (SQLite, métadonnées) voyagent avec les données — rien à reconstruire. Configs (SQLite, metadata) travel with the data — nothing to rebuild.
12 conteneurs · linuxserver.io 12 containers · linuxserver.io
Mêmes images, nouveaux chemins de montage — et QuickSync disponible pour Jellyfin. Same images, new mount paths — and QuickSync available for Jellyfin.
jellyfin.* · qbit.* · nextcloud.*
Les hostnames publics ne changent pas — seule la cible interne du tunnel change. The public hostnames don't change — only the tunnel's internal target changes.
docker-compose.yml, up -d, bascule des routes du tunnel.
Les utilisateurs n'ont rien vu — même URLs, même contenu, 14× moins de watts.
The whole stack moved with zero reinstall : rsync, adjusting paths
in docker-compose.yml, up -d, cutting over the tunnel routes.
Users saw nothing change — same URLs, same content, 14× fewer watts.
Le plan a perdu contre le pragmatisme : RAID1, pas RAIDZ1
La partie 1 annonçait fièrement un RAIDZ1 sur 3× 6 To (~12 To utiles). La réalité installée :
sdc 5.5T disk
└─md127 5.5T raid1 /mnt/storage
sdd 5.5T disk
└─md127 5.5T raid1 /mnt/storage
Un miroir mdadm à 2 disques, ~5,5 Tio utiles. Pas de ZFS. Ce qui a fait pencher la balance :
- mdadm est ennuyeux — au sens noble : vingt ans de production, intégré au kernel,
cat /proc/mdstatet c’est diagnostiqué. C’était déjà la techno de l’ancien NAS : migration mentale nulle. - ZFS et ses appétits : la règle d’or ~1 Go de RAM par To gérée se marie mal avec le plafond de 16 Go du N100M (un seul slot SO-DIMM). Entre un ARC affamé et de la RAM pour les conteneurs, j’ai choisi les conteneurs.
- Deux disques en service, des baies libres : le Jonsbo N4 a 6 baies. Commencer en miroir simple et agrandir plus tard (ou basculer vers un vrai RAIDZ quand le besoin et les disques seront là) est plus honnête que d’immobiliser trois disques pour un besoin actuel de ~2 To.
La leçon méta : un plan d’infrastructure est une hypothèse, pas un engagement. Documenter le choix réel et ses raisons vaut mieux que tordre la réalité pour coller au plan publié — c’est exactement pour ça que cette partie 2 existe.
Le découpage final du stockage : NVMe 256 Go pour l’OS (LVM), SSD SATA 500 Go monté sur /mnt pour les volumes applicatifs Docker (configs, bases SQLite, métadonnées), et le miroir 5,5 Tio sur /mnt/storage pour les données.
La migration elle-même : l’avantage Docker Compose
C’est ici que le choix « Ubuntu Server + Docker Compose » de la partie 1 paie. La migration d’une stack Compose, c’est trois opérations sans magie :
rsync -avPdes données media et des dossiers appdata — les bases SQLite de Sonarr/Radarr, les métadonnées Jellyfin, tout voyage avec les fichiers. Rien à exporter, rien à reconstruire.- Adapter les chemins dans le
docker-compose.yml(les montages pointent vers/mnt/storageet le SSD appdata) etdocker compose up -d. - Basculer les routes : les hostnames publics (
jellyfin.*,qbit.*,nextcloud.*…) sont définis dans le dashboard Cloudflare Tunnel et pointaient vers l’IP de l’ancien NAS. Changement de cible vers10.0.0.30— les URLs publiques, les certificats et les accès ne bougent pas d’un pixel.
Le résultat côté docker ps, une semaine plus tard :
jellyfin lscr.io/linuxserver/jellyfin Up 9 days
sonarr lscr.io/linuxserver/sonarr Up 9 days
radarr lscr.io/linuxserver/radarr Up 9 days
bazarr lscr.io/linuxserver/bazarr Up 9 days
prowlarr lscr.io/linuxserver/prowlarr Up 9 days
qbittorrent lscr.io/linuxserver/qbittorrent Up 9 days
flaresolverr flaresolverr/flaresolverr Up 9 days
nextcloud lscr.io/linuxserver/nextcloud Up 8 days
Bonus du gain de puissance : le N100 apporte un QuickSync moderne (décodage AV1, encodage HEVC) — le transcodage Jellyfin se fait désormais en hardware sur l’iGPU, là où le vieil i5 ramait en software sur ses gros profils.
Les invités surprise
Une machine confortable attire les workloads. Deux services ont rejoint la stack sans être dans le plan initial :
- Home Assistant — la domotique méritait mieux qu’une existence précaire ; elle a maintenant un port d’attache stable
- Bookshelf (tracker de lectures, flavor Hardcover) — le genre de petit service qu’on ne déploie jamais « parce qu’il n’y a pas de place où le mettre »
C’est un effet de second ordre des 6 W : la machine tourne 24/7 sans culpabilité énergétique, donc chaque nouveau service a un coût marginal nul.
La boucle est bouclée côté monitoring
Tout ce qui a été câblé en partie 1 couvre désormais une machine qui fait vraiment quelque chose : node_exporter remonte l’I/O du miroir RAID1 dans Grafana (le disque du NAS apparaît dans les audits du cluster), smartctl_exporter surveille la santé des disques qui portent désormais toutes les données, et l’agent Portainer (passé en 2.42.0 au passage) donne la vue conteneurs aux côtés des workloads K3s.
L’ancien NAS est éteint. 84 W → 6 W en continu, soit environ 680 kWh économisés par an — le genre de chiffre qui rend un homelab défendable en cuisine.
Ce qui reste (la vraie partie 3)
Le NAS héberge, mais il ne sert pas encore le cluster :
- Backup offload : déplacer la cible S3 des backups Longhorn (MinIO, aujourd’hui 200 Gi sur le précieux SSD de worker-2) vers le miroir du NAS
backup.sh→ CronJob K8s qui pousse les dumps hors cluster, vers/mnt/storage/backups- StorageClass NFS pour offrir au cluster un stockage orienté capacité, à côté de Longhorn
- La question UPS : des disques mécaniques qui portent tout n’aiment pas les coupures sèches
Ce sera la partie 3 — quand elle sera réellement faite, pas avant. J’ai retenu la leçon du RAIDZ1.