Fiabilidad del almacenamiento de archivos
Actualizado el 11 de agosto de 2026.
Este runbook cubre el índice de la carpeta Multitracks utilizado por el portal del personal y el host de descargas públicas. El objetivo es que la navegación de metadatos siga siendo receptiva mientras las descargas grandes y las copias de seguridad en la nube utilizan el mismo almacenamiento.
Ruta de solicitud
La página de Archivos del personal obtiene metadatos de https://files.ro.church:8080 a través de la red interna. El portal se conecta directamente a la dirección de almacenamiento mientras mantiene el nombre de host público para la verificación de TLS.
GET /list/foldersdevuelve nombres de carpetas inmediatos. Es intencionalmente O(número de carpetas) y no calcula el tamaño completo del archivo de forma recursiva.GET /list/folder-files?folder=...recorre solo la carpeta seleccionada y devuelve nombres de archivos individuales, rutas y tamaños exactos.- Las descargas continúan transmitiéndose directamente desde el almacenamiento. El portal no actúa como proxy para las cargas útiles ZIP o de audio.
- Los puntos finales de listado permanecen restringidos al host del portal por nginx. No los haga públicos para simplificar la supervisión.
size_bytes permanece 0 en las filas de carpetas para compatibilidad con código de portal anterior. El selector de carpetas ya no muestra un tamaño agregado. Los tamaños exactos solo se muestran después de seleccionar una carpeta.
La implementación anterior llamaba recursivamente a stat para cada archivo en cada carpeta durante cada solicitud de /list/folders. Debido a que el trabajo del sistema de archivos de njs es síncrono, eso bloqueaba un worker de nginx y hacía que la contención de almacenamiento rutinaria pareciera una interrupción.
Fallback del portal
El portal almacena en caché las respuestas de listado exitosas:
- los metadatos frescos se reutilizan durante dos minutos por defecto;
- los metadatos conocidos como válidos pueden mostrarse durante siete días;
- los archivos de caché contienen solo metadatos y utilizan permisos restrictivos;
- las actualizaciones de caché utilizan un archivo temporal más un renombrado atómico, por lo que un worker de PHP interrumpido no puede reemplazar un archivo de caché bueno con uno parcial;
- la creación de un enlace siempre valida la carpeta seleccionada contra el almacenamiento en vivo.
Los controles en tiempo de ejecución son FILES_LISTING_CACHE_TTL, FILES_LISTING_STALE_TTL y FILES_LISTING_MAX_BYTES.
Un índice de carpetas no disponible no debe impedir que el personal abra enlaces existentes o administre enlaces existentes.
Sincronización en la nube de Multitracks
rclone-multitracks.service es el único programador permitido para poseer la copia en la nube de Multitracks. La entrada cron raíz anterior está deshabilitada.
El servicio ejecuta /usr/local/bin/rclone-multitracks-loop.sh con:
- nivel de nice 15;
- prioridad de E/S de mejor esfuerzo 7;
- una cuota de CPU del 100%;
- dos transferencias y cuatro verificadores;
- búferes de 16 MB y fragmentos de Drive de 32 MB.
Los registros pertenecen a /var/log/rclone/multitracks_service.log. Un directorio /var/log/rclone faltante causa que cada intento de servicio falle antes de la sincronización, así que verifique ese directorio al solucionar problemas.
Estos límites favorecen la navegación y las descargas activas del personal sobre el tiempo de finalización de la copia de seguridad. No vuelva a habilitar la copia cron mientras el servicio systemd esté habilitado.
Límite de confianza de NFS
La VM del portal monta solo el subárbol de multitracks desde rocc01:
- origen:
10.200.24.2:/main-pool/bulk-storage/multitracks; - destino:
/mnt/multitracks; - cliente:
rocc-db(10.200.24.42); - opciones del cliente: NFSv4 de solo lectura, montaje duro,
_netdev,nofailyx-systemd.automount.
Ambos orquestadores de transcripciones dependen de mnt-multitracks.automount. El navegador de Archivos del portal también lee este montaje. El contenedor storage-mgr recibe el árbol de bulk-storage a través de un montaje bind local del host, por lo que sus rutas de nginx, ZIP-helper y rclone no requieren una exportación de red.
El inventario del 11 de agosto encontró solo la VM del portal conectada a NFS. Ninguna otra configuración de invitado de PVE, unidad de host, trabajo cron, registro de mountd o ruta de repositorio hacía referencia a la exportación de red. Esta es una fuerte evidencia del estado actual, pero NFSv4 no proporciona una lista histórica confiable de clientes desconectados.
La configuración actual del servidor exporta todo el padre /main-pool a todos los clientes como lectura/escritura. El reemplazo previsto de mínimo privilegio es:
/main-pool/bulk-storage/multitracks 10.200.24.42(ro,sync,no_subtree_check,root_squash,insecure)
insecure se conserva porque el cliente NFS de Linux observado utiliza un puerto de origen alto. No conserve crossmnt cuando la raíz de exportación sea el directorio exacto que necesita el portal.
Aplique el cambio solo en una ventana de mantenimiento programada:
- Conserve
/etc/exportscon su propietario y modo. - Agregue la exportación hija estrecha mientras la exportación padre aún existe, luego ejecute
exportfs -rayexportfs -v. - Desde la VM del portal, monte la exportación hija exacta de solo lectura en un directorio temporal y vacío. Realice comprobaciones de
staty listado de directorios limitadas; no copie ni imprima contenido de sermones. - Reemplace la línea padre amplia con la exportación estrecha y recargue las exportaciones.
- Verifique que el montaje existente
/mnt/multitrackssea de solo lectura, que la verificación de estado del almacenamiento de Archivos se realice correctamente, que ambas configuraciones de transcripción se validen y que una ejecución de descubrimiento sin contenido finalice sin concesiones obsoletas. - Elimine el montaje y el directorio de prueba temporales.
Si alguna verificación falla, restaure el archivo de exportaciones exacto conservado, ejecute exportfs -ra y vuelva a verificar el montaje original del portal. No solucione problemas otorgando temporalmente acceso de lectura/escritura a todos.
Verificaciones de estado
Desde la VM del portal, lo siguiente debería devolver HTTP 200 en mucho menos del tiempo de espera de solicitud de seis segundos del portal:
curl --silent --show-error --output /dev/null \
--connect-timeout 2 --max-time 8 \
--resolve files.ro.church:8080:10.200.24.5 \
--write-out 'status=%{http_code} total=%{time_total}s\n' \
https://files.ro.church:8080/list/folders
En el almacenamiento, verifique el servicio sin imprimir credenciales ni directivas de nginx que contengan secretos:
systemctl is-active nginx rclone-multitracks.service
systemctl show rclone-multitracks.service \
-p Nice -p CPUQuotaPerSecUSec \
-p IOSchedulingClass -p IOSchedulingPriority
grep -Ec '^[^#].*rclone.*multitracks' /var/spool/cron/crontabs/root
journalctl -u nginx -u rclone-multitracks.service \
--since '15 minutes ago' --no-pager -p warning
El recuento activo de cron de Multitracks debería ser 0. Un recuento distinto de cero significa que dos programadores pueden competir por el mismo trabajo de copia.
El monitor administrado por Git es
/usr/share/nginx/html/dev-portal/scripts/files-storage-watch.php. La cuenta de servicio riveroaks lo ejecuta una vez por minuto.
- mantiene la sonda de listado de origen de almacenamiento fijada a IP;
- solicita por separado la ruta no firmada
/dl/__portal-healthcheck__/a través de DNS normal y requiere un HTTP 403 verificado por TLS; - valida el estado, la latencia, el tamaño de respuesta limitado, los listados no vacíos y el esquema seguro de cada fila de listado;
- rastrea el estado de interrupción/recuperación de forma independiente para cada sonda;
- registra el estado en
/var/tmp/riveroaks-files-storage-watch.json; - alerta después de tres fallos consecutivos en lugar de una pérdida transitoria;
- envía una notificación de recuperación después de una interrupción alertada;
- alerta a
technologystaff@riveroaks.org; - nunca imprime nombres de carpetas ni cuerpos de respuesta y nunca reinicia el almacenamiento.
Revise su salida segura con:
journalctl -t portal-files-watch --since '15 minutes ago' --no-pager
php /usr/share/nginx/html/dev-portal/scripts/files-storage-watch.php --dry-run
php /usr/share/nginx/html/dev-portal/scripts/files-storage-watch.php --status
A partir del 30 de julio, el resolvedor interno 10.200.200.200 (Pi-hole dns-1) responde incorrectamente a files.ro.church con la dirección del portal 10.200.24.42. El resolvedor secundario devuelve el destino público de Archivos. Esta respuesta inconsistente reproduce el fallo del protocolo TLS del lado del personal y ahora está correctamente informado por la sonda client_path. Corrija el registro DNS local de Pi-hole para que el nombre llegue al oyente de Archivos de almacenamiento (10.200.24.5:8080, o el objetivo de hairpin público aprobado). No fije el monitor de ruta de cliente a una IP; hacerlo ocultaría el mismo fallo nuevamente.
La copia de seguridad de la crontab de la cuenta de servicio de la instalación es
/var/tmp/riveroaks-crontab.bak-20260730-files-watch en la VM del portal.
Supervise la latencia además del estado; una respuesta que se acerca a los seis segundos es una advertencia temprana de contención de almacenamiento renovada. Cuando el código del portal se promocione desde dev, mueva el programador al checkout de Git de producción y establezca FILES_WATCH_ALERT_TO=technologystaff@riveroaks.org después de que el equipo apruebe el volumen de alertas.
Reversión
Las copias de reversión del cambio del 30 de julio se almacenan en el host de almacenamiento:
/etc/nginx/njs/listing.js.bak-20260730-fast-index/usr/local/bin/rclone-multitracks-loop.sh.bak-20260730-codex/etc/systemd/system/rclone-multitracks.service.bak-20260730-codex/var/spool/cron/crontabs/root.bak-20260730-codex
Restaure solo el componente bajo investigación. Siempre ejecute nginx -t antes de recargar nginx, y bash -n más systemd-analyze verify antes de reiniciar el servicio de sincronización. Restaurar la antigua crontab raíz también restaura la sincronización duplicada y sin restricciones y debería ser un último recurso.
La aplicación del portal en sí sigue siendo administrada por Git. Los cambios del portal van a la rama dev y se implementan a través del pipeline de GitLab; no edite manualmente el checkout del portal en la VM.