Daily Archives: 23rd December 2015


Backing up a Laravel site to Amazon S3 with laravel-backup

Installing Laravel-backup

For this activity I’m going to be using the Laravel-Backup tool from Spatie

https://github.com/spatie/laravel-backup

Follow the instructions on the github readme.

  1. composer require spatie/laravel-backup
  2. add service provider to app.php  Spatie\Backup\BackupServiceProvider::class,
  3. publish the config file. This adds a new laravel-backup config item to the config folder
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"

To start with, we will test the backup using the local file system, as comes enabled  by default.

You now have a couple of additional functions in Artisan

backup-commands

Try php artisan backup:run

If it returns an error then it’s probably because your system cannot find the needed mysqldump command. If this is not found then you will have to track it down on your machine and then adjust the myqsl dump_command_path in the laravel-backup.php file.  Make sure the path ends in a forward slash as the mysqldump command will be appended to it.

'mysql' => [
 /*
 * The path to the mysqldump binary. You can leave this empty
 * if the binary is installed in the default location.
 */
 'dump_command_path' => '/Applications/MAMP/Library/bin/',

When using the default Local storage, the backup will be in the storage/app/backups folder. At this point, you should test the backup files

Configuring S3 to receive the files

Assuming that you have an AWS S3 account with Amazon.

First of all create the bucket that will be used. I recommend a separate bucket for each site since that allows you to secure them individually.

Next, create an IAM identity for the bucket. Identity and Access Management is an identity management solution and will prevent the credentials stored on this website from accessing other backups.  The last thing you want is an intruder on one site accessing the backups for other sites since these backups will contain access credentials for those other sites.

  1. Select create user
  2. Enter a name for the user (the name of the site perhaps)
  3. Copy the access credentials. These will be used to configure Laravel Flysystem in a moment.

Select the User and click Permissions then Inline Policies

Select Create One, then Custom Policy

Provide a policy name (no spaces)

Add the policy as below, adding the name of your new bucket

{
    "Version": "2012-10-17",
    "Statement": [
    {
        "Effect": "Allow",
        "Action": "*",
        "Resource": [
            "arn:aws:s3:::your-bucket-name",
            "arn:aws:s3:::your-bucket-name/*"
         ],
         "Condition": {}
     } 
     ]
}

Configure Laravel Flysystem

Edit config/filesystems.php

Under disks->s3, change the following so that the S3 keys can be picked up from .env and not end up in your repo.

 'driver' => 's3',
 'key' => env('S3_KEY'),
 'secret' => env('S3_SECRET'),
 'region' => env('S3_REGION'),
 'bucket' => env('S3_BUCKET'),

Then set the .env file with the actual values

S3_KEY='AKI****F2CH4****PFKQ' #your access key
S3_SECRET='kEjL********r3r+4QjkbU********NQIiiEfhb' #secret access key
S3_REGION='eu-west-1'
S3_BUCKET='your-bucket-name'

Next tell laravel-backup to use S3 (config/laravel-backup.php)

/* 
* The filesystem(s) you on which the backups will be stored. Choose one or more 
* of the filesystems you configured in app/config/filesystems.php 
*/ 
  'filesystem' => ['s3'],

and set the folder in which to store the backup

 /*
 * The path where the backups will be saved. This path
 * is relative to the root you configured on your chosen
 * filesystem(s).
 *
 * If you're using the local filesystem a .gitignore file will
 * be automatically placed in this directory so you don't
 * accidentally end up committing these backups.
 */
 'path' => 'backup',

Install S3 library

The S3 libraries are not shipped by default so you will need to add these via composer

composer require league/flysystem-aws-s3-v3 ~1.0

Test so far…

You should run the backup again and hopefully your files will be pushed to S3, which you can inspect through the S3 file browser

 

Configuring CRON to run the job

Configure the server to call the Schedule:run artisan command every minute. This is covered in the Laravel docs.

If your host does not support CRON, then A suggestion is made in an earlier blog post.

Setup entries in your Http/kernel.php file;

protected function schedule(Schedule $schedule)
 {
    $schedule->command('backup:run',['--only-files' => '','--suffix' => '_files'])
        ->weekly()->mondays()->at('03:00')
        ->description('My-project Files backup')
        ->sendOutputTo('storage/logs/backup.log')
        ->emailOutputTo('mark@novate.co.uk')
        ->before(function(){
            Log::info('Commencing Files Backup');
        })
        ->after(function(){
            Log::info('My-project Files backup complete');
        });

    $schedule->command('backup:run',['--only-db' => '','--suffix' => '_db'])
        ->twiceDaily(2,14)
        ->description('My-project Database backup')
        ->sendOutputTo('storage/logs/backup.log')
        ->emailOutputTo('mark@novate.co.uk')
        ->before(function(){
            Log::info('Commencing Database backup');
        })
        ->after(function(){
            Log::info('My-project Database backup complete');
    });
 }

So here, I have two backup jobs, one running once per week for all the files, and then a twice-daily database backup.  Following each, the log of the backup is sent via email.

Summary

This has been a long-winded setup as there are multiple steps.  Laravel-backup is a very flexible backup solution and leverages league\flysystem to store backups to the cloud.

Using Amazon S3 and protecting it with IAM provides a robust destination for your backups.