Create a backup of your Laravel project on Dropbox

capsulescodes

Capsules Codes

Posted on October 30, 2024

Create a backup of your Laravel project on Dropbox

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

 
 

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
Enter fullscreen mode Exit fullscreen mode

 
 

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,
    ]
];
Enter fullscreen mode Exit fullscreen mode

 
 

To start the backup :

 

php artisan backup:run
Enter fullscreen mode Exit fullscreen mode

 
 

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!
Enter fullscreen mode Exit fullscreen mode

 
 

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
                ... 
Enter fullscreen mode Exit fullscreen mode

 
 

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
Enter fullscreen mode Exit fullscreen mode

 
 

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' )

        ]
    ]
];     
Enter fullscreen mode Exit fullscreen mode

 
 

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' ]
        ],

    ...
    ]
];
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

 
 

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>
Enter fullscreen mode Exit fullscreen mode

 
 

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"}
Enter fullscreen mode Exit fullscreen mode

 
 

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
Enter fullscreen mode Exit fullscreen mode

 
 

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 );
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

 
 

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

 
 

bootstrap/providers.php

<?php

return [ App\Providers\DropboxServiceProvider::class ];
Enter fullscreen mode Exit fullscreen mode

 
 

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();
Enter fullscreen mode Exit fullscreen mode
  • 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!
Enter fullscreen mode Exit fullscreen mode

 
 

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!
Enter fullscreen mode Exit fullscreen mode

 
 

Glad this helped.

💖 💪 🙅 🚩
capsulescodes
Capsules Codes

Posted on October 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related