Je me suis récemment décidé à abandonner mon fidèle Subsonic 5.x (dont j'avais parlé en 2011, déjà !) car, étant basé sur le lecteur Flash qui semble enfin vivre ses derniers mois, j'ai eu peur que mon lecteur de streaming auto-hébergé préféré ne soit plus utilisable d'un jour à l'autre.
J'apprécie énormément cette application malgré ses quelques défauts et n'ai trouvé aucune alternative intéressante depuis que je l'ai installée la première fois sur mon serveur Usul en 2010 (qui tournait sur un Atom 230 à l'époque). J'avais même fait un don de 20€ à l'auteur pour le remercier et accessoirement obtenir une licence valide, du temps où celle-ci était accessible sans montant minimum, et où elle ne donnait simplement droit qu'à une adresse en *.subsonic.org pour la redirection (dont je n'avais par ailleurs aucune utilité puisque j'avais déjà ma redirection DNS en place).
Au fil des versions les améliorations ont continué à arriver, puis vint la refonte de la série 6.x.
Je l'ai testée, mais la nouvelle navigation ne me convenait pas. Et le nouveau système de licence mensuelle pour se débarrasser des pubs, rétablir le streaming des vidéos et pouvoir utiliser les apps mobiles n'a rien arrangé. D'autant que le code passait sous licence propriétaire alors qu'il avait été jusque-là sous licence libre.
Bref, Subsonic 6, ce n'était pas pour moi. Et j'ai laissé traîné un moment en profitant du répit de Flash qui me permettait de continuer à utiliser mon vieux Subsonic 5 sur mon serveur.
Puis j'ai découvert Airsonic, qui est simplement un fork du code de Subsonic 5, repris par la communauté, et qui continue tranquillement à évoluer sous licence libre.
Là, j'ai décidé d'y regarder de plus près, car cela avait un attrait crucial d'après moi par rapport aux alternatives que j'avais prospectées en prévision d'un inévitable remplacement (Ampache et Owncloud, puis Funkwhale le dernier) : pouvoir conserver la totalité des données de Subsonic ! (configuration, mais aussi playlists et favoris) Ainsi que la même application mobile ! (qui fonctionne très bien)
Dockerisons mes bons
Depuis la révolution que représente l'arrivée de Docker dans l'écosystème GNU/Linux (et pas que, mais principalement), j'opte très facilement pour la mise en place d'applications sur mon serveur via des containers Docker au lieu d'installer "en dur" celles-ci sur le système.
Les gains sont évidents :
- toutes les dépendances sont embarquées dans l'image (donc indépendante du système hôte, qui peut dont plus facilement être mis à jour, voire monté en version),
- un contrôle des ressources facilité, pile applicative par pile applicative,
- la mise à jour des applications en elles-mêmes est généralement d'une simplicité enfantine : docker pull && docker start (en gros),
- le risque de données éparpillées dans le système hôte réduit, donc un nettoyage réduit au minimum en cas de désinstallation.
Bien sûr, cela ne va pas sans quelques inconvénients, mais ils sont limités en comparaison des gains (un overhead supplémentaire, une dépendance à Docker et parfois des bugs spécifiques à ce mode d'exécution).
Avec Airsonic, l'idée était donc dès le départ d'installer ce serveur dans un container propre, afin notamment de ne pas dépendre d'une version de Java ou de ffmpeg spécifique sur l'hôte (ce qui d'expérience, m'avait valu quelques noeuds au cerveau quand j'étais encore sur Debian 6).
Coup de "chance" : le projet propose par défaut une image Docker du serveur... comme environ 95% des projets aujourd'hui, en fait. Il ne s'agira donc plus que de configurer l'ensemble et de migrer les données. Coup de chance (un vrai cette fois) : une procédure détaillée existe pour migrer les données de Subsonic 5 vers Airsonic très facilement. Il me suffira d'adapter ça à ma config Docker. Voyons la procédure.
Préparation de l'hôte
Subsonic possède actuellement un dossier /var/subsonic qui contient sa configuration ainsi que données travail (logs, etc.). Je vais donc réserver un dossier /var/airsonic.docker sur l'hôte qui contiendra la configuration Docker de son remplaçant, dans lequel un dossier data contiendra les données de l'application en elle-même, et playlists pour... les playlists. De cette manière, je serai toujours à temps de faire machine arrière en cas de problème.
# mkdir -p /var/airsonic.docker/{data,playslists}
Je vais également créer un utilisateur Unix dédié, appelé airsonic, auquel je donnerai les permissions nécessaires sur le dossier nouvellement créé.
# useradd --base-dir /var/airsonic.docker \
--home-dir /var/airsonic.docker \
--no-create-home \
airsonic
# chown -R airsonic /var/airsonic.docker
Ceci fait, on crée le fichier /var/airsonic.docker/docker-compose.yml qui contiendra toute la configuration du futur container Docker pour Airsonic, de manière à faciliter sa mise à jour et sa maintenance.
# Fichier /var/airsonic.docker/docker-compose.yml
version: '3.2'
services:
app:
image: airsonic/airsonic:10.1.2-RELEASE
container_name: airsonic
restart: always
user: '1018'
ports:
- '4040:4040'
volumes:
- /mnt/music:/mnt/music:ro
- /mnt/videos:/mnt/videos:ro
- ./playlists:/airsonic/playlists:rw
- ./data:/airsonic/data:rw
Qu'est-ce qui est important ici ?
- nom du container : airsonic
- redémarrage automatique au reboot de l'hôte (restart: always)
- utilisateur 1018 (ID de l'utilisateur airsonic que je viens de créer)
- mapping du port 4040 de l'hôte vers 4040 du container (accès HTTP)
- montage des volumes /mnt/music et /mnt/videos dans les dossiers équivalents dans le container
Le dernier point est crucial pour être sûr de récupérer de manière totalement transparente les données utilisateurs de la médiathèque déjà présente sur Subsonic (notes, favoris et playlists) : ce sont en effet les emplacements des Media Folders de ce dernier (sur mon installation, je précise).
De cette manière, et comme Airsonic va reprendre la base de données de Subsonic, les chemins des medias ne changeront pas d'un pouce et seront immédiatement valides même dans le nouveau container Docker.
On stoppe à présent Subsonic et on synchronise son dossier vers Airsonic, puis on renomme les fichiers subsonic* en airsonic* selon les instructions de la doc. Pour cela, je crée un fichier migration-sync-from-subsonic.txt dans le dossier d'Airsonic qui listera les fichiers à migrer. Le but étant de limiter le nombre de commandes à taper de manière à pouvoir plus facilement répéter l'opération si des ajustements sont nécessaires avant la vraie bascule.
# Fichier /var/airsonic.docker/migration-sync-from-subsonic.txt
subsonic_sh.log
subsonic.log
subsonic.properties
db/subsonic.backup
db/subsonic.data
db/subsonic.lck
db/subsonic.log
db/subsonic.properties
db/subsonic.script
# systemctl stop subsonic.service
# cd /var/airsonic.docker
# rsync -av --files-from=migration-sync-from-subsonic.txt --chown airsonic:root /var/subsonic/ /var/airsonic.docker/data/
# find /var/airsonic.docker/data/ -name "*subsonic*" -exec rename -v 's/subsonic/airsonic/' {} \;
Tout est normalement prêt à présent pour lancer Airsonic. Une mise à jour de la base sera réalisée au premier lancement, et une réindexation complète des medias est conseillée, mais normalement tout devrait "juste marcher".
On surveillera éventuellement les logs une fois le container lancé en arrière-plan.
# docker-compose up -d
# docker-composer -f logs
Me concernant, j'avais déjà configuré Apache en reverse-proxy SSL/TLS, et n'ai donc rien de plus à faire car le port est inchangé par rapport à Subsonic. Tout marche donc directement !
Et voilà Airsonic qui prend le relai, presque sans coupure de service, en tout cas, sans perturber les utilisateurs (dont les comptes ont bien sûr été conservés). Merci Airsonic et merci Docker :)