Incidente: el T7 (USB) se desconectó y dejó Docker sin arrancar (2026-10-24)¶
| Síntoma | Las apps de Docker se cayeron de un momento a otro. Después de reiniciar, el T7 tardaba mucho en aparecer y Docker no arrancaba |
| Servicio afectado | Todo lo que corre en Docker: Gitea, la tienda (k3s), Immich, memos y las sesiones de Claude (tmux-host) |
| Causa | El enlace USB del Samsung T7 se reseteó hasta desconectar el disco con escrituras a medias. El ext4 quedó con directorios corruptos, entre ellos /DATA/t7/docker/runtimes, y dockerd no pudo arrancar |
| Agravante | Todo lo crítico vivía en ese disco USB: el data-root de Docker, Gitea, k3s y la base de Immich |
| Estado | Resuelto. El T7 está reparado, lo crítico pasó al SSD y al HDD, y el T7 quedó sin ahorro de energía USB y vigilado por Telegram |
Línea de tiempo (hora local, UTC-5)¶
| Hora | Qué pasó |
|---|---|
| 22/10 y 23/10 | Ya había 105 y 96 errores USB del T7 por arranque, en ráfagas durante escrituras pesadas. Nadie los vio |
| 10:55:48 | usb 2-3: device not accepting address 2, error -62, seguido de resets en cadena |
| 10:56:56 | USB disconnect. ext4 pasa a solo lectura en plena escritura (I/O error while writing superblock) |
| 10:57–10:58 | El kernel intenta 6 veces reconocerlo y falla siempre (device descriptor read/8, error -110). En otro puerto tampoco responde: el controlador del T7 quedó colgado |
| 11:23 | Reinicio del NAS |
| 11:23:59–11:40:48 | systemd-fsck pasa 17 minutos recuperando el journal (3,9 millones de archivos). Docker tenía RequiresMountsFor=/DATA/t7, así que todas las apps esperaron |
| 11:48 | Aparecen errores de checksum en directorios (redis-server, minio) y ls /DATA/t7 devuelve Bad message |
| 11:49 | dockerd cae: failed to start daemon: readdirnames /DATA/t7/docker/runtimes: bad message |
| 12:20–12:53 | Corre recuperar-t7.sh: e2fsck, copia de lo crítico al SSD, Docker de vuelta al HDD |
| 13:32 | El T7 pasa al puerto USB 3 trasero. Se desenchufó montado, pero el journal se recuperó sin errores |
| 14:00 | Se aplica usb3_lpm_permit=0 y se instala el vigilante |
Diagnóstico¶
- Era el enlace USB, no el disco. SMART leído con
smartctl -d sntasmediada 0 errores de datos, 3 % de desgaste y 38 °C. Los errores son-62/-110y resets a nivel de protocolo USB, antes de llegar al sistema de archivos. El disco sí acumula 253 minutos por encima de la temperatura de advertencia y 40.959 horas de uso. - Se veía venir:
- Por qué tarda en aparecer después del reinicio: es el
fsck(17 min), no el reconocimiento USB: - El daño:
Daba
clean with errorsy el contador llegó a 7.199.
memos no era el disco
memos quedó en un bucle de reinicios con
table system_setting already exists. Era una migración fallida por
actualización de versión, no la corrupción. Al volver Docker al HDD,
volvió con su contenedor de imagen estable 0.28 y anduvo solo.
Recuperación¶
scripts/nas-arranque/recuperar-t7.sh se corre como servicio de systemd, así
que sobrevive aunque se caigan la terminal y la sesión de Claude:
sudo systemd-run --unit=recuperar-t7 --collect --setenv=CONFIRMO=si \
bash /DATA/AppData/k3d-lab-v3/recuperacion-t7/recuperar-t7.sh
sudo tail -f /media/HDD-Storage/recuperacion-t7/recuperar.log
- Para Docker y todos los contenedores. Usa
mask --runtimepara que ningún timer lo levante a mitad de la reparación. - Desmonta el T7 (con
umount -R, porque quedan overlays de Docker) y corree2fsck -fyD -z <undo>. El archivo undo permite revertir cone2undo. - Lo vuelve a montar, en solo lectura si
e2fsckno pudo corregir todo. - Copia
appdata/{gitea,immich,k3d-lab}al SSD (/DATA/ssd-appdata). Sirsyncdevuelve algo distinto de 0 o 24, aborta. - Reapunta los symlinks de
/media/HDD-Storage/AppData. Si encuentra una carpeta real, la aparta y verifica cada enlace. - Vuelve el
data-rootde Docker a/media/HDD-Storage/docker. Verifica el cambio y restaura el archivo si no se aplicó. - Quita los drop-ins
RequiresMountsFor=/DATA/t7. - Arranca Docker y los contenedores.
Antes de correrlo, feature-dev:code-reviewer lo revisó y encontró 8
problemas que se corrigieron. El más grave era que fuser -km sobre un T7
desmontado habría matado procesos de todo /DATA. Además se probó por
separado el cambio de daemon.json (7 formatos de espaciado) y el reapuntado
de enlaces (incluida una carpeta real con datos).
Resultado:
e2fsckterminó con código 1 (corregido).lost+foundrecibió 264 entradas (14 GB), todas restos de capas de contenedores.- Las 3 copias quedaron idénticas en cantidad de archivos.
- 29 contenedores arriba y 26 pods
Running. gitea.dbpasóintegrity_check, con los datos del día.- Immich, la tienda y Docs andan.
Cambios para que no se repita¶
| Cambio | Dónde |
|---|---|
Lo crítico fuera del USB: Gitea, k3s y la base de Immich en el SSD; el data-root de Docker en el HDD |
symlinks /media/HDD-Storage/AppData/* → /DATA/ssd-appdata, /etc/docker/daemon.json |
| Docker no depende del T7: si el T7 no está, solo faltan las miniaturas de Immich y los caches del CI | drop-ins 10-t7.conf → .disabled-* |
| Sin LPM USB 3 en el puerto del T7, al arrancar y en cada conexión | t7-usb-quirks.service, 99-t7-usb.rules |
| Aviso por Telegram de resets USB, desconexiones o errores ext4 (cada 5 min) | vigilar-usb-t7.timer |
| T7 en el puerto USB 3 trasero, directo a la placa | físico |
Por qué usb3_lpm_permit y no otra cosa¶
power/usb3_hardware_lpm_u1/u2del dispositivo son de solo lectura.- El quirk
04e8:4001:kdeusbcore(sin LPM) solo se aplica al enumerar el dispositivo, yauthorized0/1 no vuelve a leer los quirks (probado: el LPM seguíaenabled).usbcoreestá integrado al kernel y la línea de arranque de ZimaOS se reescribe en cada actualización. echo 0 > /sys/bus/usb/devices/<T7>/port/usb3_lpm_permitaplica en caliente, con el disco montado. Verificado:u1/u2pasan deenabledadisabled, y también al disparar la regla udev con un evento sintético.
d=/sys/bus/usb/devices/2-3 # el puerto puede cambiar
cat $d/port/usb3_lpm_permit $d/power/usb3_hardware_lpm_u1 $d/power/usb3_hardware_lpm_u2
Si los resets vuelven aun sin LPM, el siguiente paso es desactivar UAS para
el T7 (usb-storage.quirks=04e8:4001:u). Es más estable en algunos casos,
pero más lento.
Operación del T7 desde ahora¶
- Antes de desenchufarlo: parar
immich-serverygitea-runnery correrumount /DATA/t7. - Al conectarlo: ZimaOS lo monta solo en
/media/T7, no en/DATA/t7. Hay que corrermount /DATA/t7y reiniciarimmich-serverygitea-runner, porque sus montajes no se actualizan solos. tmux-hostmonta/DATAcomorprivate, así que no ve los remontajes del T7 hasta que se recrea. A las sesiones de Claude no les afecta.
Lecciones¶
- Un disco USB no es almacenamiento principal. Puede fallar el disco, pero también el cable, el puerto, la energía o la temperatura. Lo que no se puede caer va en discos internos; en el USB, solo lo regenerable.
- Los avisos ya estaban en el log desde dos días antes. Faltaba quien los
leyera: ahora los lee
vigilar-usb-t7. - Una dependencia de arranque es un punto único de falla.
RequiresMountsForevitaba arrancar con carpetas vacías, pero ataba todo Docker a un disco USB. - Un script de reparación se prueba antes de correrlo. Hay que revisarlo y probar por separado las partes que cambian configuración, y sobre todo que aborte en lugar de seguir con datos a medias.