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/tokenCreate 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