Weave 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

Backupmanager Laravel Package

backpack/backupmanager

Backpack BackupManager gives Laravel admins a simple panel for creating, scheduling, downloading, and restoring database and file backups. Store backups locally or in the cloud and manage everything from Backpack's admin UI—no command line needed.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install the package and its real dependency. BackupManager is a thin Backpack admin UI over spatie/laravel-backup — the package does almost no backup work itself, so your success depends on configuring spatie correctly first.

composer require backpack/backupmanager
composer require spatie/laravel-backup   # if not already pulled in
php artisan vendor:publish --provider="Backpack\BackupManager\BackupManagerServiceProvider"
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"

2. Configure config/backup.php before touching the UI. The two settings that matter on day one:

'destination' => [
    'disks' => ['backups'], // a disk name from config/filesystems.php, NOT a path
],
'source' => [
    'files' => ['include' => [base_path()], 'exclude' => [base_path('vendor'), storage_path('app/backups')]],
    'databases' => ['mysql'], // connection names from config/database.php
],

3. Prove the CLI works before trusting the button.

php artisan backup:run --only-db
php artisan backup:list

If those two commands don't produce and list a zip, the admin UI will fail too — and with a much worse error message.

4. Add the menu item. In resources/views/vendor/backpack/base/inc/sidebar_content.blade.php:

<li><a href="{{ backpack_url('backup') }}"><i class="la la-hdd-o"></i> Backups</a></li>

5. First use case. Grant yourself the permission, open /admin/backup, hit Create backup (database only), download the zip, and untar it on staging to confirm it's actually restorable. A backup you have never restored is a hypothesis, not a backup.

Where to look first when something breaks: storage/logs/laravel.log for the spatie exception, then php artisan backup:list to see what spatie thinks exists, then the filesystem on the configured disk. The UI is a view of spatie's world; it is never the source of truth.

Implementation Patterns

Pre-deploy safety net. This is the highest-value daily pattern. Wire it into your deploy script so nobody has to remember:

php artisan down
php artisan backup:run --only-db
php artisan migrate --force
php artisan up

The admin UI is for the human case — "I'm about to run a messy data fix, let me snapshot first." The CLI is for the repeatable case.

Scheduled backups + on-demand UI. Split responsibilities deliberately:

// app/Console/Kernel.php
$schedule->command('backup:clean')->daily()->at('01:30');
$schedule->command('backup:run')->daily()->at('02:00');
$schedule->command('backup:monitor')->daily()->at('04:00');

Let the scheduler handle cadence and retention; let the UI handle ad-hoc snapshots before risky operations and one-off downloads. Don't try to express a retention policy through clicking delete buttons.

Offsite is a disk config change, not a code change. Add S3/S3-compatible to backup.destination.disks and spatie writes to both:

'destination' => ['disks' => ['backups', 's3-backups']],

Keep the local disk in the list even with offsite enabled — it's what makes the UI's download and delete actions fast and cheap. Note that deletes and downloads in the UI operate per-disk, and behavior differs when the same backup name exists on multiple disks; verify in your version before relying on offsite deletes.

Access control via Backpack permissions. The route sits behind Backpack's admin middleware. Gate it through the permission manager rather than editing middleware — usually by giving a backup permission only to a super-admin role. Backups contain the entire database, so this is a privilege roughly equal to shell access. Consider adding IP restriction on the route group in config/backpack/base.php or a custom middleware.

Restore is your job — design it now. The package does not restore. Build a small artisan command and treat it as the real deliverable:

// php artisan app:restore-backup {file}
// 1. artisan down
// 2. download/unzip the archive from the disk
// 3. gunzip the .sql.gz and pipe into mysql --user --password --host db < dump.sql
// 4. php artisan up, smoke test

Keep it in version control, document it in the runbook, and rehearse it quarterly. The restore command is more important than the backup tooling.

Notifications. spatie's notifications config supports mail and Slack on success and failure. Configure both to mail and route to a shared inbox. Silent backup failure is the single most common way teams discover they have no backups, usually during an incident.

Multi-connection / multi-tenant. List every connection in backup.source.databases and run separate scheduled commands with --only-db if per-tenant isolation matters. For a true multi-tenant setup with per-tenant databases, don't use the shared UI — fan out per-tenant jobs that swap the connection config and call the spatie API directly.

Customizing the UI. Publish the package views and override the create/delete/download buttons if you need extra metadata (e.g., "tag this backup with a ticket number"). Extension points are the views and the controller; there is no event system, so keep customizations shallow — the package tracks spatie's internals, and deep forks break on upgrade.

Testing. Assert the schedule in a feature test rather than the backup itself:

$this->assertCommandIsScheduled('backup:run');

Then test your restore command against a tiny SQLite fixture in CI. That's where the real bugs live.

Gotchas and Tips

exec/proc_open must be available. mysqldump and pg_dump are shelled out. Shared hosts that list exec in disable_functions will fail with a cryptic "The dump process failed" — the cause is in php.ini, not in your code. Check dump.dump_binary_path if the binaries aren't on the web user's PATH (very common with Homebrew MySQL, MAMP, and XAMPP).

Web-triggered backups time out before the CLI does. PHP-FPM's max_execution_time and your reverse proxy's read timeout both apply to the create request. A 4 GB file backup through the admin UI is a dead end. Use database-only backups from the UI and full backups from the scheduler, or push the job onto a queue with a long timeout and have the UI refresh the list.

The disk name must exist in config/filesystems.php. Putting a path like storage/app/backups in backup.destination.disks silently writes to the default disk instead, and then the UI shows nothing. Always publish and re-run backup:list after changing disks — if backup:list shows it but the UI doesn't, you're looking at a cache issue; if neither shows it, you're looking at a disk issue.

Changing backup.name orphans everything. spatie names the folder with that value; the UI lists only the current folder. Renaming your app in the config makes all existing backups invisible (not deleted — but effectively lost to anyone clicking through the UI). Set backup.name once, deliberately, and never change it.

The same trap applies to filename_prefix. Changing it makes old files unmatched by the list and delete actions. The files are still on disk — you'll need find and manual cleanup.

UI delete ≠ retention policy. Clicking delete removes the zip from the configured disks. The cleanup strategy in cleanup.default_strategy runs only via backup:clean. If you never schedule backup:clean, disks fill silently and the next backup fails with a disk-full error — which usually surfaces as a failed deploy.

MySQL routines, events, and views are not dumped by default. If your app uses stored procedures, add --routines --events to the database dump config. A restore that's missing triggers can sit undetected for months.

SQLite needs the sqlite3 binary; PostgreSQL needs pg_dump matching (or newer than) the server major version. Version mismatch produces an opaque failure partway through the dump, and you'll get a truncated zip that looks present in the UI. Verify by opening the archive, not by looking at the file size.

Never point backups at a directory under source.files.include. Self-including backups grow exponentially. If 'include' => [base_path()], exclude storage/app/backups (or wherever your disk resolves) explicitly, and add it to .gitignore too.

Upgrades are the sharp edge. This package tracks spatie/laravel-backup, which has made breaking config changes across majors. Pin both, upgrade them together, and re-run backup:run + backup:list in staging before merging. The Laravel 5.2 floor in the package description is historical — on current Laravel, confirm the release notes for your version rather than assuming the constraint is accurate.

Debugging checklist, in order: backup:list → storage/logs/laravel.log for the underlying exception → filesystem on the configured disk → php artisan tinker with Storage::disk('backups')->allFiles() to see what the app actually sees → the web user's PATH and disable_functions. Ninety percent of "the UI is broken" reports resolve at step one or two, and are config problems rather than package bugs.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource