Saltar al contenido

Sincronización de datos entre servidores con GNU Debian (backup o copia de seguridad de web Apache base de datos Mariadb o Mysql)

La migración o respaldo de grandes directorios (en este caso, 36 GB) entre servidores remotos presenta desafíos de permisos, estabilidad de conexión y seguridad. A continuación, se detalla el procedimiento profesional para realizar una sincronización íntegra utilizando rsync sobre un puerto SSH no estándar y con elevación de privilegios.

1. Introducción al Escenario

El objetivo es copiar el contenido de un directorio protegido (/mnt/www_data/) desde un Servidor Origen (Remote) hacia un Servidor de Destino (Local), bajo las siguientes condiciones:

  • Acceso SSH: Puerto personalizado (ej. 2222).
  • Privilegios: El usuario requiere sudo para leer los datos de origen.
  • Eficiencia: Sincronización incremental (solo copia lo que ha cambiado).

2. Preparación del Servidor Origen

Para que el proceso sea automatizado o fluido, el usuario remoto debe poder ejecutar el binario de rsync con privilegios de superusuario sin que la terminal se bloquee pidiendo una contraseña de sudo.

Configuración de Sudoers

  1. Acceda al servidor de origen vía SSH.
  2. Ejecute el comando: sudo visudo.
  3. Al final del archivo, añada la siguiente regla (reemplace usuario_remoto por el suyo):
    usuario_remotoALL=(ALL) NOPASSWD: /usr/bin/mysqldump, /usr/bin/mysql, /usr/bin/mkdir, /usr/bin/chown, /usr/bin/rsync, /usr/bin/rm
    Esta configuración permite que rsyncy Mariadb lean archivos restringidos sin intervención humana durante la transferencia.

3. Ejecución del Comando de Sincronización

Desde el Servidor de Destino, utilizaremos rsync con una combinación de flags optimizada para grandes volúmenes de datos.

El comando maestro

rsync -avhP -e "ssh -p 2222" --rsync-path="sudo rsync" usuario_remoto@servidor_origen.pe:/mnt/www_data /ruta/local/backup/

Desglose de Parámetros:

  • -a (Archive): Preserva permisos, propietarios, grupos y fechas de modificación. Es recursivo.
  • -v (Verbose): Muestra los detalles de los archivos que se están procesando.
  • -h (Human-readable): Muestra los tamaños de archivo en formato legible (KB, MB, GB).
  • -P (Progress + Partial): * Muestra una barra de progreso y velocidad en tiempo real.
    • Permite reanudar la transferencia si la conexión se corta, manteniendo los archivos parcialmente descargados.
  • -e "ssh -p 2222": Especifica el protocolo de transporte y el puerto personalizado.
  • --rsync-path="sudo rsync": Instruye al servidor remoto a ejecutar rsync como root, permitiendo la lectura de archivos con permisos restringidos.

4. Consideraciones sobre el Slash (/) en las Rutas

En rsync, la barra diagonal final en la ruta de origen cambia el comportamiento drásticamente:

  • .../mnt/www_data (Sin barra): Copia la carpeta y su contenido. El resultado será /backup/www_data/...
  • .../mnt/www_data/ (Con barra): Copia únicamente el contenido de la carpeta. El resultado será /backup/archivo1/backup/archivo2, etc.

5. Gestión de Sesiones con Screen

Debido a que 36 GB pueden tardar varias horas, es crítico evitar que la transferencia se detenga si cerramos nuestra terminal local o si el equipo entra en suspensión.

  1. Instale screen: sudo apt install screen.
  2. Inicie una sesión: screen -S backup_proceso.
  3. Ejecute el comando rsync.
  4. Para desconectarse sin detener el proceso: Presione Ctrl + A y luego D.
  5. Para retomar el monitoreo: Escribe screen -r backup_proceso.

6. Verificación de Integridad

Una vez finalizada la transferencia, es vital confirmar que el tamaño de los datos en ambos extremos coincida.

En el Origen y Destino ejecute:

Bash

du -sh /ruta/del/directorio

Para una verificación más exhaustiva (Checksum): Si sospecha de archivos corruptos, añada el flag -c a su comando rsync. Esto comparará los archivos mediante hashes MD5 en lugar de solo tamaño y fecha, aunque consume más recursos de CPU.

7. Seguridad Post-Transferencia

Una vez completada la migración, se recomienda revertir los cambios en el archivo sudoers del servidor origen para mantener el principio de menor privilegio:

  1. Ejecute sudo visudo.
  2. Comente la línea agregada:Bash# usuario_remoto ALL=(ALL) NOPASSWD: /usr/bin/rsync

8. Automatización mediante Cron Jobs (Respaldo Incremental)

Una de las mayores ventajas de rsync es su capacidad para realizar respaldos incrementales. Esto significa que, después de la primera copia de 36 GB, las siguientes ejecuciones solo transferirán los archivos nuevos o modificados, reduciendo el tiempo de horas a pocos minutos.

Paso 1: Configuración de Llaves SSH (Sin Contraseña)

Para que un script automatice la tarea, no puede detenerse a pedir una contraseña. Debemos establecer una relación de confianza entre los servidores.

  1. Generar llave en el servidor de destino: ssh-keygen -t rsa -b 4096 (Presione Enter a todo).
  2. Enviar la llave al servidor de origen: ssh-copy-id -p 2222 usuario_remoto@servidor_origen.pe
    o
    ssh-copy-id -p 2222 usuario_remoto@192.168.1.2
    Qué pasará después:
    Te pedirá la contraseña de usuario_remoto. o preguntará con. «Are you sure you want to continue connecting (yes/no/[fingerprint])?» responder: Yes
  3. Verás un mensaje confirmando: Number of key(s) added: 1.
  4. ¡Listo! A partir de ese segundo, el «túnel» entre tu servidor destino y el servidor origen estará abierto y será permanente.
  5. Prueba: Intente conectar por SSH. Si entra sin pedir clave, la automatización es posible.

Paso 2: Creación del Script de Respaldo

Antes de crear el archivo .sh, debemos preparar la estructura de carpetas y los registros (logs) en tu máquina local.

1. Definir la Estructura de Directorios

Es una buena práctica separar el script de los datos y de los reportes de error. Ejecuta estos comandos en tu Debian 11:

Bash

# Crear carpeta para los scripts
mkdir -p ~/scripts

# Crear carpeta para los registros (logs)
mkdir -p ~/backup/logs

# Crear la carpeta donde se mantendrá la copia sincronizada
mkdir -p ~/backup/sincronizacion_continua

2. Verificar la Ruta del Binario de Rsync

El script necesita saber exactamente dónde está rsync para evitar errores de «comando no encontrado». Confirma la ruta con:

Bash

which rsync

(Normalmente responderá /usr/bin/rsync).

Cree un archivo llamado backup_diario.sh en su servidor de destino con el siguiente contenido:

#!/bin/bash

# =================================================================
# SCRIPT DE RESPALDO DIARIO
# Descripción: Genera volcados SQL individuales y sincroniza archivos
# =================================================================

# 1. CONFIGURACIÓN
FECHA=$(date +%Y-%m-%d_%H-%M)
LOG_FILE="/home/usuariodestino/backup/logs/backup_$FECHA.log"
ORIGEN_IP="192.168.1.2"
USUARIO_REMOTO="usuario_remoto"
PUERTO_SSH="2222"
DIR_ORIGEN="/mnt/www_data"
DIR_DESTINO="/home/usuariodestino/backup/sincronizacion_continua"
DIR_SQL_REMOTO="/mnt/www_data/backups_sql"

# Crear carpetas locales si no existen
mkdir -p /home/usuariodestino/backup/logs
mkdir -p $DIR_DESTINO

echo "==========================================================" >> $LOG_FILE
echo "INICIO DEL PROCESO: $(date)" >> $LOG_FILE
echo "==========================================================" >> $LOG_FILE

# 2. GENERACIÓN DE SQL EN EL SERVIDOR REMOTO (DERECHO)
echo "[1/3] Generando volcados SQL en origen..." >> $LOG_FILE
ssh -p $PUERTO_SSH $USUARIO_REMOTO@$ORIGEN_IP << 'EOF' >> $LOG_FILE 2>&1
    # Preparar directorio de volcado
    sudo mkdir -p /mnt/www_data/backups_sql
    sudo chown usuario_remoto:usuario_remoto /mnt/www_data/backups_sql

    # Rutas absolutas
    MYSQL="/usr/bin/mysql"
    DUMP="/usr/bin/mysqldump"

    # Obtener lista de bases de datos con sudo
    DBS=$(sudo $MYSQL -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")

    for DB in $DBS; do
        echo "Exportando base de datos: $DB"
        sudo $DUMP --single-transaction --quick --lock-tables=false "$DB" > "/mnt/www_data/backups_sql/${DB}.sql"
    done
    echo "Volcados SQL completados con éxito."
EOF

# 3. SINCRONIZACIÓN DE ARCHIVOS Y SQL (RSYNC)
echo "[2/3] Iniciando sincronización Rsync (36GB aprox)..." >> $LOG_FILE
# -a: archivo, -v: verboso, -h: legible, --delete: para espejar exactamente el origen
rsync -avh --delete -e "ssh -p $PUERTO_SSH" --rsync-path="sudo rsync" \
$USUARIO_REMOTO@$ORIGEN_IP:$DIR_ORIGEN/ $DIR_DESTINO/ >> $LOG_FILE 2>&1

# 4. VALIDACIÓN DE RESULTADO Y LIMPIEZA
if [ $? -eq 0 ]; then
    echo "[3/3] Sincronización exitosa. Limpiando archivos temporales en origen..." >> $LOG_FILE
    ssh -p $PUERTO_SSH $USUARIO_REMOTO@$ORIGEN_IP "sudo rm -f $DIR_SQL_REMOTO/*.sql" >> $LOG_FILE 2>&1
    echo "==========================================================" >> $LOG_FILE
    echo "RESULTADO: RESPALDO COMPLETADO Y LIMPIO" >> $LOG_FILE
else
    echo "==========================================================" >> $LOG_FILE
    echo "RESULTADO: ERROR EN LA TRANSFERENCIA. REVISAR LOG." >> $LOG_FILE
fi

echo "FIN DEL PROCESO: $(date)" >> $LOG_FILE
echo "==========================================================" >> $LOG_FILE

Script opcional para notificación vía email desde el servidor de origen, para ello debe tener instalado «msmtp» el servidor de origen.

#!/bin/bash

# =================================================================
# SCRIPT DE RESPALDO COMPLETO + NOTIFICACION CON EMAIL
# Emisor/Receptor: usuario.remoto@servidororigen.pe
# =================================================================

# 1. CONFIGURACIÓN
FECHA=$(date +%Y-%m-%d_%H-%M)
LOG_FILE="/home/usuariodestino/backup/logs/backup_$FECHA.log"
ORIGEN_IP="192.168.1.2"
USUARIO_REMOTO="usuario_remoto"
PUERTO_SSH="2222"
DIR_ORIGEN="/mnt/www_data"
DIR_DESTINO="/home/usuariodestino/backup/sincronizacion_continua"
DIR_SQL_REMOTO="/mnt/www_data/backups_sql"
EMAIL_CUENTA="usuario.remoto@servidororigen.pe"

mkdir -p /home/usuariodestino/backup/logs

echo "==========================================================" >> $LOG_FILE
echo "INICIO DEL PROCESO: $(date)" >> $LOG_FILE
echo "==========================================================" >> $LOG_FILE

# 2. GENERACIÓN DE SQL EN ORIGEN
echo "[1/3] Generando volcados SQL en origen..." >> $LOG_FILE
ssh -p $PUERTO_SSH $USUARIO_REMOTO@$ORIGEN_IP << 'EOF' >> $LOG_FILE 2>&1
    sudo mkdir -p /mnt/www_data/backups_sql
    sudo chown usuario_remoto:usuario_remoto /mnt/www_data/backups_sql
    
    DBS=$(sudo /usr/bin/mysql -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")
    
    for DB in $DBS; do
        echo "Respaldando: $DB"
        sudo /usr/bin/mysqldump --single-transaction --quick --lock-tables=false "$DB" > "/mnt/www_data/backups_sql/${DB}.sql"
    done
EOF

# 3. SINCRONIZACIÓN RSYNC
echo "[2/3] Sincronizando archivos hacia Debian 11..." >> $LOG_FILE
rsync -avh --delete -e "ssh -p $PUERTO_SSH" --rsync-path="sudo rsync" \
$USUARIO_REMOTO@$ORIGEN_IP:$DIR_ORIGEN/ $DIR_DESTINO/ >> $LOG_FILE 2>&1

# 4. VALIDACIÓN Y LIMPIEZA
if [ $? -eq 0 ]; then
    echo "[3/3] Sincronización exitosa. Limpiando origen..." >> $LOG_FILE
    ssh -p $PUERTO_SSH $USUARIO_REMOTO@$ORIGEN_IP "sudo rm -f $DIR_SQL_REMOTO/*.sql" >> $LOG_FILE 2>&1
    ESTADO_FINAL="EXITOSO"
else
    echo "[!] ERROR EN RSYNC. No se limpió el origen." >> $LOG_FILE
    ESTADO_FINAL="FALLIDO"
fi

echo "FIN: $(date)" >> $LOG_FILE
echo "==========================================================" >> $LOG_FILE

# 5. ENVÍO DE CORREO (AUTO-ENVÍO)
# Forzamos el remitente con el flag -from de msmtp para asegurar la entrega
(
  echo "Subject: Reporte Backup FCJP ($ESTADO_FINAL) - $FECHA"
  echo "From: $EMAIL_CUENTA"
  echo "To: $EMAIL_CUENTA"
  echo ""
  tail -n 35 "$LOG_FILE"
) | ssh -p $PUERTO_SSH $USUARIO_REMOTO@$ORIGEN_IP "msmtp --from=$EMAIL_CUENTA $EMAIL_CUENTA"

Notas

El flag --delete es opcional. Si lo activa, los archivos que borre en el servidor de origen también se borrarán en el destino, manteniendo un espejo exacto.

Explicación:

  1. Validación de Red (ping): Antes de intentar copiar nada, el script verifica si el servidor origen responde por la IP privada. Si el cable se desconectó, el script se detiene y te avisa en el log.
  2. Opción --delete: Es vital para un respaldo incremental tipo «espejo». Si borras una imagen basura en el servidor origen, el script también la borrará en tu Debian 11 para no acumular basura y ahorrar espacio.
  3. Manejo de Logs: Cada vez que el script corra, creará un archivo con la fecha (ej. backup_2026-02-24_02-00.log). Esto te permite auditar qué archivos se bajaron y si hubo errores.
  4. BatchMode=yes: Fuerza a SSH a fallar de inmediato si por alguna razón vuelve a pedir contraseña, evitando que el script se quede «colgado» infinitamente esperando una entrada manual.
    Seguridad Anti-Fallos: Explica que el condicional if [ $? -eq 0 ] actúa como un seguro de vida. Si el cable de red se desconecta o el disco se llena en medio del proceso, los archivos SQL se quedan en el servidor origen para que no pierdas nada.
  5. Higiene del Servidor: Al usar rm -f $DIR_SQL_REMOTO/*.sql al final, el servidor de producción (origen) se mantiene siempre con espacio libre, evitando que los respaldos afecten el funcionamiento de la web.
  6. Persistencia en el Destino: Aunque se borren en el origen, en tu Debian 11 (destino) los archivos seguirán existiendo dentro de la carpeta sincronizacion_continua/backups_sql/ hasta que el próximo respaldo exitoso los actualice.

Para que el sistema lo reconozca como un programa ejecutable, debes darle el permiso x. Ejecuta este comando:

chmod +x ~/scripts/backup_diario.sh

Pruebas

Es totalmente comprensible, esperar a que se sincronicen 36 GB solo para ver si el script funciona es poco práctico. Para probar la «lógica» del script (que conecte bien, que escriba el log y que encuentre las rutas) sin transferir los datos, tienes dos caminos rápidos:

Opción 1: El «Simulador» (--dry-run)

Esta es la mejor opción. Le dice a rsync que haga todo excepto copiar los archivos. Te mostrará qué archivos copiaría pero sin mover un solo byte real.

  1. Abre tu script: nano ~/scripts/backup_diario.sh
  2. Busca la línea de rsync y añade --dry-run:Bashrsync -avh --delete --dry-run \ -e "ssh -p $PUERTO_SSH -o BatchMode=yes" \ ...
  3. Guarda (Ctrl+O) y sal (Ctrl+X).
  4. Ejecútalo: bash ~/scripts/backup_diario.sh.
  5. Revisa el log: cat ~/backup/logs/backup_*.log. Verás que termina en segundos y dice «(DRY RUN)».

Opción 2: Probar con un solo archivo pequeño

Si quieres ver un archivo real siendo transferido para estar 100% seguro, puedes limitar el rsync para que solo vea un archivo específico (por ejemplo, el SQL que generamos).

Modifica temporalmente la variable DIR_ORIGEN en tu script:

Bash

# Cambia esto solo para la prueba:
DIR_ORIGEN="/mnt/www_data/backups_sql/db_full_backup.sql.gz"

Al ejecutar el script, solo buscará ese archivo, lo transferirá (o verá que ya existe) y terminará de inmediato.


¿Qué debes revisar en el Log tras la prueba?

  1. Verifica el resultado en la carpeta de destino:
    ls -l /home/usuariodestino/backup/sincronizacion_continua/ (Deberías ver el archivo nombrearchivoprueba.php allí, o la estructura de carpetas que lo contiene).
  2. Verifica que el log se haya creado correctamente:Bashls -l ~/backup/logs/ cat ~/backup/logs/backup_$(date +%Y-%m-%d)*.log

Independientemente de la opción que elijas, verifica que el log contenga estas líneas:

  • «Sincronizando datos…»: Indica que pasó la prueba del ping.
  • «SENT… RECEIVED…»: Al final del log de rsync, esto confirma que hubo comunicación.
  • «RESPALDO COMPLETADO EXITOSAMENTE»: Esto confirma que la lógica de salida ($?) del script funciona.

Importante: Una vez que estés satisfecho con la prueba, recuerda quitar el --dry-run o restaurar la ruta DIR_ORIGENoriginal para que el respaldo real pueda suceder.

Paso 3: Programación en el Crontab

Para que el script se ejecute, por ejemplo, todos los días a las 01:00 horas, siga estos pasos:

  1. De permisos de ejecución al script: chmod +x backup_diario.sh
  2. Abra el editor de cron: crontab -e
    si es la primera vez, aparcera algo parecido a esto, presiona 1 para usar nano:
usuariodestino@debian11:~/backup/scripts$ crontab -e
no crontab for usuariodestino - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.tiny

Choose 1-2 [1]: 

1. Agregar la tarea

Baja hasta el final del archivo con las flechas del teclado y pega esta línea:

00 01 * * * /home/usuariodestino/backup/scripts/backup_diario.sh

2. Guardar y Salir

  • Presiona Ctrl + O (para escribir los cambios).
  • Presiona Enter (para confirmar el nombre del archivo).
  • Presiona Ctrl + X (para salir del editor).

3. Confirmar que se guardó

Si todo salió bien, la terminal te mostrará el mensaje: crontab: installing new crontab

Puedes verificarlo listando las tareas activas:

crontab -l
Publicado enManuales