Dans cet article je vais vous expliquer comment j'ai mis en place une sauvegarde sécurisée de mon NAS vers un Object Storage OVH. Pour cela vous avez besoin d'un Raspberry Pi (un 4 pour ma part avec 4 Go de RAM ), d'un compte OVH avec un projet Public Cloud et d'un NAS.
Table of Contents
Update de l’article :
13-06-2022 : Modification de la commande pour le montage NFS avec rajout de l'option -o vers=3 pour pallier des soucis de temps de montage sur mon Pi 4 avec la version 4 du protocole par défaut.
Local network
Le réseau local qui nous intéresse ici est composé d'une BOX opérateur, d'un switch, de plusieurs PC et pour ce qui nous préoccupe dans le présent article d'un NAS et d'un Raspberry Pi 4.
Première étape monter en tant que partage réseaux le dossier du NAS que l'on souhaite sauvegarder.
Pour se faire disons que les IP des devices sont les suivantes :
NAS : 192.168.1.20
Pi : 192.168.1.21
Sur le Rapsberry Pi nous allons devoir configurer le montage réseau pour qu'il soit permanent (au reboot notamment). Pour se faire (une fois le partage NFS configuré comme il faut sur votre NAS) :
mkdir -p /home/pi/inazo/qnap_nas
sudo mount -v -t nfs 192.168.1.20:/homes /home/pi/inazo/qnap_nas -o vers=3
L'idéal c'est d'ajouter la commande qui monte le partage réseaux dans un fichier bash qui sera chargé au reboot par le Pi, exemple de fichier :
#!/bin/bash
#
##Mount the NAS on Pi
sudo mount -v -t nfs 192.168.1.20:/homes /home/pi/inazo/qnap_nas -o vers=3
On va par exemple stocker ce dernier dans le répertoire "/home/pi/inazo/scripts_backups" du Pi sous le nom "mount_devices.sh" (n'oubliez pas de rendre le script exécutable). Ainsi pour l'appeler directement au reboot il suffit d'ajouter un cron ainsi :
@reboot sleep 60;/home/pi/inazo/scripts_backups/mount_devices.sh
Reste à reboot le Pi pour tester que tout fonctionne !
Une fois que cela fonctionne on va passer à l'une des taches les plus importantes configurer et monter l'Object Storage d'OVH comme un partage réseau.
L’Object Storage préparation et montage
Une fois que vous avez créé votre Object Storage chez OVH attention à ne pas utiliser de tiret ou encore d'underscore c'est toujours toléré via l'interface OVH, mais les outils que j'utilise ensuite ne les autorise plus.
Ce qui ressemble au final dans l'interface à ceci :
Vous devez créer un utilisateur via le menu User & Roles dans l'interface de gestion PublicCloud d'OVH lui donner les droits sur les ObjectStore au minimum. Vous pouvez aussi le faire via Horizon (cf : https://docs.ovh.com/gb/en/public-cloud/access_and_security_in_horizon/).
Une fois que c'est fait vous devez récupérer le fichier openRC d'openstack cf la capture suivante :
Vous allez pouvoir maintenant ajouter les paquets qui pourraient manquer sur votre Pi :
sudo apt update && sudo apt install python3-pip
Ensuite via pip3 on va installer awscli :
pip3 install awscli awscli-plugin-endpoint
En cas d'alerte sur la dépendance et la version d'urllib3 et de requests il est nécessaire d'upgrade requests :
pip3 install --upgrade requests
On install ensuite le paquet debian :
sudo apt install awscli
Puis si ce n'est pas encore fait le client opentstack (idem si jamais vous avez une erreur sur requests lancez un upgrade cf la commande plus haut):
pip install python-openstackclient
Ensuite vous copier votre fichier openrc.sh ou vous voulez sur le Pi (ou sur une autre machine en fait on va créer nos éléments de connexion ce n'est pas obligatoire de le faire avec la machine qui va se connecter).
Attention sur buster openstack n'est pas installé au "général", mais uniquement pour votre utilisateur local donc vous devez vous rendre, pour moi par exemple, dans le dossier : /home/pi/.local/bin
Ensuite une fois dedans vous lancer la commande source pour charger la configuration de connexion à openstack :
source /home/pi/inazo/scripts_backups/openrc.sh
Le script va alors vous demander votre mot de passe Openstack exemple ci-dessous :
Et ensuite toujours depuis le dossier "/home/pi/.local/bin" vous pouvez lancer la commande de création de credentials EC2 openstack :
./openstack ec2 credentials create
Vous aurez donc un affichage similaire à :
Attention à ne pas divulguer ces informations ! Gardez-les de côté pour le moment.
Vous allez maintenant configurer l'application awscli que vous avez installé au début. Pour ce faire vous créez un dossier .aws à la racine du home de votre utilisateur, pour ma part :
mkdir /home/pi/.aws
Et dans ce dossier caché vous allez créer un fichier config :
touch /home/pi/.aws/config
Dans le fichier config nous allons ajouter les lignes suivantes attention, il faut respecter les espaces présents pour la syntaxe du fichier !
Le fichier en question :
[plugins]
endpoint = awscli_plugin_endpoint
[profile default]
aws_access_key_id = zzz
aws_secret_access_key = aaa
region = gra
s3 =
endpoint_url = https://s3.gra.cloud.ovh.net
signature_version = s3v4
addressing_style = virtual
s3api =
endpoint_url = https://s3.gra.cloud.ovh.net
A la place de zzz et aaa dans mon exemple vous renseignez pour zzz la valeur que vous a donnée la création des credentials EC2 d'openstack pour access (dans l'exemple ci-dessus : 5a4d8b8d88104123a862c527ede5a3d3). Pour remplacer aaa ce sera la chaîne correspondant à secret (dans l'exemple ci-dessus : 925d5fcfcd9f436d8ffcb20548cc53a2).
Vous n'avez pas encore fini on va ensuite installer le paquet s3fs-fuse pour pouvoir monter notre Object Storage comme un dossier système ou un partage réseau classique.
Pour se faire petite commande :
sudo apt install automake autotools-dev fuse g++ git libcurl4-gnutls-dev libfuse-dev libssl-dev libxml2-dev make pkg-config
A l'endroit de votre choix vous allez clone le répository git du projet s3fs-fuse et l'installer :
git clone https://github.com/s3fs-fuse/s3fs-fuse.git
cd s3fs-fuse
./autogen.sh
./configure --prefix=/usr --with-openssl
make
sudo make install
Ensuite on va créer un fichier en root /etc/passwd-s3fs qui va contenir une seule ligne qui est la concaténation de l'access key et du secret avec : entre les deux chaines. En suivant notre exemple, notre fichier aura donc la valeur :
5a4d8b8d88104123a862c527ede5a3d3:925d5fcfcd9f436d8ffcb20548cc53a2
Il est fortement recommandé de modifier les permissions pour limiter l'accès au fichier :
chmod 640 /etc/passwd-s3fs
Ensuite toujours en root vous allez créer un dossier à la racine par exemple qui va être le réceptionnaire de l'Object Storage :
sudo mkdir /objectstorage
Une fois fait vous allez pouvoir monter votre Object Storage via la commande :
sudo s3fs personalbackup /objectstorage -o use_cache=/tmp -o allow_other -o uid=1000 -o multireq_max=5 -o use_path_request_style -o url=https://s3.gra.cloud.ovh.net
Explication des paramètres de la commande s3fs :
- personalbackup : le nom de l'object storage créé chez OVH
- /objectstorage : le point de montage sur votre machine
- -o XXX : définis une option que l'on va voir en détail
- -o use_cache : on communique un dossier de cache à utiliser sur notre machine par exemple /tmp
- -o allow_other : on autorise d'autre personne à consulter lire le point de montage
- -o uid=1000 : ici on attribue à l'utilisateur ayant pour uid 1000 le rôle de propriétaire du montage et donc des fichiers et dossier de ce dernier
- -o multireq_max : le nombre maximum de requête que l'on va s'autoriser à effectuer
- -o use_path_request_style : On active une comptabilité avec d'ancien format de requête
- -o url : c'est bizare je l'avoue mais on a besoin l'URL publique du S3 d'OVH pour que s3fs n'utilise par une configuration par défaut d'Amazon WS
Reste à tester que tout fonctionne par exemple en créant un fichier test.txt dans /objectstorage :
echo "test" > /objectstorage/text.txt
Alors il y a une latence réseau "normal" lorsque vous allez exécuter la commande. En vous rendant dans l'interface d'OVH, vous pouvez constater la présence du fichier :
Alors je n'ai pas de doublon c'est juste que j'avais fait un test avant avec un fichier qui avait pour nom test.txt.
Voilà vous pouvez copier ce que vous voulez directement sur votre Object Storage ! Vous allez voir ensuite comment j'ai automatisé la sauvegarde du NAS vers l'Object Strorage.
Pour le monter aussi en automatique lors du reboot de la machine n'hésitez pas à compléter notre petit script du début avec la ligne :
sudo s3fs personalbackup /objectstorage -o use_cache=/tmp -o allow_other -o uid=1000 -o multireq_max=5 -o use_path_request_style -o url=https://s3.gra.cloud.ovh.net
Copie des fichiers du NAS vers l’ObjectStorage
Je vous propose pas de simplement effectuer une copie, mais de le faire de manière sérieuse c'est à dire de mettre en place un chiffrement des fichiers que l'on va copier sur l'Object Storage. Car ne perdez pas de vue que cela reste ni plus ni moins un stockage connecté à Internet.
Avant toute chose on va utiliser deux commandes pour lister les fichiers que l'on souhaite sauvegarder.
La première vous ne devrez en toute logique l'utiliser qu'une seule fois à la création de votre système de backup :
find /home/pi/inazo/qnap_nas/ ! -path "/home/pi/inazo/qnap_nas/@Recycle/*" ! -path "/home/pi/inazo/qnap_nas/.streams/*" ! -path "/home/pi/inazo/qnap_nas/.syncing_db/*" ! -path "/home/pi/inazo/qnap_nas/.@upload_cache/*" -type f -mtime +1
On va lister tous les fichiers sur le partage réseau du NAS qui ont plus d'une journée depuis leurs dernières modifications. Soit tous vos fichiers grosso modo. Ce que je ne vous le cache pas va prendre un temps considérable en fonction de vos volumes de données.
La seconde quasi identique va vous permettre de trouver les fichiers qui ont été modifié/créé il y a moins de 24H :
find /home/pi/inazo/qnap_nas/ ! -path "/home/pi/inazo/qnap_nas/@Recycle/*" ! -path "/home/pi/inazo/qnap_nas/.streams/*" ! -path "/home/pi/inazo/qnap_nas/.syncing_db/*" ! -path "/home/pi/inazo/qnap_nas/.@upload_cache/*" -type f -mtime -1
Ceci permettra de faire vos sauvegardes quotidiennes, après libre à vous de jouer avec les autres possibilités de la commande find pour ajuster comme bon vous semble la fréquence des updates. Si vous ne le faites pas depuis un Pi, mais depuis une machine plus puissante ça peut être intéressant d'augmenter la fréquence à deux fois par jour.
Alors pour vous donner un ordre d'idée sur un NAS qui contient déjà 480 Go de données environ et quasiment que des petits fichiers de moins de 20Mo il faut entre 5 à 10 minutes pour que find arrive au bout de son listing pour la version quotidienne. Pour mon usage cela et largement satisfaisant. Le chiffrement quant à lui dépend de la taille du fichier, mais cela reste peu gourmand en ressource.
Construisons donc notre script pour justement lister, chiffrer et copier nos données dans notre Object Storage tout propre.
Le script le voici en version complète, je vous l'explique juste après :
#!/bin/bash
#
# Description: script de backup des fichiers du NAS vers un ObjectStorage
# Author: Inazo
# Version: 1.0.2
# Date: 2021-09-03
#
pathToAesKey="/home/pi/inazo/scripts_backups.aes.key"
pathToLog="/home/pi/inazo/backup.log"
echo "Start backup of : `date +%Y-%m-%d`" >> $pathToLog
#Fonction pour traite les différentes action à réalsier
function cipherAndCopyFile() {
hasError=''
#Full path of file
fileToSave=$0
#The path to the keyfile
pathToAesKey=$1
#Get the dir of file
repOfFile=$(dirname -- "$fileToSave")
#Get directoory where save the file for create it before
dirToCreate=$(echo $repOfFile | sed 's/\/home\/pi\/inazo\/qnap_nas/\/objectstorage/g')
mkdir -p $dirToCreate
#Path for save the ciphered file into ObjectStorage
destinationOfFile=$(echo $fileToSave | sed 's/\/home\/pi\/inazo\/qnap_nas/\/objectstorage/g')
onlyFileName=$(basename -- "$fileToSave")
#Ciphering file to temp destination
openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -salt -in "$fileToSave" -out "/tmp/$onlyFileName" -pass file:$pathToAesKey
#Try to move the file from temp to ObjectStorage
hasError=$(mv -f "/tmp/$onlyFileName" "$destinationOfFile" 2>&1)
#If Has error log it and remove temp file
if [[ ! -z "$hasError" ]]
then
cat "$hasError" >> "/home/pi/inazo/backup_error.log"
#Remove the temp file
rmErrorr=$(rm "/tmp/$onlyFileName" 2>&1)
else
#Log action
echo "Adding file: $fileToSave" >> $2
fi
}
export -f cipherAndCopyFile
# Command pour trouver les fichier de moins d'un jour et les copier vers l'ObjectStorage
find /home/pi/inazo/qnap_nas/ ! -path "/home/pi/inazo/qnap_nas/@Recycle/*" ! -path "/home/pi/inazo/qnap_nas/.streams/*" ! -path "/home/pi/inazo/qnap_nas/.syncing_db/*" ! -path "/home/pi/inazo/qnap_nas/.@upload_cache/*" -type f -mtime -1 -exec /bin/bash -c 'cipherAndCopyFile "$@"' {} $pathToAesKey $pathToLog \;
Le script se découpe en différente partie, tout d'abord une définition de variable, ou plus précisément de chemin, un ajout au log pour dire que la tache a commencé.
On définit ensuite la fonction qui sera le vrai "moteur" de votre code de sauvegarde : cipherAndCopyFile.
Dans cette fonction en premier lieu vous récupérer les arguments qui lui sont passé, ensuite vous récupérer le dossier du fichier cible pour le transformer via la commande sed en un chemin pour créer le dossier sur l'Object Storage (s'il est déjà présent cela ne posera aucun souci). Ensuite vous trouvez la partie qui modifie le chemin du fichier pour créer le chemin de la destination du fichier dans l'Object Storage, et avant de finir tout cela la commande de chiffrement du fichier.
Ainsi vous n'aurez jamais copié de fichier en clair dans l'Object Storage car le chiffrement est fait en même temps que la copie. Vous remarquerez que le fichier est chiffré sur le Raspberry Pi avant d'être copié sur l'Object Storage. En effet cela améliore les performances de copie et va limiter la création de segments sur l'Object Storage.
Commande de chiffrement
Revenons sur la commande qui réalise le chiffrement de manière symétrique puisque nous utilisons ici de l'AES-256.
La commande la voici en entier :
openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -salt -in $fileToSave -out $destinationOfFile -pass file:$pathToAesKey
Pour tous les détails des options je vous invite à consulter le site suivant qui explique tout ça très bien [1]. Néanmoins vous remarquerez que le passage du secret pour chiffrer les fichiers a été modifié. En effet vous ne devez plus utiliser la syntaxe -kfile, car déprécié par OpenSSL donc je vous invite à utiliser la nouvelle syntaxe : -pass file:Path_to_file.
Petit rappel il n'est pas dans les bonnes pratique de passer votre clé de chiffrement et donc de déchiffrement en ligne de commande. C'est pour cela que je vous ai fait stocker le secret dans un fichier accessible par vous uniquement.
Pour déchiffrer vos fichiers il suffira de simplement lancer la commande suivante par fichier :
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -salt -in $fileToSave -out $destinationOfFile -pass file:$pathToAesKey
A noter l'ajoute uniquement de l'option -d
Pourquoi le chiffrement symétrique, car il vous permettra de chiffrer des fichiers de gros volume ce que vous n'auriez pas pu faire avec du RSA par exemple.
Amélioration possible ?
- lancer un wakeonlan pour boot le NAS s'il est offline
- faire un mécanisme d'attente que le NAS soit disponible
- mécanisme d'alerte en cas d'erreur de backup
- contrôle de l'existence des répertoires pour ne pas tenter leurs créations systématiquement
- Ajouter un log rotate sur le fichier de log (il va finir par peser avec le temps)
Conclusion
J'espère que cela vous sera utile et vous permettra de mettre en place des sauvegardes sécurisées de vos données à moindre coût. Ce qui fait liaison avec un autre article que j'avais écrit à l'époque : https://www.kanjian.fr/comment-mettre-en-place-une-sauvegarde-efficace-pour-une-pme-tpe-pour-moins-de-1500-e.html
N'hésitez pas à me laisser des commentaires suggestions pour la suite !
(Acheter un Raspberry Pi 4 8Go - lien affilié amazon)
Design : Technologie vecteur créé par fullvector - fr.freepik.com
Source :
[1] https://www.lyes-touati.com/tutoriel-utilisation-de-base-de-openssl