1 estrella2 estrellas3 estrellas4 estrellas5 estrellas (1 votos, promedio: 5,00 de 5)
Cargando...

Hoy en día, la mayoría de proveedores de alojamiento web ya ofrecen gratuitamente un servicio de copias de seguridad, pero en algunos casos te puede interesar tenerlo en tu equipo en local, o tal vez tengas un servidor dedicado y quieras tener tus archivos a buen recaudo en tu casa. Por este motivo voy a compartir un script para poder tener un backup de tu web con un sistema Linux, y completamente automatizado.

Para tener este sistema de copias completamente automatizado, necesitamos un script y tener configurado un administrador de procesos como es systemd.

Funciones y características del script

El script crea en nuestra home local una carpeta llamada Backups donde se guardan todas las copias. Es compatible con Archlinux, Debian y sus derivadas.

  • Crea las carpetas necesarias.
  • Crea una clave ssh pública.
  • Envía nuestra clave al servidor host.
  • Detecta que distribución utilizamos e instala las dependencias necesarias.
  • Crea una copia completa cada día 1 del mes. Esta es permanente y nunca se elimina.
  • Crea una copia completa cada lunes. Esta solo se conserva 1 semana.
  • De martes a domingo hace copias diferenciales sobre la del lunes.
  • Todos los días hace un backup de la base de datos.

Diagrama de como quedan las carpetas creadas:

Esquema de carpetas - Backup de tu Web con un sistema Linux

Primero que nada, vamos a hacer una explicación del funcionamiento del Script separándolo por secciones. Explicaremos que se debe y que no se debe modificar.

Luego explicaremos como activar el proceso para que inicie automáticamente. Veremos que es un poco diferente dependiendo de la distribución que utilicemos.

El Script

Vamos a explicar por partes cada sección que función tiene.

#!/bin/bash
## VARIABLES ##

nom="MyWeb"
origen="CarpetaOrigen"

# Datos conexión SSH #
sshUser="UserSsh"
sshPass="PassSsh"
sshHost="HostSsh"

# Datos conexión DATABASE #
dbUser="UserDB"
dbPass="PassDB"
dbHost="HostDB"
dbName="NombreDB"

# Directorios #
dest="$HOME/Backups/$nom/Temporales/archivos"
destMes="$HOME/Backups/$nom/Mensuales"
destDb="$HOME/Backups/$nom/Temporales/DB"
logs="$HOME/Backups/$nom/Temporales/logs"

rutas=(" $dest $logs $destDb $destMes " )
deps=(" openssh mariadb expect tar rsync curl" )
deps_deb=(" openssh-client mariadb-client expect tar rsync curl" )

fecha="$(date '+%d-%m-%Y_%H:%M')"
diaSem="$(date '+%u')"
diaSemA="$(date '+%A')"
diaNum="$(date '+%d')"
diaMes="$(date '+%d_%B')"
lun="$(date -dlast-monday +%A)"	

Este primer bloque son las variables que utilizamos. Aquí hay algunos campos que debemos actualizar con nuestros datos, pero solo los que especifico a continuación. Cambiar otros campos ocasionará que deje de funcionar el script.

Campos a configurar:

nom="MyWeb"															
origen="CarpetaOrigen"

# Datos conexión SSH #
sshUser="UserSsh"														
sshPass="PassSsh"													
sshHost="HostSsh"													

# Datos conexión DATABASE #
dbUser="UserDB"														
dbPass="PassDB"														
dbHost="HostDB"															
dbName="NombreDB"
  • nom: Pondremos el nombre con el que queramos identificar la web que le hacemos backup. Ejemplo: Catlinux
  • origen: El nombre de la carpeta donde se aloja nuestra web, por ejemplo: worldpress
  • Datos conexión SSH: escribiremos los datos correspondientes.
  • Datos conexión DATABASE: Igual que arriba, pondremos los datos de nuestras bases de datos.
  • Directorios: Podemos cambiarlo, pero son unas rutas adecuadas y recomendadas.

Los siguientes bloques ya no deben tocarse, pero vamos a explicarlos uno por uno.

Clave ssh:

# CREA LA CLAVE SSH SI NO ESTÁ CREADA EN NUESTRO EQUIPO
if [ ! -f $HOME/.ssh/idrsa-1 ]; then
  ssh-keygen -t rsa -N "$sshPass" -f $HOME/.ssh/idrsa-1
	expect << EOF
		spawn ssh-add $HOME/.ssh/idrsa-1
		expect "Enter passphrase for $HOME/.ssh/idrsa-1:"
		send "$sshPass\r"
		expect eof
EOF
fi

# INTRODUCIMOS EN EL EQUIPO REMOTO LA CLAVE SSH SI NO EXISTE
expect -c "
  log_user 0
	spawn ssh-copy-id -i $HOME/.ssh/idrsa-1.pub -o StrictHostKeyChecking=no ${sshUser}@${sshHost}
  match_max 100000
	expect \"*?assword:*\" { send -- \"$sshPass\r\"}
	sleep 1
	log_user 1
	exit"

La primera parte, tiene la función de crear la clave pública para conectarse remotamente mediante ssh. Básicamente comprueba si la tienes creada, y si no la tienes, la crea en una carpeta oculta llamada ssh en tu directorio home.

La segunda parte la manda nuestra clave pública al servidor remoto, para de esta forma conectarse sin que nos pida la contraseña cada vez. Sin esta parte, no podemos tener las copias automatizadas, ya que tendríamos que poner siempre la contraseña.

# COMPROBAMOS SI TENEMOS LOS DIRECTORIOS PARA LAS COPIAS, DE LO CONTRARIO LOS CREA
for f in $rutas; do
	[ -d $rutas 2> /dev/null ] && direc+="$f " || ndirec+="$f "
done
mkdir -p $ndirec

En una variable anterior, especificamos los directorios que se necesitan para guardar los backups. Estas líneas comprueban que estén creados, y si no lo están, se encarga de crearlos automáticamente.

# COMPROBAMOS E INSTALAMOS LOS PAQUETES NECESARIOS PARA DISTRIBUCIONES ARCHLINUX Y DEBIAN
install_deps () {
	if [ -x "$(command -v apt-get)" ]; then
		for e in ${deps_deb[*]}
		do
			if ! (which $e >/dev/null); then
				insta_deb=$insta_deb" "$e
			fi
		done
		if [ -n "$insta_deb" ]; then
			echo "Necesitamos instalar: $insta_deb"
			sleep 3
			sudo apt install -y $insta_deb
		fi
	elif [ -x "$(command -v pacman)" ]; then
		for d in ${deps[*]}
		do
			if ! (pacman -Q $d >/dev/null); then
				insta_arch=$insta_arch" "$d
			fi
		done
		if [ -n "$insta_arch" ]; then
			echo "Necesitamos instalar: $insta_arch"
			sleep 3
			sudo pacman -S $insta_arch --noconfirm
		fi
	else
		echo "Este gestor de paquetes no es compatible con el script. Instala las dependencias manualmente." >&2;
		exit 1;
	fi
}

install_deps

Esta parte lo que hace es comprobar que distribución tenemos instalada, y si es una de las dos compatibles o una derivada, instala los paquetes necesarios para que funcione el script correctamente.

# Copia mensual completa - se realiza cada día 1
if [ $diaNum = "01" ]; then
	rsync -avzz --delete --timeout=20 -e "ssh" $sshUser@$sshHost:$origen/ $destMes/$diaMes > $logs/back_$fecha.log 2>&1
	ssh $sshUser@$sshHost "mysqldump -h $dbHost -u $dbUser -p$dbPass -B $dbName | gzip -9 -c" > $destMes/$diaMes/DB_$diaMes.sql.gz
	tar -cjf $destMes/$nom_$diaMes.tar.bz2 $destMes/$diaMes
	rm -Rf $destMes/$diaMes
fi

# Copia semanal completa - se realiza cada domingo
if [ $diaSem = "1" ]; then
	rsync -avzz --delete --timeout=20 -e "ssh" $sshUser@$sshHost:$origen/ $dest/$diaSemA > $logs/back_$fecha.log 2>&1
else
	rsync -avzz --delete --timeout=20 --compare-dest=$dest/$lun -e "ssh" $sshUser@$sshHost:$origen/ $dest/$diaSemA > $logs/back_$fecha.log 2>&1
fi

# RESPALDO DE LA BASE DE DATOS - Todos los días menos el 1ero de cada mes
if [ ! $diaNum = "01" ]; then
	ssh $sshUser@$sshHost "mysqldump -h $dbHost -u $dbUser -p$dbPass -B $dbName | gzip -9 -c" > $destDb/DB_$diaMes.sql.gz
fi

Esta es la parte de la copia, donde en el primer párrafo comprueba si es día primero de mes y si lo es hace una copia completa de archivos y copia de la base de datos. Lo pone en la misma carpeta y lo comprime. Si no es día uno, se salta este apartado.

El segundo párrafo, comprueba si es domingo, y en caso afirmativo hace una copia de todos los archivos en una carpeta con nombre domingo. Si es la primera vez se crea y copian ficheros, y si ya está hecha de otras semanas la sobreescribe, por lo que no se acumulan nunca más de un domingo.

Si no es domingo se salta este párrafo y pasa al tercero, donde hace una copia diferencial sobre el último domingo, copiando solamente los archivos que han cambiado, y de esta forma ahorrando espacio.

Al final de este bloque, si no es día 1 de cada mes, hace un backup de la base de datos y la guarda en una carpeta destinada a las bases de datos.

# BORRAD0 DE ARCHIVOS ANTIGUOS - Se eliminan los logs y bases de datos de más de un mes de antiguedad.
find $logs/* -type f -mtime +30 -exec rm -f \{\} \;
find $destDb/* -type f -mtime +30 -exec rm -f \{\} \;

Para terminar, el último bloque lo que hace es eliminar los archivos log y los backups de las bases de datos de más de un mes de antigüedad.

Puedes descargar el script completo de aquí: Script BackupHost

El administrador de procesos systemd.

Para automatizar el proceso, nos ayudaremos del administrador de procesos systemd. Mi primera intención era utilizar cron, pero al activar el proceso utilizaba una identidad diferente y no podía conectar al servidor con la clave pública del usuario y generaba un error. Por este motivo, aunque es un poco más laborioso de configurar utilizaremos systemd.

Cambia un poco de Archlinux a Debian, ya que en Arch debemos crear un proceso del propio usuario, y en Debian lo instalaremos como proceso del sistema. Esta es la forma que he conseguido que me funcione en ambos sistemas. De todos modos, seguiré investigando para unificar y facilitar el proceso y añadir compatibilidad con más distribuciones.

Archlinux:

Como hemos dicho, en Archlinux lo instalaremos como un proceso del usuario. Primero crearemos la carpeta que contendrá los archivos de servicio. No utilicemos sudo en ningún momento, ya que trabajamos siempre desde el mismo usuario:

$ mkdir -p .config/systemd/user

Ahora creamos el archivo del servicio:

$ nano .config/systemd/user/backuphost.service

En su interior pegaremos el siguiente contenido.

[Unit]
Description=Script para copias de seguridad de la web

[Service]
WorkingDirectory=/home/USUARIO/Scripts
ExecStart=/bin/bash /home/USUARIO/Scripts/BackupHost.sh

[Install]
WantedBy=multi-user.target

Debemos sustituir USUARIO por nuestro nombre de usuario. Guardamos y cerramos.

Vamos por el siguiente archivo:

$ nano .config/systemd/user/backuphost.timer
[Unit]
Description=Timer para Script BackupHost

[Timer]
OnCalendar=*-*-* 00:01:00
Persistent=true

[Install]
WantedBy=timers.target

En este archivo podemos modificar 00:01:00. Esto es la hora a la que se ejecuta el script. En mi caso se ejecuta pasado un minuto de la medianoche todos los días. Si por ejemplo queremos que se ejecute a las cinco y media de la tarde pondremos 17:30:00.

Ya podemos guardar y cerrar. Ahora vamos a iniciar y revisar que esté correcto.

Recargamos los servicios del usuario activo con:

$ systemctl --user daemon-reload

Para iniciar el servicio y que arranque después de reiniciar el equipo, ejecutaremos:

$ systemctl --user start backuphost.timer
$ systemctl --user enable backuphost.timer

Solamente queda revisar si a iniciado sin problemas con:

$ systemctl --user list-timers
Servicio funcionando en Archlinux

Como veis no debe dar ningún error. Si nos aparece un mensaje parecido a este sin retornar errores ya lo tenemos funcional.

Debian:

En el caso de Debian, el servicio debemos instalarlo como proceso del sistema, como usuario no nos funcionará. Empecemos creando el primer archivo. En este caso si necesitamos hacer uso de sudo:

$ sudo nano /etc/systemd/system/BackupHost.service

Copiamos lo siguiente:

[Unit]
Description=Script para copias de seguridad de la web

[Service]
WorkingDirectory=/home/USUARIO/Scripts
ExecStart=/bin/bash /home/USUARIO/Scripts/BackupHost.sh
User=USUARIO

[Install]
WantedBy=multi-user.target

Igual que antes cambiamos USER por nuestro usuario. También veis que hemos añadido una línea que en Archlinux no poníamos. “User=USUARIO“, le especificamos que el servicio debe iniciarse con nuestro usuario, o de lo contrario no nos conectaría al remoto por ssh con nuestras claves públicas y nos retornaría un error.

Crearemos y editaremos el siguiente archivo:

$ sudo nano /etc/systemd/system/BackupHost.timer
[Unit]
Description=Timer para Script BackupHost

[Timer]
OnCalendar=*-*-* 00:01:00
Persistent=true

[Install]
WantedBy=timers.target

Igual que con Archlinux, aquí podemos editar la hora del proceso si es necesario.

Ya solo queda recargar, activar, iniciar y comprobar:

$ sudo systemctl daemon-reload
S sudo systemctl start BackupHost.timer
$ sudo systemctl enable BackupHost.timer
$ sudo systemctl list-timers
Servicio funcionando en Debian

Con esto hemos terminado de configurar nuestro sistema de copias. A continuación dejo enlaces de descarga y fuentes de información.


Descarga:

https://gitlab.com/catlinux/BackupHost

Fuentes:

https://es.stackoverflow.com/

https://wiki.archlinux.org/index.php/Systemd_(Espa%C3%B1ol)/Timers_(Espa%C3%B1ol)

https://wiki.archlinux.org/index.php/Systemd_(Espa%C3%B1ol)

https://wiki.archlinux.org/index.php/Rsync

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *