Support the ongoing development of Laravel.io →
Article Hero Image

Create a backup of your Laravel project on Dropbox

30 Oct, 2024 6 min read 58 views

Photo by Getty Images on Unsplash

How to quickly create a backup of a Laravel project and store it on Dropbox using Spatie Laravel-backup and Flysystem-dropbox packages.

 Dropbox Backup Image 000

A sample Laravel project can be found on this Github Repository. Find out more on Capsules or X.

In web project management, performing regular backups is essential to prevent permanent data loss. Various types of data require backups, including databases, user-generated files, or even files directly related to the web project itself.

Project files are often already managed by a version control system like Github or Gitlab. However, it’s generally not recommended to store user data there. Dropbox can be an excellent choice for securely storing this type of data.

Before transferring backups to Dropbox, it’s useful to generate them first. Spatie’s laravel-backup package makes this task much simpler. Use the following command to install it :

composer require spatie/laravel-backup

Next, simply create the backup configuration file to quickly set up the project backup:

config/backup.php

<?php

return [

    'backup' => [

        'name' => 'capsules',

        'source' => [

            'files' => [

                'include' => [ base_path() ],

                'exclude' => [ base_path( 'vendor' ), base_path( 'node_modules' ) ],

                'relative_path' => null
            ],

            'databases' => [ 'sqlite' ]
        ],

        'database_dump_filename_base' => 'database',

        'database_dump_file_extension' => '',

        'destination' => [

            'compression_method' => ZipArchive::CM_DEFAULT,

            'compression_level' => 9,

            'filename_prefix' => "backup-",

            'disks' => [ 'local' ]
        ],

        'temporary_directory' => '',

        'password' => null,

        'encryption' => 'default',

        'tries' => 1,

        'retry_delay' => 0,
    ]
];

To start the backup :

php artisan backup:run
Starting backup...
Dumping database /dropbox/database/database.sqlite...
Determining files to backup...
Zipping 110 files and directories...
Created zip containing 110 files and directories. Size is 112.76 KB
Copying zip to disk named local...
Successfully copied zip to disk named local.
Backup completed!

The php artisan backup:run command creates a compressed backup that includes the items specified in the include key while excluding those listed in exclude. It also adds the specified databases and stores everything in the folder defined by the name key, naming the file with the filename_prefix followed by the backup date in the format YYY-MM-DD-HH-mm-ss. This backup is saved in the location set by the disks key, which in this case is local and redirects to storage/app/private.

Additional configuration elements, not mentioned here above, are nonetheless essential for the proper functioning of the package.

storage
	> app
		> private 
			> capsules
				- backup-2024-10-29-08-30-00.zip
				- backup-2024-10-28-08-30-00.zip
				...	

With the backup procedure now operational, the next step is to link it to your Dropbox account. For this, we once again turn to Spatie and its flysystem-dropbox package. As the name suggests, this is the Flysystem adapter for the Dropbox V2 API.

composer require spatie/flysystem-dropbox

A new configuration needs to be added to the filesystems configuration file.

config/filesystems.php

<?php

return [

    'disks' => [

	...

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

Laravel backup also needs to be linked to the new dropbox disk. This is a good opportunity to adjust some additional settings.

<?php

return [

    'backup' => [

	...

        'name' => '',

	    ...

        'destination' => [

	    ...

            'filename_prefix' => Illuminate\Support\Str::replace( '.', '-', env( 'DROPBOX_APP_NAME' ) ) . '-',

            'disks' => [ 'dropbox' ]
        ],

	...
    ]
];
  • The name key is left empty to avoid duplicating the folder name ith the Dropbox app, and the filename_prefix now uses the DROPBOX_APP_NAME environment variable instead of backup-.

It is now time to configure the Dropbox integration. The following steps detail the Dropbox setup process. Be aware that some steps may be overly complex.

A. Create a Dropbox Application :

  1. Go to : https://www.dropbox.com/developers/apps
  2. Click on Create app
  3. Choose an API : Scoped access
  4. Select the access type : App folder
  5. Name the app : Capsules Codes Article
  6. Go to the Permissions tab and check the following options : [ files.metadata.write, files.metadata.read, files.content.write, files.content.read ]
  7. Click on Submit

B. Authorize Access :

  1. Grant access to the Capsules Codes Article app by modifying <YOUR_APP_KEY> in the following url.
  2. Continue and Authorize.
https://www.dropbox.com/oauth2/authorize?client_id=<YOUR_APP_KEY>&response_type=code&token_access_type=offline

C. Generate the Required Token :

  1. Obtain the refresh_token by replacing <ACCESS_CODE> with the previously generated access code, along with <APP_KEY> and <APP_SECRET> found in the settings of the newly created app :
curl https://api.dropbox.com/oauth2/token -d code=<ACCESS_CODE> -d grant_type=authorization_code -u <APP_KEY>:<APP_SECRET>

A response in the following format will appear, and a folder will be created in the Dropbox interface :

{"access_token": "sl.B48oJpRyl-FP61gr56g1GUa4G26L3TAQasMbiRRyuAGHpUQXz0hyeA4OrO8Zes6clhQxhA8dyFurNcx4_gwPXJb_K3ZZOfdzBIVwHieInx-EEFNgIc6ZOR3VMRjoOQ-Ske_QjGMePmzS", "token_type": "bearer", "expires_in": 14399, "refresh_token": "PKnAG5FX-ngAAAAAAAAAAVaXknd9i45Xk6t4-FrmXGjR4jWEljmBALOF3Xexp4AY", "scope": "account_info.read files.content.read files.content.write files.metadata.read files.metadata.write", "uid": "682879329", "account_id": "dbid:AADQ-j2-ihak-i0IwMiVS8F5-KhkcyTHyg8"}

The refresh_token should be added to the application’s environment variables, along with the app_key and app_secret located in the settings of the newly created Dropbox application. These can then be added to the .env file.

.env.example

DROPBOX_APP_NAME="Capsules Codes Article"
DROPBOX_APP_KEY=
DROPBOX_APP_SECRET=
DROPBOX_REFRESH_TOKEN=
DROPBOX_TOKEN_URL=https://${DROPBOX_APP_KEY}:${DROPBOX_APP_SECRET}@api.dropbox.com/oauth2/token

The final step is to create the service provider that will establish the connection to the Dropbox service : DropboxServiceProvider.

app\Providers\DropboxServiceProvider.php

<?php

namespace App\Providers;

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

class DropboxServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Storage::extend( 'dropbox', function( Application $app, array $config )
        {
            $resource = ( new Client() )->post( $config[ 'token_url' ] , [ 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => $config[ 'refresh_token' ] ] ]);

            $accessToken = json_decode( $resource->getBody(), true )[ 'access_token' ];

            $adapter = new DropboxAdapter( new DropboxClient( $accessToken ) );

            return new FilesystemAdapter( new Filesystem( $adapter, $config ), $adapter, $config );
        });
    }
}

Do not forget to add it to the providers.php .

bootstrap/providers.php

<?php

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

All that is left is to add the daily backup scheduling commands in the console.php file.

routes/console.php

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command( 'backup:run' )->daily();
Schedule::command( 'backup:clean' )->daily();
  • This code allows the various commands to run once a day using the daily method, provided that a scheduler has been configured for the application. Without this daily command, the refresh_token will expire.
> php artisan backup:run

Starting backup...
Dumping database /dropbox/database/database.sqlite...
Determining files to backup...
Zipping 35 files and directories...
Created zip containing 35 files and directories. Size is 36.74 KB
Copying zip to disk named dropbox...
Successfully copied zip to disk named dropbox.
Backup completed!

Backup Dropbox Image 001

> php artisan backup:clean

Starting cleanup...
Cleaning backups of  on disk dropbox...
Used storage after cleanup: 36.74 KB.
Cleanup completed!

Glad this helped.

Last updated 3 weeks ago.

driesvints liked this article

1
Like this article? Let the author know and give them a clap!
mho (MHO) Full time side project full stack web developer | designer Work @ http://capsules.codes

Other articles you might like

Article Hero Image November 18th 2024

Laravel Custom Query Builders Over Scopes

Hello 👋 Alright, let's talk about Query Scopes. They're awesome, they make queries much easier to r...

Read article
Article Hero Image November 19th 2024

Access Laravel before and after running Pest tests

How to access the Laravel ecosystem by simulating the beforeAll and afterAll methods in a Pest test....

Read article
Article Hero Image November 11th 2024

🍣 Sushi — Your Eloquent model driver for other data sources

In Laravel projects, we usually store data in databases, create tables, and run migrations. But not...

Read article

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.