Problema
En muchos homelabs el storage de medios o datos críticos se separa del hipervisor para aprovechar ZFS, replicación o simplemente por conveniencia. La arquitectura típica es: un servidor NAS (TrueNAS, FreeNAS, etc.) que exporta un share NFS, y un nodo Proxmox que monta ese share y lo inyecta dentro de contenedores LXC o máquinas virtuales Docker. El inconveniente surge al reiniciar o tras un corte de energía: Proxmox arranca sus máquinas en orden alfabético o según prioridad, sin comprobar si el NAS ya está online. Si un LXC que depende del NFS se inicia antes de que el share esté disponible, el contenedor verá directorios vacíos. Aplicaciones como Jellyfin, Plex o bases de datos pueden interpretar esa ausencia como borrado y comenzar a limpiar sus índices, lo que genera escaneos innecesarios y, en casos extremos, pérdida de metadatos. El reto es garantizar que los contenedores esperen a que el NFS esté montado sin forzar a que todo el resto del entorno dependa del NAS.
Causa
- Orden de arranque predeterminado – Proxmox no tiene una noción de dependencias entre contenedores y recursos externos. Los LXC se inician tan pronto como el host termina su propio proceso de boot, lo que puede ser antes de que la red LAN o el NAS estén operativos.
- Montaje NFS en
/etc/fstabsin opciones de retry – Un entry típico (<nas_ip>:/media /mnt/media nfs ro 0 0) falla rápidamente si el servidor no responde, dejando el punto de montaje sin contenido. - Falta de supervisión de disponibilidad – Ni systemd ni los scripts de arranque de LXC verifican la presencia de archivos o la conectividad al NAS antes de lanzar los servicios internos.
- Hardlinks y permisos – Cuando la capa de almacenamiento depende de hardlinks (por ejemplo, qBittorrent → Radarr → NFS), una ausencia temporal del share rompe la cadena de enlaces y los contenedores pueden intentar recrear estructuras vacías.
Estos factores combinados hacen que el problema sea recurrente en setups donde el storage está desacoplado del hipervisor.
Solución
La solución se basa en tres pilares:
- Montaje resiliente del NFS – Configura el cliente NFS para que intente reconectar indefinidamente y para que el montaje sea “lazy”.
- Unit de systemd que controle la disponibilidad del share – Crea un servicio que verifique la conectividad y el contenido esperado antes de marcar el recurso como listo.
- Dependencia explícita de los contenedores LXC – Usa la opción
lxc.cgroup2.devices.allowo, más sencillo, la directivaafter/requiresde systemd para que el contenedor solo arranque cuando la unidad NFS esté activa.
Paso a paso
1. Montaje NFS con reconexión automática
Edita /etc/fstab añadiendo opciones bg,soft,intr,retry=5,timeo=14. Un ejemplo:
<NAS_IP>:/media /mnt/media nfs ro,bg,soft,intr,retry=5,timeo=14 0 0
bgenvía el intento a segundo plano si el servidor no responde.softpermite que las operaciones fallen después de los reintentos, evitando que el kernel bloquee el arranque.retry=5ytimeo=14ajustan la cantidad y el intervalo de reintentos.
2. Unit de systemd para validar el share
Crea /etc/systemd/system/nfs-media.mount (si no usas fstab) o un servicio de verificación independiente:
# /etc/systemd/system/nfs-media-wait.service
[Unit]
Description=Esperar a que el share NFS de medios esté disponible
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/mnt/media
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wait-nfs.sh /mnt/media 30
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
El script wait-nfs.sh verifica que el punto de montaje exista y que contenga al menos un archivo esperado (por ejemplo, movies/):
#!/usr/bin/env bash
MOUNT=$1
TIMEOUT=$2
ELAPSED=0
while [[ $ELAPSED -lt $TIMEOUT ]]; do
if mountpoint -q "$MOUNT" && [[ -d "$MOUNT/movies" ]]; then
exit 0
fi
sleep 2
((ELAPSED+=2))
done
echo "NFS share no disponible después de $TIMEOUT segundos" >&2
exit 1
Hazlo ejecutable (chmod +x /usr/local/bin/wait-nfs.sh) y habilita el servicio:
systemctl enable --now nfs-media-wait.service
3. Vincular LXC al servicio NFS
En la configuración del contenedor (/etc/pve/lxc/ID.conf) añade:
lxc.start-order: 100
lxc.start-delay: 10
lxc.hook.start: /usr/local/bin/lxc-nfs-wait.sh
El hook lxc-nfs-wait.sh simplemente llama a systemctl start nfs-media-wait.service y espera a que termine con éxito antes de devolver control a Proxmox. Alternativamente, puedes usar la opción systemd dentro del contenedor para declarar:
[Unit]
After=nfs-media-wait.service
Requires=nfs-media-wait.service
Si el contenedor está basado en un template con systemd, crea /etc/systemd/system/jellyfin.service.d/override.conf con esas directivas.
Con este enfoque, el LXC no iniciará hasta que el share NFS esté montado y contenga la estructura esperada, pero los demás VMs y contenedores que no dependan de NFS seguirán su arranque normal.
Cuándo aplicar esta solución
- Síntomas: Al reiniciar, el contenedor muestra directorios vacíos, logs de “media not found”, o la aplicación elimina entradas del índice.
- Entorno: Proxmox con LXC o VMs que consumen datos vía NFS/SMB desde un NAS independiente.
- Escenarios válidos: Homelabs, laboratorios de pruebas y pequeñas infraestructuras donde el NAS puede tardar en arrancar (RAID resync, ZFS pool import).
No aplicar si el share está en el mismo host o si la aplicación tolera la ausencia del directorio (por ejemplo, contenedores que crean su propio storage local). En esos casos, la complejidad adicional no aporta valor.
Código
# /etc/fstab entry (ejemplo)
192.168.1.10:/media /mnt/media nfs ro,bg,soft,intr,retry=5,timeo=14 0 0
# /usr/local/bin/wait-nfs.sh
#!/usr/bin/env bash
MOUNT=$1
TIMEOUT=${2:-30}
ELAPSED=0
while [[ $ELAPSED -lt $TIMEOUT ]]; do
if mountpoint -q "$MOUNT" && [[ -d "$MOUNT/movies" ]]; then
exit 0
fi
sleep 2
((ELAPSED+=2))
done
echo "NFS share no disponible después de $TIMEOUT segundos" >&2
exit 1
# systemd unit (nfs-media-wait.service)
[Unit]
Description=Esperar a que el share NFS de medios esté disponible
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/mnt/media
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wait-nfs.sh /mnt/media 30
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Verificación
- Reinicia el nodo Proxmox sin encender el NAS.
- Ejecuta
systemctl status nfs-media-wait.service. Debería estar en failed o inactive mientras el share falta. - Enciende el NAS y verifica que el servicio cambie a active (exited) en menos de 30 s.
- Comprueba que el contenedor LXC haya arrancado (
pct status <ID>). Los logs de la aplicación (Jellyfin, Plex, etc.) deben mostrar los archivos de media presentes. - Simula un corte del NAS mientras el contenedor está en ejecución; el servicio NFS se marcará como failed pero el contenedor continuará operando con los datos ya montados, evitando una nueva inicialización.
Notas adicionales
- Hardlink preservation: Mantén la opción
no_root_squashen el export de TrueNAS para que los UID/GID coincidan entre host y contenedor; de lo contrario, los hardlinks pueden romperse al montar como read‑only. - Timeout ajustable: En entornos con discos ZFS que tardan más de 30 s en importarse, incrementa el parámetro del script (
wait-nfs.sh) a 60 s o más. - Monitorización: Añade una alerta de Prometheus o Zabbix que vigile
systemdunitnfs-media-wait.servicepara detectar fallos recurrentes. - Alternativa con
autofs: Si prefieres montar bajo demanda,autofspuede crear el punto de montaje la primera vez que el contenedor accede, eliminando la necesidad de un servicio de espera, aunque perderás la garantía de que el share está listo antes del arranque del contenedor.
Con estas prácticas, los contenedores LXC en Proxmox pueden coexistir de forma segura con storage externo NFS, reduciendo la ventana de error tras reinicios y manteniendo la integridad de los índices de medios.