nyoncode/laravel-backup-manager
Laravel Backup Manager is a Laravel package for organizing application backups in one place. It focuses on simplifying backup configuration, running and monitoring backup tasks, and integrating scheduled database and file backups into familiar Laravel workflows.
path defaults to backups for all profiles, the default multi-profile-on-one-disk arrangement meant a nightly backup:clean under one profile could prune another profile's fortnightly fulls, with nothing reported. If we run more than one profile on a shared disk, this is a patch-worthy correctness fix, not a nice-to-have — it directly invalidates any retention or RPO commitment we've made on paper.StoredBackup::$profile / belongsTo() and CleanupReport turn retention from an implicit side effect into something we can report on and evidence.backup:clean --dry-run per profile to confirm the keep-set, then let the real cleaner run. Cheap, but it needs a ticket, not a footnote.backup:clean (with --sync escape hatch, and --dry-run deliberately never queued) removes an unbounded-memory, invisible-to-failed_jobs job from the scheduler process on the web node. This is a reliability decision we can make without new infrastructure — it makes cleanup observable in the queue dashboard we already have. Same logic applies to the empty queue.queue fallback: we stop dispatching onto a queue name no worker listens on.queue.restore_timeout acknowledges that restores (download, decrypt, unpack, pre-restore snapshot) outlast backups. Supports deciding whether restore is a "run it and watch" operation or a genuine self-service/DR capability.CleanupManager collapses four divergent copies (CLI, queue, dashboard, MCP tool) into one policy application point. That's a maintainability argument for staying on the package rather than growing our own wrapper — and it means our dashboard/MCP surfaces can't drift from CLI semantics.backup:list, backup:verify, backup:restore) change what operators see. Any runbook, support script, or internal admin UI that assumed a flat list of everything on a destination needs a revisit — schedule that with the upgrade, not after it.Adopt (or upgrade to ≥ v1.3.0) when:
CleanupManager centralisation is the cleaner operating model.restore_timeout matters.Look elsewhere or defer when:
SnapshotDriver and cannot absorb a signature change (the new optional ?string $profile parameter must be added) — cost is small but it is a code change, and null preserves the old whole-path behaviour, so a driver left unfixed keeps the old, now-incorrect, semantics silently. Budget the edit.mysqldump plus object storage versioning covers it — the profile/destination/retention model is more machinery than the problem warrants.To executives: This release closes a silent data-loss bug. Where two backup schedules shared a disk — the package's default layout — one schedule's cleanup could delete the other's backups without any error, so a stated retention promise could quietly not be met. After v1.3.0, every backup is tagged with the schedule that created it, retention counts and deletes only its own, and cleanup produces a report we can point at. We should upgrade on a maintenance window rather than wait for the next routine bump, because the risk window is "any night the cleaner runs." There is one ordering caveat: backups written before the upgrade carry no tag and are still attributed to whoever is cleaning, so the first post-upgrade cleanup is verified with a dry run rather than assumed.
To engineering: Four things to action. (1) Upgrade and confirm per-profile retention actually holds in our environment — this is a behaviour change, so verify rather than assume. (2) Before the first real backup:clean, run --dry-run per profile: pre-upgrade (untagged or unreadable-manifest) backups are counted as the asking profile's, so the old cross-profile pruning is still reachable exactly once. (3) Any custom SnapshotDriver needs the new optional ?string $profile parameter in applyRetention(); leaving it out keeps the old whole-path behaviour, which is now the wrong answer. (4) backup:list / backup:verify / backup:restore are profile-scoped now, so anything parsing or paging those outputs needs a look. On the upside: cleanup can go to the queue (BACKUP_QUEUE=true, --sync to force inline, --dry-run never queues), restores get their own queue.restore_timeout, and four copies of the retention sequence are now one CleanupManager, so CLI, dashboard and MCP can't drift. Empty queue.queue also no longer dispatches to a queue name no worker listens on. Tests are on Pest 4, with Pest 5 arriving alongside Laravel 13 / PHP 8.4.
How can I help you explore Laravel packages today?