Después de unos meses de infructosos intentos conseguí esta semana hacer backups remotos con rsync, dado que me costó tanto he decidido compartir la experiencia y espero que le ahorre a alguien unos cuantos meses y disgustos. Ahí va!

El escenario es el siguiente: tenemos un dos servidores, Alice y Bob, y queremos que Alice guarde backups de Bob. Pero Alice y Bob estan en distintas redes y lo único que los conecta es Internet, con lo cual cosas como Samba quedan descartadas. Originalmente lo que se me ocurrió fue escribir un pequeño script en Perl que hiciera archivos tar.bz2 incrementales todos los días, cada domingo un tar.bz2 total y que Bob los enviara por ftp a Alice. Pero esto es una chapuza, fijense el nivel de vaguería, con tal de no tener que aprenderme los comandos de rsync preferí escribir un script en Perl… las cosas que uno hace. Así que me puse las pilas y esto es lo que salió: usando llaves conseguimos que Alice pueda acceder por SSH a Bob y usando rsync sacamos un snapshot el primero domingo de cada mes, luego snapshots incrementales contra el del dia anterior y cada domingo hacemos un snapshot incremental contra el snapshot original del primer domingo. Si, ya se que suena rebuscado y complicado, pero ya verán como es una buena idea.

Configurar acceso con llaves por SSH

Esto fué altamente frustrante, pero es una tontería. Primero generamos una llave publica y privada en Alice

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
c3:de:3c:46:d2:dd:87:34:ec:63:ed:09:c5:55:07:c9 root@alice

Dejamos todo por defecto y usamos una passphrase vacía, esto es importante porque sino nos la pedirá cada vez que intentemos usar la llave y así no se puede automatizar (que yo sepa). Abrimos /root/.ssh/id_rsa.pub, copiamos la cadena y la pegamos en /root/.ssh/authorized_keys en Bob. Ahora en Bob configuramos sshd, en Gentoo el archivo de configuración se encuentra en /etc/ssh/sshd_config. (Atención: no confundir con ssh_config, este último es para el cliente, sshd_config es para el servidor). Estas son las directrizes a tener en cuenta:

PermitRootLogin no
AuthorizedKeysFile     .ssh/authorized_keys

Y dejando el resto comentado funciona, pero como todo el mundo tiene SSH configurado distinto es cuestión de ir probando y ver que funciona, sin embargo hay dos cosas a tener en cuenta.

PermitRootLogin no te permite acceder directamente a la cuenta root, pero al usar llaves esto no le afecta. Es decir, sin usar llaves no podremos conectarnos como root, sino que tendremos que acceder con una cuenta normal y luego elevar privilegios con su, pero usando llaves podemos acceder como root directamente. Sin embargo no podemos tener root en DenyUsers porque eso sí que no funciona.

La directriz de Protocol es confusa, este HOWTO usa el protocolo 1 ya que guardamos la llave en authorized_keys, si la guardamos en authorized_keys2 debería usar cualquier protocol, pero esto no lo he probado y no se como va.

Reiniciamos el servidor SSH en Bob e intentamos acceder manualmente desde Alice a Bob para ver si funciona

# ssh root@bob
Last login: Fri Oct  6 17:06:25 2006 from **************.*****.co.uk
[root@bob root]#

Usando rsync

Ahora que Alice puede acceder a Bob sin contraseñas pasamos a la parte de hacer los backups.

# rsync -v -u -a --delete --rsh=ssh --stats bob://misc /backup
receiving file list ... done
misc/
misc/prueba.txt

Number of files: 2
Number of files transferred: 1
Total file size: 6 bytes
Total transferred file size: 6 bytes
Literal data: 6 bytes
Matched data: 0 bytes
File list size: 57
Total bytes sent: 32
Total bytes received: 119

sent 32 bytes  received 119 bytes  60.40 bytes/sec
total size is 6  speedup is 0.04
  • -v = verbose
  • -u = update
  • -a = archive
  • –delete = borra en Alice los archivos que hayan sido borrados en Bob, veremos más adelante que esto no es necesario
  • –rsh=ssh = especifica que queremos usar ssh para conectarnos
  • –stats = nos muestra las estadísticas tan simpáticas

Especificamos la fuente y luego el destino, lo que hace el ejemplo es hacer una copia de /misc en Bob y la pone en /backup en Alice. Sin embargo esto compara /backup con /misc y luego copia los archivos que hayan cambiado, esto no nos sirve para hacer backups incrementales. rsync tiene un parametro llamado --compare-dest que nos permite decirle a rsync que copie a /backup los archivos que hayan cambiado en /misc pero comparando con otra carpeta en Alice. Esto es altamente confuso, asi que pongo un ejemplo:

Usando la estructura que expliqué al principo tenemos un árbol tal que:

backups
  monthly-06-08-06
  weekly-13-08-06
  weekly-20-08-06
  weekly-27-08-06
  monthly-03-09-06
  weekly-10-09-06
  weekly-17-09-06
  weekly-24-09-06
  monthly-01-10-06
  weekly-08-10-06
  weekly-15-10-06
  weekly-22-10-06
  weekly-29-10-06

El método es el siguiente, cada primer domingo de mes hacemos un snapshot (los monthly-DD-MM-YY), luego cada domingo de ese mes hacemos otro snapshot incremental (weekly-DD-MM-YY) comparando con el monthly y luego cada día hacemos un snapshot incremental comparando con el del último domingo, estos últimos los he omitido porque sino esto se pone confuso, pero el método es igual que el de la semana.

Cada primer domingo de mes hacemos

rsync -vua --delete --rsh=ssh --stats bob://desde /backups/monthly-01-10-06

y luego cada siguiente domingo hacemos

# rsync -vua --delete --rsh=ssh --stats \
> --compare-dest=/backups/monthly-01-10-06 \
> bob://desde /backups/weekly-08-10-06

Antes dije que la opción de --delete no sirve, como estamos haciendo un backup incremental /backup/weekly-08-10-06 estará vacio antes de empezar, con lo cual no hay nada para borrar.

Digamos que el disco duro de Bob decide que ya esta cansado de girar y decide expirar, lo re-emplazamos por uno nuevo y restauramos todos los archivos de la siguiente manera:

Primero copiamos el último snapshot mensual, luego copiamos encima el último snapshot semanal y luego copiamos todos los snapshots diarios desde ese último domingo. La razon de hacer snapshots semanales es para evitar que si el disco duro muere a fin de mes tengamos que copiar casi 30 snapshots diarios. De esta manera solo tenemos que copiar seis snapshots diarios, un semanal y un mensual como máximo.

Y bueno, ahí lo tenemos, lo único que falta es escribir algún script en bash o PHP para que lo automatice. La idea es guardar los últimos tres meses, con lo cual hay que ir borrando los meses antiguos.

Recomiendo leerse man rsync, rsync tiene muchas opciones interesantes.

Espero que esto le sirva a alguien, si hay sugerencias o correcciones hagan uso de los comentarios :-P

 

3 Responses to HOWTO: Backups remotos con rsync

  1. xergio says:

    Gracias por el link :) Me voy a inspirar en tu idea para hacerme un script a mi gusto.

    Solo una cosa más: “Alice y Bob estan en distintas redes y lo único que los conecta es Internet, con lo cual cosas como Samba quedan descartadas”. Nooooo :P Si que se puede, de hecho yo hasta hace poco tenía samba en el VPS y en el windows del curro y del trabajo una unidad conectada. Pero acabé quitándolo para dejar más recursos libres en el VPS.

    Saludos.

  2. Hermann says:

    Bueno, descartado descartado no, pero me pareció un poco cutre teniendo utilidades mejor preparadas para tal tarea. Ademas no estaba muy seguro de cuales serian los problemas de seguridad de tener algo asi montado sin estar encriptado (o se puede encriptar?)

  3. Un curioso que llega tarde. says:

    Llego un poco tarde, pero a ver si todavía me puedes mirar esto. Donde dices:
    <>

    En realidad lo que quieres decir es:
    <>

    Corrígeme si me equivoco. Saludos.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Set your Twitter account name in your settings to use the TwitterBar Section.