la sauvegarde avec Garage et Restic
Wed, 26 Jun 2024 17:40:50 +0200La sauvegarde est une composante impĂ©rative dans un systĂšme d’information mais aussi pour un particulier. Les annecdotes de particuliers ayant perdu des semaines de travail ou de prĂ©cieuses photos de famille sont rĂ©currentes, mais il est vrai qu’on ne s’y intĂ©resse qu’une fois le mal fait.
Il existe un nombre incalculable de solutions diffĂ©rentes pour appliquer des sauvegardes, pour ma part j’utilise depuis des annĂ©es Restic associĂ© Ă un serveur S3.
Restic est une solution de sauvegarde en ligne de commande (en Go), ce qui permet de facilement l’automatiser via un tĂąche cron, sur des serveurs et poste de travail. Il sait utiliser diffĂ©rentes solutions de stockage en cloud comme Azure, Google Cloud, Wasabi, et bien sĂ»r Amazon S3.
L’avantage de S3 est qu’il existe un grand nombre de clone qui ont implĂ©mentĂ© l’API d’Amazon comme Scaleway Object Storage, mais aussi des logiciels libres comme Minio (en Go) ce qui permet de possĂ©der son propre serveur S3.
J’ai dĂ©couvert il y a peu cette implĂ©mentation libre de S3. Garage est un serveur dĂ©veloppĂ© en Rust, donc par nature plus lĂ©ger et rapide que Minio, il se veut aussi plus simple car il ne possĂšde pas d’interface web. Garage est dĂ©veloppĂ© par l’association française Deuxfleurs, vous pouvez retrouver une vidĂ©o de prĂ©sentation lors du Pas Sage En Seine 2023 : Surmonter les difficultĂ©s de lâauto-hĂ©bergement ensemble avec Garage.
L’intĂ©rĂȘt pour moi face Ă Minio est donc sa lĂ©gĂšretĂ© et sa rapiditĂ©, ce qui doit permettre de l’utiliser avec un RaspberryPi. Pour ma part je l’utilise avec un NUC (core I3/16Go RAM) avec 2 disques de 1To. Auparavant j’utilisais le service S3 de Scaleway, mais l’augmentation de la taille des sauvegardes de mon poste de travail fait que la facture peut ĂȘtre salĂ©e. Dans ce cas l’auto-hĂ©bergement sur ses propres disques peut ĂȘtre une solution. Si l’on veut plus de rĂ©silience on peut monter un cluster entre diffĂ©rentes localisations : Deployment on a cluster. Ainsi les donnĂ©es sont rĂ©pliquĂ©es et sĂ©curisĂ©es en cas d’incident sur un lieu.
L’installation est trĂšs simple puisqu’il s’agit de tĂ©lĂ©charger un fichier binaire selon votre architecture (X86 ou ARM). Pour ce service je n’ai pas choisi un environnement Docker / Nomad, car pour l’instant il ne s’agit que d’un usage local. Je suis parti du quick-start pour dĂ©marrer la configuration et mis en place un service systemd (voir la doc). A savoir que j’ai commentĂ© la ligne DynamicUser=true
car mes disques sont montés dans /opt
et pas dans /var/lib/garage
:
cat /etc/systemd/system/garage.service
[Unit]
Description=Garage Data Store
After=network-online.target
Wants=network-online.target
[Service]
Environment='RUST_LOG=garage=info' 'RUST_BACKTRACE=1'
ExecStart=/usr/bin/garage server
StateDirectory=garage
#DynamicUser=true
ProtectHome=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
cat /etc/garage.toml
metadata_dir = "/opt/garage/meta"
data_dir = [
{ path = "/opt/garage/sdc", capacity = "1T" },
{ path = "/opt/garage/sdd", capacity = "1T" },
]
db_engine = "lmdb"
replication_factor = 1
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "IP_NUC:3901"
rpc_secret = "TOKEN"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = ".s3.garage.localhost"
[s3_web]
bind_addr = "[::]:3902"
root_domain = ".web.garage.localhost"
index = "index.html"
[k2v_api]
api_bind_addr = "[::]:3904"
[admin]
api_bind_addr = "[::]:3903"
admin_token = "TOKEN"
metrics_token = "TOKEN"
Comme indiqué dans la doc, les tokens ont été générés par openssl rand -hex 32
. On lance le service par systemctl enable --now garage
puis on le prépare :
garage status
# on récupÚre l'ID
garage layout assign -z home -c 1T ID
garage layout apply --version 1
garage bucket create nuc
garage key create nuc-app-key
# on note les TOKEN générées dans son gestionnaire de pass
garage bucket allow --read --write --owner nuc --key nuc-app-key
On vérifie que le bucket est opérationnel avec garage bucket info nuc
puis on peut passer Ă Restic.
Sur son PC de travail on l’installe via pacman ou en tĂ©lĂ©chargeant le binaire. Ensuite on Ă©crit dans un fichier .restic_garage :
cat .restic_garage
export AWS_ACCESS_KEY_ID=TOKEN
export AWS_SECRET_ACCESS_KEY=TOKEN
export AWS_DEFAULT_REGION='garage'
export AWS_ENDPOINT_URL='http://IP_NUC:3900'
export RESTIC_REPOSITORY=s3:http://IP_NUC:3900/nuc/restic
Les tokens sont celles générées précédement sur le serveur NUC par la commande garage key create nuc-app-key
. Puis il faut appliquer ce fichier avec source .restic_garage
(ajouter cette commande dans son .bashrc / .zshrc).
Et pour finir lancer :
restic init
Restic demande alors un nouveau mot de passe que je conseille de gĂ©nĂ©rer via son gestionnaire de passe. Puis l’ajouter Ă la fin du fichier .restic_garage
:
export AWS_ACCESS_KEY_ID=TOKEN
export AWS_SECRET_ACCESS_KEY=TOKEN
export AWS_DEFAULT_REGION='garage'
export AWS_ENDPOINT_URL='http://IP_NUC:3900'
export RESTIC_REPOSITORY=s3:http://IP_NUC:3900/nuc/restic
export RESTIC_PASSWORD=PASS
source .restic_garage
â ïž
Restic chiffre les sauvegardes sur le serveur S3, vos données seront alors illisible si on vole vos disques (bien) ou si vous perdez votre mot de passe (pas bien). Les données sont également compressées.
â ïž
On peut maintenant sauvegarder ses répertoires, exemple avec le répertoire code
:
restic --verbose backup code
Attention selon le volume du rĂ©pertoire cela peut prendre du temps la premiĂšre fois. Au prochain backup Restic n’enverra que la diffĂ©rence.
Ensuite on peut consulter ses snapshots
restic snapshots
repository 73f79abc opened (version 2, compression level auto)
ID Time Host Tags Paths
---------------------------------------------------------------------------
bc5d52a3 2024-06-26 08:16:29 zenbook /home/fred/code
2e21a158 2024-06-26 08:45:05 zenbook /home/fred/Documents
a0b642bf 2024-06-26 09:23:30 zenbook /home/fred/Images
7d0a765c 2024-06-26 14:31:04 zenbook /home/fred/code
---------------------------------------------------------------------------
4 snapshots
On voit ici 2 snapshots pour le répertoire code
. On peut soit restaurer une version particuliĂšre en prĂ©cisant l’ID :
restic restore bc5d52a3 --target /
Soit la version la plus récente :
restic restore latest --target / --path "/home/fred/code"
On peut aussi monter Restic dans un répertoire si on veut naviguer dans son dépÎt avant une restauration :
mkdir /tmp/restic
restic mount /tmp/restic/
repository 73f79abc opened (version 2, compression level auto)
[0:00] 100.00% 25 / 25 index files loaded
Now serving the repository at /tmp/restic/
Use another terminal or tool to browse the contents of this folder.
When finished, quit with Ctrl-c here or umount the mountpoint.
ls -alh /tmp/restic/
total 0
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 .
drwxrwxrwt 30 root root 4,8K 26 juin 15:40 ..
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 hosts
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 ids
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 snapshots
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 tags
ls -alh /tmp/restic/hosts/zenbook/2024-06-26T14:31:04+02:00/
total 0
dr-xr-xr-x 2 root root 0 26 juin 14:31 .
dr-xr-xr-x 1 fred fred 0 26 juin 15:39 ..
drwxrwxr-x 2 fred fred 0 25 juin 11:04 code
Un exemple de script cron journalier avec en bonus le service Gotify pour recevoir des notifications sur mon laptop et smartphone (voir Gotify et notification desktop) :
cat /etc/cron.daily/restic_backup
#!/bin/bash
source /root/.restic_scw
DATE=$(date +%Y-%m-%d_%Hh%M)
curl -X POST "https://gotify.fredix.xyz/message?token=TOKEN" -F "title=node1 : restic backup" -F "message=restic started : ${DATE}" -F "priority=3"
/usr/bin/ionice -c2 nice -n19 /usr/local/bin/restic backup /opt > /var/log/restic_opt.log
/usr/bin/ionice -c2 nice -n19 /usr/local/bin/restic backup /swarm/volumes/nomad --exclude="/swarm/volumes/nomad/radicle/node/.radicle/storage/" > /var/log/restic_backup.log
/usr/bin/ionice -c2 nice -n19 /usr/local/bin/restic backup /etc > /var/log/restic_backup_etc.log
/usr/bin/ionice -c2 nice -n19 /usr/local/bin/restic backup /usr/local/bin > /var/log/restic_backup_usr_local_bin.log
DATE=$(date +%Y-%m-%d_%Hh%M)
curl -X POST "https://gotify.fredix.xyz/message?token=TOKEN" -F "title=node1 : restic backup" -F "message=restic finished : ${DATE}" -F "priority=3"
ionice
permet de lancer restic avec une priorité des I/O faible.
On peut se retrouver avec un grand nombre de snapshots inutiles, aussi il est nĂ©cessaire d’appliquer une politique de purge. Voici un script exĂ©cutĂ© sur mon serveur tous les weekend :
cat /etc/cron.weekly/restic_purge
#!/bin/bash
source /root/.restic_scw
DATE=$(date +%Y-%m-%d_%Hh%M)
curl -X POST "https://gotify.fredix.xyz/message?token=TOKEN" -F "title=restic purge" -F "message=restic purge started : ${DATE}" -F "priority=3"
/usr/bin/ionice -c2 nice -n19 /usr/local/bin/restic forget --keep-last 3 --prune > /var/log/restic_purge.log
DATE=$(date +%Y-%m-%d_%Hh%M)
curl -X POST "https://gotify.fredix.xyz/message?token=TOKEN" -F "title=restic purge" -F "message=restic purge finished : ${DATE}" -F "priority=3"
Je conserve les 3 derniers backups, mais la politique de purge peut ĂȘtre beaucoup plus complexe, voir la doc removing-snapshots-according-to-a-policy. L’option --prune
demande à Restic de supprimer physiquement les données du serveur S3.
Le duo Garage / Restic est trĂšs efficace, mĂȘme si un utilisateur lambda prĂ©ferera une interface graphique comme DejaDup ou une solution payante type pCloud. A noter l’existence du projet Resticity comme interface graphique Ă Restic.