Por qué una sola máquina para cuatro bibliotecas
Dejar Plex, Google Fotos, Spotify o Audible conduce casi siempre al mismo esquema: un servicio por tipo de medio, cada uno en su pequeño servidor o en el NAS del salón. El resultado son cuatro actualizaciones que seguir, cuatro certificados y cuatro copias de seguridad que planificar. Un único VPS lo reduce a un punto de entrada, una red de Docker y un plan de copias.
La dificultad no es la instalación, que nuestras guías de Immich, Jellyfin, Navidrome y Audiobookshelf ya detallan. La dificultad es el dimensionamiento: Immich y la transcodificación de vídeo aplastan un servidor pequeño, mientras que Navidrome y Audiobookshelf pasan casi inadvertidos. Este artículo responde a una sola pregunta: qué máquina, para qué biblioteca.
Lo que gana al reunirlo todo
- Un único punto de entrada — un proxy inverso, un subdominio por servicio, certificados obtenidos y renovados automáticamente.
- Memoria compartida — Navidrome y Audiobookshelf consumen poco, y la memoria que uno deja libre beneficia los picos del otro.
- Un único plan de copias — cuatro carpetas de configuración, un volcado de PostgreSQL, un script.
- Escalado vertical — cuando la biblioteca crece, aumenta RAM, vCPU y disco del mismo VPS sin reinstalar la pila.
- Acceso root completo — usted elige la distribución, ajusta el kernel e instala lo que la pila exija.
El presupuesto de memoria y procesador, servicio por servicio
Solo las cifras de Immich y de Jellyfin proceden de una documentación oficial; las demás líneas son ajustes de partida, que hay que medir en su máquina. Obtenga sus valores una vez en marcha la pila con docker stats --no-stream y ajuste.
Immich es la partida dominante. Su documentación indica 6 GB de RAM como mínimo y 8 GB recomendados, 2 núcleos como mínimo y 4 recomendados. También precisa que en una máquina de 4 GB Immich puede funcionar con el aprendizaje automático desactivado, y que la base PostgreSQL necesita al menos 2 GB si fija límites de recursos en Docker. Desde la versión 3, la imagen de aprendizaje automático en amd64 exige el nivel de conjunto de instrucciones x86-64-v2: compruebe que el plan elegido lo expone.
En cuanto al procesador, es la indexación inicial la que satura: la detección de rostros y la búsqueda semántica usan todos los núcleos disponibles durante horas, y luego vuelve la calma. Los demás servicios casi no se notan mientras no transcodifique.
Presupuesto de reserva por servicio
Desplace la tabla
| Servicio | RAM a reservar | Qué la hace crecer |
|---|---|---|
| Caddy (proxy inverso) | Ajuste de partida: 100 MB, a medir | Casi nada: el número de subdominios apenas lo cambia |
| Navidrome | Ajuste de partida: 250 MB, a medir | Los escaneos de una biblioteca grande y los clientes que piden transcodificación de audio |
| Audiobookshelf | Ajuste de partida: 250 MB, a medir | Los pódcast descargados automáticamente y los escaneos de metadatos |
| Jellyfin en reproducción directa | Ajuste de partida: 1 GB, a medir (Jellyfin menciona 4 GB como posible suficiente en un servidor Linux sin interfaz, 8 GB recomendados en un despliegue medio) | Los análisis de la biblioteca y las imágenes generadas en la pasada inicial |
| Jellyfin con transcodificación por software | Sin cifra oficial por flujo: medir con un flujo de prueba | Cada flujo convertido en paralelo, sobre todo en HEVC o con subtítulos incrustados |
| Immich (servidor, ML, PostgreSQL, Valkey) | 6 GB mínimo, 8 GB recomendados | La indexación inicial, el reconocimiento facial, la búsqueda semántica |
| Pila completa, una sola máquina | Al menos 8 GB (valor recomendado de Immich), 16 GB de margen: una estimación a comprobar | Las tareas de Immich lanzadas mientras se transcodifica una película |
El presupuesto de disco: calcule en GB antes de elegir
El disco es el primer techo de un VPS multimedia, y se calcula. Para el vídeo, la fórmula es: tasa de bits en Mb/s multiplicada por la duración en segundos, dividida entre 8. Una película de dos horas a 8 Mb/s pesa unos 7 GB, a 4 Mb/s unos 3,6 GB. Para la música, un álbum de 45 minutos en MP3 a 320 kb/s ocupa unos 110 MB; en FLAC, cuente más bien de 300 a 500 MB. Un audiolibro de 10 horas a 64 kb/s pesa cerca de 290 MB.
Para las fotos, parta de 3 MB por imagen: 10 000 fotos ocupan por tanto unos 30 GB, sin contar los vídeos del teléfono. La documentación de Immich añade que las miniaturas y los vídeos transcodificados aumentan el tamaño de la fototeca entre un 10 y un 20 % de media.
Separe después lo que debe ser rápido de lo que debe ser grande. La base PostgreSQL de Immich pesa típicamente de 1 a 3 GB, debe vivir en un SSD local y nunca en un recurso de red. Lo mismo vale para la configuración de Jellyfin y Audiobookshelf: Audiobookshelf desaconseja expresamente colocar su carpeta de configuración en un recurso de red, con el riesgo de corromper su base SQLite. Los medios, en cambio, pueden ir a un volumen aparte y más grande.
No transcodificar: la regla que protege a un VPS pequeño
Jellyfin distingue cuatro modos de reproducción, del más ligero al más pesado: reproducción directa, remux, flujo directo y transcodificación. Su documentación describe la reproducción directa como la entrega del archivo sin modificación, con casi ninguna carga adicional para el servidor; la transcodificación de vídeo es el modo más costoso.
Sin tarjeta gráfica, toda transcodificación de vídeo pasa por el procesador, y la documentación de Jellyfin recuerda que siempre se recomienda una GPU para ello. También advierte de que HEVC, VP9 y AV1 pueden ser muy exigentes en decodificación por software, y de que la conversión de HDR a SDR (tone-mapping) usa siempre un codificador por software si no hay GPU.
La regla práctica se resume en tres gestos. Guarde sus películas en un formato que sus dispositivos lean de forma nativa, típicamente H.264 en MP4 o MKV. Convierta una vez, de antemano, los archivos problemáticos en lugar de convertirlos en cada reproducción. Y use el ajuste por usuario de Jellyfin para prohibir la transcodificación de audio y vídeo a las cuentas que no la necesitan. Para comprobar que un flujo no consume nada, inicie una reproducción y observe el panel: allí se muestra el tipo de reproducción, y el procesador debe permanecer en reposo.
Montar la pila: una red, un proxy, un subdominio por servicio
Crear las carpetas, los permisos y la red compartida
Separe medios, fotos y configuraciones, asigne la propiedad al usuario 1000 y cree la red que compartirán todos los contenedores:
sudo mkdir -p /srv/media/video /srv/media/music /srv/media/audiobooks /srv/photos /srv/stack/media /srv/stack/immichsudo mkdir -p /srv/stack/jellyfin/config /srv/stack/jellyfin/cache /srv/stack/navidrome/data /srv/stack/audiobookshelf/config /srv/stack/audiobookshelf/metadatasudo chown -R 1000:1000 /srv/stack /srv/photossudo chmod -R a+rX /srv/mediadocker network create edgeApuntar cuatro subdominios al VPS
Cree cuatro registros A (jellyfin, music, books, photos) hacia la IPv4 del VPS. Caddy obtiene los certificados solo si los registros A o AAAA apuntan al servidor y los puertos 80 y 443 están abiertos desde el exterior.
Escribir el compose de los tres servicios ligeros
En
/srv/stack/media/compose.yaml, declare Jellyfin, Navidrome y Audiobookshelf. No se publica ningún puerto: solo Caddy habla con la rededge. Los medios se montan en solo lectura para Jellyfin y Navidrome.services:jellyfin:image: jellyfin/jellyfinuser: 1000:1000volumes:- /srv/stack/jellyfin/config:/config- /srv/stack/jellyfin/cache:/cache- /srv/media/video:/media:rorestart: unless-stoppednetworks: [edge]navidrome:image: navidrome/navidrome:latestuser: 1000:1000volumes:- /srv/stack/navidrome/data:/data- /srv/media/music:/music:rorestart: unless-stoppednetworks: [edge]audiobookshelf:image: ghcr.io/advplyr/audiobookshelf:latestuser: 1000:1000volumes:- /srv/stack/audiobookshelf/config:/config- /srv/stack/audiobookshelf/metadata:/metadata- /srv/media/audiobooks:/audiobooksrestart: unless-stoppednetworks: [edge]Añadir Caddy al mismo archivo
Complete el archivo con el servicio del proxy, y luego las declaraciones de la red externa y del volumen de certificados:
caddy:image: caddy:2ports:- "80:80"- "443:443"volumes:- ./Caddyfile:/etc/caddy/Caddyfile:ro- caddy_data:/datarestart: unless-stoppednetworks: [edge]networks:edge:external: truevolumes:caddy_data:Escribir el Caddyfile, un bloque por servicio
En
/srv/stack/media/Caddyfile, basta un nombre de dominio para activar el TLS automático, y Caddy redirige HTTP a HTTPS por sí solo:jellyfin.your-domain.com {reverse_proxy jellyfin:8096}music.your-domain.com {reverse_proxy navidrome:4533}books.your-domain.com {reverse_proxy audiobookshelf:80}photos.your-domain.com {reverse_proxy immich_server:2283}Instalar Immich con su compose oficial
Descargue los dos archivos de la última versión y no modifique el compose en sí:
cd /srv/stack/immichwget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.ymlwget -O .env https://github.com/immich-app/immich/releases/latest/download/example.envEn
.env, defina los tres valores siguientes (la contraseña solo admite letras y cifras):UPLOAD_LOCATION=/srv/photos/libraryDB_DATA_LOCATION=/srv/stack/immich/postgresDB_PASSWORD=<mot-de-passe-A-Za-z0-9>Conectar Immich a la red común
Cree
/srv/stack/immich/docker-compose.override.yml. Docker Compose lo fusiona automáticamente con el archivo oficial, que permanece intacto y sustituible en cada actualización:services:immich-server:networks: [default, edge]networks:edge:external: trueArrancar y comprobar cada entrada
Arranque las dos pilas, espere la emisión de los certificados y pruebe después las cabeceras HTTP y el TLS. Debe obtener un código 2xx o 3xx sobre HTTPS, nunca un error de certificado:
cd /srv/stack/media && docker compose up -dcd /srv/stack/immich && docker compose up -dcurl -I https://jellyfin.your-domain.comcurl -I https://photos.your-domain.comMedir y luego ajustar Immich
Durante la indexación, consulte
docker stats --no-streamy la carga del procesador. Si la memoria roza el techo, desactive una función de aprendizaje automático (búsqueda inteligente, reconocimiento facial) en los ajustes de administración, o reduzca la concurrencia de las tareas sin superar el número de núcleos.
Copia de cada servicio, restauración antes de necesitarla
Una pila de cuatro aplicaciones tiene cuatro formas de perder datos. La trampa clásica es copiar las fotos sin la base de datos: Immich no escanea su carpeta de biblioteca, confía en su base para saber qué existe. La documentación distingue las carpetas originales (library, upload, profile), que hay que copiar sí o sí, de las regenerables (thumbs, encoded-video).
Immich genera además sus propios volcados de la base, por defecto cada día a las 2 de la madrugada, conservando los 14 últimos en la carpeta backups de la ubicación de subida. Contienen solo metadatos, nunca las fotos. Para garantizar la coherencia, detenga el contenedor del servidor durante la copia; si no, copie primero la base y después los archivos.
La restauración, en una máquina de pruebas, sigue el procedimiento oficial (y después la inyección del volcado en psql). Atención: down -v borra todos los datos de Immich de la máquina donde lo ejecute:
docker compose down -vdocker compose pulldocker compose createdocker start immich_postgres
Plan de copias por servicio
- Immich, base de datos — un volcado comprimido fuera del VPS:
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=immich --username=postgres | gzip > "/srv/backup/immich-db.sql.gz", adaptando nombre de base y usuario a su.env. - Immich, archivos —
library,uploadyprofilecopiados conrsynca un almacenamiento remoto;thumbsyencoded-videopueden regenerarse. - Jellyfin — la carpeta
/srv/stack/jellyfin/config(bibliotecas, usuarios, metadatos), con el contenedor detenido mientras se archiva. La caché se reconstruye. - Navidrome —
/srv/stack/navidrome/data(base, listas de reproducción, caché); la música es su fuente de verdad y se copia como cualquier carpeta de archivos. - Audiobookshelf —
/configy/metadata: la base SQLite y el progreso de escucha viven en la primera, las copias internas en la segunda. - La restauración se prueba — repita el procedimiento oficial de Immich, detallado arriba, en una máquina de pruebas antes de fiarse.
Resolución de problemas: memoria saturada, permisos denegados, subidas cortadas
Los fallos de esta pila se reparten en dos familias: la memoria, cuando Immich y una transcodificación se disputan los mismos gigabytes, y los permisos, cuando un contenedor sin root no puede leer o escribir una carpeta montada. Para la primera, empiece buscando una traza del kernel con dmesg -T | grep -i "out of memory": si aparece un proceso de Immich, el kernel lo mató por falta de memoria y el contenedor se reinicia en bucle. Para la segunda, compare siempre el identificador del usuario del contenedor con el propietario de las carpetas montadas.
Errores encontrados y su remedio
- Immich se reinicia en bucle en un plan pequeño — el kernel mata el contenedor de aprendizaje automático (busque
out of memoryendmesg). Desactive la búsqueda inteligente y el reconocimiento facial, o pase a un plan con al menos 8 GB. can't set healthcheck.start_interval as feature require Docker Engine v25 or later— su Docker es demasiado antiguo. Actualícelo, o comente la líneastart_intervalen la seccióndatabasedel compose, como indica la documentación de Immich.- Subidas de vídeo cortadas al cabo de un minuto — la documentación de Immich señala un código 499 detrás de Traefik con el tiempo de lectura por defecto de 60 segundos, y recomienda 600 segundos. Revise el tiempo de espera de su proxy.
- Navidrome:
unable to open database file— la carpeta/datano admite escritura. Asigne la propiedad al identificador definido por la directivauser. - Navidrome arranca pero la biblioteca sigue vacía, con
permission denieden los registros — la carpeta de música no es legible: apliquechmod -R a+rXen/srv/media/music. - Jellyfin no ve las películas — el usuario 1000 del contenedor no puede leer la carpeta montada. Pruebe con
docker exec jellyfin ls /mediay corrija los permisos;PUIDyPGIDno funcionan con estas imágenes, solo cuenta la directivauser.
Qué plan para qué biblioteca
Desplace la tabla
| Perfil de biblioteca | Plan recomendado | Margen y límite |
|---|---|---|
| Música, audiolibros y algunas películas en reproducción directa, Immich sin aprendizaje automático, uno o dos usuarios | VPS Start: 2 vCPU, 4 GB, 50 GB SSD, a 99 DH/mes | Memoria justa: Immich queda sin ML y conviene evitar la transcodificación; el disco limita a unas pocas películas (≈ 7 GB para una película de dos horas a 8 Mb/s) |
| Fototeca familiar de unas 10 000 imágenes (30 a 36 GB) con ML activo, música y audiolibros, reproducción directa | VPS Power: 4 vCPU, 8 GB, 100 GB SSD, a 299 DH/mes | Alcanza los 8 GB recomendados solo para Immich; la indexación inicial ralentiza el resto |
| Pila completa de cuatro servicios, dos o tres usuarios, una transcodificación puntual | VPS Business: 8 vCPU, 16 GB, 200 GB SSD, a 499 DH/mes | Holgado; el disco pasa a ser el techo en cuanto el vídeo supera unos cientos de GB |
| Varios flujos transcodificados a la vez | VPS Business como mínimo, y conversión previa de los archivos | Sin GPU, añadir vCPU no basta: conviene convertir una vez en lugar de transcodificar en cada reproducción |
Medir antes de pagar más
Empiece por el plan que indica la tabla, lance la indexación de Immich y consulte la memoria con docker stats --no-stream durante un día de máxima actividad. Si el margen supera el 30 %, el tamaño es correcto; si el kernel mata un contenedor, suba de plan. El escalado vertical del VPS evita reinstalar: RAM y disco aumentan, sus carpetas /srv y sus compose se quedan donde están.
La documentación oficial y los pasos siguientes
Los valores de esta guía proceden de la documentación de los editores: requisitos de Immich, copia y restauración de Immich, elección del hardware para Jellyfin, transcodificación de Jellyfin, Navidrome con Docker y el HTTPS automático de Caddy.
Para elegir un proxy distinto de Caddy, lea nuestra comparativa de Caddy, Traefik y Nginx Proxy Manager. Si deja Plex, el proceso se detalla en nuestra guía de migración a Jellyfin y Navidrome.