thomas.io

May 28, 2017

Sauvegarder Laravel 5.4 sur Amazon S3 (+ notification par SMS avec Free Mobile)

J'ai mis beaucoup trop de temps avant de configurer la sauvegarde de mes sites sous Laravel et c'est pourtant tellement simple que c'est la première chose que vous devriez faire une fois votre site en ligne.

Sauvegarde sur Amazon S3

On va utiliser le package laravel-backup développé par Spatie. Pour ceux qui ne connaissent Spatie, c'est une agence Belge qui contribue beaucoup à l'univers open-source et qui crée de très bon packages, entre autre pour Laravel.

Configuration du Package

Première étape, téléchargez le package à l'aide de composer:

$ composer require spatie/laravel-backup

Ensuite, dans config/app.php, ajoutez Ă  votre liste de providers :

Spatie\Backup\BackupServiceProvider::class,

Puis publiez le fichier de configuration:

$ php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"

Par défaut, la sauvegarde est créé en local, vous devrez modifier la destination par Amazon S3:

// config/laravel-backup.php

/*
 * The disk names on which the backups will be stored.
 */
'disks' => [
    's3',
],

Configuration d'Amazon S3

Pour pouvoir communiquer avec Amazon S3, on a besoin du package league/flysystem-aws-s3-v3.

$ composer require league/flysystem-aws-s3-v3

Création du compartiment

Si ce n'est pas déjà fait, vous devrez vous créer un compte sur Amazon S3.
Une fois connecté, rendez-vous sur https://console.aws.amazon.com/s3.
Créez un nouveau compartiment, nommez le comme vous voulez et choisissez une région idéalement au plus près des serveurs que vous allez sauvegarder.
Pro tip: Sachez que lorsque vous ferez des sauvegardes, elles seront rangées dans un dossier avec le nom de votre site. Vous pouvez donc créer un seul compartiment pour plusieurs sites.

Une fois votre compartiment créé, cliquez dessus pour l'ouvrir, et notez tout de suite la région dans laquelle il se trouve. C'est le parametre region dans votre url.
Exemple pour un compartiment Ă  Londres : eu-west-2.

Les identifiants d'accès avec Amazon IAM

Dans votre menu en haut à droite, cliquez sur votre nom, puis Mes informations d'identification de sécurité.

Stratégie

Nous allons d'abord créer la stratégie qui va donner les droits à notre compartiment.

Vous pouvez l'appeller Programmatic_Access et collez les données ci-dessous, en remplaçant VOTRE_COMPARTIMENT par le nom du compartiment dans lequel vous allez stocker vos sauvegardes.

{
  "Version": "2017-05-28",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::VOTRE_COMPARTIMENT"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": ["arn:aws:s3:::VOTRE_COMPARTIMENT/*"]
    }
  ]
}

Cette stratégie est séparée en deux instructions. La première autorise l'accès à votre compartiment, la seconde autorise la modification des objects à l'intérieur.

Utilisateur

Créez un nouvel utilisateur. Dans type d'accès, choissisez ** Accès par programmation**.

Lors des définitions des autorisations, choisissez Attacher directement les stratégies existantes et selectionnez la stratégie que vous venez de créer.

Copiez l'ID de clé d'accès et la Clé d'accès secrète.

Configuration du fichier .env

Ouvrez votre fichier .env et ajouter les 4 lignes suivantes, avec les données que vous avez récupéré.

AWS_KEY="ID de clé d'accès"
AWS_SECRET="Clé d'accès secrète"
AWS_REGION="La région de votre compartiment"
AWS_BUCKET="Le nom de votre compartiment"

Suivant votre version de Laravel, vérifiez que dans votre fichier config/filesystems.php vous avez bien ces meme variables:

// config/filesystems.php

's3' => [
    'driver' => 's3',
    'key' => env('AWS_KEY'),
    'secret' => env('AWS_SECRET'),
    'region' => env('AWS_REGION'),
    'bucket' => env('AWS_BUCKET'),
],

Sauvegarde

Vous n'avez plus qu'Ă  executer la commande suivante pour sauvegarder sur Amazon S3.

$ php artisan backup:run

Ainsi que les commandes :

# Sauvegarder seulement la base de données
$ php artisan backup:run --only-db
# Sauvegarder seulement les fichiers
$ php artisan backup:run --only-files

Si vous souhaitez tout le temps ne jamais sauvegarder les fichiers ou la base de données, vous pouvez aussi modifier votre fichier config/laravel-backup.php

Si vous ne souhaitez pas sauvegarder les fichiers, modifiez include en commantant ou en supprimant base_path()

//config/laravel-backup.php

/*
 * The list of directories and files that will be included in the backup.
 */
 'include' => [
    // base_path(),
 ],

Si vous ne souhaitez pas sauvegarder la base de données, modifiez databases en commantant ou en supprimant mysql

// config/laravel-backup.php

/*
 * The names of the connections to the databases that should be backed up
 * MySQL, PostgreSQL, SQLite and Mongo databases are supported.
 */
'databases' => [
    // 'mysql',
],

Planification

En supposant que vous ayez déjà un cron job actif, vous n'avez plus qu'à ajouter vos commandes dans le kernel, pour lancer les sauvegardes automatiquement.

// app/Console/Kernel.php

protected function schedule(Schedule $schedule)
{
    $schedule->command('backup:clean')->daily()->at('01:00');
    $schedule->command('backup:run')->daily()->at('02:00');
}

Cela vous lancera un nettoyage Ă  une heure du matin, aisin qu'une sauvegarde Ă  deux heures.

Nettoyage

Il est conseillé de faire un nettoyage, afin d'éviter de garder un nombre trop important de sauvegardes.

La stratégie par défault est définie comme ceci :

// config/laravel-backup.php

'defaultStrategy' => [

    /*
     * Le nombre de jours pour lequel toutes les sauvegardes
     * seront gardées
     */
    'keepAllBackupsForDays' => 7,

    /*
     * Le nombre de jours pour lequel une sauvegarde par jour sera gardée
     */
    'keepDailyBackupsForDays' => 16,

    /*
     * Le nombre de semaines pour lequel une sauvegarde par semaine
     * sera gardée
     */
    'keepWeeklyBackupsForWeeks' => 8,

    /*
     * Le nombre de mois pour lequel une sauvegarde par mois sera gardée
     */
    'keepMonthlyBackupsForMonths' => 4,

    /*
     * Le nombre d'années pour lequel une sauvegarde par année
     * sera gardée
     */
    'keepYearlyBackupsForYears' => 2,

    /*
     * Après le nettoyage, supprimer les plus vielles sauvegardes jusqu'à
     * ce que cette limite de megabytes soit atteinte
     */
    'deleteOldestBackupsWhenUsingMoreMegabytesThan' => 5000,
],

Avec cette stratégie par défaut, vous allez garder :

  • toutes vos sauvegardes pendant 7 jours
  • une sauvegarde par jour pendant les 16 jours suivants
  • une sauvegarde par semaine pendant les 8 semaines suivantes
  • une sauvegarde par mois pendant les 4 mois suivants
  • une sauvegarde par an pendant les 2 annĂ©es suivantes
  • le tout, sans dĂ©passer 5000 megabytes

Le commande pour le nettoyage est celle-ci :

$ php artisan backup:clean

Notification par SMS avec Free Mobile

Ce passage ne vous interessera que si vous ĂŞtes client Free Mobile.

Free propose à ses abonnés une API qui leurs permet de s'envoyer des SMS gratuitement depuis internet.
Cela devient interessant lorsque vous voulez vous envoyer des notifications lorsque par exemple une sauvegarde se passe mal. C'est exactement ce que nous allons faire.

Le package Free Mobile

Pas besoin de réinventer la roue, il existe déjà un package Free Mobile pour Laravel.

$ composer require akibatech/laravel-free-mobile-sms

Dans config/app.php, ajoutez le service provider :

Akibatech\FreeMobileSms\ServiceProvider::class,

RĂ©cuperez vos identifiants Free Mobile :
Allez sur votre compte, GĂ©rer mon compte, Mes options.
Si ce n'est pas déjà fait, activez l'option "Notification par SMS" et récuperer votre pass : Notification par SMS Free Mobile

Ajoutez dans votre .env :

FREE_USER="VOTRE_IDENTIFIANT_FREE"
FREE_PASS="VOTRE_PASS_FREE"

Création de la Notification

Dans votre terminal, créer une nouvelle notification pour Laravel :

$ php artisan make:notification BackupHasFailed

Et modifiez votre fichier comme ceci :

// app/Notifications/BackupHasFailed.php
<?php

namespace App\Notifications;

use Akibatech\FreeMobileSms\Notifications\FreeMobileChannel;
use Akibatech\FreeMobileSms\Notifications\FreeMobileMessage;
use Spatie\Backup\Notifications\Notifications\BackupHasFailed as BaseNotification;

class BackupHasFailed extends BaseNotification
{
    public function toFreeMobile($notifiable)
    {
        return (new FreeMobileMessage("La sauvegarde du site " . env('APP_NAME') . " a échouée."));
    }
}

Configuration de laravel-backup

Il ne vous reste plus qu'à modifier le fichier config/laravel-backup.php pour définir notre nouvelle notification.

Importez FreeMobileChannel en haut de votre fichier :

// config/laravel-backup.php
<?php

use \Akibatech\FreeMobileSms\Notifications\FreeMobileChannel as FreeMobileChannel;

return [

    'backup' => [

Puis remplacez la notification lors de l'Ă©chec de la sauvegarde

/*
     * You can get notified when specific events occur. Out of the box you can use 'mail' and 'slack'.
     * For Slack you need to install guzzlehttp/guzzle.
     *
     * You can also use your own notification classes, just make sure the class is named after one of
     * the `Spatie\Backup\Events` classes.
     */
    'notifications' => [

        'notifications' => [
            // \Spatie\Backup\Notifications\Notifications\BackupHasFailed::class => ['mail'],
            \App\Notifications\BackupHasFailed::class => ['mail', FreeMobileChannel::class],

Vous revevrez donc maintenant un SMS et un mail dès qu'une sauvegarde va échouer.

Ressources

Writing IAM Policies: How to Grant Access to an Amazon S3 Bucket
Notifications on Laravel
Spatie laravel-backup documentation