spatie/laravel-backup
Spatie Laravel Backup creates zip backups of your app files and database, storing them on any Laravel filesystem (even multiple). Includes health monitoring, notifications, and automatic cleanup of old backups. Run with php artisan backup:run.
Installation:
composer require spatie/laravel-backup
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"
This publishes the default config (config/backup.php) and migrations (if using database monitoring).
First Backup:
php artisan backup:run
By default, this backs up:
storage/ and bootstrap/cache/.env)Where to Look First:
config/backup.php (define sources, destinations, schedules, and cleanup rules).backup:run – Create a backup.backup:monitor – Check backup health.backup:clean – Remove old backups.destinations array (e.g., s3, ftp, local, or custom filesystems).First Use Case: Schedule a daily backup to S3 and local storage:
// config/backup.php
'schedules' => [
\Spatie\Backup\Tasks\ScheduleTask::class => [
\Spatie\Backup\Tasks\Backup\CreateBackup::class,
\Spatie\Backup\Tasks\Backup\Notify::class,
],
],
Then add to app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->command('backup:run')->daily();
}
Defining Backup Sources:
'sources' => [
\Spatie\Backup\Tasks\Backup\Sources\Source::local()
->addFiles('/path/to/custom/directory')
->addDatabase(MySqlDatabase::create())
->addDatabase(PostgresDatabase::create())
->addDatabase(MongoDatabase::create()),
],
Source::local() for file backups.addFiles(), addDatabase(), or exclude() for granular control.Multi-Destination Backups:
'destinations' => [
'local' => [
'driver' => 'local',
'path' => storage_path('backups'),
],
's3' => [
'driver' => 's3',
'bucket' => 'my-backup-bucket',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => 'us-east-1',
'path' => 'laravel-backups',
],
],
BackupDestination::create() for custom logic (e.g., encryption).Monitoring Backup Health:
php artisan backup:monitor
storage/logs/laravel-backup.log by default.Notifications:
'notifications' => [
'notifiable' => \App\Notifications\BackupFailed::class,
'channel' => 'mail', // or 'slack', 'database', etc.
],
Spatie\Backup\Notifications\BackupNotification for custom logic.BackupWasSuccessful, BackupHasFailed) to trigger notifications.Cleanup Automation:
php artisan backup:clean
config/backup.php under cleanup.default_strategy.CleanupStrategy interface.Database-Specific Backups:
$database = MySqlDatabase::create()
->setUssername(env('DB_USERNAME'))
->setPassword(env('DB_PASSWORD'))
->setHost(env('DB_HOST'))
->setName(env('DB_DATABASE'))
->setSocket('/path/to/mysql.sock'); // For socket-based connections
Excluding Files:
Source::local()->exclude(['storage/logs/*', 'node_modules/*']);
Encryption:
use Spatie\Backup\Tasks\Backup\EncryptBackup;
'tasks' => [
EncryptBackup::class,
],
config/backup.php.Testing Backups:
php artisan backup:run --test
Custom Destinations:
BackupDestination::create('custom')
->type(\Spatie\Backup\BackupDestination\BackupDestinationType::FTP)
->connection('ftp_connection_name')
->path('backups/laravel');
Disk Space:
df -h (Linux) or Get-PSDrive (Windows).Large Databases:
--single-transaction for MySQL to avoid locks:
MySqlDatabase::create()->setDumpOptions(['--single-transaction']);
--gzip to compress dumps:
MongoDatabase::create()->setDumpOptions(['--gzip']);
Permission Issues:
Windows Limitations:
Time Zones in Cleanup:
config/app.php if needed.Monitoring False Positives:
backup:monitor --ignore-checksums to bypass temporarily.Database Connection Drops:
max_execution_time in php.ini or use chunked backups:
MySqlDatabase::create()->setChunkSize(100000);
Verbose Output:
php artisan backup:run --verbose
Log Files:
storage/logs/laravel-backup.log for errors.config/backup.php:
'debug' => env('BACKUP_DEBUG', false),
Dry Runs:
php artisan backup:run --test
Manual Cleanup:
php artisan backup:clean --destination=local
Default Destinations:
destinations are configured, backups are not saved. Always define at least one.Database Credentials:
.env variables for security:
MySqlDatabase::create()
->setUsername(env('DB_USERNAME'))
->setPassword(env('DB_PASSWORD'));
Overwriting Backups:
BackupDestination::overwrite() to force:
BackupDestination::create('s3')->overwrite();
Parallel vs. Sequential:
BackupDestination::sequential() to process one at a time:
BackupDestination::create('s3')->sequential();
Custom Backup Names:
'name' => 'myapp_backup_' . date('Y-m-d'),
Custom Tasks:
config/backup.php:
'tasks' => [
\Spatie\Backup\Tasks\Backup\CreateBackup::class,
\App\Tasks\CustomTask::class, // Your custom logic
\Spatie\Backup\Tasks\Backup\Notify::class,
],
Spatie\Backup\Tasks\Task interface.Custom Destinations:
Spatie\Backup\BackupDestination\BackupDestinationHow can I help you explore Laravel packages today?