Aujourd'hui, nous allons voir comment effectuer des sauvegardes de sa base de donnée MySQL sur un site utilisant Rails (pour ce mini-tutoriel, j'ai utilisé Rails en version 5.2.1).

 

Le procédé comme vous allez pouvoir le constater est relativement aisé. Allez trêve de plaisanterie, c'est parti !

1. Mise en place du cronjob

Nous allons commencer par installer la gemme nécessaire, à savoir whenever cette gemme permet de créer des tâches cron sur votre serveur. Elle est nécessaire uniquement si vous souhaitez automatiser les sauvegardes.

Procédons à l'installation de la gemme. Ajoutez cette ligne dans votre Gemfile :

gem 'whenever', require: false

Maintenant que la gemme est installée, générez le fichier de configuration avec cette commande :

wheneverize .

Si la commande ne fonctionne pas sur votre environnement de développement essayez en ajoutant bundle exec devant la commande.

En utilisant cette commande, un fichier nommé schedule.rb a été créé dans le dossier config de votre application. Nous allons ouvrir ce fichier et l'éditer si vous le voulez bien !

Voici le code à insérer :

#BACKUP RAILS APPLICATION EVERY X
every :sunday, at: '3am' do
    rake "backup:db RAKE_ENV=production"
end

Ce code veux dire que un cronjob va être lancé tous les dimanches à 3 heures du matin :). Concernant le rake, nous y viendrons tout de suite !

 

2. Création d'une tâche pour Rails

Maintenant que le cronjob est créé (mais pas encore activé !) nous allons ajouter une tâche avec Rails comme celles utilisées pour créer les bases de données, compiler les assets, etc.

Pour ce faire on va lancer la commande suivante :

rails g task backup db

Une fois la commande exécutée, un fichier backup.rake a été créé dans le dossier lib/tasks à la racine de votre application.

Nous allons ouvrir ce fichier et y insérer le code suivant :

Celui-ci est fait pour les bases de données MySQL uniquement. À vous de l'adapter si ce n'est pas ce que vous utilisez.

namespace :backup do
    desc "rails backup database"
    task db: :environment do
        settings = Rails.configuration.database_configuration[Rails.env]
        output_name = "#{settings['database']}-#{Time.now.strftime('%Y%m%d-%H:%M')}"
        output_file = Rails.root.join('backups', "#{output_name}.sql")

        #mac sql save
        if Rails.env == "development"
            system("/usr/local/mysql/bin/mysqldump -h localhost -u #{settings['username']} -p#{settings['password']} #{settings['database']} > #{output_file}")
        else
        #linux (for production) save
            system("/usr/bin/env mysqldump -h localhost -u #{settings['username']} -p#{settings['password']} #{settings['database']} > #{output_file}")
        end
        #File SQL saved ! Compress with gzip
        system("gzip #{output_file}")

        #send by mail
        UserMailer.send_backup_message(1, "#{output_file}.gz", output_name).deliver
    end
end

Expliquons un peu le code et ce qu'il va faire.

Tout d'abord on va sélectionner en fonction de l'environnement, la base de donnée à utiliser lors de la sauvegarde. Ensuite, on va créer le nom du futur fichier à savoir nom_de_la_base-date_heure_sauvegarde. Et nous lui disons que ce fichier devra être enregistré à la racine de l'application dans un nouveau dossier nommé backups.

 

Pour la suite, j'ai laissé ma configuration afin qu'il utilise mysqldump sous /usr/local sous Mac (l'OS avec lequel je développe) et sinon il utilisera la config /usr/bin/env pour mon serveur sous Linux CentOS.

Pour finir, il va compresser la base de donnée créé afin de minimiser la taille.

 

HEY ! attend, c'est quoi cette dernière ligne là ? c'est un MAAIL ?!

Oui effectivement c'est le petit bonus, si vous ne souhaitez pas recevoir la base par e-mail, passez directement à l'étape 4 de ce tutoriel et supprimez la ligne concernée.

 

3. Création du template pour l'e-mail

Nous allons utiliser le Mailer de Rails 5 pour créer ce mail. Pour ce faire, créer un fichier nommé user_mailer.rb dans le dossier app/mailers.

Maintenant vous allez ajouter le code suivant :

class UserMailer < ApplicationMailer
    default from: "[email protected]"
    def send_backup_message(user, file, name)
        @user = User.find(user) #passing to view
        attachments["#{name}.sql.gz"] = File.read(file)
        mail(:to => @user.email, :subject => "[SHINIX.me] copie de la sauvegarde de la base de donnée !")
    end
end

Passons en revu le code ci-dessus.

Nous allons commencer par sélectionner l'utilisateur en fonction de l'id passé dans la définition. Ensuite, nous allons ajouter le fichier compressé de la sauvegarde à l'email. Pour finir, nous envoyons le mail à l'utilisateur.

 

Passons à la création du mail en lui-même.

Créez un fichier nommé send_backup_message.html.erb dans le dossier app/views/user_mailer. Ajoutez le code suivant (ou celui que vous voulez c'est juste un peu de blabla pour expliquer qu'on a fait la sauvegarde).

<h2 style="font-size: 20px;">Bonjour <%= @user.first_name %>,</h2>
<br>
<p>Veuillez trouver ci-joint, le backup de la base de donnée principale de votre site internet.</p><br>
<p>Cette archive est également disponible à la racine de votre site dans le dossier <strong>backups</strong> ainsi que toutes les futurs sauvegardes.</p><br>
<p>Cet e-mail a été généré automatiquement. Vous l'avez reçu car a priori tout a fonctionné correctement.</p>

Voilà, maintenant tout est enfin prêt pour le grand final !

 

4. Test du code et génération du cronjob

Nous allons commencer par tester le code. Vérifier bien que pour l'envoi du mail vous avez bien mis le bon User (dans mon code, il s'agissait de l'utilisateur ayant l'id 1).

Maintenant créez manuellement le dossier backups à la racine de votre application (ça évitera des problèmes si le système n'arrive pas à le créer de lui-même).

Et enfin, lancer la commande de sauvegarde manuellement comme ceci :

rake backup:db RAILS_ENV=development

ou si la commande n'est pas reconnue

bundle exec rake backup:db RAILS_ENV=development

 

Normalement si tout s'est déroulé comme prévu, un fichier est disponible dans le dossier backups et vous avez également dû recevoir un e-mail avec ce même fichier ! cool

Configurons maintenant le cronjob

Pour ce faire, il vous suffit de taper la ligne de commande suivante :

whenever --update-crontab

 

Et voilà, c'est terminé ! vous avez mis en place votre système de backup pour votre base de donnée en quelques minutes seulement !

 

5. Modifications et optimisations possibles

Il se peut qu'au bout d'un moment le dossier backups comporte beaucoup de sauvegardes puisque je n'ai pas fait de suppression au bout d'un certain nombre de fichier ou simplement de temps. Une idée d'optimisation pourrait être de créer un nouveau cron qui va supprimer les plus anciens backups en gardant un maximum de 10 fichiers. Enfin, c'est une idée, à vous de voir si vous voulez la mettre en pratique !

Une autre modification intéressante serait d'envoyer le mail à tous les administrateurs. Ceci n'est pas du tout compliqué à mettre en place, dans le mailer il suffirait de supprimer l'id et de remplacer par un where admin: true.

Une dernière pour la route, serait de créer une table et y insérer les backups. Ainsi, ils pourraient être directement gérés depuis votre administration et vous permettraient de les supprimer, télécharger ... et pourquoi pas de les restaurer !

 

Une dernière...

Si vous avez des problèmes lors de la réalisation de ce tutoriel, n'hésitez pas à en parler dans les commentaires ci-dessous ! Par ailleurs, si vous êtes intéressés par d'autres tutoriel sur Ruby on Rails, vous pouvez vous abonnez à ma newsletter (scroll en bas de page pour avoir le popup d'inscription). Je n'envoie presque aucun mail, uniquement lorsqu'un nouvel article est disponible ! (d'ailleurs, à voir... ça peut être une idée d'article sealed).