How to Set Up Laravel 12 Automatic Backups with Spatie Backup and Dropbox

Laravel 12 provides a good and easy way for backing up project along with database file. Spatie laravel backup is a popular package for automatic backup among all developers. Here in this tutorial we will use dropbox as our storage. We will also use scheduler so that it creates backup automatically . Backup is very necessary for preventing data loss and it also helps to recover data if something went wrong. 

Dropbox is a popular cloud service for storing file for personal, official as well as enterprise use. It also give features for storing file using API. We will take the benefits of it. Let's start it.


Steps for Backing Up Laravel 12 using Dropbox:

1. Install Laravel 12 Fresh Project

2. Install Necessary Composer Dependencies and Packages

3. Setup Dropbox Apps and Folder

4. Create Necessary Class and Files

5. Run Backup Script

6. Add Backup Script in Schedular

1. Install Laravel 12 Fresh Project

We will create a fresh laravel 12 project to implement our backup automation. We can also use this in our existing laravel 12 project as well

composer create-project --prefer-dist laravel/laravel laravel12-backup
cd laravel12-project

2. Install Necessary Composer Dependencies and Packages

Here we will use spatie backup package and dropbox filesystem as dependencies

composer require spatie/laravel-backup
composer require spatie/flysystem-dropbox


Now publish vendor Spatie\Backup\BackupServiceProvider and it will create a file config/backup.php. Do change according to your need. Here is a example config/backup.php file.

return [
    'backup' => [
        'name' => '',

        'source' => [
            'files' => [
                'include' => [
                    base_path('storage/app/public'),
                ],
                'exclude' => [
                    base_path('vendor'),
                    base_path('node_modules'),
                ],
                'follow_links' => false,
                'ignore_unreadable_directories' => false,
                'relative_path' => null,
            ],
            'databases' => [
                env('DB_CONNECTION', 'mysql'),
            ],
        ],

        'database_dump_compressor' => null,
        'database_dump_file_timestamp_format' => null,
        'database_dump_filename_base' => 'database',
        'database_dump_file_extension' => '',

        'destination' => [
            'compression_method' => ZipArchive::CM_DEFAULT,
            'compression_level' => 9,
            'filename_prefix' => Illuminate\Support\Str::replace('.', '-', env('DROPBOX_APP_NAME')) . '-',
            'disks' => ['local','dropbox'],
        ],

        'temporary_directory' => storage_path('app/backup-temp'),
        'password' => env('BACKUP_ARCHIVE_PASSWORD'),
        'encryption' => 'default',
        'tries' => 1,
        'retry_delay' => 0,
    ],

    'notifications' => [
        'notifications' => [
            \Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification::class => ['mail'],
            \Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFoundNotification::class => ['mail'],
            \Spatie\Backup\Notifications\Notifications\CleanupHasFailedNotification::class => ['mail'],
            \Spatie\Backup\Notifications\Notifications\BackupWasSuccessfulNotification::class => ['mail'],
            \Spatie\Backup\Notifications\Notifications\HealthyBackupWasFoundNotification::class => ['mail'],
            \Spatie\Backup\Notifications\Notifications\CleanupWasSuccessfulNotification::class => ['mail'],
        ],

        'notifiable' => \Spatie\Backup\Notifications\Notifiable::class,

        'mail' => [
            'to' => env("APP_DEVELOPER_EMAIL",'[email protected]'),
            'from' => [
                'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
                'name' => env('MAIL_FROM_NAME', 'Example'),
            ],
        ],

        'slack' => [
            'webhook_url' => '',
            'channel' => null,
            'username' => null,
            'icon' => null,
        ],

        'discord' => [
            'webhook_url' => '',
            'username' => '',
            'avatar_url' => '',
        ],
    ],

    'monitor_backups' => [
        [
            'name' => env('APP_NAME', 'laravel-backup'),
            'disks' => ['local'],
            'health_checks' => [
                \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1,
                \Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000,
            ],
        ],
    ],

    'cleanup' => [
        'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class,
        'default_strategy' => [
            'keep_all_backups_for_days' => 7,
            'keep_daily_backups_for_days' => 16,
            'keep_weekly_backups_for_weeks' => 8,
            'keep_monthly_backups_for_months' => 4,
            'keep_yearly_backups_for_years' => 2,
            'delete_oldest_backups_when_using_more_megabytes_than' => 5000,
        ],
        'tries' => 1,
        'retry_delay' => 0,
    ],

];


Add a dropbox driver in config/filesystems.php

return [

    'default' => env('FILESYSTEM_DISK', 'local'),

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app/private'),
            'serve' => true,
            'throw' => false,
        ],

        'dropbox' => [ //dropbox configuration
            'driver' => 'dropbox',
            'token_url' => env( 'DROPBOX_TOKEN_URL' ),
            'refresh_token' => env( 'DROPBOX_REFRESH_TOKEN' ),
        ],

    ],


3. Setup Dropbox Apps and Folder

We will create a dropbox app from developer panel and give necessary permissions to that app. Follow the steps

Step 1. Create a Dropbox Application

  • Visit Dropbox Developer Apps
  • Click Create app.
  • Under Choose an API, select Scoped access.
  • For Access type, choose App folder.
  • Enter the app name: Capsules Codes Article.
  • Navigate to the Permissions tab and enable the following:

files.metadata.write

files.metadata.read

files.content.write

files.content.read

Click Submit to create the app.




Step2: Give Access to Our Newly Created app and Create Access Code. After getting passcode and copy in somewhere

https://www.dropbox.com/oauth2/authorize?client_id=&response_type=code&token_access_type=offline


Step3: Now Create Refresh token using Curl Command from Terminal. We will use access code, app key , app secret

curl https://api.dropbox.com/oauth2/token -d code=<ACCESS_CODE> -d grant_type=authorization_code -u <APP_KEY>:<APP_SECRET>

This will create json response and return refresh token like below

{"access_token": "sl.H884ghyl-FP61gr56g1GUa4G26L3TAQasMbiRRyuAGHpUxxxxxxxxxxxxxxxxBIVwHieInx-EEFNgIc6ZOR3VMRjoOQ-Ske_QjGMePmzS", "token_type": "bearer", "expires_in": 14399, "refresh_token": "PKnAG5FX-ngACCCCCCCCCknd9i45Xk6t4-FhjfYFSkiopDLOF3Xexp4AY", "scope": "account_info.read files.content.read files.content.write files.metadata.read files.metadata.write", "uid": "682879329", "account_id": "dbid:AADQ-j2-ihak-UFJS-KFHDiojDYF"}


Now we will change our .env with credentials. It should be field by app key, app secret, refresh token

DROPBOX_APP_NAME="Programming Mindset"
DROPBOX_APP_KEY=app key here
DROPBOX_APP_SECRET=app secret here
DROPBOX_REFRESH_TOKEN=PKnAG5FX-ngACCCCCCCCCknd9i45Xk6t4-FhjfYFSkiopDLOF3Xexp4AY
DROPBOX_TOKEN_URL=https://${DROPBOX_APP_KEY}:${DROPBOX_APP_SECRET}@api.dropbox.com/oauth2/token

Create Necessary Class and Files

To run our backup script we should create DropboxServiceProvider and register in our bootstrap/providers.php  file

namespace App\Providers;

use GuzzleHttp\Client;
use League\Flysystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Contracts\Foundation\Application;

class DropboxServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {

        Storage::extend( 'dropbox', function( Application $app, array $config )
        {
            $resourceData = ( new Client() )->post( $config[ 'token_url' ] , [ 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => $config[ 'refresh_token' ] ] ]);
            $accessToken = json_decode( $resourceData->getBody(), true )[ 'access_token' ];
$adapter = new DropboxAdapter( new DropboxClient( $accessToken ) ); return new FilesystemAdapter( new Filesystem( $adapter, $config ), $adapter, $config ); }); } }

Register DropboxServiceProvider in bootstrap/providers.php file like below

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\DropboxServiceProvider::class,
];

4. Add Backup Script in Scheduler

We will now add our backup console command in bootstrap/app file like below

 ->withExceptions(function (Exceptions $exceptions) {

        if (!app()->isLocal()) { //this will redirect to homepage if any page returns 404 and environment is production
            $exceptions->render(function (Throwable $e) {
                if ($e instanceof NotFoundHttpException) {
                    return redirect('/', 301);
                }
            });
        }
    })->withSchedule(function () {

        Schedule::command('backup:run')->timezone('Asia/Dhaka')->weeklyOn(5, '23:00'); //friday 11.00pm
        Schedule::command('backup:clean')->timezone('Asia/Dhaka')->weeklyOn(5, '23:00'); //friday 11.00pm

    })->create();

5. Run Backup Script in Terminal

We will test our backup script by running backup:run from terminal. Here is the command and output

php artisan backup:run


Result after running the command backup:run

λ php artisan backup:run
Starting backup...
Dumping database blog_server...
Determining files to backup...
Zipping 2 files and directories...
Created zip containing 2 files and directories. Size is 84.7 KB
Copying zip to disk named local...
Successfully copied zip to disk named local.
Copying zip to disk named dropbox...
Successfully copied zip to disk named dropbox.
Backup completed!


This will create zip file in dropbox along with  project files as well as sql file

Hope this article will help you. If you get benefits, then regularly follow our blog, share it and watch our youtube channel as well

Tags: