L'idée de cette page est de proposer une architecture matérielle et logicielle pour partager les sauvegardes. Le principe général est simple, c'est du donnant donnant : Alice a des données à sauvegarder, Bob aussi. Alors Bob met à disposition chez lui un endroit pour déposer les sauvegardes distances d'Alice, et échange du même service.
On utilisera le logiciel Borg et l'outil Borgmatic qui permet une automatisation facile. Borg est un outil de sauvegardes puissant et pratique à mon goût :
De plus, Borgmatic permet d'envoyer nos sauvegardes sur plusieurs dépôts (distants ou locaux). On peut donc imaginer un système à plus que deux, et accueillir Carole et Dave, au moins !
Pour avoir un échange équitable, le mieux est qu'Alice et Bob participent également. Quelques possibilités :
L'idée ensuite est pour Alice de pouvoir se connecter via SSH à un petit serveur, fusse-t-il physique (Raspberry Pi + disque dur externe) ou virtuel (machine virtuelle avec un bon gros disque de stockage, si besoin).
À présent, prenons l'exemple suivant : Alice et/ou Bob préparent le matériel qui restera chez Bob, à destination d'Alice. Le matériel consiste en un Raspberry Pi et un disque dur externe, mais ça ne change pas grand chose au schmilblik.
Voilà les étapes principales :
Sur le serveur de sauvegardes, seul le logiciel Borg est nécessaire (et un serveur SSH évidemment). Sur le serveur à sauvegarder, il faudra Borg et Borgmatic.
Quelques étapes simples :
# Créer le compte sudo useradd --create-home alice # Accès en écriture sudo mkdir /backup/alice sudo chown -R alice:alice /backup/alice
# On se connecte en tant qu'alice sudo su alice # On crée le dossier .ssh et un fichier qui autorise à se connecter avec des clés mkdir ~/.ssh touch ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys # On crée la clé en se laissant guider. Sans passphrase. ssh-keygen # On autorise cette clé pour la connexion cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Et on peut refiler la clé id_rsa
à Alice. Elle pourra l'utiliser pour se connecter elle-même manuellement, ou bien automatiquement avec Borgmatic.
Ça se fait avec Borg. Là, on a le choix : un seul dépôt, sous /backup/alice
par exemple, ou bien si on en veut plusieurs : /backup/alice/serveur1
, /backup/alice/serveur2
, etc. Prenons le premier cas pour l'exemple.
D'abord, il nous faut générer une repokey, une sorte de phrase de passe que Borg utilise pour chiffrer et déchiffrer le dépôt. On peut utiliser un générateur de mot/phrase de passe ou bien si vous n'avez pas d'idée, on peut utiliser openssl
s'il est installé : openssl rand -base64 45
. Pour l'exemple, la phrase de passe sera PHRASE-DE-PASSE
.
Ensuite, on lance Borg :
borg init --encryption repokey /backup/alice
On nous demande deux fois la phrase de passe (à garder quelque part pour la suite), et c'est bon, le dépôt est initialisé. Pour vérifier et utiliser Borg un petit peu, on peut faire :
borg info /backup/alice
Maintenant on est sur le serveur à sauvegarder, on va utiliser Borgmatic.
Pour l'exemple, on a un dossier /srv/borg
dans lequel on met nos fichiers de configuration.
On va mettre notre phrase de passe (PHRASE-DE-PASSE
) dans le fichiers /srv/borg/passphrase
. On met dans le dossier la clé id_rsa
. Et puis le fichier de configuration config.yaml
qui ressemble à ça :
location: # Quels dossiers sauvegarder source_directories: - /srv/apps/ # À quels dépôts Borg envoyer (distants ou locaux) repositories: - alice@chez.bob.fr:/backup/alice # On peut exclure des patterns. Utile pour les bases de données qu'on exporte autrement exclude_patterns: - "*/*/db" storage: # La phrase de passe encryption_passcommand: "cat /srv/borg/passphrase" # Quelle compression on veut, on peut choisir compression: lz4 # La commande pour se connecter au serveur distant, avec la clé SSH ssh_command: ssh -i /srv/borg/id_rsa # Combien de temps on garde les sauvegardes ? retention: # Keep all archives within this time interval. keep_within: 24H # Number of daily archives to keep. keep_daily: 7 # Number of weekly archives to keep. keep_weekly: 4 # Number of monthly archives to keep. keep_monthly: 6 consistency: # List of one or more consistency checks to run: "repository", "archives", "data", # and/or "extract". Defaults to "repository" and "archives". Set to "disabled" to # disable all consistency checks. "repository" checks the consistency of the # repository, "archives" checks all of the archives, "data" verifies the integrity # of the data within the archives, and "extract" does an extraction dry-run of the # most recent archive. Note that "data" implies "archives". checks: - disabled # - repository # - archives
Pour tester si ça fonctionne, on peut demander via Borgmatic comment est le dépôt Borg :
borgmatic info -c /srv/borg/config.yaml
Et si ça marche, lancer une sauvegarde (ça peut être très long si c'est la première) :
borgmatic --progress -C -c /srv/borg/config.yaml
Et voilà comment mettre en place un système de sauvegardes partagé, entre copain·e·s ☺
Borgmatic propose l'utilisation de hooks, c'est-à-dire qu'il peut exécuter une commande en fonction d'événements. Ce que je fais pour sauvegarder mes bases de données, c'est qu'avant le processus de compression et d'envoi vers le serveur de sauvegardes, je lance un petit script codé de mes petites mains pour exporter la base de données dans un fichier sql compressé, placé dans le dossier du service à sauvegarder. Et paf, tout est sauvegardé comme ça.
Voilà le script en question, adapté à mes besoins (docker-compose etc), à réadapter peut-être, donc :
#!/bin/bash # Default values TYPE="postgres" SERVICE="" CONTAINER="" ENV_FILE=".env" ALREADY_UP=true while getopts "t:s:c:e:" opt do case "$opt" in t) TYPE="$OPTARG";; s) SERVICE="$OPTARG";; c) CONTAINER="$OPTARG";; e) ENV_FILE="$OPTARG";; esac done ### # Preparation FILENAME="${SERVICE}_$(date +"%Y%m%d-%H%M").sql" mkdir -p /srv/apps/$SERVICE/dump rm -rf /srv/apps/$SERVICE/dump/* # Load env file (user, db name) source /srv/apps/$SERVICE/$ENV_FILE cd /srv/apps/$SERVICE/ # Check if the service was up or not, to stop it if necessarry in the end if [ -z `docker-compose ps -q $CONTAINER` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q $CONTAINER)` ]; then echo "Service not running, starting it…" docker-compose -f /srv/apps/$SERVICE/docker-compose.yml up -d $CONTAINER ALREADY_UP=false else echo "Service already running." fi # Dump (within the container) if [ $TYPE == "postgres" ] then docker-compose \ -f /srv/apps/$SERVICE/docker-compose.yml\ exec -T $CONTAINER\ pg_dump -U $POSTGRES_USER -d $POSTGRES_DB -f /$FILENAME elif [ $TYPE == "mysql" ] then docker-compose \ -f /srv/apps/$SERVICE/docker-compose.yml\ exec -T $CONTAINER\ mysqldump -u $MYSQL_USER --databases $MYSQL_DATABASE -p${MYSQL_PASSWORD} -r /$FILENAME fi # Copy the dump file to host echo "Copying the dump file to host…" docker cp ${SERVICE}_${CONTAINER}_1:/$FILENAME /srv/apps/$SERVICE/dump # Compressing echo "Compressing $FILENAME…" gzip /srv/apps/$SERVICE/dump/$FILENAME #docker exec -ti ${SERVICE}_${CONTAINER}_1 cat /$FILENAME > /srv/apps/$SERVICE/dump/$FILENAME #docker-compose -f /srv/apps/${SERVICE}/docker-compose.yml exec -T ${CONTAINER} cat /${FILENAME} > /srv/apps/$SERVICE/dump/$FILENAME # Remove the dump file in the container docker-compose \ -f /srv/apps/$SERVICE/docker-compose.yml\ exec -T $CONTAINER rm /$FILENAME -v if ! $ALREADY_UP ; then echo "Stopping service" docker-compose -f /srv/apps/$SERVICE/docker-compose.yml stop $CONTAINER fi
Exemple d'usage : /srv/borg/scripts/dump_database.sh -t postgres -s hedgedoc -c dbhedgedoc
Et pour l'utiliser dans le config.yaml
, il faut ajouter à la fin du fichier la section hooks suivante :
hooks: before_backup: - echo "Starting a backup." - /srv/config/borg/scripts/dump_database.sh -t postgres -s hedgedoc -c dbhedgedoc
Pour simplifier l'utilisation de plusiers clés SSH, on peut ajouter la configuration suivante dans /root/.ssh/config
:
Host raspibackup HostName raspibackup.bob.fr IdentityFile /srv/borg/id_rsa_raspibackup User alice
On peut donc enlever la ligne ssh_command: ssh -i /srv/borg/id_rsa
du fichier config.yaml
.
En ajoutant plusieurs Hosts
on pourra se connecter à plusieurs serveurs distants. Il faudra juste configurer config.yaml
en conséquence. Par exemple :
location : source_directories: ... repositories: - alice@chez.bob.fr:/backup/alice - alice@chez.carole.bzh:/backup/alice