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

Filament Google Drive Backup Manager Laravel Package

webteractive/filament-google-drive-backup-manager

A Filament plugin for managing Google Drive backups from your admin panel. Configure OAuth credentials, browse and create backups, monitor storage usage, and restore files without leaving Filament. Simple setup and a clean UI for effortless backup management.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish.

    composer require webteractive/filament-google-drive-backup-manager
    php artisan vendor:publish --tag="filament-google-drive-backup-manager-config"
    

    Check whether the package ships migrations/config keys for storing the OAuth token; if so, run php artisan migrate.

  2. Read the config file first. It is the map of the whole package: the Google client credentials (client_id, client_secret, redirect_uri), the target Drive folder ID, the retention count, and the backup source (database dump path / storage disks). Almost every "why didn't it work" question is answered by one of these keys.

  3. Create the Google side before touching Filament. In Google Cloud Console: enable the Drive API, create an OAuth Web client, and add the package's callback URL as an authorized redirect URI. Put the credentials in .env — never in the committed config.

  4. Register the plugin in your panel provider:

    ->plugin(GoogleDriveBackupManagerPlugin::make())
    

    The plugin adds the settings/backup page where you connect the Google account and trigger an on-demand run.

  5. First successful run = connect, then back up manually. Connect the account through the UI (that's what stores the access + refresh token), then hit the manual backup action and confirm you see the file in Drive. Only after that works should you wire up a schedule.

  6. Then schedule it:

    Schedule::command('...backup...')->daily()->at('02:00');
    

    and point the scheduler at cron (* * * * * php artisan schedule:run). Verify with php artisan schedule:list rather than assuming.

Implementation Patterns

Manual action as the smoke test, schedule as the real job. The Filament page action is a great first-run/debug path because it runs inside a normal web request (fresh process, fresh token). If manual works but the nightly run fails, the problem is almost always the worker environment — config, env vars, or a stale long-lived process — not the Google credentials.

Run the backup on a dedicated queue. Backups block on an HTTP upload; keep them off default so a slow Drive upload doesn't starve other jobs. Give the queue a worker with a sane --timeout and --tries=1 (a retried backup can duplicate files or hammer Drive's rate limits — make the job idempotent, or fail fast and alert).

Treat a disconnected Google account as an operational state, not an exception. Since v0.4.3 a dead/revoked refresh token throws an explicit "the stored Google account must be reconnected" error instead of a bare 401. Catch that case in your job (or in Filament's failed() hook) and route it to a notification/Slack channel plus a visible admin banner, because only a human can fix it by reconnecting. Distinguish it from transient failures (network, 5xx, rate limit) which should be retried with backoff.

Override per run, don't mutate the config at runtime. If you need different folders or retention per tenant/environment, do it through the documented per-run config path rather than editing the singleton config array — the package rebuilds the disk from config on each run, so runtime mutations outside that hook may not be picked up.

Keep secrets rotatable. Store client credentials in .env, run php artisan config:cache in deploy, and run php artisan queue:restart after any credential change so workers pick up the new env. A worker booted before the change keeps serving old config forever.

Local/CI strategy. Don't let tests or local dev hit the real Drive. In tests, Storage::fake() / a local disk stub and assert on the command/job being dispatched rather than the upload. For staging, use a separate Google account and a throwaway Drive folder so a misfired retention setting can't wipe production backups.

Gotchas and Tips

  • Long-lived workers hold a stale disk (fixed in 0.4.3, but know why). Laravel caches resolved disks per process. A Horizon worker running with --max-time=0 reuses the gdbm disk — and the OAuth token minted at boot — until the process dies. Once the token expired (~1h) or the refresh token rotated, every backup 401'd even right after reconnecting. applyBackupConfig() now forgets the disk each run. Implication for you: never cache the gdbm disk yourself (app('filesystem')->disk('gdbm') stored on a singleton, in a service provider, or in a custom job's properties) — you'll reintroduce exactly this bug. Always resolve the disk inside the run.
  • Long-lived processes in general. The same class of bug applies to anything that doesn't boot per request — Horizon, queue:work without --max-time, Octane. If you're on 0.4.2 or lower, this release is effectively a required upgrade for scheduled backups. Upgrade and queue:restart.
  • Per-run token minting is the new cost. Forgetting the disk means a token is fetched per run. For a nightly backup this is irrelevant; if you're doing many small backups per hour, batch them into one job rather than firing several.
  • Refresh tokens expire for non-published OAuth apps. Google invalidates refresh tokens after ~7 days for apps whose consent screen is left in "Testing". If you reconnect every week, this is why — publish the app (or add the account as a test user and accept the cadence).
  • The 0.4.3 error is good news for debugging. Previously refreshToken() returned an error array instead of throwing, so a revoked token looked identical to a Drive permission problem. Now you get a specific message; grep your logs for the reconnect phrasing before assuming a 401 is an API scope issue.
  • Reconnecting is not just "log in again". Rotating the refresh token on the Google side invalidates the old one; any process still holding the old credentials is dead. Reconnect, then restart workers.
  • Debugging order that actually works: manual backup from the UI → if that passes, run the scheduled command synchronously in a worker-like context (php artisan <cmd> in the same container/queue config) → then check that the queue worker is running the new code (stale deploy is a common false positive).
  • Check retention before trusting it. Verify pruning behaviour against a non-production folder at least once; a misconfigured folder ID or retention count is the difference between a backup system and a data-loss incident.
  • config:cache and .env. After any credential change on the server, re-cache config and restart workers — a cached config with old values reproduces the "I reconnected but it still fails" symptom without any token actually being revoked.
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