spatie/laravel-backup-server
Securely store and manage backups from multiple Laravel apps on a dedicated backup server. Built on spatie/laravel-backup, it automatically receives and organizes incoming backups, with setup and docs tailored for Laravel deployments.
Install the Package
composer require spatie/laravel-backup-server
php artisan vendor:publish --provider="Spatie\BackupServer\BackupServerServiceProvider"
Publish the config file (config/backup-server.php) and migrations.
Configure Destinations
Define a storage disk in config/filesystems.php (e.g., backup_disk with local driver) and create a Destination model:
use Spatie\BackupServer\Models\Destination;
Destination::create([
'name' => 'primary_backup',
'disk_name' => 'backup_disk',
'capacity_in_mb' => 100000, // Optional: Set capacity for monitoring
]);
Add a Source
Register a remote server as a source (via backup-server:sources table or Tinker):
use Spatie\BackupServer\Models\Source;
Source::create([
'name' => 'production_app',
'ssh_host' => 'user@remote-server.com',
'backup_hour' => 3, // Run backups at 3 AM
'includes' => ['/var/www/html', '/etc/nginx'],
'excludes' => ['/var/www/html/storage/logs'],
'pre_backup_commands' => ['mysqldump -u root -p db_name > /tmp/db_backup.sql'],
'post_backup_commands' => ['rm /tmp/db_backup.sql'],
]);
Run a Backup Manually trigger a backup for a source:
php artisan backup-server:backup production_app
Or schedule it hourly via Laravel’s scheduler:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule) {
$schedule->command('backup-server:dispatch-backups')->hourly();
}
Verify Backups Check source/destination health:
php artisan backup-server:list --sortBy=healthy
php artisan backup-server:list-destinations
Centralized Backup Management
Destination for each environment (e.g., production_backups, staging_backups) and route sources accordingly.Incremental Backups with Rsync
rsync for efficient transfers. Only changed files are copied; identical files use hard links to save space./node_modules) from includes to reduce backup size.Pre/Post-Backup Automation
pre_backup_commands to:
mysqldump, pg_dump).post_backup_commands to:
Health Monitoring
php artisan backup-server:monitor-health
Source::find(1)->update(['pause_notifications_until' => now()->addHours(2)]);
Cleanup Strategy
$schedule->command('backup-server:cleanup')->daily();
Destination models (e.g., keep backups for 30 days).Search and Restore
php artisan backup-server:find-files production_app "*.env"
php artisan backup-server:find-content production_app "SECRET_KEY"
/storage/backup_disk/<source-id>/backup-<timestamp>/).Database Backups
pre_backup_commands to dump databases to a file (e.g., /tmp/db_backup.sql) and include the file in includes.'pre_backup_commands' => [
'mysqldump -u root -p db_name > /tmp/db_backup.sql',
'gzip /tmp/db_backup.sql',
],
'includes' => ['/tmp/db_backup.sql.gz'],
'post_backup_commands' => ['rm /tmp/db_backup.sql.gz'],
Notifications
// config/backup-server.php
'notifications' => [
\Spatie\BackupServer\Notifications\Notifications\BackupFailedNotification::class => ['mail', 'slack'],
],
'slack' => [
'webhook_url' => env('SLACK_WEBHOOK_URL'),
'channel' => '#alerts',
],
SSH Key Management
config/backup-server.php or a secrets manager like AWS Secrets Manager).// config/backup-server.php
'ssh' => [
'private_key_path' => '/path/to/private_key',
'passphrase' => env('SSH_KEY_PASSPHRASE'),
],
Testing Backups
# Copy a file from backup to local
cp /storage/backup_disk/<source-id>/backup-*/path/to/file /tmp/restored_file
rsync to verify integrity:
rsync -avz --delete user@remote-server.com:/path/to/source /tmp/local_copy
Scaling Destinations
Destination models with different disks (e.g., s3, local with different paths).Destination::create([
'name' => 's3_backups',
'disk_name' => 's3',
'capacity_in_mb' => null, // S3 capacity is managed externally
]);
SSH Connection Issues
chmod 600 /path/to/private_key).ssh_host format in Source models (e.g., user@hostname or hostname with ssh_username in config).ssh -i /path/to/private_key user@remote-server.com
Permission Denied on Destination
chown -R www-data:www-data /storage/backup_disk
chmod -R 755 /storage/backup_disk
PutObject permissions.Hard Link Limitations
cp -r /storage/backup_disk/<source-id>/backup-* /tmp/restore_target
Large Backup Size Calculations
config/backup-server.php:
'backup_size_calculation_timeout_in_seconds' => 3600, // 1 hour
/var/lib/docker).Notification Delays
pause_notifications_until field in sources table.notifiable class in config/backup-server.php is correct.php artisan backup-server:notify-healthy-sources
Rsync Overhead
rsync transfers are slow or fail for large files.'rsync_options' => ['-z'], // Enable compression
How can I help you explore Laravel packages today?