De un VPS comercial al salón de casa. Parte 4 – Copia de seguridad
He dividido la copia de seguridad en dos partes. La primera comprende una copia de las carpetas donde se encuentra el contenido de las webs y las bases de datos. La segundo consiste en crear una imagen completa de la tarjeta MicroSD.
Depende de vuestro caso particular es posible que mi solución no os valga y tengáis que buscar alguna alternativa para la primera parte o simplemente descartarla.
Mi situación parte de que tengo un disco NAS con OpenWRT lo que me permite configurar una carpeta para mi copia de seguridad del server de forma muy sencilla.
Primera parte
┌─────────────────────────┐
│ Red LAN │
│ 192.168.2.0/24 │
└───────────┬─────────────┘
│
┌────────────────────────┴────────────────────────┐
│ │
┌───────────────────────┐ ┌────────────────────────┐
│ Raspberry Pi │ │ NAS OpenWrt │
│ 192.168.2.160 │ │ 192.168.2.150 │
│ │ │ │
│ Debian Bookworm │ │ OpenWrt 22.x │
│ │ │ │
│ Servicios activos │ │ Disco USB / SATA │
│ - nginx │ │ /dev/sda3 1.8T │
│ - php-fpm │ │ │
│ - bases de datos │ │ Montaje real │
│ │ │ /mnt/sda/backupRPI │
│ Script backup │ │ │
│ /usr/local/bin/ │ │ Bind mount │
│ backup_raspi.sh │ │ /backupRPI -> /mnt/sda│
│ │ │ │
│ Punto NFS │ NFSv4 │ Export NFS │
│ /mnt/backupRPI ────────────────► │ /backupRPI │
│ │ │ │
│ rsync (nice+ionice) │ │ FS ext4 │
│ │ │ │
│ Backup resultante │ │ Datos almacenados │
│ /etc │ │ current/ │
│ /var │ │ snapshot_YYYY-MM-DD │
│ /home │ │ │
│ /boot/firmware │ │ │
└───────────────────────┘ └────────────────────────┘
Configuración en el NAS
# Ver todos los discos y comprobar el disco grande df -h # Crear carpeta real de backups en el disco grande mkdir -p /mnt/sda/backupRPI # Ajustar permisos para que la Raspberry pueda escribir chown -R 1000:1000 /mnt/sda/backupRPI chmod 775 /mnt/sda/backupRPI # Crear punto exportado independiente rm -rf /backupRPI mkdir /backupRPI # Bind mount para que /backupRPI apunte al disco grande nano /etc/fstab
Tip: Nano es un editor de archivos desde línea de comandos. Siempre que tengáis que modificar un archivo simplemente pegar el contenido que se indique y a continuación pulsar CTRL+O seguido de ENTER para guardar y CTRL+X para salir.
# contenido a pegar en /etc/fstab (Guardar y salir de nano) /mnt/sda/backupRPI /backupRPI none bind 0 0 # Aplicar mounts mount -a # Configurar export NFS nano /etc/exports # contenido de /etc/exports (Guardar y salir de nano) /backupRPI 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash) # Recargar exports NFS exportfs -ra /etc/init.d/nfsd restart
Configuración en la Raspi
# Crear punto de montaje local sudo mkdir -p /mnt/backupRPI # Montar el recurso NFS del NAS sudo mount -t nfs 192.168.2.150:/backupRPI /mnt/backupRPI # Verificar tamaño correcto del destino (Debe verse el tamanño real del disco (ej: 1.8T)) df -h /mnt/backupRPI
Automatizamos la copia de archivos mediante este script de shell
# Creamos el script sudo nano /usr/local/bin/backup_raspi.sh
#!/bin/bash
set -euo pipefail
DEST="/mnt/backupRPI"
MIN_FREE_GB=20
LOCK="/tmp/backup_raspi.lock"
DATE=$(date +%F)
LOG="$DEST/backup_$DATE.log"
exec 9>"$LOCK" || exit 1
trap 'rm -f "$LOCK"' EXIT
flock -n 9 || exit 0
if ! mountpoint -q "$DEST"; then
logger -t BACKUP_RPI "ABORTADO: destino no montado"
exit 1
fi
FSTYPE=$(findmnt -n -o FSTYPE --target "$DEST")
if [[ "$FSTYPE" != nfs* ]]; then
logger -t BACKUP_RPI "ABORTADO: destino no es NFS"
exit 1
fi
FREE_GB=$(df -BG --output=avail "$DEST" | tail -1 | tr -dc '0-9')
if (( FREE_GB < MIN_FREE_GB )); then
logger -t BACKUP_RPI "ABORTADO: espacio insuficiente"
exit 1
fi
if [[ "$DEST" == "/" || "$DEST" == "/mnt" || "$DEST" == "/mnt/" ]]; then
logger -t BACKUP_RPI "ABORTADO: destino inseguro"
exit 1
fi
mkdir -p "$DEST/current"
nice -n 19 ionice -c2 -n7 rsync -a \
--numeric-ids \
--delete \
--info=stats2 \
--no-acls \
--no-xattrs \
--exclude={"/proc/*","/sys/*","/dev/*","/run/*","/tmp/*","/mnt/*","/media/*","/lost+found"} \
/etc \
/home \
/var \
/boot/firmware \
"$DEST/current" >> "$LOG" 2>&1
if [[ "$(date +%u)" -eq 7 ]]; then
cp -al "$DEST/current" "$DEST/snapshot_$DATE"
fi
# Permisos sudo chmod +x /usr/local/bin/backup_raspi.sh # Ejecutar backup manualmente (tarda unos minutos dependiendo del volumen del backup) sudo /usr/local/bin/backup_raspi.sh # Si el backup ha ido bien lo programamos # Editar cron del root sudo crontab -e # Backup diario a las 03:00 0 3 * * * /usr/local/bin/backup_raspi.sh
Diagnóstico y comprobaciones
# Ver mensajes de aborto del script journalctl -t BACKUP_RPI # Ver logs del backup del dia ls -lh /mnt/backupRPI/backup_$(date +%F).log tail -n 20 /mnt/backupRPI/backup_$(date +%F).log # Ver contenido del backup actual ls -lh /mnt/backupRPI/current du -sh /mnt/backupRPI/current
Comandos de recuperación ante fallo de la copia
# Parar una copia de seguridad colgada sudo pkill rsync # Desmontar NFS de forma segura sudo umount -l /mnt/backupRPI # Limpiar lock manualmente (solo si no hay backup activo) sudo rm -f /tmp/backup_raspi.lock
Restaurar desde la copia de seguridad
| Paso | Descripcion |
|---|---|
| Parar servicios | Evitar escrituras |
| Restaurar /etc | Configuracion |
| Restaurar /var | Datos |
| Restaurar /home | Usuarios |
| sync | Vaciar cache |
| reboot | Aplicar cambios |
# Detenemos todo lo que escriba en disco sudo systemctl stop nginx sudo systemctl stop php8.2-fpm sudo systemctl stop mariadb sudo systemctl stop postgres sudo systemctl stop smbd sudo systemctl stop cron # Restaurar en tres fases # 1) Restaurar /etc (restaura usuarios, servicios y configuraciones) sudo rsync -a \ --numeric-ids \ /mnt/backupRPI/current/etc/ \ /etc/ # 2) Restaurar /var (restaura webs, bases de datos, logs y caches) sudo rsync -a \ --numeric-ids \ /mnt/backupRPI/current/var/ \ /var/ # 3) Restaurar /home (usuarios) sudo rsync -a \ --numeric-ids \ /mnt/backupRPI/current/home/ \ /home/ # Sincronizar sync # Reiniciar sudo reboot # Comprobar tras el reinicio systemctl status nginx php8.2-fpm df -h
Segunda parte
Si no dispones de otra máquina, el plan B consiste en crear una imagen completa de la tarjeta midroSD de forma manual. Este proceso se puede hacer tanto desde Linux como desde Windows con herramientas como Raspberry Pi Imager, Win32 Disk Imager o BalenaEtcher. La únicas pegas son que mientras creas la imagen dejas el servidor fuera de servicio durante unos minutos y que tienes que tener la disciplina para crear la copia semanalmente. Por lo demás, con este método puedes tener otra microSD gemela preparada ante desastre con un lapsus de datos de 1 semana como máximo.