Installer Audiobookshelf avec Docker et Caddy

This article is also available in English

Audiobookshelf (ABS pour les intimes) est un serveur auto-hébergé de livres audio et de podcasts. On lui donne un dossier, il en fait une bibliothèque propre, avec les jaquettes, les chapitres et la progression d'écoute synchronisée entre tous vos appareils. Côté podcasts, il s'abonne aux flux et télécharge les nouveaux épisodes tout seul. C'est un peu le Plex des livres audio, et il tourne chez moi depuis un bon moment.

Il est multi-utilisateurs, vous pourrez en faire profiter vos amis et membres de votre famille.

1. Ce qu'il faut avant de commencer

  • un serveur avec Docker et le plugin docker compose ;
  • un nom de domaine dont un enregistrement DNS pointe vers ce serveur (dans les exemples : abs.example.com) ;
  • les ports 80 et 443 ouverts vers le serveur : Caddy en a besoin pour obtenir son certificat Let's Encrypt.

2. Un réseau Docker partagé

Plutôt que de publier le port d'Audiobookshelf sur l'hôte et de faire pointer Caddy dessus, je mets les deux conteneurs sur un même réseau Docker. Caddy joint alors ABS par le nom de son conteneur, et rien d'autre n'est exposé que les ports 80 et 443 de Caddy. Ce réseau est créé une fois pour toutes, à la main :

docker network create front_network

Il est déclaré external dans chaque compose.yml : il doit donc exister avant le premier up, sinon la stack refuse de démarrer.

3. Le compose d'Audiobookshelf

Dans un dossier dédié, par exemple ~/docker/audiobookshelf/, un fichier compose.yml :

services:
  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf
    restart: unless-stopped
    # Pas d'élévation de privilèges à l'intérieur du conteneur
    security_opt:
      - no-new-privileges:true
    # « Le service répond », et pas seulement « le conteneur tourne »
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:$${PORT:-80}/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    volumes:
      - /media/mediatheque/Livres Audios:/audiobooks
      - /media/mediatheque/Podcasts:/podcasts
      - ./config:/config
      - ./metadata:/metadata
    environment:
      - TZ=Europe/Paris
    networks:
      - front_network

networks:
  front_network:
    external: true

Quelques explications :

  • /audiobooks et /podcasts : vos médias. Le nom à l'intérieur du conteneur est libre, c'est lui que vous choisirez en créant les bibliothèques. ABS doit pouvoir écrire dans le dossier des podcasts, puisqu'il y télécharge les épisodes.
  • /config : la base de données (un fichier SQLite) et la configuration. C'est le dossier à ne surtout pas perdre.
  • /metadata : jaquettes, cache, journaux et sauvegardes internes d'ABS.
  • Aucune section ports : c'est voulu, Caddy passe par le réseau partagé. Si vous voulez aussi y accéder directement depuis le LAN (une appli qui ne passe pas par le nom de domaine, par exemple), ajoutez ports: ["13378:80"].

Évitez par ailleurs de mettre /config sur un partage réseau (NFS, SMB) : SQLite supporte très mal les systèmes de fichiers réseau. Les médias, eux, peuvent très bien y être.

4. Premier démarrage : créer le compte root AVANT d'ouvrir l'accès

C'est le piège le plus important de l'article. Au premier lancement, Audiobookshelf affiche une page d'initialisation qui demande de choisir le mot de passe du compte root. Cette page est accessible à n'importe qui tant que personne ne l'a remplie. Si vous publiez le site sur Internet avant de l'avoir fait, le premier visiteur venu (ou un robot qui scanne les nouveaux certificats, et ils sont rapides) devient administrateur de votre instance.

Donc on démarre d'abord le conteneur sans route Caddy :

docker compose -f ~/docker/audiobookshelf/compose.yml up -d

et on initialise l'instance en local. Sans port publié, le plus simple est de récupérer l'IP du conteneur et d'ouvrir un tunnel SSH depuis son poste :

# sur le serveur
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' audiobookshelf

# sur votre poste (remplacez l'IP par celle obtenue)
ssh -L 13378:172.18.0.5:80 moi@mon-serveur

On se rend alors sur http://localhost:13378, on choisit le mot de passe root, et seulement ensuite on passe à Caddy. On peut vérifier à tout moment si l'instance est initialisée : la route /status renvoie "isInit": true une fois le compte root créé.

5. Le bloc Caddy

Le compose de Caddy doit lui aussi rejoindre front_network. Ensuite, dans le Caddyfile, trois lignes suffisent :

abs.example.com {
	reverse_proxy audiobookshelf:80
}

Et c'est tout. Caddy se charge seul du certificat HTTPS (obtention et renouvellement) et de la redirection du HTTP vers le HTTPS.

On recharge caddy :

docker compose -f ~/docker/caddy/compose.yml restart caddy

Cela peut prendre quelques dizaines de secondes, le temps que le certificat SSL soit provisionné.

6. Créer ses bibliothèques

Une fois connecté en root sur https://abs.example.com : Paramètres / Bibliothèques / Nouvelle bibliothèque. On choisit le type (Livres ou Podcasts) et on désigne le dossier vu depuis le conteneur : /audiobooks ou /podcasts, pas le chemin de l'hôte.

Pour les livres audio, ABS s'en sort le mieux avec une arborescence Auteur/Titre/fichiers (ou Auteur/Série/Titre/). Il sait aller chercher les métadonnées et les jaquettes en ligne (Audible, Google Books…) via le mode match, très pratique.

7. Les applis

Il existe une application mobile officielle, et quelques applis tierces utilisent l'API d'Audiobookshelf. Côté podcasts, j'ai fini par écrire la mienne, je vous en reparle bientôt). Dans tous les cas, on renseigne l'URL du serveur (https://abs.example.com) et ses identifiants.

8. Mises à jour et sauvegardes

La mise à jour, c'est le classique :

docker compose -f ~/docker/audiobookshelf/compose.yml pull
docker compose -f ~/docker/audiobookshelf/compose.yml up -d

Pour les sauvegardes, deux possibilités qui se complètent :

  • Les sauvegardes intégrées (Paramètres / Sauvegardes) : ABS archive régulièrement sa base et ses métadonnées dans /metadata/backups. Pratique, mais elles vivent sur le même disque que l'original : à copier ailleurs.
  • Une copie du fichier SQLite : on arrête le conteneur, on copie config/absdatabase.sqlite, on le relance. Copier une base SQLite pendant qu'elle est utilisée peut donner une copie incohérente, d'où l'arrêt : quelques secondes de coupure, la nuit, personne ne s'en rend compte.
cd ~/docker/audiobookshelf
docker compose stop audiobookshelf
cp config/absdatabase.sqlite ~/backups/abs-$(date +%F).sqlite
docker compose up -d audiobookshelf

Les médias, eux, se sauvegardent avec le reste de votre médiathèque.

Pour conclure

Une vingtaine de lignes de YAML, trois lignes de Caddyfile, et on a un serveur de livres audio et de podcasts en HTTPS, synchronisé entre tous ses appareils. Les deux points à retenir : on crée le compte root avant d'ouvrir l'accès, et on sauvegarde avant chaque mise à jour.

Testé avec Audiobookshelf 2.37.1 et Caddy 2.

Écrit par Kevin Gautreau — développeur & formateur PHP/Drupal freelance en Auvergne. me contacter

Commentaires (0)