When working with large websites containing critical data, regular database backups are non-negotiable. Imagine losing weeks of customer transactions or content updates due to an unexpected server failure. Automated backups act as your safety net, ensuring you can restore your application quickly when disaster strikes.
In this comprehensive guide, I’ll walk you through setting up scheduled database backups (daily, weekly, or monthly) in your Laravel 12 application using Laravel’s built-in task scheduling.
The Solution Overview
We’ll implement this backup system by:
- Creating a custom Artisan command to handle database backups
- Configuring storage for backup files
- Setting up the scheduling frequency
- Deploying to production with cron jobs
Let’s dive into the implementation!
Step 1: Install a Fresh Laravel 12 Application
If you’re starting a new project, begin with a clean Laravel installation:
composer create-project laravel/laravel example-app
For existing projects, ensure you’re running Laravel 12 and have database credentials properly configured in your .env file.
Step 2: Create the Backup Command
Laravel’s Artisan console makes it easy to create custom commands. Generate our backup command with:
php artisan make:command DatabaseBackUp
Now, let’s implement the backup logic in app/Console/Commands/DatabaseBackUp.php:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class DatabaseBackUp extends Command
{
/**
* The command signature for Artisan
*
* @var string
*/
protected $signature = 'database:backup';
/**
* The command description
*
* @var string
*/
protected $description = 'Automatically generate a database backup';
/**
* Execute the console command
*/
public function handle()
{
$filename = "backup-" . now()->format('Y-m-d_H-i-s') . ".gz";
$command = "mysqldump --user=" . env('DB_USERNAME')
. " --password=" . env('DB_PASSWORD')
. " --host=" . env('DB_HOST')
. " " . env('DB_DATABASE')
. " | gzip > " . storage_path() . "/app/backups/" . $filename;
$returnVar = NULL;
$output = NULL;
exec($command, $output, $returnVar);
if($returnVar === 0) {
$this->info("Database backup created successfully: " . $filename);
} else {
$this->error("Database backup failed");
}
}
}
Key Improvements:
- Added timestamp with hours/minutes/seconds for more precise backups
- Included success/error feedback messages
- Changed folder name to “backups” (more conventional)
Step 3: Set Up the Backup Storage
Create a dedicated folder for backups with proper permissions:
mkdir -p storage/app/backups
chmod -R 775 storage/app/backups
This ensures Laravel can write backup files to the directory.
Step 4: Configure the Backup Schedule
Now let’s schedule our command in app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
// Daily backup at 2:30 AM
$schedule->command('database:backup')->dailyAt('2:30');
// Weekly backup (alternatively)
// $schedule->command('database:backup')->weekly();
// Monthly backup (alternatively)
// $schedule->command('database:backup')->monthly();
}
Pro Tip: For production environments, consider:
- Daily backups for active databases
- Weekly full backups with daily differentials
- Storing backups in multiple locations (AWS S3, etc.)
Step 5: Test Your Backup Command
Verify everything works by running:
php artisan database:backup
Check your storage/app/backups directory for a new compressed backup file.
Step 6: Configure Server Cron Job (Production)
For scheduled backups to work in production, add this to your server’s crontab:
crontab -e
Add this line (adjust the path to match your project):
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This cron entry will check for scheduled tasks every minute.