Debian 13: SSHFS vs NFS — elige el que no se cuelgue aleatoriamente (y configúralo bien) (caso #21)

¿Te fue útil?

No notas que un sistema de archivos remoto es frágil hasta el momento exacto en que se convierte en todo tu incidente. El trabajo de compilación se atasca en “copying artifacts…”, las shells dejan de responder cuando haces cd, y tu gráfica de monitorización parece bien porque tu monitor nunca intentó tocar el montaje.

Debian 13 facilita montar casi cualquier cosa. No facilita montarla bien. Si quieres que “no se cuelgue aleatoriamente” sea una propiedad no negociable, debes elegir el protocolo correcto y configurar las semánticas de fallo a propósito.

La decisión: ¿cuál no se colgará aleatoriamente?

Si tu requisito es “un montaje que no se cuelgue aleatoriamente en producción”, la respuesta honesta es:

  • Elige NFSv4.1+ para almacenamiento compartido en producción (servicios, artefactos de CI, directorios de usuarios, volúmenes de contenedores cuando proceda), y configura timeouts/retrans/semánticas de automount para que la falla esté acotada.
  • Usa SSHFS para herramientas: acceso ad-hoc rápido, migraciones puntuales, depuración, “necesito ese directorio ahora” o flujos de trabajo limitados de desarrolladores—pero trátalo como una capa de conveniencia, no como una plataforma de almacenamiento.

¿Por qué? Porque los “cuelgues aleatorios” generalmente no son aleatorios. Son semánticas bloqueantes encontrándose con una red inestable, un servidor muerto, o un desajuste de estado. NFS tiene décadas de perillas operacionales para definir qué significa “caído” y cómo deben comportarse los clientes. SSHFS es un sistema de archivos FUSE respaldado por un protocolo interactivo (SFTP) que no fue diseñado para proveer semánticas POSIX estrictas y de baja latencia ante fallos.

Dicho esto: NFS también puede colgar tus procesos. La diferencia es que con NFS puedes elegir cómo falla y hacerlo observable. Con SSHFS, pasas más tiempo invirtiendo por qué una petición FUSE está atascada detrás de un canal SSH bloqueado.

Regla práctica: si te molestaría un ls atascado a las 3 a.m., no diseñes tu sistema alrededor de SSHFS. Si te molestaría un ls atascado a las 3 a.m., tampoco despliegues NFS sin opciones de montaje explícitas. Bienvenido al almacenamiento.

Una cita para mantenerte honesto: La esperanza no es una estrategiaRick Page.

Broma #1: SSHFS es como una navaja multiusos. Genial hasta que intentas remodelar tu casa con ella.

Hechos e historia para usar en argumentos

Puntos cortos y concretos que explican por qué estas herramientas se comportan como lo hacen:

  1. NFS data de 1984 (Sun Microsystems). Se construyó para sistemas de archivos Unix compartidos en LAN, con una larga historia de ajuste operacional y expectativas empresariales.
  2. NFSv4 pasó de ser “sopa de RPC” a un protocolo más integrado, reduciendo la dependencia de daemons/puertos separados comparado con NFSv3, y añadiendo características con estado como delegaciones y mejor bloqueo.
  3. Las semánticas de montaje “hard” de NFS son intencionadamente tercas: el cliente reintentará I/O porque fallar una escritura puede corromper las suposiciones a nivel de aplicación. Ese “cuelgue” es una característica hasta que no lo es.
  4. SSHFS es un sistema de archivos FUSE. Eso significa que cada operación pasa al espacio de usuario, y el comportamiento de rendimiento/latencia depende mucho del demonio FUSE y su manejo de peticiones.
  5. SSHFS usa SFTP, que no es “nativo de sistema de archivos”. Es un protocolo de transferencia de archivos adaptado para parecer un sistema de archivos, lo que crea desajustes alrededor de operaciones de metadatos y bloqueo.
  6. FUSE puede crear procesos que parecen inmatables cuando el kernel espera respuestas del espacio de usuario. Puedes hacer kill -9 al proceso; el kernel aún espera si la petición está bloqueada.
  7. NFS tiene el conocido comportamiento de “stale file handle” cuando los directorios exportados cambian debajo del cliente (por ejemplo, el fs del servidor se reemplaza, failover mal hecho). Es un clásico, no una novedad.
  8. Los units de automount de systemd cambiaron las reglas para montajes de red: puedes evitar cuelgues en el arranque y acotar fallos montando al acceder en lugar de en el arranque.

Qué significa realmente “colgar” en Linux

La gente dice “el montaje se colgó”. Linux normalmente quiere decir una de estas:

1) Tu proceso está en sueño no interrumpible (estado D)

Clásico para montajes NFS hard, y también posible con FUSE cuando el kernel espera una respuesta del demonio FUSE. Si está realmente en estado D, el proceso no morirá hasta que el I/O subyacente se resuelva o el kernel lo abandone (a menudo: no lo hace).

2) Tu shell está bien, pero cualquier ruta bajo el montaje bloquea

Este es el modo de fallo más sigiloso. La monitorización revisa la carga del host y el espacio en disco y se encoge de hombros. Mientras tanto, cualquier cosa que toque /mnt/share es un alto total.

3) “Colgado” es en realidad DNS o autenticación

Los helpers de montaje pueden bloquearse en búsquedas DNS inversas, adquisición de tickets Kerberos, o en contactar rpcbind/mountd (NFSv3). Parece almacenamiento. A menudo es resolución de nombres.

4) “Colgado” es el camino de red, no el protocolo

MTU mismatched, enrutamiento asimétrico, agotamiento de conntrack, firewall que descarta fragmentos, un ToR inestable, o una VPN con timeouts agresivos por inactividad. SSH sobrevive mejor a algunos de estos porque viaja en un único stream TCP. O peor: sobrevive quedándose detenido para siempre.

Operativamente, quieres dos cosas:

  • Fallo acotado: las solicitudes expiran y los llamantes reciben errores en lugar de estancamientos infinitos.
  • Buena observabilidad: cuando falla, puedas ver por qué en logs/métricas y reproducirlo con herramientas simples.

SSHFS en Debian 13: dónde sobresale y dónde te atrapa

SSHFS es seductoramente simple. Ya tienes SSH. Ejecutas un comando, obtienes un montaje. No hay daemon servidor que ajustar (más allá de sshd), no hay exports, no idmap, no reunión del comité de firewall.

Y luego empieza a “colgarse aleatoriamente”. Esto es por qué ocurre y qué hacer al respecto.

Modelo de fiabilidad de SSHFS (lo que realmente estás comprando)

  • Sesión TCP única cifrada (SSH) que transporta peticiones SFTP.
  • Sistema de archivos en espacio de usuario (FUSE) que traduce operaciones tipo POSIX a acciones SFTP.
  • El fallo a menudo se presenta como “syscall bloqueada” porque el kernel espera a FUSE, y FUSE espera a SSH, y SSH espera a la red.

SSHFS es excelente cuando el flujo tolera stalls ocasionales, o cuando “está caído” significa “lo intentaré otra vez” y nada está atendiendo tráfico de usuarios.

Desencadenantes comunes de cuelgues en SSHFS

  • Sesiones TCP inactivas matadas por NAT/VPN: el canal SSH está “arriba” desde la perspectiva del cliente pero queda en un agujero negro en la ruta.
  • Sobrecarga del lado servidor: sshd y la subsistema SFTP están limitados por CPU (cifrado, compresión o demasiadas sesiones).
  • Trabajos con muchos metadatos: git status, búsquedas recursivas, instalaciones de dependencias. SSHFS tiende a amplificar latencia y sensibilidad al RTT.
  • Acumulación de backlog de peticiones FUSE: el daemon en espacio de usuario se bloquea; el kernel espera; los procesos se amontonan.

Cómo ejecutar SSHFS sin sabotearte

En Debian 13, asume que usas sshfs con FUSE3. Las tácticas:

  • Usa keepalives de SSH para que caminos muertos se detecten.
  • Usa automount para que un servidor caído no bloquee el arranque o servicios que no lo necesitan.
  • Acepta que el cacheo es delicado. Sobre-cachear mejora velocidad e incrementa riesgo de vistas obsoletas; sub-cachear puede convertir un repo en un benchmark de latencia.
  • No finjas que el locking es perfecto. Si necesitas comportamiento POSIX multi-cliente correcto, SSHFS es la herramienta equivocada.

Broma #2: La forma más rápida de encontrar un problema de SSHFS es anunciar que “lo usaré en producción—temporalmente”.

NFS en Debian 13: de nivel producción, si lo respetas

NFS tiene mala reputación por dos fuentes: gente que usó NFSv3 en redes no fiables, y gente que dejó los valores por defecto sin tocarlos y luego se sorprendió cuando ocurrió el comportamiento por defecto.

Modelo de fiabilidad de NFS

Los clientes NFS hacen que el I/O remota parezca local. Cuando el servidor o la ruta falla, el cliente decide qué hacer según las opciones de montaje:

  • Montajes hard: siguen reintentando. Genial para la integridad de datos, peligroso para la disponibilidad si no aislas el radio de impacto.
  • Montajes soft: abandonan y devuelven un error. Mejor para herramientas interactivas y lecturas “mejor esfuerzo”; arriesgado para escrituras.
  • Timeouts y retrans: definen cuánto esperas y con qué agresividad reintentas.
  • Systemd automount: monta solo al acceder y evita deadlocks en el arranque.

Cómo se ve un “cuelgue aleatorio” en territorio NFS

Casi siempre es uno de estos:

  • Hard mount + servidor inalcanzable ⇒ tareas en estado D, potencialmente acumulándose.
  • Problemas de recuperación de estado / bloqueo tras reinicio del servidor ⇒ cuelgues o errores de I/O según versión y carga.
  • Desajuste DNS/idmap ⇒ raros permisos que parecen bugs de la aplicación.
  • Intervención de firewall/NAT ⇒ stalls intermitentes bajo carga (especialmente con los servicios extra de NFSv3).

Qué desplegar por defecto

Si quieres la línea base sensata para clientes Debian 13:

  • NFSv4.1 o superior (4.2 si tu servidor lo soporta), TCP.
  • Systemd automount para cualquier cosa no esencial en el arranque; para montajes esenciales, sé explícito con dependencias y timeouts.
  • Hard mounts para datos críticos con muchas escrituras, pero aíslalos (servicio separado, espacio de nombres de montaje separado si hace falta) y monitoriza I/O atascado.
  • Soft mounts solo para accesos mayormente de lectura y no críticos, y solo si tu aplicación tolera errores de I/O.

Fallo acotado con NFS no significa “nunca hard”. Significa: hard donde la corrección importa, y rodeado de guardarraíles para que no congelen todo el host.

Tareas prácticas: comandos, salidas, decisiones (12+)

Estos son los chequeos que realmente ejecuto cuando llega un informe de “cuelgue aleatorio”. Cada tarea incluye lo que implica la salida y qué decisión tomar después.

Task 1 — Identify what’s mounted and how

cr0x@server:~$ findmnt -t nfs,nfs4,fuse.sshfs
TARGET      SOURCE                  FSTYPE     OPTIONS
/mnt/build  nfs01:/exports/build    nfs4       rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,proto=tcp,sec=sys,clientaddr=10.0.2.10
/mnt/tools  dev@jump:/srv/tools     fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000

Meaning: you can see protocol, version, and whether NFS is hard/soft. SSHFS shows up as fuse.sshfs.

Decision: if NFS is hard and the mount is on a path used by critical system services (like /var subpaths), you prioritize blast-radius reduction (automount or service isolation).

Task 2 — Verify NFS version negotiation from the client

cr0x@server:~$ nfsstat -m
/mnt/build from nfs01:/exports/build
 Flags:	rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.2.10

Meaning: this confirms what the kernel is actually using, not what you think you configured.

Decision: if it says vers=3 and you expected v4, you investigate server support, mount options, and firewall constraints (v3 is more fragile across networks).

Task 3 — Detect “stuck” processes and whether it’s D-state

cr0x@server:~$ ps -eo pid,state,comm,wchan:32,args | awk '$2 ~ /D/ {print}'
23144 D  rsync  nfs_wait_on_request        rsync -a /mnt/build/ /var/cache/build/

Meaning: D-state with nfs_* wait channels screams “blocked on NFS I/O.” If it’s fuse_wait, think SSHFS/FUSE.

Decision: stop restarting apps blindly. You now know it’s kernel I/O wait; focus on network/server path, not the application.

Task 4 — Check kernel logs for NFS client errors

cr0x@server:~$ journalctl -k -n 50 --no-pager
Dec 30 10:12:03 server kernel: NFS: server nfs01 not responding, still trying
Dec 30 10:12:33 server kernel: NFS: server nfs01 not responding, still trying
Dec 30 10:13:04 server kernel: NFS: server nfs01 OK

Meaning: transient server/path issues. If you see “still trying” repeatedly, the client is stuck in retry loops (hard mount behavior).

Decision: if this happens frequently, you tune timeouts and investigate network drops; you don’t “fix” it by adding more application retries.

Task 5 — Confirm the server export from the client side

cr0x@server:~$ showmount -e nfs01
Export list for nfs01:
/exports/build 10.0.2.0/24

Meaning: validates the server is exporting and your network is permitted. (Mostly relevant to NFSv3; still useful for sanity checks.)

Decision: if it fails or hangs, suspect firewall/rpc services, or DNS misdirection.

Task 6 — Validate name resolution and reverse DNS (yes, it matters)

cr0x@server:~$ getent hosts nfs01
10.0.2.20       nfs01
cr0x@server:~$ getent hosts 10.0.2.20
10.0.2.20       nfs01

Meaning: forward and reverse resolution are consistent. Inconsistent resolution causes weird auth, delays, and “it hangs only sometimes” behavior.

Decision: if reverse lookup is slow or wrong, fix DNS or add sane entries in the appropriate resolver stack. Don’t accept 5-second DNS stalls on every mount path.

Task 7 — Measure basic RTT and packet loss to the server

cr0x@server:~$ ping -c 5 nfs01
PING nfs01 (10.0.2.20) 56(84) bytes of data.
64 bytes from 10.0.2.20: icmp_seq=1 ttl=64 time=0.41 ms
64 bytes from 10.0.2.20: icmp_seq=2 ttl=64 time=0.38 ms
64 bytes from 10.0.2.20: icmp_seq=3 ttl=64 time=0.43 ms
64 bytes from 10.0.2.20: icmp_seq=4 ttl=64 time=0.40 ms
64 bytes from 10.0.2.20: icmp_seq=5 ttl=64 time=0.39 ms

--- nfs01 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4090ms
rtt min/avg/max/mdev = 0.38/0.40/0.43/0.02 ms

Meaning: basic connectivity looks fine, but ping isn’t proof NFS/SSH won’t stall. Still, loss here is a red flag.

Decision: if packet loss exists, fix the network first. Storage tuning is pointless on a lossy path.

Task 8 — Check for MTU or path weirdness with tracepath

cr0x@server:~$ tracepath nfs01
 1?: [LOCALHOST]                                         pmtu 1500
 1:  nfs01                                                0.439ms reached
     Resume: pmtu 1500 hops 1 back 1

Meaning: PMTU is sane and path is simple. If PMTU drops unexpectedly, you can see fragmentation risk.

Decision: if PMTU is lower than expected (e.g., 1400 on a LAN), verify overlays/VPNs and align MTU to avoid intermittent stalls.

Task 9 — Verify SSH keepalive settings for SSHFS scenarios

cr0x@server:~$ ssh -G jump | egrep 'serveraliveinterval|serveralivecountmax|tcpkeepalive'
tcpkeepalive yes
serveraliveinterval 15
serveralivecountmax 3

Meaning: SSH will detect dead paths in ~45 seconds. Without this, SSH can sit on a dead TCP session for a long time depending on the network.

Decision: if these are missing or large, add them to your SSHFS invocation or SSH config to make failures fail.

Task 10 — Reproduce the “hang” with a single syscall and a timeout wrapper

cr0x@server:~$ timeout 5s stat /mnt/build/. || echo "stat timed out"
stat timed out

Meaning: this proves the hang is in filesystem access, not the calling program. Using timeout makes it visible and scriptable.

Decision: if stat hangs but ping is fine, you suspect server-side NFS thread starvation, firewall state issues, or client-side stuck RPCs.

Task 11 — Inspect live NFS RPC activity (client side)

cr0x@server:~$ nfsstat -rc
Client rpc stats:
calls      retrans    authrefrsh
124981     317        0

Client nfs v4:
null         read         write        commit       open         open_conf
3            20811        14402        0            9812         14

Meaning: retrans increasing rapidly suggests packet loss or server slowness. A small stable retrans count during normal operation is fine; spikes are not.

Decision: if retrans climbs during incidents, treat it like a network/server capacity problem, not “NFS is bad.”

Task 12 — Confirm systemd ordering and whether boot is at risk

cr0x@server:~$ systemctl show -p After -p Wants remote-fs.target
After=network-online.target
Wants=network-online.target

Meaning: your remote mounts are tied to network-online.target. If network-online is flaky, boot can be slow or stuck.

Decision: for non-critical mounts, switch to systemd automount so the system boots even if storage is down.

Task 13 — Spot SSHFS/FUSE backpressure and blocked requests

cr0x@server:~$ ps -eo pid,state,comm,wchan:32,args | egrep 'sshfs|fuse' | head
18211 S  sshfs  wait_woken                     sshfs dev@jump:/srv/tools /mnt/tools -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3

Meaning: not D-state yet, but you can correlate timing with a stall report. If you see many processes stuck in fuse_wait or similar, SSHFS is wedged.

Decision: if it wedges regularly under load, stop using SSHFS for that workload. This is a design mismatch, not a tuning problem.

Task 14 — Confirm NFS server is reachable on the right port (v4)

cr0x@server:~$ nc -vz nfs01 2049
Connection to nfs01 (10.0.2.20) 2049 port [tcp/nfs] succeeded!

Meaning: TCP/2049 is open. NFSv4 primarily needs this. If it fails intermittently, suspect firewall state or load balancers doing “helpful” things.

Decision: if 2049 is blocked, stop. No mount option will negotiate around “port closed.” Fix network policy.

Task 15 — Verify actual mount options from /proc (ground truth)

cr0x@server:~$ grep -E ' /mnt/build | /mnt/tools ' /proc/mounts
nfs01:/exports/build /mnt/build nfs4 rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.2.10 0 0
dev@jump:/srv/tools /mnt/tools fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000 0 0

Meaning: this is what the kernel uses. If you think you set an option and it’s not here, it didn’t apply.

Decision: correct the mount unit/fstab/command and remount.

Guion rápido de diagnóstico

Cuando alguien dice “el montaje remoto se colgó”, puedes perder una hora conjeturando. O puedes hacer esto en cinco minutos y parecer que lo planificaste.

Primero: determina si es NFS o SSHFS, y si hay algo en estado D

  • Ejecuta: findmnt -t nfs,nfs4,fuse.sshfs y ps ... | awk '$2 ~ /D/'
  • Si existe estado D: es espera de I/O del kernel. Reiniciar apps no lo arreglará. Pasa a chequear red/servidor.
  • Si no hay estado D: puede seguir siendo lento/estancado en espacio de usuario (SSHFS) o resolución de nombres/autenticación.

Segundo: comprueba la prueba de vida más simple para la ruta exacta del montaje

  • Ejecuta: timeout 5s stat /mnt/whatever
  • Si stat se cuelga: lo has reproducido con una syscall. Ahora puedes correlacionar con logs, estadísticas RPC y la red.
  • Si stat funciona: tu “cuelgue” probablemente esté en capas superiores (bloqueo de la app, recorrido enorme de directorio, metadatos lentos).

Tercero: aisla el dominio—red, servidor, cliente o semánticas

  • Red: ping, tracepath, revisa retrans en nfsstat -rc, verifica puerto 2049 con nc.
  • Servidor: busca “server not responding” en logs del kernel; si tienes acceso, comprueba saturación de hilos NFS y latencia de disco (fuera de alcance aquí, pero ya sabes qué mirar).
  • Configuración cliente: confirma opciones en /proc/mounts y qué hace systemd en el arranque.
  • Desajuste de semánticas: si la carga es intensiva en metadatos y estás en SSHFS, para. Si necesitas semánticas de fallo estrictas pero montaste NFS hard en una ruta crítica, rediseña.

Errores comunes (síntomas → causa raíz → arreglo)

1) Síntoma: “Todo el host está congelado,” pero solo algunos comandos cuelgan

Causa raíz: una shell o servicio del sistema tocó una ruta NFS montada hard; procesos quedan en estado D esperando I/O.

Arreglo: usa x-systemd.automount para montajes no críticos, y evita poner NFS bajo rutas usadas por servicios núcleo. Para montajes críticos, aísla servicios y monitoriza stalls de NFS.

2) Síntoma: el montaje SSHFS funciona y luego se “congela aleatoriamente” tras inactividad

Causa raíz: timeout de inactividad de NAT/VPN que pone en agujero negro la sesión TCP; SSH no lo detecta rápido sin keepalives.

Arreglo: configura ServerAliveInterval y ServerAliveCountMax (lado cliente), y contempla keepalive TCP. Prefiere automount para que se restablezca al acceder.

3) Síntoma: montajes NFS a veces tardan 30–90 segundos, a veces instantáneo

Causa raíz: retrasos en lookup inverso DNS o resolver intermitente; o negociación de versiones/puertos que esperan antes de retroceder.

Arreglo: arregla consistencia DNS; especifica vers=4.2 explícitamente; asegúrate de que TCP/2049 esté permitido punto a punto.

4) Síntoma: “Permiso denegado” en NFSv4 a pesar de UID/GID coincidentes

Causa raíz: desajuste de idmapping/dominio o exportación con root_squash que no coincide con el modelo de identidad del cliente.

Arreglo: alinea los ajustes de idmap si dependes de mapeo por nombre, o usa IDs numéricos consistentes entre sistemas. Verifica las opciones de exportación en el servidor.

5) Síntoma: “Stale file handle” tras mantenimiento/failover

Causa raíz: filesystem del servidor reemplazado/movido; los clientes mantienen referencias a filehandles antiguos.

Arreglo: remonta el sistema de archivos; evita reemplazar árboles exportados sin un remount coordinado del cliente o semánticas HA adecuadas.

6) Síntoma: trabajos de CI se ralentizan en SSHFS; CPU se dispara en ambos extremos

Causa raíz: operaciones intensivas en metadatos sobre SFTP cifrado + conmutaciones de contexto FUSE; la compresión opcional lo empeora.

Arreglo: usa NFS para artefactos de compilación; si debes usar SSHFS, desactiva la compresión en LAN y evita usarlo en rutas calientes.

7) Síntoma: arranque se cuelga esperando montajes remotos

Causa raíz: montajes en /etc/fstab sin automount; network-online.target no está realmente en línea; montaje hard esperando.

Arreglo: usa nofail, x-systemd.automount, y x-systemd.mount-timeout=; asegúrate de que el servicio network-online esté correctamente implementado para tu stack de red.

8) Síntoma: NFS funciona, pero algunas apps se comportan raramente (locks, escrituras parciales, errores extraños)

Causa raíz: usar soft para cargas que asumen que las escrituras nunca fallan a mitad de camino; o mezclar versiones antiguas de NFS con expectativas de lock.

Arreglo: usa hard para cargas críticas de escritura; asegura NFSv4 y correcto manejo de lock/estado; rediseña apps para manejar errores de I/O si insistes en soft.

Listas de verificación / plan paso a paso

Plan A: Necesitas un sistema de archivos compartido fiable (la mayoría de casos de producción)

  1. Elige NFSv4.2 sobre TCP salvo que tengas una razón convincente para no hacerlo.
  2. Decide semánticas de fallo por montaje:
    • Crítico para escrituras: hard, pero aísla.
    • Mayormente lectura y no crítico: considera soft con timeouts cortos.
  3. Usa systemd automount para todo lo no requerido en el arranque.
  4. Establece timeouts y retrans explícitos en lugar de confiar en valores por defecto no testados.
  5. Monitoriza mensajes “server not responding” y picos de retrans.
  6. Documenta el radio de impacto: ¿qué servicios tocan el montaje? ¿Qué nodos? ¿Qué sucede si se queda atascado?

Plan B: Solo necesitas acceso seguro ad-hoc (herramientas de desarrollador, migraciones)

  1. Usa SSHFS con keepalives y comportamiento de reconexión.
  2. Evita flujos de trabajo intensivos en metadatos (repos grandes, gestores de paquetes de lenguajes) en SSHFS cuando te importe la velocidad o estabilidad.
  3. Monta bajo demanda con systemd o comandos manuales, no como dependencia crítica de arranque.
  4. Prefiere rsync/scp para transferencias masivas cuando no necesites una vista montada.

Fragmentos de configuración de Debian 13 que puedes desplegar

Paquetes cliente NFS y una entrada fstab sensata (con automount)

cr0x@server:~$ sudo apt-get update
...output...
cr0x@server:~$ sudo apt-get install -y nfs-common
...output...
cr0x@server:~$ sudo mkdir -p /mnt/build
cr0x@server:~$ sudo sh -c 'printf "%s\n" "nfs01:/exports/build /mnt/build nfs4 rw,vers=4.2,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,x-systemd.automount,x-systemd.idle-timeout=300,noatime,nofail,x-systemd.mount-timeout=30s 0 0" >> /etc/fstab'

Lo que te aporta: el host arranca incluso si NFS está caído (nofail), el montaje ocurre al acceder (automount), y si no puede montarse rápido, falla deprisa en lugar de bloquear el arranque.

SSHFS con keepalives y reconnect (montaje manual)

cr0x@server:~$ sudo apt-get install -y sshfs
...output...
cr0x@server:~$ sudo mkdir -p /mnt/tools
cr0x@server:~$ sshfs dev@jump:/srv/tools /mnt/tools -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,IdentityFile=/home/dev/.ssh/id_ed25519,allow_other

Nota operativa: allow_other requiere user_allow_other en /etc/fuse.conf. Úsalo solo cuando lo necesites; de lo contrario mantén los montajes privados por usuario.

Systemd automount para SSHFS (para que no bloquee el arranque)

Cuando SSHFS lo usa un servicio, prefiero unidades systemd para que puedas fijar timeouts y comportamiento de reinicio.

cr0x@server:~$ sudo tee /etc/systemd/system/mnt-tools.mount &>/dev/null <<'EOF'
[Unit]
Description=SSHFS tools mount
After=network-online.target
Wants=network-online.target

[Mount]
What=dev@jump:/srv/tools
Where=/mnt/tools
Type=fuse.sshfs
Options=_netdev,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,IdentityFile=/home/dev/.ssh/id_ed25519,allow_other

[Install]
WantedBy=multi-user.target
EOF
...output...
cr0x@server:~$ sudo tee /etc/systemd/system/mnt-tools.automount &>/dev/null <<'EOF'
[Unit]
Description=Automount SSHFS tools

[Automount]
Where=/mnt/tools
TimeoutIdleSec=300

[Install]
WantedBy=multi-user.target
EOF
...output...
cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl enable --now mnt-tools.automount
Created symlink /etc/systemd/system/multi-user.target.wants/mnt-tools.automount → /etc/systemd/system/mnt-tools.automount.

Decisión: si el servidor SSHFS está caído, los accesos a /mnt/tools intentarán montar y fallarán dentro de los límites de timeout de systemd, en lugar de dejar atascado el arranque.

Tres mini-historias corporativas desde el campo

Historia 1: El incidente causado por una suposición equivocada (“es solo un montaje”)

Una empresa mediana ejecutaba Debian en runners de build. Alguien necesitó acceso rápido a una tienda de artefactos legacy que solo tenía SSH abierto a través de un jump host endurecido. SSHFS fue el atajo obvio: sin petición de firewall, sin cambios en servidor, y funcionó los primeros cinco minutos.

Conectaron el montaje SSHFS en /etc/fstab en los runners porque el job de CI esperaba que /mnt/artifacts existiera. Era “temporal”, que en tiempo empresarial significa “hasta la siguiente reorganización”. Durante semanas pareció estar bien, porque la ruta de red era estable y el jump host estaba poco usado.

Entonces un cambio en la VPN introdujo un timeout por inactividad. Las sesiones SSH que quedaban quietas no se cerraban limpiamente; quedaban en agujeros negros. Las llamadas SSHFS empezaron a bloquearse. Los workers de CI no estaban caídos; eran peores. Estaban arriba, consumiendo slots de ejecutores en jobs que se estancaban durante la extracción con tar.

La suposición equivocada fue que un montaje es como un directorio local con diferente latencia. No lo es. Es una dependencia con modos de fallo. Cuando falla, tiende a fallar dentro de syscalls donde tu aplicación no puede “capturarlo”.

La solución no fue heroica: quitar SSHFS de fstab, añadir automount de systemd con keepalives, y mover la tienda de artefactos a NFS detrás del firewall donde debía estar. El cambio más importante fue cultural: los montajes remotos pasaron a ser tratados como bases de datos—con responsables, monitorización y revisiones.

Historia 2: La optimización que salió mal (más grande no siempre es mejor)

Otro equipo tenía un share NFS usado por jobs analíticos. Vieron problemas de throughput y hicieron lo que todos hacen: aumentaron rsize y wsize, habilitaron cache agresivo en cliente, y declararon victoria cuando un benchmark secuencial mejoró.

No fue malicia. Fue normal. Alguien corrió un test de lectura secuencial y obtuvo un buen número. Luego la carga cambió: miles de archivos pequeños, muchas operaciones de metadatos y múltiples clientes. De pronto la configuración “rápida” produjo largos stalls en horas punta.

El problema vino por dos frentes. Primero, tamaños de I/O más grandes no ayudan cargas intensivas en metadatos y a veces hacen la recuperación más lenta cuando se pierden paquetes (más datos por retrans). Segundo, las semánticas de automount/timeout seguían por defecto, así que cuando el servidor se puso ocupado, los clientes se acumularon en reintentos y todo se sintió congelado.

Lo solucionaron tratando el tuning como específico para la carga. Mantuvieron grandes tamaños de I/O para la ruta de datos secuencial pero separaron los árboles intensivos en metadatos en exports diferentes y aplicaron timeouts sensatos en clientes. La mayor mejora vino de hacer las fallas visibles y acotadas, no de sacar otro 5% de throughput.

Historia 3: La práctica aburrida y correcta que salvó el día (y nadie ganó un trofeo)

Un entorno regulado montaba directorios home por NFS. Todos temían los “cuelgues NFS”, así que la tentación era poner soft mounts por todas partes. Pero el equipo de ops hizo algo deliberadamente soso: clasificaron montajes por requisitos de corrección y fijaron políticas acorde.

Los home se montaron hard porque perder escrituras era inaceptable. Pero también los montaron con systemd automount y los mantuvieron fuera de rutas críticas de arranque. Las sesiones de usuario se bloquearían si el filer moría, pero el host no se volvía inservible. Esa distinción importa cuando intentas arreglar el problema.

También tenían una comprobación rutinaria semanal: muestrear latencia de stat, monitorizar la tasa de logs del kernel por “not responding”, y alertar en picos de retrans en NFS. Nada sofisticado. Sin buzzwords. Solo pequeñas comprobaciones que detectan “esto se está poniendo raro” antes de convertirse en incendio.

Cuando un mantenimiento de red causó pérdida breve de paquetes, vieron retrans subir y mensajes de “server not responding”. Porque tenían baselines, pudieron decir: “esto es anormal y se correlaciona con la ventana de cambio”. La reparación fue rápida y el impacto a usuarios se mantuvo limitado.

Lo mejor: el runbook funcionó incluso con on-call nuevos. El sistema no dependía de un mago que recordara el outage de 2019.

Preguntas frecuentes

1) ¿Cuál es más rápido en Debian 13: SSHFS o NFS?

Para la mayoría de cargas reales, NFS es más rápido y predecible, especialmente bajo concurrencia y acceso intensivo en metadatos. SSHFS añade sobrecarga por cifrado, cruces a espacio de usuario y coste de traducción SFTP.

2) ¿Cuál es más seguro por defecto?

SSHFS hereda el cifrado y la autenticación de SSH, por lo que suele ser más fácil de desplegar seguro sobre redes no confiables. NFS puede ser seguro, pero debes diseñarlo: aislamiento de red, reglas de firewall y (si es necesario) Kerberos.

3) ¿Qué causa realmente los “cuelgues aleatorios” en NFS?

Más comúnmente: montajes hard reintentando durante problemas de servidor/ruta, pérdida de paquetes en la red causando tormentas de retrans, o dolor de recuperación de estado/bloqueo durante reinicios del servidor. La solución suele ser semánticas de fallo mejores más arreglar la red/servidor subyacente.

4) ¿Se puede hacer SSHFS “no colgante”?

Puedes reducir la probabilidad usando keepalives y automount, pero no puedes cambiar el hecho de que FUSE + SFTP pueden bloquear syscalls cuando el canal se queda atascado. Si “nunca colgar” es tu barra, no pongas SSHFS en rutas críticas.

5) ¿Debería usar montajes soft de NFS para prevenir cuelgues?

Sólo para cargas mayormente de lectura y no críticas donde tu aplicación pueda manejar errores de I/O. Los montajes soft cambian “colgar para siempre” por “fallar a veces”, y fallar escrituras a mitad puede causar corrupción sutil a nivel de aplicación.

6) ¿Es systemd automount mejor que autofs?

Para muchos setups Debian 13, systemd automount es más simple e integra bien con ordenamiento de arranque y timeouts. Autofs sigue siendo válido cuando necesitas lógica avanzada de mapas o comportamiento legacy.

7) ¿Qué opciones de montaje importan más para evitar dolor a nivel host?

x-systemd.automount (evita dependencia de arranque y acota acceso), nofail, y timeo/retrans explícitos para que sepas qué significa “caído”. También: no montes sistemas remotos bajo rutas de las que dependen servicios núcleo a menos que realmente lo quieras.

8) ¿Por qué df se cuelga cuando el montaje está roto?

df pregunta estadísticas de filesystem para todos los montajes. Si un montaje remoto bloquea, df bloquea. Usa df -l para local-only, o apunta a filesystems específicos cuidadosamente.

9) ¿Está bien usar NFS sobre Wi‑Fi o Internet público?

Sob re Wi‑Fi: puede funcionar, pero espera variabilidad y retrans. Sobre Internet público: no, a menos que sepas exactamente lo que haces con transporte seguro, expectativas de latencia y semánticas de fallo. Herramientas basadas en SSH suelen ser mejor opción para ese entorno.

10) ¿Cuál es la recomendación segura por defecto más simple?

NFSv4.2 con systemd automount para compartidos de producción; SSHFS con keepalives para acceso ad-hoc solamente. Si te tienta invertir eso, estás a punto de aprender algo caro.

Conclusión: qué hacer el lunes por la mañana

Si solo recuerdas una cosa: los sistemas de archivos remotos son dependencias que fallan dentro de syscalls. Elige el protocolo que coincida con tu tolerancia a fallos, y luego configúralo para que la falla esté acotada y sea observable.

  1. Inventaría montajes con findmnt y clasifícalos: escrituras críticas vs lecturas de conveniencia.
  2. Migra rutas compartidas de producción a NFSv4.2 cuando sea posible. Mantén SSHFS para herramientas, no para cimientos.
  3. Añade systemd automount para montajes no críticos de arranque. Haz que “storage down” sea un estado recuperable.
  4. Establece timeouts y keepalives explícitos (NFS timeo/retrans; SSH ServerAliveInterval/CountMax).
  5. Escribe una página de runbook con los pasos rápidos de diagnóstico: check D-state, timeout stat, logs, retrans, comprobación de puertos.

El objetivo no es “nunca falla”. El objetivo es “falla de formas que puedas soportar, depurar y explicar sin mentir”. Eso evita que los montajes se conviertan en misterios—y evita que tu on-call aprenda nuevas palabras soeces.

← Anterior
ZFS sharenfs/sharesmb: Conveniencia vs Control en Producción
Siguiente →
I/O wait al 100% en Proxmox: localizar la VM/CT ruidosa y detener los congelamientos del host

Deja un comentario