Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Backup Restore Laravel Package

wnx/laravel-backup-restore

Restore database backups created by spatie/laravel-backup. Adds an interactive php artisan backup:restore command to pick a backup and optionally decrypt it, then run configurable post-restore health checks to validate the restored DB.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Steps to Begin
1. **Installation**:
   ```bash
   composer require wnx/laravel-backup-restore
   php artisan vendor:publish --tag="backup-restore-config"
  • Ensure spatie/laravel-backup is installed (this package depends on it).
  1. First Use Case: Restore the latest backup interactively:

    php artisan backup:restore
    
    • The command will prompt for backup selection, encryption password, and confirmation.
  2. Key Configurations:

    • Verify config/backup.php (from spatie/laravel-backup) is correctly set up with:
      • Destinations (e.g., s3, local).
      • Sources (database connections).
      • Encryption (if applicable).
    • Check config/laravel-backup-restore.php for health checks (default: DatabaseHasTables).

Implementation Patterns

Core Workflows

  1. Interactive Restoration:

    php artisan backup:restore
    
    • Automatically lists available backups (based on APP_NAME and config/backup.php destinations).
    • Prompts for:
      • Backup selection (supports latest).
      • Encryption password (defaults to config/backup.php).
      • Confirmation (skipped with --no-interaction).
  2. Non-Interactive (CI/CD/Pipelines):

    php artisan backup:restore \
      --disk=s3 \
      --backup=latest \
      --connection=mysql \
      --password=my-secret \
      --reset \
      --no-interaction
    
    • Flags:
      • --disk: Override default destination (e.g., s3, local).
      • --backup: Specify backup file (e.g., backup-2024-01-01.sql.gz or latest).
      • --connection: Target database connection (from config/backup.php sources).
      • --password: Manual override for encrypted backups.
      • --reset: Drop tables before restore (default: false).
      • --keep: Preserve downloaded/decrypted files (default: false).
      • --no-interaction: Bypass prompts (critical for automation).
  3. Health Checks Integration:

    • Extend default checks (e.g., verify critical data exists post-restore):
      // app/HealthChecks/CustomCheck.php
      namespace App\HealthChecks;
      use Wnx\LaravelBackupRestore\HealthChecks\HealthCheck;
      use Wnx\LaravelBackupRestore\PendingRestore;
      
      class CustomCheck extends HealthCheck {
          public function run(PendingRestore $pendingRestore) {
              $result = Result::make($this);
              if (!Model::count()) {
                  return $result->failed('Critical data missing!');
              }
              return $result->ok();
          }
      }
      
    • Register in config/laravel-backup-restore.php:
      'health-checks' => [
          \Wnx\LaravelBackupRestore\HealthChecks\Checks\DatabaseHasTables::class,
          \App\HealthChecks\CustomCheck::class,
      ],
      
  4. Automated Validation (GitHub Actions):

    • Use the provided workflow template to test backup integrity periodically:
      - name: Restore Backup
        run: php artisan backup:restore --backup=latest --no-interaction
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          BACKUP_ARCHIVE_PASSWORD: ${{ secrets.BACKUP_ARCHIVE_PASSWORD }}
      

Integration Tips

  • Database-Specific Quirks:

    • MySQL GTID Issues: Add --set-gtid-purged=OFF to config/backup.php under dump for DigitalOcean-managed DBs:
      'dump' => [
          'add_extra_option' => '--set-gtid-purged=OFF',
      ],
      
    • PostgreSQL: Supports binary dumps (v1.9.0+). Ensure pg_dump/pg_restore paths are correct.
  • Multi-Environment:

    • Use environment-specific APP_NAME to isolate backups (e.g., APP_NAME=staging for staging backups).
    • Override config/backup.php per environment (e.g., via .env or environment variables).
  • Backup Rotation:

    • Combine with spatie/laravel-backup retention policies to manage storage costs.

Gotchas and Tips

Pitfalls

  1. Backup Naming Convention:

    • The package assumes backup folders match APP_NAME. Mismatches (e.g., APP_NAME=App but backup folder is app) cause failures.
    • Fix: Ensure APP_NAME in .env matches the backup folder name.
  2. Encryption Passwords:

    • Hardcoding passwords in commands or scripts is insecure. Use environment variables or Laravel’s secret manager:
      php artisan backup:restore --password=$BACKUP_PASSWORD
      
    • Tip: Store BACKUP_ARCHIVE_PASSWORD in .env and exclude it from version control.
  3. Database Connection Conflicts:

    • Restoring to a connection with existing data may cause conflicts (e.g., duplicate keys).
    • Solution: Use --reset to drop tables first, or restore to a fresh database.
  4. File Permissions:

    • Backups stored locally require write permissions on the destination path.
    • Debug: Check storage/backups/ permissions or S3 bucket policies for remote storage.
  5. Health Check Failures:

    • Custom health checks may fail silently. Log results for debugging:
      public function run(PendingRestore $pendingRestore) {
          $result = Result::make($this);
          try {
              if (!Model::count()) {
                  return $result->failed('Data missing!');
              }
          } catch (\Exception $e) {
              return $result->failed("Check failed: {$e->getMessage()}");
          }
          return $result->ok();
      }
      
  6. GTID Errors (MySQL):

    • DigitalOcean’s managed MySQL enables GTID by default, causing restore failures.
    • Workaround: Disable GTID in config/backup.php (as shown above) before creating backups. Existing GTID-enabled backups cannot be restored with this package.
  7. Post-Restore Data Validation:

    • Health checks run after restore. If they fail, the database may be in an inconsistent state.
    • Tip: Test restores in a staging environment first.

Debugging Tips

  1. Verbose Output:

    • Enable debug mode for detailed logs:
      php artisan backup:restore --verbose
      
    • Check Laravel logs (storage/logs/laravel.log) for errors.
  2. Manual Backup Paths:

    • Specify exact backup paths to avoid ambiguity:
      php artisan backup:restore --backup="backups/app/backup-2024-01-01.sql.gz"
      
  3. Dry Runs:

    • Use --keep to inspect downloaded/decrypted files:
      php artisan backup:restore --backup=latest --keep
      
    • Check storage/backups/decrypted/ for the extracted SQL file.
  4. Connection Issues:

    • Verify database credentials in config/backup.php sources match the target environment.
    • Test connectivity manually:
      mysql -h localhost -u root -p
      
  5. Health Check Isolation:

    • Test custom health checks in isolation:
      use App\HealthChecks\CustomCheck;
      $check = new CustomCheck();
      $result = $check->run(new PendingRestore(...));
      dd($result->isOk()); // Debug output
      

Extension Points

  1. Custom Health Checks:

    • Extend Wnx\LaravelBackupRestore\HealthChecks\HealthCheck to validate business logic (e.g., user counts, critical records).
    • Example: Check for admin users post-restore:
      class AdminUserCheck extends HealthCheck {
          public function run(PendingRestore $pendingRestore) {
              $result = Result::make($this);
              if (User::where('role', 'admin')->doesntExist()) {
                  return $result->failed('No admin users found!');
              }
              return $result->ok();
          }
      }
      
  2. Pre/Post-Restore Hooks:

    • Use Laravel’s registering/registered events for the backup:restore command (via service providers) to run custom logic before/after restore.
  3. Backup Metadata:

    • Parse backup filenames (e.g., backup-2024-01-01.sql.gz) to extract timestamps or tags for dynamic selection:
      $backup = 'backup-2024-01-01.sql.gz';
      $date = substr($backup, 7, 10); // Extracts '2024-01-01'
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony