Sauvegardes chiffrées et incrémentielles avec restic (Ubuntu/Debian)
Cela devrait toujours fonctionner, mais Hetzner a sorti de ses cartons un Object Storage (s3) qui pourrait être plus adapté pour des sauvegardes (je suis en tout cas passé sur cette solution)
J'utilise restic
pour la sauvegarde de mes serveurs, notamment parce qu'il fait des sauvegardes chiffrées de bout-en-bout par défaut, incrémentielles, etc, et qu'il supporte plein de stockages de fichiers différents (local, s3, sftp...)
Ici je vais installer restic
avec restic-runner
et sauvegarder sur une Storage Box d'Hetzner pour moins de 4€/mois pour 1TB d'espace disque, en utilisant SFTP.
Installation de restic
sudo apt update && sudo apt install restic
Installation de restic-runner
restic
tout seul peut se montrer assez peu user-friendly et peu automatisable. restic-runner
permet de l'utiliser plus simplement et de l'automatiser plus facilement.
La commande suivante télécharge le binaire depuis GitHub dans /usr/local/bin
: sudo wget -O /usr/local/bin/restic-runner https://raw.githubusercontent.com/alphapapa/restic-runner/master/restic-runner
La commande suivante rend le binaire exécutable : sudo chmod +x /usr/local/bin/restic-runner
Normalement pour vérifier que ça marche on lance la commande permettant d'afficher la version du logiciel, mais restic-runner
n'a pas prévu ça 😔
On peut donc lancer restic-runner --help
à la place
Configuration de la Storage Box
Création du dossier pour les sauvegardes
Une fois achetée et livrée (c'est très rapide), il faut aller sur le Robot d'Hetzner à l'adresse robot.hetzner.com. Le site vérifiera que vous n'êtes pas vous même un robot 😬
On va ensuite sur "Storage Box" dans la barre de gauche et on clique sur sa Storage Box, au centre de la page
Sur cette page, on désactive toutes les options sauf "SSH support" et "External reachability". Ensuite on fait "reset password" et on copie le mot de passe.
On se connecte (sur le port 23 car Hetzner ne peut pas faire comme tout le monde) comme ceci : ssh -p23 uXXXXX@uXXXXX.your-storagebox.de
et on entre le mot de passe qu'on a eu en le réinitialisant (remplacez évidemment les X
par les valeurs trouvées sur Hetzner Robot)
Une fois connecté en SSH, on va créer un dossier pour notre premier serveur : mkdir serveur1
, et on peut se déconnecter.
Création du sous-utilisateur
On retourne sur le Robot Hetzner et on va créer un sous-utilisateur, j'aime en faire un par machine. Notre sous-utilisateur sera "bloqué" dans le dossier qu'on vient de créer.
Sur le Robot, on va dans "sub-account" et on en crée un nouveau :
- dans "base directory", on clique sur le dossier qu'on vient de créer
- on coche "allow ssh"
- on coche "external reachability"
- on met un commentaire pour se souvenir à quoi correspond l'utilisateur
L'interface affiche un nom d'utilisateur finissant par -sub1
et un mot de passe. On copie le tout.
Configuration d'une clé SSH sur la machine à sauvegarder
On va passer en full-root, ça sera plus simple, et nécessaire pour sauvegarder certains dossiers : `sudo su`
On va utiliser une clé SSH pour se connecter, mais on va devoir d'abord passer par le mot de passe pour installer la clé publique. Si on veut en générer une spécifique pour la Storage Box, on peut faire par exemple : ssh-keygen -f ~/.ssh/backup
. (dans cet exemple, je partirai du principe que la clé à installer se trouve à cet endroit, dans mon dossier personnel, et qu'elle s'appelle backup
). N'entrez pas de passphrase
On installe la clé sur la Storage Box : cat ~/.ssh/backup.pub | ssh -p23 uXXXXX-sub1@uXXXXX.your-storagebox.de install-ssh-key
. Il faut bien envoyer la clé publique .pub
et pas sa clé privée ! Les X
dans la commande sont bien sûr à remplacer par les valeurs trouvées sur la page de la Storage Box. Le mot de passe demandé est celui qu'on vient d'obtenir en le réinitialisant
Une fois la clé installée, on va créer une entrée dans ~/.ssh/config
pour s'y connecter plus rapidement :
Host backup
User uXXXXX-sub1
HostName uXXXXX.your-storagebox.de
Port 23
IdentityFile ~/.ssh/backup
Cette fois c'est bien la clé privée qu'il faut spécifier !
La configuration ci-dessus nous permet de simplement faire `ssh backup`, les infos de configuration étant directement récupérées de `~/.ssh/config`. On peut le faire pour tester puis se déconnecter.
Configuration de restic-runner
Initialisation de restic
Il nous faut d'abord un mot de passe pour chiffrer la sauvegarde et accéder au dépôt restic
, qu'on peut générer comme on veut, par exemple date | md5sum
. On va le mettre dans ~/.restic
: nano ~/.restic
. Le fichier ne doit contenir que le mot de passe. C'est une très bonne idée de le mettre également dans son gestionnaire de mots de passe
Il faut ensuite faire une configuration pour restic-runner
: ses configurations se trouvent sous ~/.config/backup/restic/repos
. On va créer ce dossier, puis le premier dépôt avec mkdir -p ~/.config/backup/restic/repos && nano ~/.config/backup/restic/repos/storagebox
Le nom du fichier édité sera le nom de notre dépôt. Il est possible de le modifier par la suite sans problème, en déplacant le fichier avec un autre nom.
Dans ce fichier, on peut mettre :
export RESTIC_REPOSITORY=sftp:backup:restic
export RESTIC_PASSWORD_FILE=/root/.restic
keep_policy=(
--keep-last 5
--keep-daily 7
--keep-weekly 8
--keep-monthly 12
--keep-yearly 10
)
include_paths=(
/home
/etc
/root
/tmp/synapse.sql
/tmp/mastodon.sql
)
exclude_if_present=(
.nobackup
)
Ce fichier de configuration s'analyse comme ceci :
- d'abord, on définit où se trouve le dépôt. Il se trouve via sftp, dans la config
backup
(définie dans~/.ssh/config
), dans le dossierrestic
- ensuite, on indique où se trouve le mot de passe
- ensuite, on définit la politique de rétention (que je ne comprends pas trop et que j'ai donc copié sur une amie)
- ensuite, on définit les dossiers (ou fichiers) à inclure dans la sauvegarde
- enfin, on instruit à
restic-runner
de ne pas sauvegarder les dossiers contenant un fichier.nobackup
(qu'on peut créer en faisanttouch .nobackup
dans le dossier en question)
On ne spécifie pas dans ce fichier le dossier `serveur1` qu'on a créé plus haut, puisque de toute manière, notre sous-utilisateur est bloqué dans ce dossier
Maintenant, on devrait pouvoir initialiser notre dépôt avec : restic-runner --repo storagebox init
. On peut ignorer bc: command not found
, ou l'installer
Première sauvegarde ! 🎉
Une fois tout bien configuré, on peut lancer restic-runner --repo storagebox backup
pour démarrer la sauvegarde, c'est aussi simple que ça
Automatisation 🤖
Le mieux à mon sens est de créer un script qui fera toutes vos maintenances automatisées. Le mien ressemble à ça :
#!/usr/bin/sh
## Dump databases
docker exec synapse-db-1 pg_dumpall -U synapse > /tmp/synapse.sql
docker exec mastodon-db-1 pg_dumpall -U postgres > /tmp/mastodon.sql
## Run backup
restic-runner --repo storagebox backup
restic-runner --repo storagebox expire
## Delete dumps
rm /tmp/*.sql
exit 0
- D'abord je crée une sauvegarde instantanée de chaque base de données (qui se trouvent chacune dans un conteneur Docker). Si vous n'utilisez pas Docker, il faudra adapter ces commandes. Je ne suis pas responsable de vos mauvais choix de vie si vous n'utilisez pas 🙏 Docker 🙏
- Ensuite je lance la sauvegarde, comme vu précédemment
- Ensuite, je lance
expire
, qui applique la politique de rétention configurée en supprimant les sauvegardes plus anciennes - Enfin, je supprime les dumps des bases de données, puisqu'elles ont été sauvegardées, elles ne servent plus à rien
On peut mettre ce script dans notre logiciel de cron
préféré pour automatiser son lancement, par exemple avec crontab -e
Lister les snapshots
Ça n'est pas une commande native de restic-runner
, mais celui-ci permet de lancer n'importe quelle commande de restic
avec restic-runner --repo storagebox command <commande>
Pour lister les snapshots : restic-runner --repo storagebox command snapshots
Restauration
Personnellement, je monte toujours le dépôt et je vais fouiller dedans après
- D'abord je crée le point de montage avec
mkdir /mnt/backup
- Ensuite je lance
restic-runner --repo storagebox mount /mnt/backup
- Et je vais fouiller :
cd /mnt/backup/snapshots
,ls
, etc.
Le dossier monté contient sous snapshots
toutes les snapshots créées par restic
via restic-runner
.
On peut entrer dans chaque dossier, et restaurer par exemple en lancant rsync -aH --progress /mnt/backup/snapshots/<date>/home/coco/ /home/coco/
(ça c'est pour restaurer mon dossier personnel)
Pour restaurer une base de données (toujours en utilisant Docker), je fais :
cp /mnt/backup/snapshots/<date>/tmp/mastodon.sql /tmp/mastodon.sql
cat /tmp/mastodon.sql | docker exec -i mastodon-db-1 psql -U postgres
Ou quelque chose comme ça.