rsync es la herramienta estándar para copiar grandes volúmenes de datos entre servidores Linux: solo transfiere lo que ha cambiado, conserva permisos y propietarios, y puede retomar una transferencia interrumpida. En este tutorial copiarás un directorio grande de un servidor a otro por SSH con Ubuntu 24.04, harás pasadas incrementales hasta el corte final, controlarás el ancho de banda y verificarás que la copia es idéntica al original.

Requisitos previos

  • Dos servidores Linux con Ubuntu 24.04 LTS (origen y destino), por ejemplo VPS de CubePath. Los comandos sirven igual en Debian 12 y Rocky Linux 9.
  • Un usuario no root con privilegios sudo en ambos servidores.
  • Conectividad SSH desde el origen hacia el destino.
  • Espacio libre suficiente en el destino. Compruébalo antes con df -h.

En esta guía, /srv/data/ es el directorio que se copia, your_user tu usuario, y new_server_ip la IP del destino. Sustitúyelos por tus valores.

Paso 1: Instalar rsync y preparar el acceso SSH

rsync debe estar instalado en los dos extremos, porque en cada lado se ejecuta un proceso que compara los archivos. Viene instalado en Ubuntu 24.04; si no lo está:

sudo apt update
sudo apt install rsync

Comprueba la versión. A partir de la 3.2 admite compresión zstd y verificación con xxhash, que usarás más adelante:

rsync --version | head -n 1
rsync  version 3.2.7  protocol version 31

En el origen, crea una clave SSH si no tienes una y cópiala al destino para que la transferencia no pida contraseña:

ssh-keygen -t ed25519
ssh-copy-id your_user@new_server_ip

Comprueba que accedes sin contraseña:

ssh your_user@new_server_ip 'hostname'

Paso 2: Medir lo que vas a copiar

Conocer el tamaño y el número de archivos ayuda a estimar la duración y a elegir opciones. Muchos archivos pequeños se transfieren más despacio que unos pocos grandes del mismo tamaño total:

sudo du -sh /srv/data
sudo find /srv/data -type f | wc -l
412G	/srv/data
1873420

Con un enlace de 1 Gbit/s, el máximo teórico ronda los 110 MB/s, es decir, unos 400 GB por hora. En la práctica, el disco y el número de archivos suelen ser el límite.

Paso 3: Hacer una prueba en seco

Antes de transferir nada, ejecuta rsync con --dry-run (-n) para ver qué haría. Es la forma más rápida de detectar un error en las rutas:

rsync -aHAX -n --stats /srv/data/ your_user@new_server_ip:/srv/data/

Estas son las opciones que usarás en todos los comandos:

OpciónQué hace
-aModo archivo: recursivo, conserva permisos, fechas, propietarios, grupos y enlaces simbólicos
-HConserva los enlaces duros (sin esta opción, se copian como archivos independientes)
-AConserva las ACL
-XConserva los atributos extendidos
-nPrueba en seco, no transfiere nada

Paso 4: Permitir que rsync escriba como root en el destino

Para conservar propietarios y grupos distintos del tuyo, rsync tiene que ejecutarse como root en ambos lados. En el origen basta con sudo; en el destino, el proceso remoto se lanza con --rsync-path="sudo rsync", lo que requiere que sudo no pida contraseña para rsync.

En el destino, crea una regla de sudo limitada a rsync:

echo 'your_user ALL=(root) NOPASSWD: /usr/bin/rsync' | sudo tee /etc/sudoers.d/rsync-migracion
sudo chmod 440 /etc/sudoers.d/rsync-migracion
sudo visudo -c
/etc/sudoers: parsed OK
/etc/sudoers.d/rsync-migracion: parsed OK

Como en el origen rsync también se ejecutará con sudo, SSH buscará las claves de root en lugar de las tuyas. Indícale tu clave con -e. Para no repetirla, guárdala en una variable de la sesión:

SSH_CMD="ssh -i /home/your_user/.ssh/id_ed25519"

Si solo copias archivos que te pertenecen, puedes omitir sudo, --rsync-path y -e en todos los comandos siguientes.

Paso 5: Lanzar la primera transferencia

Una transferencia de horas no debe depender de que tu sesión SSH siga abierta. Ejecútala dentro de tmux, que ya viene en Ubuntu, para poder desconectarte y volver:

tmux new -s rsync

Lanza la copia completa desde el origen:

sudo rsync -aHAX --numeric-ids --partial --info=progress2 --no-inc-recursive \
  --log-file=/var/log/rsync-migracion.log \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/
  • --numeric-ids conserva los UID y GID numéricos en lugar de traducirlos por nombre. Es lo correcto en migraciones, donde los usuarios de las aplicaciones deben tener los mismos números en ambos servidores.
  • --partial guarda los archivos a medio transferir si la copia se corta, para continuar desde ahí en lugar de empezar el archivo de cero.
  • --info=progress2 muestra un único progreso global. --no-inc-recursive hace que rsync cuente todos los archivos antes de empezar, de modo que el porcentaje sea real.
  • --log-file registra cada archivo transferido y los errores.

Durante la copia verás una línea como esta:

 97,113,452,544  23%  108.52MB/s    0:14:13 (xfr#402113, to-chk=1437650/1873420)

Para salir de tmux sin detener la copia pulsa Ctrl+b y después d. Vuelve a ella con tmux attach -t rsync.

Paso 6: Ajustar la velocidad de la transferencia

Las opciones predeterminadas suelen ser las más rápidas en una red entre centros de datos. Ajusta solo si tienes un motivo concreto.

Limitar el ancho de banda para no saturar el enlace de un servidor en producción. --bwlimit acepta unidades; este ejemplo limita a 50 MB/s:

sudo rsync -aHAX --numeric-ids --partial --info=progress2 --bwlimit=50M \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Comprimir solo si la conexión es lenta (por debajo de unos 100 Mbit/s) y los datos se comprimen bien, como texto, logs o volcados SQL. Con archivos ya comprimidos (vídeo, imágenes, .gz, .zip) o en redes rápidas, la compresión consume CPU y ralentiza. Con rsync 3.2 o superior en ambos lados, usa zstd:

sudo rsync -aHAX --numeric-ids --partial --info=progress2 -z --compress-choice=zstd \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Reducir la carga del origen con nice e ionice, para que la copia ceda CPU y disco a los servicios en marcha:

sudo nice -n 10 ionice -c2 -n7 rsync -aHAX --numeric-ids --partial --info=progress2 \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Excluir lo que no hace falta migrar, como cachés o archivos temporales. Las rutas de --exclude son relativas al directorio de origen:

sudo rsync -aHAX --numeric-ids --partial --info=progress2 \
  --exclude='cache/' --exclude='*.tmp' \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Paso 7: Reanudar una transferencia interrumpida

Si la conexión se corta, rsync termina con un código de salida distinto de 0. No hace falta hacer nada especial para continuar: ejecuta exactamente el mismo comando. Los archivos que ya están completos y no han cambiado se saltan tras comparar tamaño y fecha, y gracias a --partial los archivos grandes a medias se aprovechan.

Comprueba el código de salida del último comando:

echo $?
CódigoSignificadoQué hacer
0ÉxitoNada
23Transferencia parcial por errores en algunos archivosRevisa el log: suelen ser permisos o archivos que desaparecieron
24Algunos archivos desaparecieron durante la copiaNormal si el origen está en uso; la siguiente pasada lo corrige
30Tiempo de espera agotadoRepite el comando
12, 255Error de protocolo o de SSHComprueba la conexión y la clave SSH

Para localizar los errores en el log:

sudo grep -E 'rsync: |rsync error' /var/log/rsync-migracion.log

Si la red es inestable y quieres que rsync reintente solo, una línea basta; no hace falta un script:

until sudo rsync -aHAX --numeric-ids --partial --timeout=300 \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/; do echo "Reintentando en 60 s"; sleep 60; done

--timeout=300 hace que rsync falle si no hay tráfico durante cinco minutos, en lugar de quedarse colgado.

Paso 8: Hacer la sincronización final

Si el origen sigue en uso, los datos cambian mientras copias. Por eso una migración se hace en varias pasadas: la primera copia todo y tarda horas; las siguientes solo transfieren cambios y tardan minutos. Repite la sincronización las veces que haga falta mientras el servicio sigue funcionando.

Para el corte, detén las aplicaciones que escriben en /srv/data y lanza la pasada final con --delete, que elimina en el destino los archivos borrados en el origen desde la primera copia:

sudo rsync -aHAX --numeric-ids --delete --info=progress2 \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Paso 9: Verificar la copia

Por defecto, rsync decide qué transferir comparando tamaño y fecha de modificación, y verifica cada archivo transferido con una suma de comprobación. Para asegurarte de que toda la copia es idéntica, lanza una pasada en seco con --checksum (-c), que lee y compara el contenido de cada archivo en ambos lados:

sudo rsync -aHAXc -n --numeric-ids --delete --itemize-changes \
  -e "$SSH_CMD" --rsync-path="sudo rsync" \
  /srv/data/ your_user@new_server_ip:/srv/data/

Si no muestra ninguna línea, origen y destino son idénticos. Cada línea que aparezca es un archivo diferente: por ejemplo, >fc....... indica un archivo cuyo contenido no coincide. Esta verificación lee todos los datos en los dos servidores, así que tarda casi tanto como la primera copia; hazla una vez, al final.

Como comprobación rápida adicional, compara el tamaño y el número de archivos en el destino con los del paso 2:

ssh -t your_user@new_server_ip 'sudo du -sh /srv/data; sudo find /srv/data -type f | wc -l'

Cuando termines la migración, elimina la regla de sudo del destino:

sudo rm /etc/sudoers.d/rsync-migracion

Solución de problemas

  • Se crea /srv/data/data/ en el destino: falta la barra final en la ruta de origen. Borra el directorio sobrante y repite con /srv/data/.
  • sudo: a terminal is required to read the password: falta la regla de sudo del paso 4 en el destino o la ruta de rsync no es /usr/bin/rsync. Compruébala con command -v rsync.
  • Permission denied (publickey) al usar sudo rsync: SSH está usando las claves de root. Añade -e "ssh -i /home/your_user/.ssh/id_ed25519".
  • Todos los archivos acaban con propietario root o con tu usuario: rsync no se ejecutó como root en el destino. Usa --rsync-path="sudo rsync".
  • La transferencia es muy lenta con millones de archivos pequeños: el cuello de botella son las operaciones por archivo, no la red. Si el directorio no cambia durante la copia, empaquetarlo con tar y enviarlo por SSH suele ser más rápido para la primera copia; usa después rsync para las pasadas incrementales.

Conclusión

Has copiado un directorio grande entre servidores con rsync conservando permisos, propietarios, ACL y enlaces duros, con una transferencia que sobrevive a cortes, y has verificado con sumas de comprobación que el destino es idéntico al origen. Como siguientes pasos, planifica el orden de las pasadas incrementales dentro de tu plan de migración y, si necesitas mantener los datos sincronizados de forma continua hasta el corte, valora herramientas como lsyncd.