Como saben, Linuxito ha migrado de un servicio de hosting tradicional (donde te dan un espacio y un panel de control en un servidor compartido) a un VPS (Virtual Private Server). ¿Qué es un VPS? Una simple máquina virtual (KVM, VMware, Hyper-V, VirtualBox) o contenedor (Docker, Jails, LXC) en la nube (cloud, en un centro de cómputos remoto). Un servicio de hosting compartido nos da todo "digerido", mientras que, cuando se trabaja con un VPS, uno es responsable de todo lo relacionado a software y servicios. Este artículo sirve como guía para aquellos administradores de sitios Web, montados en servidores virtuales en la nube, que desean implementar un sistema de copias de seguridad (backup) simple, eficiente y seguro, utilizando sólo las herramientas al alcance de la mano (sin recurrir a software específico de backup).

En un servicio de hosting tradicional, el proveedor sólo da acceso a un panel de control (típicamente CPanel, Webmin, WHM u otro) desde el cual el Webmaster (administrador del sitio Web) puede gestionar, con una herramienta gráfica, los recursos del servicio (archivos, bases de datos, copias de seguridad, certificados, dominio y más). La ventaja que tiene esta alternativa es que al servidor lo administra otro, todos los servicios están instalados y configurados, el servidor se actualiza automáticamente (al menos es lo esperable). No es necesario tener conocimientos de sistemas operativos y redes, y toda la tecnología es transparente. Esto significa que los backups se realizan automáticamente; el servicio de correo simplemente funciona y se accede desde un cliente Web (y tal vez mediante POP/IMAP); los archivos se administran con un gestor de archivos Web, al igual que la base de datos ("la" porque generalmente proveen una sola base de datos) con phpMyAdmin; incluso servicios de bajo nivel como DNS se gestionan desde un panel Web. En definitiva, todo está pensado para que una persona pueda gestionar su sitio Web sin contar con conocimiento alguno de sistemas operativos y servicios de Internet.

Sin embargo, la desventaja principal es la poca flexibilidad y disponibilidad de recursos. Uno generalmente no puede personalizar servicio alguno ni modificar archivos de configuración, y está limitado a los recursos asignados: poco espacio en disco, una o dos bases de datos, etc. Tampoco es posible utilizar el servidor con otro propósito que no sea el de servir páginas Web, ya que muy pocos proveedores permiten el acceso a una shell en el servidor. Ni mucho menos instalar software o controlar las versiones de los servicios básicos de Internet como Apache, PHP, MySQL, etc.

Pero hay otra desventaja, tal vez muy importante para los motores de búsqueda (SEO), que es el hecho de compartir la dirección IP. ¿Qué significa compartir la dirección IP? Que existe más de un dominio asociado a la misma dirección IP. Esto se debe a que se comparte el servidor Web con "vecinos" desconocidos, lo cual puede tener muchas implicancias negativas, principalmente desde el punto de vista de seguridad. Piensen qué sucede si se produce una brecha de seguridad en otro sitio alojado en el mismo servidor. Nuestro sitio podría ser comprometido a causa de un "vecino" poco seguro. A su vez esto podría marcar a la dirección IP del servidor (nuestra dirección IP) como insegura (mucho peor si uno de nuestros vecinos es un spammer), situación que perjudicaría notablemente a nuestro sitio en términos de posicionamiento.

A causa de todas estas desventajas, muchos Webmasters optan por contratar un VPS. Además, notablemente un VPS suele ser más económico que un espacio de hosting en un servidor compartido. ¿Por qué digo "notablemente"? Porque cuando uno contrata un VPS recibe su propio servidor dedicado, con su propia memoria, procesador, muchos Gigabytes de espacio en disco y, más importante, su propia dirección IP dedicada. Pero a pesar de requerir muchos más recursos de hardware, un VPS es más económico porque no requiere administración por parte del proveedor, más allá de la gestión de la infraestructura de virtualización. Simplemente es cuestión de hacer un deploy de una máquina virtual, y allí termina la administración de la VM por parte del proveedor, quien básicamente debe preocuparse por mantener los RAID y el host en funcionamiento.

La administración de servidores y sistemas en general implica mano de obra altamente especializada, la cual es más costosa que el hardware en sí. Incluso el proveedor se ahorra el alto costo de licenciamiento de software como CPanel (el cual es muy bueno, pero muy costoso, no es software libre), y dolores de cabeza por brechas de seguridad en servidores compartidos.

Entonces, toda la carga de administración pasa para el Webmaster. Esto implica que la principal "desventaja" de un VPS es que el Webmaster debe hacer todo manualmente y debe contar con conocimientos intermedios/avanzados de administración de sistemas operativos, redes y servicios. En un VPS no hay backups automáticos, no hay servicios preconfigurados, no hay paneles de control. Todo se hace desde consola y se debe tener cuidado con la cantidad de servicios que se levantan si no se cuenta con suficiente memoria (a veces se deben resignar servicios como el correo a causa de esto). Y más aún, el Webmaster debe contar con conocimientos de seguridad básicos para proteger al servidor.

Enough talk!

Suficiente introducción, el propósito de este artículo es implementar un mecanismo sencillo de resguardo automático de la información contenida en el servidor. Este esquema debe crear copias de seguridad periódicas tanto de los archivos como de las bases de datos, alojadas dentro del sistema de archivos del propio servidor, pero además debe subir estas copias a un servicio de almacenamiento en la nube, para mayor seguridad y persistencia de los datos.

Partiendo de un servidor Web corriendo Apache y bases de datos MySQL, el esquema utilizará sólo scripts Bash y tareas de cron para llevar a cabo esta importante tarea.

Hands on

NOTA: este artículo esta orientado a sistemas basados en Debian.

Crear la jerarquía de directorios necesaria para almacenar las copias de seguridad (backups):

root@linuxito:~# mkdir /backup
root@linuxito:~# mkdir /backup/scripts
root@linuxito:~# mkdir /backup/tmp
root@linuxito:~# mkdir /backup/data
root@linuxito:~# ll /backup
total 12
drwxr-xr-x 2 root root 4096 Aug 10 08:55 data
drwxr-xr-x 2 root root 4096 Aug 10 08:29 scripts
drwxr-xr-x 2 root root 4096 Aug 10 08:45 tmp

/backup es el directorio base para backups, /backup/scripts almacenará los scripts Bash que llevan a cabo las tareas, /backup/tmp es un directorio para archivos temporales, y /backup/data es el directorio donde se almacenarán las copias de seguridad.

El primer script a crear se llama backup_files.sh, el cual se encarga de generar copias de seguridad de los archivos de los sitios Web:

root@linuxito:~# cd /backup/scripts
root@linuxito:/backup/scripts# nano backup_files.sh 

El código fuente del script es el siguiente:

#!/bin/bash

# Directorios de trabajo
BASE_DIR="/backup"
BACKUP_DIR=$BASE_DIR"/data"

# Obtener el nombre del directorio/archivo a resguardar
if [ $# -lt 1 ]
then
  echo "uso: $0 DIR"
  exit -1
fi

# Eliminar las barras (/) del nombre
DIR=$1
DIR_C=$(echo $DIR | sed 's/\///g')

# Obtener la fecha y hora actual
DATE=$(date +%Y-%m-%d_%H%M%S)

# Comprimir y resguardar
tar cjf $BACKUP_DIR/${DIR_C}_$DATE.tar.bzip2 $DIR 2>/dev/null

Este script toma como parámetro un archivo/directorio, el cual comprime en formato bzip2, para luego resguardarlo dentro del directorio /backup/data.

Otorgar permisos de ejecución al script ejecutando:

root@linuxito:/backup/scripts# chmod +x backup_files.sh

Para verificar el funcionamiento del script, crear copias de seguridad de los directorios /etc (archivos de configuración del sistema) y /var/www (archivos de sitios Web de Apache en servidores Debian):

root@linuxito:/backup/scripts# ./backup_files.sh /etc
root@linuxito:/backup/scripts# ./backup_files.sh /var/www/

Se generan los siguientes archivos:

root@linuxito:/backup/scripts# ll -h ../data/
total 138M
-rw-r--r-- 1 root root 558K Aug 10 08:54 etc_2015-08-10_085412.tar.bzip2
-rw-r--r-- 1 root root 137M Aug 10 08:56 varwww_2015-08-10_085509.tar.bzip2

El siguiente script, backup_database.sh se encargará de resguardar volcados de bases de datos MySQL:

root@linuxito:/backup/scripts# nano backup_database.sh

El código fuente del script es el siguiente:

#!/bin/bash

BASE_DIR="/backup"
BACKUP_DIR=$BASE_DIR"/data"
TMP_DIR=$BASE_DIR"/tmp"

# Credenciales de un usuario MySQL con acceso de sólo lectura
MYUSER=
MYPASS=****

# Parámetros y opciones para mysqldump
ARGS="-u$MYUSER -p$MYPASS --add-drop-database --add-locks \
--create-options --complete-insert --comments --disable-keys \
--dump-date --extended-insert --quick --routines --triggers"

if [ $# -lt 1 ]
then
        echo "uso: $0 DATABASE"
        exit -1
fi

# Recuperar el nombre de base de datos pasado como parámetro
DB=$1

# Obtener un volcado de la base de datos
mysqldump ${ARGS} $DB > $TMP_DIR/$DB.sql

# Obtener la fecha y hora actual
DATE=$(date +%Y-%m-%d_%H%M%S)

# Comprimir y resguardar
tar cjf $BACKUP_DIR/${DB}_$DATE.tar.bzip2 $TMP_DIR/$DB.sql 2>/dev/null

# Eliminar el volcado
rm $TMP_DIR/$DB.sql

Por seguridad se debe utilizar un usuario de MySQL que posea permisos de sólo lectura sobre todas las bases de datos. Además se debe eliminar el permiso de lectura para el script para "others", ya que posee la contraseña hardcodeada en texto plano:

root@linuxito:/backup/scripts# chmod 750 backup_database.sh

Si aún no se cuenta con un usuario MySQL que tenga acceso de lectura a cualquier base de datos, es posible crear uno conectándose al motor de bases de datos MySQL como "root" desde línea de comandos:

$ mysql -u root -p

Y ejecutar las siguientes consultas para crear un usuario "backup":

mysql> create user 'backup'@'localhost' identified by '12345678';
mysql> grant lock tables, select on *.* to 'backup'@'localhost';

En este ejemplo he asignado la contraseña del 1 al 8 para que sea segura.

Verificar el funcionamiento del script:

root@linuxito:/backup/scripts# ./backup_database.sh linuxito

Notar que se genera el archivo linuxito_2015-08-10_110156.tar.bzip2:

root@linuxito:/backup/scripts# ll ../data/
total 141900
-rw-r--r-- 1 root root    571339 Aug 10 08:54 etc_2015-08-10_085412.tar.bzip2
-rw-r--r-- 1 root root   1129485 Aug 10 11:01 linuxito_2015-08-10_110156.tar.bzip2
-rw-r--r-- 1 root root 143595513 Aug 10 08:56 varwww_2015-08-10_085509.tar.bzip2

Con estos dos scripts (backup_files.sh y backup_database.sh) tenemos suficiente para crear copias de seguridad de directorios y bases de datos. Sólo resta enviar estas copias de seguridad a un servidor adicional, preferentemente en otro centro de cómputos. De esta forma, en caso de una catástrofe (créanme que son más frecuentes de lo que algunos piensan y lamentablemente es común perder todos los datos) tendremos las copias de seguridad de nuestro sitio resguardadas en un servidor aparte.

Por supuesto, contratar un servicio y/o software de backup es costoso, por ello el motivo de este artículo. Sin embargo es posible utilizar herramientas gratuitas como Dropbox, Drive, OneDrive o Copy para implementar un esquema de respaldos alternativo. Personalmente recomiendo utilizar Copy porque no requiere trabajar con un demonio residente en memoria. Es posible sincronizar los archivos manualmente, invocando al agente sólo cuando sea necesario. De esta forma evitamos tener un servicio más en ejecución utilizando memoria (en un VPS siempre vamos a querer ahorrar memoria porque es lo más costoso).

Por favor, crear una cuenta desde el siguiente enlace: https://copy.com?r=8uE7nS. De esta forma me estarán regalando 5 GB adicionales, a modo de retribución por este genial artículo que estoy compartiendo. Muchas gracias, desde ya :)

A continuación se explica cómo instalar, configurar y utilizar Copy para resguardar nuestras copias de seguridad en la nube.

Cambiar al directorio /usr/local:

root@linuxito:~# cd /usr/local/

Descargar el agente para GNU/Linux:

root@linuxito:/usr/local# wget https://copy.com/install/linux/Copy.tgz

Extraer el contenido del paquete:

root@linuxito:/usr/local# tar xf Copy.tgz

Se observa que se ha creado el directorio /usr/local/copy, el cual posee los siguientes subdirectorios:

root@linuxito:/usr/local# ll copy/
total 16
drwxrwxr-x 2 1000 1000 4096 Apr  7 15:24 armv6h
-rw-rw-r-- 1 1000 1000 1639 Apr  7 15:24 README
drwxrwxr-x 3 1000 1000 4096 Apr  7 15:14 x86
drwxrwxr-x 3 1000 1000 4096 Apr  7 15:05 x86_64

Borrar el paquete (opcional):

root@linuxito:/usr/local# rm Copy.tgz

Modificar adecuadamente los permisos del directorio "copy":

root@linuxito:/usr/local# chown -R root:staff copy/

Como buen sysadmin, no es deseable que el agente de Copy se ejecute como root. Por ello es recomendable crear un usuario, también llamado "copy", cuyo directorio $HOME será /backup/copy:

root@linuxito:/usr/local# cd /backup/
root@linuxito:/backup# mkdir copy
root@linuxito:/backup# useradd -d /backup/copy -c "Usuario Copy" -M -s /bin/bash copy
root@linuxito:/backup# chown -R copy:copy /backup/copy
root@linuxito:/backup# chown -R root:copy /usr/local/copy/

El último comando es necesario para que el usuario "copy" pueda generar archivos de log dentro del directorio /usr/local/copy/.

Crear el script upload2copy.sh, el cual se encarga de enviar a Copy todos los archivos con extensión "bzip2" (dentro del directorio /backup/copy):

#!/bin/bash

COPY_DIR="/backup/copy"
COPY_USR="copy"

# Ruta al ejecutable, cambia de acuerdo a la arquitectura
COPY_BIN="/usr/local/copy/x86_64/CopyCmd"

# Credenciales de la cuenta de Copy
USER=
PASS=****

# Enviar cada archivo con extensión "bzip2" a Copy
for F in $(ls $COPY_DIR/*bzip2); do
  su - $COPY_USR -c "cd $COPY_DIR && $COPY_BIN Cloud -username=$USER -password=$PASS put $F /"
done

Al igual que antes, quitar permiso de lectura al script para "others" pues contiene las credenciales de acceso a la cuenta de Copy harcodeadas:

root@linuxito:/backup/scripts# chmod 750 upload2copy.sh

Copiar los backups realizados hasta la fecha al directorio /backup/copy:

root@linuxito:/backup/scripts# cp /backup/data/* /backup/copy/

Verificar el funcionamiento del script. Notar que en la cuenta de Copy inicialmente no existen archivos:

Ejecutar el script:

root@linuxito:/backup/scripts# /backup/scripts/upload2copy.sh      
Logged in as linuxito
etc_2015-08-10_085412.tar.bzip2 -> /etc_2015-08-10_085412.tar.bzip2
 (557.9 kB / 557.9 kB) [0 B/sec]             
Logged in as linuxito
linuxito_2015-08-10_110156.tar.bzip2 -> /linuxito_2015-08-10_110156.tar.bzip2
 (1.0 MB / 1.0 MB) [0 B/sec]             
Logged in as linuxito
linuxito_2015-08-11_020008.tar.bzip2 -> /linuxito_2015-08-11_020008.tar.bzip2
 (1.0 MB / 1.0 MB) [0 B/sec]             
Logged in as linuxito
varwww_2015-08-10_085509.tar.bzip2 -> /varwww_2015-08-10_085509.tar.bzip2
 (5 MB / 136.9 MB) [0 B/sec]             
 (10 MB / 136.9 MB) [0 B/sec]             
 (15 MB / 136.9 MB) [0 B/sec]             
 (20 MB / 136.9 MB) [0 B/sec]             
 (25 MB / 136.9 MB) [0 B/sec]             
 (30 MB / 136.9 MB) [0 B/sec]             
 (35 MB / 136.9 MB) [0 B/sec]             
 (40 MB / 136.9 MB) [0 B/sec]             
 (45 MB / 136.9 MB) [0 B/sec]             
 (50 MB / 136.9 MB) [0 B/sec]             
 (55 MB / 136.9 MB) [40 MB/sec]             
 (60 MB / 136.9 MB) [40 MB/sec]             
 (65 MB / 136.9 MB) [40 MB/sec]             
 (70 MB / 136.9 MB) [40 MB/sec]             
 (75 MB / 136.9 MB) [40 MB/sec]             
 (80 MB / 136.9 MB) [40 MB/sec]             
 (85 MB / 136.9 MB) [40 MB/sec]             
 (90 MB / 136.9 MB) [40 MB/sec]             
 (95 MB / 136.9 MB) [40 MB/sec]             
 (100 MB / 136.9 MB) [40 MB/sec]             
 (105 MB / 136.9 MB) [40 MB/sec]             
 (110 MB / 136.9 MB) [40 MB/sec]             
 (115 MB / 136.9 MB) [40 MB/sec]             
 (120 MB / 136.9 MB) [40 MB/sec]             
 (125 MB / 136.9 MB) [40 MB/sec]             
 (130 MB / 136.9 MB) [40 MB/sec]             
 (135 MB / 136.9 MB) [60 MB/sec]             
 (136.9 MB / 136.9 MB) [60 MB/sec]             

Se observa que los archivos han sido subidos exitosamente:

Ahora es necesario crear un script backup_2copydir.sh, el cual se encargue de seleccionar qué archivos enviar a Copy. Esta configuración depende de las necesidades de cada uno, y puede ser implementada de diferentes maneras. Personalmente considero que no es necesario enviar a Copy todos los backups diarios de bases de datos, me basta con que se envíe a Copy una vez por semana (para ahorrar ancho de banda).

#!/bin/bash

COPY_DIR="/backup/copy"
BACKUP_DIR="/backup/data"

# Borrar copias de respaldo viejas
rm $COPY_DIR/*.bzip2 >/dev/null 2>&1

# Copiar copias de respaldo nuevas
for F in $(find $BACKUP_DIR -type f -name "*.bzip2" -mtime -1); do
  cp $F $COPY_DIR
done

# Subir a Copy
/backup/scripts/upload2copy.sh

Este script se encarga de mantener, dentro del directorio /backup/copy, sólo las versiones más recientes de backups de bases de datos y archivos. Utiliza find para encontrar dentro de /backup/data los archivos *.bzip2 modificados en las últimas 24 horas. Por ello es importante que este script corra una vez que se haya creado un backup fresco de los archivos (a lo sumo 23 horas más tarde).

El último paso consiste en configurar las tareas de cron para ejecutar estos scripts automáticamente, de forma periódica:

root@linuxito:/backup/scripts# nano /etc/cron.d/backup
# Backup database "linuxito" (everyday)
0 2 * * * root /backup/scripts/backup_database.sh "linuxito" >> /var/log/backup/backup_database.log 2>&1
# Backup /var/www (weekly)
0 2 * * 1 root /backup/scripts/backup_files.sh /var/www >> /var/log/backup/backup_files.log 2>&1
# Upload 2 Copy (weekly)
0 3 * * 1 root /backup/scripts/backup_2copy.sh >> /var/log/backup/backup_2copy.log 2>&1

Una vez al día, a las 2:00 AM, se crea un backup fresco de las bases de datos. El primer día de cada semana se crea un backup fresco de los archivos, a las 2:00 AM, y luego se suben a Copy, a las 3:00 AM.

Para terminar, crear el directorio para almacenar los logs de backup:

root@linuxito:/backup/scripts# mkdir /var/log/backup

En el próximo artículo: cómo crear un script que nos envíe por mail un resumen diario de las tareas de backup.

En caso de hallar un error en este artículo, por favor indicarlo en la sección de comentarios.

Enlace para crear una cuenta de Copy: https://copy.com?r=8uE7nS ;)


Tal vez pueda interesarte


Compartí este artículo