Óscar García Amor

Ingeniero de Sistemas Exóticos

Copias de seguridad con Restic

Las copias de seguridad de los sistemas informáticos deberían de ser tan importantes como lo es para un ser humano el poder respirar.

Esta frase (o alguna similar) debería de cincelarse en Lonsdaleíta y entregarse una copia a cada persona del mundo. De hecho si te suena exagerada quiere decir que tienes un problema ya que, probablemente, no tienes una copia de seguridad de tus datos.

Todos los que llevamos años dedicándonos a este maravilloso mundo conocemos de primera mano la importancia del backup. No es algo baladí o que deba ignorarse, puesto que no tener una copia de tus datos puede significar que, de la noche a la mañana, has perdido todo. Pero no me tienes que creer a mi, para muestra no tienes que mas que leer sobre el ingente número de personas que son víctimas del ramsomware para darte cuenta de que no es tan complicado quedarte con la cuenta a cero. Es más, ni siquiera es necesario un ataque por parte de nadie. Un fallo del disco o, incluso, un simple corte de luz pueden arruinar completamente todo aquello que has ido atesorando a lo largo de los años. Es por eso que la importancia del backup es vital para cualquier persona.

Sobre el backup

Bien, si has llegado hasta aquí es que la cosa te interesa o, al menos, te preocupa eso de perderlo todo en el cementerio de los binarios olvidados.

Soluciones de copia de seguridad hay varias, tenemos desde el incombustible Bacula a Borg o duplicity entre otros, todos ellos soluciones muy potentes y muy válidas para nuestro día a día, sin embargo yo os voy a hablar sobre Restic.

¿Por qué Restic?

La verdad es que no hay un solo porqué, cada persona elige el software de copia de seguridad según sus propios gustos y motivos, en mi caso concreto lo que me hizo decantarme por Restic fue lo siguiente.

  1. Sencillez de uso. Restic es altamente sencillo de utilizar, no solo por como monta sus comandos sino que también porque se trata de un único binario programado en Go lo que te evita el lidiar con dependencias.
  2. Es multiplataforma. Uno de los privilegios de Go es estar disponible en otras plataformas como Windows, si bien yo no uso esta posibilidad a día de hoy, es algo que si valoro como un posible de cara que pueda hacerme falta en el futuro.
  3. Es seguro por definición. Las copias de seguridad se almacenan cifradas con contraseña por lo que en caso de sufrir una rotura de acceso a donde tengas almacenado el backup no debes preocuparte, si has establecido una contraseña segura para tu copia, les llevara unos cuantos miles de años a los atacantes acceder a tus datos.
  4. Es rápido, muy rápido. De hecho inicialmente ese fue el motivo que me hizo cambiar mi sistema puesto que antiguamente yo utilizaba duplicity, pero recuperar cualquier elemento del backup era algo que me llevaba eones. Con Restic no existe ese problema, de hecho es tan potente que funciona perfectamente en una Rasberry Pi 2 o ¡incluso en la 1! (eso si, en la 1 no esperéis que vuele).
  5. Deduplica. Este tal vez sea, junto con el cifrado, el punto mas interesante de Restic. La deduplicación lo que consigue es que a igual trozo de fichero me quedo únicamente con una copia y simplemente hago una referencia a esa copia. Esto implica que no solo nos evitamos el copiar ficheros duplicados mas de una vez, sino que si utilizamos el mismo repositorio para hacer copia de diferentes máquinas, si estas tienen ficheros iguales (como por ejemplo los ficheros del propio sistema operativo), no nos ocuparán espacio en nuestra copia de seguridad. Es más, como los ficheros se dividen en trozos si dos máquinas tienen el mismo documento pero en una de ellas esta modificado con algún agregado solamente se ocupara el espacio de la diferencia.
  6. Las copias son snapshots no existe el concepto de copia completa y copia incremental. Esto realmente es una derivada del punto anterior, al existir deduplicación las copias realmente no tienen ni completas ni incrementales, solo se almacena una imagen lo que existía en el momento en el que se realizó la copia de seguridad que ocupará mas o menos espacio dependiendo de los cambios que haya habido frente a lo ya almacenado, esto quiere decir que fácilmente podemos tener snapshots con tamaño cero.
  7. Y por supuesto, lo mas importante, es código abierto.

Usando Restic

Como ya he comentado anteriormente, Restic es muy sencillo de utilizar aunque debemos tener claro el concepto de repositorio.

Para Restic el repositorio es el lugar donde se almacenan las copias de seguridad. Puede ser desde un punto de montaje local a un servidor a tal efecto, pasando por múltiples backends de como SFTP, un object storage compatible con S3 o incluso una conexión con rclone lo cual amplía exponencialmente las opciones.

Como podéis imaginar la elección del backend del repositorio es lo primero que debemos hacer. No hay uno que sea mejor que otro en términos de almacenamiento, sin embargo, por poner un ejemplo, utilizar el servidor REST propio tiene un mejor rendimiento que utilizar SFTP. En cualquier caso donde debemos hacer especial hincapié es en que nuestro repositorio se encuentre en un lugar distinto de donde se encuentran los datos a copiar, no vale de nada que hagamos backup de nuestro disco duro en el mismo disco. Si tenéis curiosidad, personalmente yo hago el backup vía SFTP a un servidor remoto en la nube (no uso la API porque no necesito velocidad), pero es tarea de cada uno analizar cual es el que le encaja mejor.

En mis ejemplos voy a utilizar un repositorio local en /tmp. Si, ya se que no vale de mucho, pero simplemente sería modificar la dirección del repositorio para un entorno mas real. Tenéis todos los ejemplos de como se configuran los diversos repositorios en la documentación oficial.

Inicializando el repositorio

Para inicializar el repositorio utilizamos la orden init.

% restic init --repo /tmp/restic
enter password for new repository:
enter password again:
created restic repository b2678d7532 at /tmp/restic

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.

Como se puede ver al crear el repositorio nos pregunta la contraseña, esta es la misma contraseña que debemos utilizar mas adelante para acceder a los datos o para realizar las copias, es importantísimo que la contraseña sea lo suficientemente segura (no vale de nada poner 123456) y que no nos olvidemos de ella (lo que significaría una pérdida total de los datos).

Es posible generar nuevas contraseñas con la orden key, esto puede ser útil para que, por ejemplo, cada máquina tenga la suya propia, pero debemos tener en cuenta que el acceso al repositorio es plano, cualquiera de las llaves nos va a dar un acceso completo al mismo. Para listar las llaves activas (por ahora solo tendremos una).

% restic -r /tmp/restic key list
enter password for repository:
repository b2678d75 opened successfully, password is correct
created new cache in /home/ogarcia/.cache/restic
 ID        User     Host  Created
---------------------------------------------
*0b375b77  ogarcia  hell  2021-12-20 16:49:03
---------------------------------------------

NOTA: La orden -r es la que indica donde se encuentra el repositorio.

Si queremos crear una nueva llave de acceso.

% restic -r /tmp/restic key add --host otro_host --user otro_user
enter password for repository:
repository b2678d75 opened successfully, password is correct
enter new password:
enter password again:
saved new key as <Key of [email protected]_host, created on 2021-12-20 17:00:03.472455973 +0100 CET m=+21.348917995>

Al crear una nueva contraseña le podemos indicar con --host el nombre del host que va a utilizar esa contraseña y con --user el nombre del usuario. Si no indicamos estos datos cogerá los del propio sistema. Acto seguido nos preguntará por una contraseña de acceso válida al repositorio y por la nueva contraseña. Como comenté antes el acceso es plano, por lo que cualquier contraseña válida puede crear otra. Si queremos diferenciar entre usuarios la única opción que tendríamos sería crear repositorios distintos.

Con el nuevo acceso creado podemos autenticar indistintamente con una contraseña u otra y listar las actuales.

% restic -r /tmp/restic key list
enter password for repository: # Usando la contraseña de otro_user
repository b2678d75 opened successfully, password is correct
 ID        User       Host       Created
----------------------------------------------------
*2beac8df  otro_user  otro_host  2021-12-20 17:00:03
 0b375b77  ogarcia    hell       2021-12-20 16:49:03
----------------------------------------------------

% restic -r /tmp/restic key list
enter password for repository: # Usando la contraseña de ogarcia
repository b2678d75 opened successfully, password is correct
 ID        User       Host       Created
----------------------------------------------------
 2beac8df  otro_user  otro_host  2021-12-20 17:00:03
*0b375b77  ogarcia    hell       2021-12-20 16:49:03
----------------------------------------------------

Haciendo backup

Antes de continuar (y para simplificar los comandos), Restic es capaz de leer cierta información de las variables de entorno. Una de las variables es RESTIC_REPOSITORY. Si la exportamos con la ruta al repositorio, nos podemos ahorrar el -r /tmp/restic en todos los comandos.

% export RESTIC_REPOSITORY=/tmp/restic

Para realizar la copia de seguridad se utiliza la orden backup. Esta orden tiene bastantes atributos, pero inicialmente hagamos una prueba.

% echo "Hola" > /tmp/saludo.txt
% restic backup --verbose /tmp/saludo.txt
open repository
enter password for repository:
repository b2678d75 opened successfully, password is correct
lock repository
load index files
no parent snapshot found, will read all files
start scan on [/tmp/saludo.txt]
start backup on [/tmp/saludo.txt]
scan finished in 0.202s: 1 files, 5 B

Files:           1 new,     0 changed,     0 unmodified
Dirs:            1 new,     0 changed,     0 unmodified
Data Blobs:      1 new
Tree Blobs:      2 new
Added to the repo: 740 B

processed 1 files, 5 B in 0:00
snapshot 75eb7b6f saved

Recuerda que hemos exportado la variable RESTIC_REPOSITORY, si no lo has hecho el comando anterior fallará con el error Fatal: Please specify repository location (-r or --repository-file).

Si ahora lanzamos de nuevo el backup sin modificar el fichero podemos ver que efectivamente detecta que el fichero no ha sido modificado.

% restic backup --verbose /tmp/saludo.txt
open repository
enter password for repository:
repository b2678d75 opened successfully, password is correct
lock repository
load index files
using parent snapshot 75eb7b6f
start scan on [/tmp/saludo.txt]
start backup on [/tmp/saludo.txt]
scan finished in 0.203s: 1 files, 5 B

Files:           0 new,     0 changed,     1 unmodified
Dirs:            0 new,     1 changed,     0 unmodified
Data Blobs:      0 new
Tree Blobs:      1 new
Added to the repo: 358 B

processed 1 files, 5 B in 0:00
snapshot 6d5ccf8d saved

Si modificamos el fichero y lanzamos de nuevo el comando si detecta el cambio.

% echo " Restic" >> /tmp/saludo.txt
% restic backup --verbose /tmp/saludo.txt
open repository
enter password for repository:
repository b2678d75 opened successfully, password is correct
lock repository
load index files
using parent snapshot 6d5ccf8d
start scan on [/tmp/saludo.txt]
start backup on [/tmp/saludo.txt]
scan finished in 0.204s: 1 files, 13 B

Files:           0 new,     1 changed,     0 unmodified
Dirs:            0 new,     1 changed,     0 unmodified
Data Blobs:      1 new
Tree Blobs:      2 new
Added to the repo: 752 B

processed 1 files, 13 B in 0:00
snapshot 0187a798 saved

En ambos casos se genera un snapshot ya que Restic siempre genera un snapshot cuando se llama a la orden backup solo que en el primero no hay cambios a guardar y en el segundo si.

Mas adelante veremos mas opciones para backup, pero antes vamos a ver como se listan las copias realizadas.

Listando los backups

Para sacar un listado de las copias se utiliza la orden snapshots.

% restic snapshots
enter password for repository:
repository b2678d75 opened successfully, password is correct
ID        Time                 Host        Tags        Paths
----------------------------------------------------------------------
75eb7b6f  2021-12-20 17:16:13  hell                    /tmp/saludo.txt
6d5ccf8d  2021-12-20 17:22:59  hell                    /tmp/saludo.txt
0187a798  2021-12-20 17:29:40  hell                    /tmp/saludo.txt
----------------------------------------------------------------------
3 snapshots

Esta orden tiene modificadores del tipo --host o --path para indicarle que solo nos saque el listado de un host o ruta concreta respectivamente.

Copiando con mas estilo

Anteriormente vimos como llamar a la orden backup de manera sencilla, pero esta orden tiene bastantes modificadores. Todos están estupendamente detallados en la documentación oficial, pero aquí listo los mas interesantes.

  • --dry-run/-n. Simula lo que va a hacer sin hacer nada, útil para saber si hemos construido correctamente el comando.
  • --exclude. Tal vez la opción mas importante, indica que ruta (relativa a la ruta a la que le estamos haciendo backup) debe ser excluida de la copia de seguridad. Esto nos permite, por ejemplo, indicar que queremos hacer copia de todo nuestro home y excluir ciertos directorios como el de descargas. Luego veremos un ejemplo.
  • --exclude-caches. Ciertos softwares cuando crean un directorio de caché incluyen dentro del mismo un fichero especial para indicar que ese directorio es una caché y que por tanto puede ser obviada en la copia de seguridad, con esta opción le indicamos precisamente eso, que no copie estos directorios.
  • --tag. Antes cuando listamos los snapshots vimos que tenían un atributo tag que estaba en blanco. Con esta opción podemos poner etiquetas cada vez que hacemos una copia, de tal forma que luego podemos listar o buscar por esas etiquetas. Si necesitamos poner mas de una simplemente repetimos la orden --tag todas las veces que lo necesitemos.

Por ejemplo, si quisiéramos hacer backup de todo /tmp pero ignorando el propio repositorio de Restic en /tmp/restic sería de la siguiente manera.

% restic backup --verbose --exclude restic --tag prueba --tag temporal /tmp
open repository
enter password for repository:
repository b2678d75 opened successfully, password is correct
lock repository
load index files
no parent snapshot found, will read all files
start scan on [/tmp]
start backup on [/tmp]
scan finished in 0.204s: 5 files, 131.772 KiB

Files:           5 new,     0 changed,     0 unmodified
Dirs:           23 new,     0 changed,     0 unmodified
Data Blobs:      4 new
Tree Blobs:     13 new
Added to the repo: 142.680 KiB

processed 5 files, 131.772 KiB in 0:00
snapshot 7c6fa52c saved

Si nos fijamos en el --exclude le indico la ruta relativa que debe ignorar. En este caso estoy copiando /tmp y quiero que no se incluya en la copia /tmp/restic por tanto simplemente indico que excluya restic, que es la ruta relativa a /tmp. Si en lugar de eso estuviese copiando mi home en /home/ogarcia y quisiera que no se incluyese la papelera de GNOME (que por defecto esta en /home/ogarcia/.local/share/Trash) pues le pondría en el --exclude la ruta relativa .local/share/Trash. Este comando también admite comodines, por lo que si quisiera, por ejemplo, excluir todo aquello que comience por a pues podría simplemente indicando --exclude a*.

Otra cosa que he incluido en mi copia han sido dos etiquetas, prueba y temporal. Esto me puede valer par filtrar a la hora de listar.

% restic snapshots --tag temporal
enter password for repository:
repository b2678d75 opened successfully, password is correct
ID        Time                 Host        Tags             Paths
-----------------------------------------------------------------
7c6fa52c  2021-12-20 18:04:15  hell        prueba,temporal  /tmp
-----------------------------------------------------------------
1 snapshots

Para ver el contenido de un snapshot podemos utilizar la orden ls con el identificador de snapshot que nos interese.

% restic ls 7c6fa52c
enter password for repository:
repository b2678d75 opened successfully, password is correct
snapshot 7c6fa52c of [/tmp] filtered by [] at 2021-12-20 18:04:15.710442253 +0100 CET):
/tmp
/tmp/.ICE-unix
/tmp/.Test-unix
/tmp/.X11-unix
/tmp/.XIM-unix
/tmp/.font-unix
/tmp/saludo.txt
/tmp/tracker-extract-3-files.1000
/tmp/v8-compile-cache-1000

Recuperar de la copia de seguridad

Restic tiene varias formas de recuperar elementos de la copia de seguridad, tenemos la orden restore donde le podemos indicar un snapshot concreto de donde queremos sacar la información, pero para mi lo mejor que podemos utilizar es la orden mount.

Con la orden mount lo que podemos hacer es montar todo el sistema de copias de seguridad en un directorio dado y navegar por él, para ello primero hacemos mount en una consola.

% mkdir /tmp/montaje_restic
% restic mount /tmp/montaje_restic
enter password for repository:
repository b2678d75 opened successfully, password is correct
Now serving the repository at /tmp/montaje_restic
When finished, quit with Ctrl-c or umount the mountpoint.

Ahora abrimos otra consola y accedemos a /tmp/montaje_restic.

% cd /tmp/montaje_restic
% tree
.
├── hosts
│   └── hell
│       ├── 2021-12-20T17:16:13+01:00
│       │   └── tmp
│       │       └── saludo.txt
│       ├── 2021-12-20T17:22:59+01:00
│       │   └── tmp
│       │       └── saludo.txt
│       ├── 2021-12-20T17:29:40+01:00
│       │   └── tmp
│       │       └── saludo.txt
│       ├── 2021-12-20T18:04:15+01:00
│       │   └── tmp
│       │       ├── saludo.txt
│       │       ├── tracker-extract-3-files.1000
│       │       └── v8-compile-cache-1000
│       └── latest -> 2021-12-20T18:04:15+01:00
├── ids
│   ├── 0187a798
│   │   └── tmp
│   │       └── saludo.txt
│   ├── 6d5ccf8d
│   │   └── tmp
│   │       └── saludo.txt
│   ├── 75eb7b6f
│   │   └── tmp
│   │       └── saludo.txt
│   └── 7c6fa52c
│       └── tmp
│           ├── saludo.txt
│           ├── tracker-extract-3-files.1000
│           └── v8-compile-cache-1000
├── snapshots
│   ├── 2021-12-20T17:16:13+01:00
│   │   └── tmp
│   │       └── saludo.txt
│   ├── 2021-12-20T17:22:59+01:00
│   │   └── tmp
│   │       └── saludo.txt
│   ├── 2021-12-20T17:29:40+01:00
│   │   └── tmp
│   │       └── saludo.txt
│   ├── 2021-12-20T18:04:15+01:00
│   │   └── tmp
│   │       ├── saludo.txt
│   │       ├── tracker-extract-3-files.1000
│   │       └── v8-compile-cache-1000
│   └── latest -> 2021-12-20T18:04:15+01:00
└── tags
    ├── prueba
    │   ├── 2021-12-20T18:04:15+01:00
    │   │   └── tmp
    │   │       ├── saludo.txt
    │   │       ├── tracker-extract-3-files.1000
    │   │       └── v8-compile-cache-1000
    │   └── latest -> 2021-12-20T18:04:15+01:00
    └── temporal
        ├── 2021-12-20T18:04:15+01:00
        │   └── tmp
        │       ├── saludo.txt
        │       ├── tracker-extract-3-files.1000
        │       └── v8-compile-cache-1000
        └── latest -> 2021-12-20T18:04:15+01:00

Como podemos ver una vez montada la copia la navegación por la misma es muy potente, podemos acceder, aparte de por fecha, por identificador de snapshot, por host o incluso por etiquetas lo cual nos permite localizar de una manera rápida lo que estamos buscando. Además siempre dispondremos de un enlace simbólico latest a la ultima copia realizada.

Una vez localizado lo que queremos restaurar simplemente hacemos un cp y lo sacamos a donde nosotros queramos. Evidentemente la navegación por los diferentes directorios del backup la podemos hacer desde consola o desde cualquier aplicación gráfica, eso ya queda al gusto de cada uno.

Conclusión

Estas han sido simplemente unas pinceladas de como utilizar Restic y de porque es importante incluir un backup de calidad en nuestro día a día. Evidentemente Restic es mucho mas potente de lo que yo os cuento aquí ya que esto no es mas que una introducción para que le perdáis el miedo. Si queréis sacarle todo el jugo yo os aconsejo que os leáis la documentación oficial y no dudéis en contactarme si tenéis alguna cuestión.