Ir al contenido
  1. Posts/

Audiobookshelf y Kavita: mi biblioteca digital completa en el homelab

·2644 palabras·13 mins
Tabla de contenido

Tengo una confesión: compro más libros de los que leo. Físicos, ebooks, audiolibros, lo que sea. El problema es que los tenía desperdigados por todas partes: Kindle, Audible, Google Play Books, archivos CBZ en carpetas random del NAS.

Hasta que monté Audiobookshelf y Kavita en el homelab. Ahora tengo una biblioteca digital centralizada, accesible desde cualquier dispositivo, con sincronización de progreso y sin depender de Amazon.

Te cuento cómo lo hice, qué aprendí, y por qué creo que es una de las mejores cosas que he montado en el homelab.

El problema: libros por todas partes
#

Mi setup antes era un desastre:

  • Ebooks comprados en Kindle (bloqueados con DRM)
  • PDFs técnicos en Dropbox
  • Cómics en CBZ/CBR en el NAS
  • Audiolibros de Audible (también con DRM)
  • Algunos EPUBs en Calibre que nunca sincronicé

Resultado: para leer algo tenía que acordarme dónde lo había comprado. Para escuchar un audiolibro, Audible era la única opción. Para leer un cómic, tenía que conectarme al NAS con Samba.

Quería algo como Plex pero para libros. Un servidor donde subir todo, organizado, con portadas bonitas, y accesible desde el móvil, tablet o e-reader.

Audiobookshelf: tu propio Audible self-hosted
#

Audiobookshelf es un servidor de audiolibros y podcasts. Piensa en Plex pero específicamente diseñado para audio narrativo.

Lo que me convenció:

  • Interfaz web limpia que funciona en cualquier navegador
  • Apps nativas para iOS y Android
  • Sincronización de progreso entre dispositivos
  • Streaming sin límite de bitrate (adiós compresión de Audible)
  • Metadata automática desde Audible, Google Books, iTunes
  • Gestión de podcasts (aunque yo uso Pocket Casts)

La primera vez que abrí Audiobookshelf y vi mi colección organizada con portadas, narrador, duración y progreso sincronizado entre el móvil y el iPad, supe que no había vuelta atrás.

Kavita: lector de ebooks y cómics con sincronización
#

Kavita es el equivalente para ebooks, manga, cómics y novelas. Lee EPUB, PDF, CBZ, CBR, y hasta archivos de imagen sueltos.

Por qué Kavita y no Calibre-Web:

  • UI moderna que no parece de 2010
  • Progreso de lectura sincronizado entre dispositivos
  • OPDS nativo para conectar e-readers externos
  • Lector web integrado que realmente funciona bien
  • Soporte de series (perfecto para manga)
  • Marcadores y notas guardados en la DB

Calibre es el estándar y lo respeto, pero Kavita se siente como una app moderna. Es lo que usaría alguien que no es sysadmin.

Mi setup: K3s + NFS + Cloudflare Tunnels
#

Lo tengo todo corriendo en un cluster K3s de 3 nodos. Las bibliotecas están en un NAS Synology montado por NFS.

Por qué K3s y no Docker Compose:

  • Tengo múltiples nodos y quiero que los pods se muevan automáticamente si uno cae
  • Persistent volumes compartidos por NFS (los 3 nodos leen la misma biblioteca)
  • Fácil exponer servicios con Ingress
  • Escalabilidad futura (aunque para esto probablemente no lo necesite)

Pero si no tienes K3s, Docker Compose funciona perfectamente. Te muestro ambos.

Estructura de archivos en el NAS
#

Esto es importante. Si lo haces bien desde el principio, Audiobookshelf y Kavita detectan todo automáticamente.

Mi estructura:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/volume1/Biblioteca/
├── Audiobooks/
│   ├── Brandon Sanderson/
│   │   ├── El Archivo de las Tormentas 1 - El Camino de los Reyes/
│   │   │   ├── cover.jpg
│   │   │   ├── 001.mp3
│   │   │   ├── 002.mp3
│   │   │   └── ...
│   │   └── Nacidos de la Bruma 1/
│   │       └── ...
│   └── Patrick Rothfuss/
│       └── ...
├── Ebooks/
│   ├── Ficcion/
│   │   ├── Brandon Sanderson/
│   │   │   ├── El Camino de los Reyes.epub
│   │   │   └── Palabras Radiantes.epub
│   │   └── ...
│   └── Tecnica/
│       ├── Kubernetes in Action.pdf
│       └── Designing Data-Intensive Applications.epub
└── Comics/
    ├── Marvel/
    │   ├── Spider-Man Vol 1/
    │   │   ├── Spider-Man 001.cbz
    │   │   ├── Spider-Man 002.cbz
    │   │   └── ...
    └── Manga/
        └── One Piece/
            └── ...

Reglas que sigo:

  • Carpeta por autor en Audiobooks
  • Subcarpeta por libro con todos los MP3 dentro
  • Portada como cover.jpg en cada carpeta de audiolibro
  • Archivos individuales para ebooks (EPUB/PDF)
  • Carpetas de serie para cómics/manga con archivos CBZ numerados

Con esta estructura, Audiobookshelf detecta automáticamente autor, libro y orden de capítulos. Kavita detecta series y orden de volúmenes.

Audiobookshelf en K3s (mi configuración real)
#

Este es el deployment que uso. Lo tengo en un namespace dedicado ebooks:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: audiobookshelf-config
  namespace: ebooks
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: local-path

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: audiobooks-nfs
spec:
  capacity:
    storage: 500Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.15
    path: /volume1/Biblioteca/Audiobooks
  mountOptions:
    - nfsvers=4.1
    - hard
    - timeo=600

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: audiobooks
  namespace: ebooks
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Gi
  volumeName: audiobooks-nfs

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: audiobookshelf
  namespace: ebooks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: audiobookshelf
  template:
    metadata:
      labels:
        app: audiobookshelf
    spec:
      containers:
      - name: audiobookshelf
        image: ghcr.io/advplyr/audiobookshelf:latest
        ports:
        - containerPort: 80
        env:
        - name: TZ
          value: "Europe/Madrid"
        volumeMounts:
        - name: config
          mountPath: /config
        - name: metadata
          mountPath: /metadata
        - name: audiobooks
          mountPath: /audiobooks
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "1Gi"
            cpu: "500m"
      volumes:
      - name: config
        persistentVolumeClaim:
          claimName: audiobookshelf-config
      - name: metadata
        persistentVolumeClaim:
          claimName: audiobookshelf-config
      - name: audiobooks
        persistentVolumeClaim:
          claimName: audiobooks

---
apiVersion: v1
kind: Service
metadata:
  name: audiobookshelf
  namespace: ebooks
spec:
  selector:
    app: audiobookshelf
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: audiobookshelf
  namespace: ebooks
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - abs.midnightlab.build
    secretName: audiobookshelf-tls
  rules:
  - host: abs.midnightlab.build
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: audiobookshelf
            port:
              number: 80

Lo importante aquí:

  • PersistentVolume de NFS para compartir la biblioteca entre nodos
  • Recursos limitados (no necesita mucho, es streaming de audio)
  • Timezone configurado (afecta a las fechas en la UI)
  • Ingress con TLS automático vía cert-manager

Audiobookshelf en Docker Compose (alternativa simple)
#

Si no tienes K3s, esto es lo que necesitas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
version: '3.8'

services:
  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf
    restart: unless-stopped
    ports:
      - "13378:80"
    environment:
      - TZ=Europe/Madrid
    volumes:
      - ./config:/config
      - ./metadata:/metadata
      - /mnt/nas/Biblioteca/Audiobooks:/audiobooks

Cambia /mnt/nas/Biblioteca/Audiobooks por donde tengas montado tu NAS o disco duro externo.

Kavita: configuración en K3s
#

Similar a Audiobookshelf pero para ebooks:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: kavita-config
  namespace: ebooks
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: local-path

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: ebooks-nfs
spec:
  capacity:
    storage: 500Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.15
    path: /volume1/Biblioteca/Ebooks
  mountOptions:
    - nfsvers=4.1
    - hard

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebooks
  namespace: ebooks
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Gi
  volumeName: ebooks-nfs

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kavita
  namespace: ebooks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kavita
  template:
    metadata:
      labels:
        app: kavita
    spec:
      containers:
      - name: kavita
        image: kizaing/kavita:latest
        ports:
        - containerPort: 5000
        env:
        - name: TZ
          value: "Europe/Madrid"
        volumeMounts:
        - name: config
          mountPath: /kavita/config
        - name: ebooks
          mountPath: /books
        resources:
          requests:
            memory: "512Mi"
            cpu: "200m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
      volumes:
      - name: config
        persistentVolumeClaim:
          claimName: kavita-config
      - name: ebooks
        persistentVolumeClaim:
          claimName: ebooks

---
apiVersion: v1
kind: Service
metadata:
  name: kavita
  namespace: ebooks
spec:
  selector:
    app: kavita
  ports:
  - port: 5000
    targetPort: 5000
  type: ClusterIP

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kavita
  namespace: ebooks
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - kavita.midnightlab.build
    secretName: kavita-tls
  rules:
  - host: kavita.midnightlab.build
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kavita
            port:
              number: 5000

Nota el proxy-body-size: 100m en las annotations. Sin eso, no puedes subir ebooks grandes desde la UI.

Kavita en Docker Compose
#

Versión simple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
version: '3.8'

services:
  kavita:
    image: kizaing/kavita:latest
    container_name: kavita
    restart: unless-stopped
    ports:
      - "5000:5000"
    environment:
      - TZ=Europe/Madrid
    volumes:
      - ./config:/kavita/config
      - /mnt/nas/Biblioteca/Ebooks:/books
      - /mnt/nas/Biblioteca/Comics:/comics

Puedes montar múltiples carpetas y luego añadirlas como bibliotecas separadas en la UI.

Primera configuración: importar bibliotecas
#

Audiobookshelf
#

  1. Abre http://tu-ip:13378 (o tu dominio si usas Ingress)
  2. Crea cuenta de administrador
  3. Ve a Settings → Libraries → Add Library
  4. Nombre: “Audiobooks”
  5. Folder: /audiobooks (la ruta dentro del contenedor)
  6. Library Type: Audiobooks
  7. Guarda y haz Scan

El primer escaneo tarda. En mi caso, con 200 audiolibros, tardó unos 15 minutos. Descarga metadata, portadas, información de narrador, todo automáticamente.

Kavita
#

  1. Abre http://tu-ip:5000
  2. Registra cuenta (el primero es admin)
  3. Settings → Libraries → Add Library
  4. Name: “Ebooks”
  5. Folder: /books
  6. Library Type: Book
  7. Scan Library

Kavita es más rápido. 500 ebooks en 5 minutos.

Para cómics/manga, crea otra biblioteca con Library Type: Comic.

Apps móviles: la experiencia real
#

Audiobookshelf (iOS/Android)
#

La app oficial es gratuita y funciona sorprendentemente bien. No esperaba que fuera tan pulida.

Características:

  • Descarga offline de audiolibros completos
  • Control de velocidad de reproducción (yo escucho a 1.3x)
  • Temporizador de sueño (útil para escuchar antes de dormir)
  • Bookmarks para marcar secciones interesantes
  • Sincronización instantánea de progreso

Empiezas a escuchar en el coche, pausas, y cuando abres el iPad en casa, continúa exactamente donde lo dejaste. Es magia.

OPDS: conecta tu e-reader
#

OPDS (Open Publication Distribution System) es un estándar para distribuir catálogos de ebooks. Básicamente, tu e-reader se conecta al servidor y descarga libros directamente.

Kavita tiene OPDS integrado. Para activarlo:

  1. Settings → Users → tu usuario → Get API Key
  2. Copia la API Key
  3. URL de OPDS: https://kavita.tudominio.com/api/opds/{tu-api-key}

En mi caso, uso un Boox Palma 2 (e-reader Android). En la app de lectura:

  • Añado fuente OPDS
  • Pego la URL
  • Ahora puedo explorar mi biblioteca y descargar libros directamente al dispositivo

Funciona con Kindle (hackeado), Kobo, PocketBook, cualquier lector que soporte OPDS.

Gestión de metadata: portadas, autores, series
#

Ambos servicios descargan metadata automáticamente, pero a veces se equivocan o falta información.

Audiobookshelf
#

Click derecho en un libro → Match → busca en Audible/Google/iTunes → selecciona el correcto → aplica metadata.

Si quieres cambiar la portada manualmente, sube un cover.jpg a la carpeta del audiolibro y haz re-scan.

Kavita
#

Similar. Click en un libro → Edit Metadata → busca en servicios online o edita manualmente.

Para series, Kavita detecta automáticamente si usas nomenclatura correcta:

  • Harry Potter 1 - La Piedra Filosofal.epub
  • Harry Potter 2 - La Camara Secreta.epub

Detecta “Harry Potter” como serie y los ordena. Simple.

Copias de seguridad: no pierdas tu progreso
#

Los archivos de audio/ebook están en el NAS, que ya tiene su backup. Pero la base de datos con progreso, marcadores y configuración está en el contenedor.

Audiobookshelf
#

Backup de /config y /metadata:

1
2
3
tar -czf audiobookshelf-backup-$(date +%Y%m%d).tar.gz \
  /ruta/a/docker/audiobookshelf/config \
  /ruta/a/docker/audiobookshelf/metadata

Yo lo hago con un cronjob semanal que sube a Backblaze B2.

Kavita
#

Backup de /kavita/config:

1
2
tar -czf kavita-backup-$(date +%Y%m%d).tar.gz \
  /ruta/a/docker/kavita/config

La DB está en SQLite dentro de /kavita/config/kavita.db. Fácil de respaldar.

Uso real: mi experiencia después de 6 meses
#

Llevo medio año con este setup y es de las cosas que más uso en el homelab.

Cambios en mi rutina:

  • Dejé Audible. Total. Los audiolibros los consigo en otros sitios (algunos legales, otros menos) y los subo a Audiobookshelf
  • Leo más en el iPad porque Kavita es más cómodo que Apple Books
  • Los PDFs técnicos los tengo organizados por categoría en lugar de perdidos en Dropbox
  • El progreso sincronizado entre dispositivos ha eliminado el problema de “en qué capítulo iba”

Problemas encontrados:

  • Los audiolibros en formato M4B (un solo archivo) funcionan pero pierdes los marcadores de capítulo. Convertir a MP3 individuales es mejor
  • Kavita a veces se confunde con PDFs escaneados (sin texto OCR). Funciona pero no puedes buscar
  • El primer escaneo de una biblioteca grande (500+ libros) puede colgar el servidor si tiene poca RAM. Añade los límites de recursos que mostré arriba

Lo que me falta:

  • Integración con Goodreads o similar para trackear qué he leído
  • Recomendaciones automáticas basadas en lo que escucho
  • Compartir progreso con otros usuarios (tipo club de lectura)

Pero son cosas menores. El 95% de lo que necesito está cubierto.

Comparación con alternativas comerciales
#

Audible vs Audiobookshelf:

  • Audible: biblioteca enorme, DRM, 1 libro/mes por suscripción, streaming limitado
  • Audiobookshelf: tu propia biblioteca, sin DRM, sin límites, calidad sin comprimir

Kindle/Apple Books vs Kavita:

  • Kindle/Books: ecosistema cerrado, DRM, sincronización solo dentro del ecosistema
  • Kavita: cualquier formato, cualquier dispositivo, control total

Plex vs Audiobookshelf:

  • Plex soporta audiolibros pero está pensado para video. La experiencia es mediocre
  • Audiobookshelf está diseñado específicamente para audio narrativo. Se nota

Recursos y consumo
#

Setup completo (Audiobookshelf + Kavita):

  • RAM: ~1GB total
  • CPU: casi nada excepto durante escaneos
  • Disco: las DBs ocupan unos 500MB con 200 audiolibros y 500 ebooks
  • Red: streaming de audio consume ~128kbps, ebooks casi nada

En un homelab moderno es insignificante.

Alternativas que consideré
#

Calibre + Calibre-Web: El estándar. Funciona, tiene todas las features. Pero la UI se siente antigua y configurarlo es un lío. Calibre-Web mejora la interfaz pero sigue sin convencerme.

Booksonic: Específico para audiolibros. Más simple que Audiobookshelf pero menos pulido. Las apps móviles son peores.

Ubooquity: Para cómics principalmente. Funciona pero desarrollo lento. Kavita lo supera en todo.

Readarr: Para descargar ebooks automáticamente (tipo Sonarr/Radarr). Lo probé pero prefiero conseguir libros manualmente. Demasiado automatizado para mi gusto.

Próximos experimentos
#

Cosas que quiero probar:

  • Whisper para transcripciones: convertir audiolibros a texto con Whisper y tener ambas versiones sincronizadas
  • Inteligencia de recomendaciones: script que analice qué leo y sugiera similar
  • Integración con e-ink: usar un tablet e-ink viejo como dashboard de “últimos libros añadidos”
  • Estadísticas: tiempo total escuchado, libros terminados por mes, autores favoritos

Conclusión: biblioteca digital que realmente funciona
#

He probado muchas soluciones self-hosted en el homelab. Algunas son proyectos interesantes que nunca uso. Otras las monto, las pruebo, y las apago a la semana.

Audiobookshelf y Kavita no. Los uso todos los días. Han cambiado genuinamente cómo consumo contenido.

Si lees o escuchas libros con regularidad, y tienes un homelab, esto es no negociable. El esfuerzo de montarlo se amortiza en una semana.

Empieza con Docker Compose en un mini PC. Sube 10 libros para probar. Configura las apps móviles. Y cuando veas que funciona, migras toda tu biblioteca.

No vas a volver a depender de Amazon para leer.