Postgres backups on aaPanel: the Laravel schedule I trust for a CMS
Short answer: aviwebsquad.in backs up Postgres nightly with pg_dump, rotates files on disk, and copies encrypted archives off the VPS—because MCP agents can bulk-write faster than you can undo in Filament.
Why CMS backups differ from app backups
Posts, media metadata, and Sanctum tokens live in DB. Code is in Git. Restore DB without restore code is still useful; the reverse is not.
Schedule sketch
Schedule::command('backup:run --only-db')->dailyAt('02:30');
Implementation may use Spatie Backup or a thin Artisan command—principle matters more than package.
aaPanel cron
Laravel scheduler needs one cron entry:
* * * * * cd /www/wwwroot/aviwebsquad.in/current && php artisan schedule:run
aaPanel UI cron is where I verify it actually runs (silent failures happen).
Restore drill (quarterly)
- Spin local Sail Postgres
- Restore latest dump
php artisan migrate:status- Open Filament—count posts vs production
After MCP bulk publish mistakes
DB backup is faster than hand-deleting 20 posts. Pair with token rotation.
FAQ
File backups for storage/?
Yes—media binaries are not in SQL. rsync storage/app/public weekly.
Ransomware angle?
See ransomware checklist—backups offline.
ClickHouse someday?
What is ClickHouse is analytics-only—would not replace OLTP backups.
Encryption at rest
GPG encrypt dumps before rclone to object storage—keys in aaPanel secret file, not repo.
Point-in-time recovery
Without WAL archiving, max RPO = 24h—documented in internal runbook; upgrade path is managed Postgres if RPO tightens.
Test restore after MCP bulk ops
Any time an agent publishes >10 posts, I verify backup timestamp <24h old before revoking dry-run mode.
FAQ (extended)
SQLite locally?
Sail uses Postgres image to match prod types—no SQLite drift.
Media + DB restore order?
DB first (metadata), then storage/ rsync—IDs must align.