¿Por qué alojar tu biblioteca de audio?
Las plataformas de audiolibros imponen sus catálogos, su DRM y sus cuotas mensuales. Con Audiobookshelf importas tus propios archivos M4B, MP3 o FLAC — comprados, prestados o producidos por ti — y accedes a ellos desde cualquier dispositivo con las apps móviles de código abierto. La biblioteca crece a tu ritmo, no al suyo.
Lo que aporta Audiobookshelf en un VPS de ServOrbit
- Streaming y sincronización — retoma un audiolibro donde lo dejaste, en la web o en el móvil, sin cuenta cloud de terceros.
- Apps iOS y Android de código abierto — los clientes oficiales son GPL-3.0, auditables y mantenidos por la comunidad.
- Copias de seguridad programadas integradas — el servidor puede generar por sí mismo un archivo de su base de datos y sus metadatos, con retención ajustable.
- Podcasts integrados — suscríbete a feeds RSS; los episodios se descargan automáticamente y se reproducen en la misma interfaz.
- Multiusuario — cada miembro de la familia tiene su cuenta, su historial y sus listas de reproducción.
- Metadatos automáticos — portadas, capítulos y descripciones pueden obtenerse de proveedores como Audnexus, sin escribir nada a mano.
Formatos de audio compatibles
Audiobookshelf reproduce los formatos habituales, entre ellos MP3, M4A, M4B (con capítulos), AAC, OGG, FLAC, WAV y OPUS. Los capítulos M4B aparecen en el reproductor con su título y su duración. Los archivos de Audible protegidos con DRM no se reproducen tal cual: importa solo archivos que tengas derecho a usar, en un formato abierto.
Requisitos y dimensionado
El servidor en sí es modesto: un VPS Ubuntu 24.04 con Docker basta para una familia. Lo que pesa es el disco, porque la biblioteca (sobre todo los episodios de podcast, que se descargan con el tiempo) crece sin parar, y la CPU solo cuando un cliente pide transcodificación con ffmpeg en lugar de reproducción directa. Dimensiona el volumen de datos según tu colección y deja margen para metadatos, portadas y copias de seguridad, que por defecto viven en el mismo volumen /metadata.
La base SQLite del servidor debe permanecer en el disco local del VPS. La documentación de Audiobookshelf es explícita: la carpeta /config no debe montarse sobre un recurso de red, o te expones a lentitud y luego a corrupción. Los archivos de audio sí pueden estar en otro sitio.
Desplegar Audiobookshelf con Docker Compose
Preparar el VPS y Docker
Conéctate por SSH, actualiza el sistema e instala Docker y el plugin Compose. Comprueba con
docker compose version. En un VPS de ServOrbit, la plantilla de Audiobookshelf hace estos pasos por ti: esta guía sirve para entender qué se ejecuta y retomar el control.Crear las carpetas y fijar el propietario
Crea una carpeta por volumen:
mkdir -p /opt/audiobookshelf/{config,metadata,audiobooks,podcasts}. Elige el usuario con el que correrá el contenedor (por ejemplo 1000:1000) y entrégale las carpetas:chown -R 1000:1000 /opt/audiobookshelf. Las cuatro carpetas deben ser puntos de montaje distintos, sin anidarse.Escribir el docker-compose.yml
Declara un servicio
audiobookshelfcon la imagenghcr.io/advplyr/audiobookshelf(fija la etiqueta de la versión que hayas comprobado en lugar delatest),restart: unless-stopped, la directivauser: "1000:1000", el puerto127.0.0.1:13378:80y los cuatro montajes/opt/audiobookshelf/config:/config,/opt/audiobookshelf/metadata:/metadata,/opt/audiobookshelf/audiobooks:/audiobooksy/opt/audiobookshelf/podcasts:/podcasts. AñadeTZ=Africa/Casablanca(o tu zona horaria) como variable de entorno. Audiobookshelf no usa las variables PUID y PGID: la directivauser:fija el usuario.Arrancar y comprobar
Ejecuta
docker compose up -dy luegodocker compose logs -f audiobookshelf. En el primer arranque el servidor aplica sus migraciones de base de datos: espera la línea que anuncia que escucha en el puerto 80 del contenedor. Sidocker compose psmuestra el servicio reiniciándose sin parar, ve directamente a la sección de resolución de problemas.Crear la cuenta de administrador y la biblioteca
Abre la interfaz (por túnel SSH o con tu dominio), crea la cuenta root y añade una biblioteca que apunte a
/audiobooksy otra a/podcasts. Lanza un escaneo: los libros aparecen con sus portadas y capítulos.Conectar la app móvil
En la app iOS o Android, introduce la dirección HTTPS de tu instancia, tu usuario y tu contraseña. El progreso se sincroniza entonces entre el teléfono y la web. Para un uso permanente, coloca un proxy inverso HTTPS delante del contenedor siguiendo la página «Reverse Proxy» de la documentación de Audiobookshelf (en particular el paso de los WebSocket).
Configuración sin nombre de dominio
Audiobookshelf no necesita un nombre de dominio para funcionar. Con la plantilla de ServOrbit, el contenedor solo escucha en el loopback del VPS, puerto 13780. Abre un túnel SSH desde tu equipo: ssh -L 13378:127.0.0.1:13780 root@<ip-vps> y entra en http://localhost:13378. Para un uso permanente desde la app móvil, asocia un dominio desde tu área de cliente de ServOrbit — nginx hace de proxy del contenedor en HTTPS — o usa el subdominio gratuito {app}.{dns_slug}.servorbit-dns.com incluido con cada VPS.
Permisos de los volúmenes y usuario no root
Cuatro volúmenes, cuatro funciones. /config contiene la base SQLite y los scripts de migración. /metadata contiene los metadatos, las portadas, las imágenes de autores, los registros, la caché y, por defecto, las copias de seguridad. /audiobooks y /podcasts dan acceso a los archivos multimedia. El servidor debe poder escribir en /config y /metadata; en /audiobooks, la escritura solo hace falta si quieres que escriba metadatos junto a los archivos, y en /podcasts es imprescindible porque ahí se descargan los episodios.
Por defecto, el ejemplo oficial no fija ningún usuario. Para endurecer, añade la directiva user:: el contenedor deja de tener derechos de root sobre los montajes, y ahí es justo donde aparecen los errores de permisos. La regla es simple: el propietario de las carpetas del host debe ser el UID:GID de la directiva user:. Prueba antes de cargar la biblioteca: docker compose exec audiobookshelf touch /config/test /metadata/test y borra después los dos archivos.
En un sistema de archivos con ACL (ZFS con ACL NFSv4, por ejemplo), un chown no siempre basta: el incidente descrito más abajo lo ilustra, con un contenedor como usuario 568, sin ninguna capacidad, sobre un dataset ZFS.
Volumen con nombre o carpeta del host para /config y /metadata
Desplace la tabla
| Criterio | Volumen con nombre de Docker | Carpeta del host |
|---|---|---|
| Propietario inicial | Gestionado por Docker, a menudo root | Lo fijas tú con chown |
| Compatibilidad con `user:` | Comprobar antes de la primera importación | Directa, si el UID:GID coincide |
| Copia en frío | Usar `docker volume inspect` para hallar la ruta | `rsync` directo de la carpeta |
| Legibilidad de la ruta | Menos evidente | Ruta fija y conocida |
| Portabilidad a otro VPS | Prever la exportación del volumen | Copiar la carpeta |
| Uso recomendado | Prueba rápida, plantilla lista para usar | Producción con usuario no root |
Copias de seguridad coherentes: qué cubre la copia integrada
Audiobookshelf puede crear sus propias copias desde la interfaz (programación, número de copias conservadas, tamaño máximo). Cada archivo contiene la base de datos y las imágenes de portada de la carpeta de metadatos; los archivos multimedia almacenados con los elementos de la biblioteca no están incluidos. Por defecto, los archivos se escriben en /metadata/backups, es decir, en el mismo disco que los datos: una avería del VPS se lleva ambos. Cópialos con regularidad fuera del servidor.
Una copia solo protege si es coherente. La base es un archivo SQLite vivo: copiar /config con cp o rsync mientras el servidor escribe (progreso de escucha, escaneos) puede producir un archivo incoherente. Dos métodos seguros: usar la copia integrada del servidor y luego copiar el archivo generado; o detener el contenedor durante la copia. Los archivos de audio se respaldan aparte, con rsync o una herramienta de copias con deduplicación.
Una restauración se hace en el mismo tipo de sistema: la documentación advierte de que una copia de Linux se restaura en Linux, y de que pasar de un método de instalación a otro puede hacer perder progreso y metadatos.
Copia en frío y restauración manual
Detener el contenedor
Desde la carpeta del compose, ejecuta
docker compose stop audiobookshelf. Ya no hay escrituras en curso sobre la base.Copiar la configuración y los metadatos
Copia
/opt/audiobookshelf/configy/opt/audiobookshelf/metadataa un destino fuera del VPS conrsync -a, conservando los permisos. Añade las carpetas de audio según tu estrategia de copia de medios.Reiniciar y comprobar
Ejecuta
docker compose start audiobookshelfy comprueba en los registros que el servidor vuelve a escuchar. La interrupción dura lo que tarda la copia de la base.Restaurar desde un archivo del servidor
Detén el contenedor, descomprime el archivo más reciente de
metadata/backups, copiaaudiobookshelf.sqliteen la carpeta de configuración sustituyendo el existente y copia después las carpetasmetadata-authorsymetadata-itemsaauthorseitems. Si el archivo no sirve, prueba el anterior. La página Copias de seguridad de la interfaz también ofrece un botón de restauración.Probar una restauración de ensayo
Una vez por trimestre, restaura una copia en un VPS de pruebas y comprueba que están los usuarios, el progreso y las bibliotecas. Una copia que nunca se restauró sigue siendo una hipótesis.
Actualizaciones y versiones: fijar en lugar de seguir latest
La plantilla de ServOrbit descarga la imagen latest. Es cómodo, pero te expone a regresiones de una versión a otra. La actualización documentada es sencilla: docker compose pull, docker compose down, docker compose up --detach. Antes de cada actualización, haz una copia (integrada o en frío) y lee las notas de versión en la página de releases del repositorio de GitHub.
Un caso reciente lo justifica. La versión 2.37.0 pasó el servidor a Node.js 24, y la 2.37.1 sufrió un bucle de reinicio en algunas instalaciones (ver abajo). La corrección está publicada en la 2.37.2, que es, en el momento de escribir, la última versión estable que lista el proyecto. Una etiqueta fijada y una copia previa permiten volver atrás sin improvisar.
Resolución de problemas: bucle de reinicio al arrancar (EPERM … copyfile)
Síntoma: el contenedor se reinicia en bucle tras actualizar a la 2.37.1, y los registros muestran «Failed to copy migrations to the config directory», luego «EPERM: operation not permitted, copyfile» de la carpeta /app/dist-server/server/migrations/ a /config/migrations/, seguido de «Database migration failed».
Estado real del incidente (issue n.º 5637 del repositorio advplyr/audiobookshelf, abierta en octubre de 2026): está cerrada. Quien la reportó usaba TrueNAS SCALE, un contenedor como usuario 568, sin capacidades y con no-new-privileges, con /config en un dataset ZFS montado como bind mount. Varios usuarios de TrueNAS informaron de lo mismo. La discusión no establece formalmente una causa raíz; una prueba mostró que copyFileSync fallaba con EPERM en ese montaje mientras que escribir un archivo directamente funcionaba con el mismo usuario, y se sospecha una regresión de la copia ligada a Node.js 24. La corrección (PR n.º 5668) añade una alternativa cuando la copia falla; llega en la 2.37.2.
Solución: actualiza a la 2.37.2 o posterior. Si no puedes actualizar enseguida, la solución temporal mencionada en la issue es volver a la 2.36.1 con una copia hecha antes de la actualización. Si el mismo mensaje persiste tras actualizar, revisa el propietario de la carpeta de configuración y las ACL del dataset: ya no es ese error.
Resolución de problemas: la copia nocturna tumba el contenedor (SQLITE_BUSY)
Síntoma: el servidor se detiene a la hora de la copia programada, con «FATAL: [Server] Uncaught exception» y SQLITE_BUSY: database is locked. Con restart: unless-stopped, Docker relanza el contenedor: solo se ve un corte breve, que delata un contador de reinicios distinto de cero (docker inspect --format '{{.RestartCount}}' <contenedor>; sustituye el nombre por el de tu contenedor).
Estado real (issue n.º 4572, abierta en agosto de 2025): sigue abierta. Un colaborador explica la causa: la copia SQLite emite el error de «base ocupada» como un evento sin oyente, que Node.js trata como una excepción no capturada, y no se reintenta. El fallo ocurre cuando otra escritura, por ejemplo un cliente que guarda el progreso de escucha, mantiene el bloqueo más de un segundo durante la copia. La PR n.º 5660 (copia por lotes que reintenta ante el bloqueo y errores de sesión registrados en lugar de provocar el fallo) está abierta y sin fusionar a día de hoy: ninguna versión publicada la contiene. Una PR competidora anterior se cerró a favor de esta.
Mientras tanto, tres paliativos reportados en la issue: alejar la copia de las horas de escucha (mejor el amanecer que la tarde); conservar restart: unless-stopped para que el contenedor vuelva solo; o sustituir la copia integrada por una copia en frío programada en el host, que detiene el contenedor unos instantes. Recordatorio de la documentación: la base debe estar en un disco local, nunca en un recurso de red.
Otros errores frecuentes
- Permission denied en los registros — el propietario de las carpetas del host no coincide con el UID:GID de la directiva
user:. Corrige conchown -Ry reinicia. - Biblioteca vacía tras el escaneo — la ruta de la biblioteca no es la del contenedor. Añade
/audiobookso/podcasts, no una ruta del host. - «Cannot find module '/index.js'» — la documentación señala una caché de imagen obsoleta en algunos gestores de contenedores: recrea el contenedor o el stack tras un
docker compose pull. - La app móvil no conecta — revisa la dirección HTTPS, el certificado y el paso de WebSocket por el proxy inverso; un túnel SSH solo sirve para el navegador.
- Contenedor «unhealthy» — la comprobación de salud consulta el puerto 80 del contenedor: mira
docker compose logspara ver si una migración falla al arrancar.
Endurecimiento mínimo
Fija la etiqueta de la imagen, ejecuta el contenedor con user:, publica el puerto solo en 127.0.0.1 detrás de un proxy inverso HTTPS, copia cada semana los archivos de /metadata/backups fuera del VPS y prueba una restauración. Esta guía se ofrece tal cual: ServOrbit no da soporte a la aplicación en sí.
Ir más lejos
Cuando el servidor esté estable, añade una segunda capa de protección: una copia cifrada de las carpetas de configuración en almacenamiento remoto y una alerta si el contenedor se reinicia más de una vez al día. Sigue las issues citadas aquí: el fallo de la copia habrá que revisarlo de nuevo en cuanto la PR n.º 5660 se fusione y se publique.