Why Automated Backups are Crucial
In my 9+ years of developing web applications, I have seen many situations where a server crashed, a database got corrupted, or a wrong query wiped out production data. If you do not have a reliable, off-site backup system, you are risking your entire business. Relying on manual backups is a bad idea because we, as humans, eventually forget.
A good backup strategy must be automated, stored securely outside your main server, and should notify you immediately if it fails. In this guide, I will show you how to set up daily MySQL database backups in Laravel, upload them to Amazon S3, and receive instant success or failure alerts on your Slack channel.
Step 1: Install the Spatie Laravel Backup Package
Instead of writing a custom backup script from scratch, we will use the highly popular and reliable spatie/laravel-backup package. It handles database dumping, file compression, and uploading to external disks easily.
Run the following command in your terminal:
composer require "spatie/laravel-backup"Once the installation is complete, publish the configuration file using this command:
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"This will create a config/backup.php file where we can configure our backup settings.
Step 2: Configure AWS S3 Storage
Storing your backups on the same server as your application is a major security risk. If the server goes down, you lose your backups too. We will use AWS S3 to store our backups safely.
First, install the Flysystem S3 adapter via Composer:
composer require league/flysystem-aws-s3-v3 "^3.0"Next, open your .env file and add your AWS credentials. Make sure you create a dedicated IAM user in AWS with read/write access to your specific S3 bucket:
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_DEFAULT_REGION=ap-south-1
AWS_BUCKET=your-backup-bucket-name
AWS_USE_PATH_STYLE_ENDPOINT=falseNow, open config/backup.php and update the destination disk to s3:
'destination' => [
'disks' => [
's3',
],
],Step 3: Configure Slack Notifications
Knowing that a backup failed is even more important than knowing it succeeded. The Spatie package makes it very easy to send notifications to Slack.
First, you need to create an Incoming Webhook in your Slack workspace. Once you have the webhook URL, add it to your .env file:
LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXXOpen config/backup.php and scroll down to the notifications section. Ensure that Slack is enabled for both success and failure events:
'notifications' => [
'notifications' => [
\Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification::class => ['slack'],
\Spatie\Backup\Notifications\Notifications\BackupWasSuccessfulNotification::class => ['slack'],
],
'slack' => [
'webhook_url' => env('LOG_SLACK_WEBHOOK_URL'),
'channel' => '#backups',
'username' => 'Laravel Backup Bot',
],
],Step 4: Schedule the Backups to Run Daily
We want this process to run automatically without any manual intervention. We can schedule the backup command in Laravel's task scheduler.
Open your app/Console/Kernel.php file (or routes/console.php in newer Laravel versions) and add the following cron schedule:
protected function schedule(Schedule $schedule)
{
// Run database backup daily at midnight
$schedule->command('backup:run --only-db')->daily()->at('00:00');
// Clean up old backups daily at 1:00 AM to save S3 space
$schedule->command('backup:clean')->daily()->at('01:00');
}The backup:clean command is highly recommended because it automatically deletes old backups based on the retention rules defined in your config/backup.php, saving you from high AWS storage bills.
Make sure you have a system cron job configured on your production server to run the Laravel scheduler every minute:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1Step 5: Testing Your Setup
Before leaving it to run on its own, you must test it manually. Run this command in your terminal:
php artisan backup:run --only-dbIf everything is configured correctly, you should see:
- A zip file containing your MySQL database dump uploaded to your AWS S3 bucket.
- A green notification message in your Slack channel indicating that the backup was successful.
If it fails, the terminal output or your Laravel log file (storage/logs/laravel.log) will show you the exact error, which is usually related to incorrect AWS credentials or missing system tools like mysqldump.
Final Thoughts
Setting up automated backups takes less than 30 minutes, but it can save your business from a major disaster. By moving your backups to AWS S3 and setting up Slack alerts, you can sleep peacefully knowing your production data is secure and you will be alerted immediately if anything breaks.
If you need help setting up advanced backup strategies, server optimization, or secure cloud integrations for your Laravel application, feel free to reach out to me.
Common Questions
Do I need mysqldump installed on my server for this to work?
Yes, the Spatie Laravel Backup package relies on the native 'mysqldump' utility to export your MySQL database. Most Linux servers with MySQL installed already have this, but if you are using a managed database service, make sure the CLI tool is available on your application server.
Can I back up my uploaded files along with the database?
Yes. By default, running 'php artisan backup:run' without the '--only-db' flag will back up both your database and the files specified in your 'config/backup.php' under the 'source.files.include' array.
How do I prevent AWS S3 costs from rising over time?
You should use the 'php artisan backup:clean' command in your scheduler. This command deletes older backups based on the retention rules defined in 'config/backup.php' (e.g., keeping daily backups for 7 days, weekly backups for 4 weeks, etc.).