lara-pack / database-backup
Scheduled database backups for Laravel, configured from .env: schedule, retention, zstd/gzip compression, any disk or Google Drive.
Requires
- php: ^8.1
- ext-zlib: *
- illuminate/console: ^10.0|^11.0|^12.0|^13.0
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/filesystem: ^10.0|^11.0|^12.0|^13.0
- illuminate/http: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- symfony/process: ^6.2|^7.0|^8.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Backup database Laravel secara berkala. Semua pengaturan (jadwal, lama penyimpanan, lokasi, kompresi) cukup lewat .env.
- Driver: MySQL, MariaDB, PostgreSQL, SQLite
- Jadwal otomatis terdaftar di Laravel Scheduler (tanpa edit
routes/console.php/Kernel.php) - Hapus backup lama otomatis berdasarkan umur (hari) dan/atau jumlah maksimum
- Simpan ke disk mana pun (
local,s3,ftp,sftp, ...) atau langsung ke Google Drive (tanpa package tambahan) - Kompresi zstd (lebih kecil dan cepat) bila tersedia di server, otomatis kembali ke gzip bila tidak ada
- Lewati tabel tertentu (mis. tabel riwayat
_history_*) agar file lebih kecil - Laravel 10, 11, 12, 13 ยท PHP 8.1+
Instalasi
composer require lara-pack/database-backup
Service provider terdaftar otomatis (package auto-discovery).
Package belum ada di Packagist? Lihat bagian Instalasi tanpa Packagist.
Pastikan cron Laravel Scheduler sudah jalan di server:
* * * * * cd /path/ke/project && php artisan schedule:run >> /dev/null 2>&1
Di Windows: buat task di Task Scheduler yang menjalankan php artisan schedule:run setiap menit, atau jalankan php artisan schedule:work saat development.
Konfigurasi .env
Semua opsional. Nilai default ditampilkan:
# Aktifkan jadwal otomatis (false = hanya manual lewat artisan) DB_BACKUP_ENABLED=true # Koneksi yang di-backup, pisahkan koma. Kosong = DB_CONNECTION DB_BACKUP_CONNECTIONS= # ---- Periode ---- # hourly | daily | twiceDaily | weekly | monthly # everyMinute | everyFiveMinutes | everyTenMinutes | everyFifteenMinutes | everyThirtyMinutes # everyTwoHours | everyThreeHours | everyFourHours | everySixHours | quarterly | yearly # atau cron expression, contoh: "0 */3 * * *" DB_BACKUP_FREQUENCY=daily DB_BACKUP_TIME=02:00 # daily/weekly/monthly (hourly pakai menitnya saja) DB_BACKUP_TIME_2=14:00 # jam kedua untuk twiceDaily DB_BACKUP_DAY= # weekly: 0=Minggu..6=Sabtu (default 0) | monthly: 1..31 (default 1) DB_BACKUP_TIMEZONE= # contoh Asia/Jakarta, kosong = app.timezone DB_BACKUP_ON_ONE_SERVER=false # true jika app jalan di banyak server (butuh cache redis/database/memcached) # ---- Lama penyimpanan ---- DB_BACKUP_KEEP_DAYS=7 # hapus backup lebih tua dari N hari (0 = tidak hapus berdasarkan umur) DB_BACKUP_KEEP_MAX=0 # simpan maksimal N file per koneksi (0 = tanpa batas) DB_BACKUP_CLEANUP_AFTER_BACKUP=true # ---- Lokasi ---- DB_BACKUP_DISK=local # disk di config/filesystems.php, atau google_drive DB_BACKUP_PATH=db-backups # folder di dalam disk / Google Drive (dibuat otomatis) DB_BACKUP_FALLBACK_DISK=local # simpan ke disk ini jika upload gagal, kosong = nonaktif DB_BACKUP_PREFIX= # awalan nama file, kosong = slug APP_NAME DB_BACKUP_TEMP_PATH= # folder sementara, kosong = storage/app/db-backup-temp # ---- Google Drive (hanya jika DB_BACKUP_DISK=google_drive) ---- GOOGLE_DRIVE_CLIENT_ID= GOOGLE_DRIVE_CLIENT_SECRET= GOOGLE_DRIVE_REFRESH_TOKEN= GOOGLE_DRIVE_FOLDER_ID= # kosong = My Drive # ---- Kompresi ---- DB_BACKUP_COMPRESSION=auto # auto (zstd jika ada, kalau tidak gzip) | zstd | gzip | none DB_BACKUP_COMPRESSION_LEVEL= # zstd 1..19 (default 10) | gzip 1..9 (default 9) # ---- Dump ---- DB_BACKUP_EXCLUDE_TABLES= # tabel yang dilewati, pisahkan koma, dukung *, mis. _history_*,telescope_* DB_BACKUP_TIMEOUT=3600 # detik DB_BACKUP_MYSQLDUMP_PATH=mysqldump DB_BACKUP_PG_DUMP_PATH=pg_dump DB_BACKUP_ZSTD_PATH=zstd
Backup terbaru tidak pernah dihapus walaupun sudah melewati DB_BACKUP_KEEP_DAYS, jadi selalu ada minimal satu backup.
Setelah ubah .env di production, jalankan php artisan config:clear (atau config:cache lagi).
Contoh
Backup setiap 6 jam, simpan 14 hari:
DB_BACKUP_FREQUENCY=everySixHours DB_BACKUP_KEEP_DAYS=14
Backup tiap Senin jam 23:30 WIB ke S3, simpan 8 file terakhir:
DB_BACKUP_FREQUENCY=weekly DB_BACKUP_DAY=1 DB_BACKUP_TIME=23:30 DB_BACKUP_TIMEZONE=Asia/Jakarta DB_BACKUP_DISK=s3 DB_BACKUP_KEEP_DAYS=0 DB_BACKUP_KEEP_MAX=8
Kompresi
Dengan DB_BACKUP_COMPRESSION=auto (default), backup dikompres dengan zstd (-T0 -10, semua core CPU) bila perintah zstd ada di server. File jauh lebih kecil dan proses lebih cepat dibanding gzip. Jika zstd tidak ada, otomatis memakai gzip bawaan PHP.
Install zstd di server:
sudo apt install zstd # Ubuntu / Debian sudo dnf install zstd # CentOS / RHEL / Rocky
Windows: unduh zstd-vX.Y.Z-win64.zip dari https://github.com/facebook/zstd/releases lalu isi DB_BACKUP_ZSTD_PATH dengan path zstd.exe.
Agar file lebih kecil lagi, lewati tabel yang tidak perlu di-backup:
DB_BACKUP_EXCLUDE_TABLES=_history_*,telescope_*,pulse_*
Google Drive
Backup bisa langsung diupload ke Google Drive tanpa package tambahan:
DB_BACKUP_DISK=google_drive DB_BACKUP_PATH=db-backups GOOGLE_DRIVE_CLIENT_ID=xxxx.apps.googleusercontent.com GOOGLE_DRIVE_CLIENT_SECRET=xxxx GOOGLE_DRIVE_REFRESH_TOKEN=xxxx
Cara mendapatkan kredensial:
- Buka https://console.cloud.google.com, buat atau pilih project.
- APIs & Services > Library, cari Google Drive API, klik Enable.
- APIs & Services > OAuth consent screen: pilih External (atau Internal untuk Google Workspace), isi nama aplikasi dan email, simpan. Di bagian Audience klik Publish app sampai statusnya In production. Jika masih Testing, refresh token kedaluwarsa setelah 7 hari dan upload berhenti.
- APIs & Services > Credentials > Create credentials > OAuth client ID:
- Application type: Web application
- Authorized redirect URIs:
https://developers.google.com/oauthplayground - Salin Client ID ke
GOOGLE_DRIVE_CLIENT_IDdan Client secret keGOOGLE_DRIVE_CLIENT_SECRET.
- Buka https://developers.google.com/oauthplayground:
- Klik ikon gear (kanan atas), centang Use your own OAuth credentials, isi Client ID dan Client secret.
- Di kolom Input your own scopes isi
https://www.googleapis.com/auth/drive.file, klik Authorize APIs, login dengan akun Google tempat backup disimpan. Jika muncul peringatan aplikasi belum diverifikasi, klik Advanced > Go to ... (itu aplikasi Anda sendiri). - Klik Exchange authorization code for tokens, salin Refresh token ke
GOOGLE_DRIVE_REFRESH_TOKEN.
- Jalankan
php artisan config:clear && php artisan db-backup:run. Folderdb-backupsakan muncul di My Drive.
Catatan:
- Untuk menyimpan ke folder yang sudah ada atau ke Shared Drive, isi
GOOGLE_DRIVE_FOLDER_IDdengan ID folder (bagian akhir URLhttps://drive.google.com/drive/folders/<ID>) dan gunakan scopehttps://www.googleapis.com/auth/drivedi langkah 5. Scopedrive.filehanya bisa melihat file/folder yang dibuat oleh aplikasi ini. - Backup lama dihapus permanen (tidak masuk Trash), jadi kuota Drive langsung kembali.
- Gunakan akun Google biasa atau user Workspace. Service account tidak punya kuota penyimpanan di Drive pribadi.
- Langkah-langkah ini juga ada sebagai komentar di
config/db-backup.php.
Jika upload gagal
Kalau upload ke disk utama gagal (misalnya Google Drive sedang gangguan atau token dicabut), backup disimpan ke DB_BACKUP_FALLBACK_DISK (default local) di folder DB_BACKUP_PATH, jadi tidak hilang. Command tetap melaporkan gagal dan event BackupFailed tetap dikirim, dengan lokasi file fallback di pesan error:
ERROR Backup [mysql] failed: Google Drive upload failed (...). Backup saved to fallback disk [local] db-backups/my-app-mysql-2026-11-05-020000.sql.gz.
Backup lama di disk fallback ikut dihapus sesuai aturan retensi. Isi DB_BACKUP_FALLBACK_DISK= (kosong) untuk menonaktifkan.
Perintah artisan
php artisan db-backup:run # backup sekarang + bersihkan backup lama php artisan db-backup:run --connection=mysql # koneksi tertentu (bisa diulang) php artisan db-backup:run --no-cleanup # backup tanpa menghapus backup lama php artisan db-backup:clean # hanya bersihkan backup lama php artisan db-backup:list # daftar backup tersimpan php artisan schedule:list # cek jadwal "db-backup" sudah terdaftar
Nama file: {prefix}-{koneksi}-{YYYY-MM-DD-HHMMSS}.sql.zst (atau .sql.gz; SQLite: .sqlite.zst / .sqlite.gz).
Pembersihan hanya menyentuh file dengan pola nama ini, file lain di folder yang sama aman.
Kebutuhan server
| Driver | Butuh |
|---|---|
| MySQL / MariaDB | mysqldump (atau mariadb-dump) di PATH, atau set DB_BACKUP_MYSQLDUMP_PATH |
| PostgreSQL | pg_dump di PATH, atau set DB_BACKUP_PG_DUMP_PATH |
| SQLite | tidak ada (file langsung disalin) |
| Kompresi zstd | zstd di PATH (opsional, tanpa ini memakai gzip) |
Contoh Windows: DB_BACKUP_MYSQLDUMP_PATH="C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe"
Password database tidak pernah muncul di daftar proses: MySQL memakai file kredensial sementara (--defaults-extra-file), PostgreSQL memakai env PGPASSWORD.
Restore
File .zst (zstd):
zstd -dc my-app-mysql-2026-11-05-020000.sql.zst | mysql -u user -p nama_database zstd -dc my-app-pgsql-2026-11-05-020000.sql.zst | psql -U user -d nama_database zstd -d my-app-sqlite-2026-11-05-020000.sqlite.zst -o database/database.sqlite
File .gz (gzip):
# MySQL / MariaDB gunzip < my-app-mysql-2026-11-05-020000.sql.gz | mysql -u user -p nama_database # PostgreSQL gunzip < my-app-pgsql-2026-11-05-020000.sql.gz | psql -U user -d nama_database # SQLite gunzip -c my-app-sqlite-2026-11-05-020000.sqlite.gz > database/database.sqlite
Kustomisasi lanjut
Publish file config jika ingin mengubah opsi mysqldump / pg_dump:
php artisan vendor:publish --tag=db-backup-config
Event
Dengarkan event untuk notifikasi (email, Slack, Telegram, dll):
LaraPack\DatabaseBackup\Events\BackupSucceededโ properti:connection,disk,path,sizeLaraPack\DatabaseBackup\Events\BackupFailedโ properti:connection,exception
use LaraPack\DatabaseBackup\Events\BackupFailed; use Illuminate\Support\Facades\Event; Event::listen(BackupFailed::class, function (BackupFailed $event) { logger()->critical("Backup {$event->connection} gagal: {$event->exception->getMessage()}"); });
Instalasi tanpa Packagist
Dari GitHub/GitLab (repo private atau publik) โ tambahkan di composer.json project Laravel:
"repositories": [ { "type": "vcs", "url": "https://github.com/bhagaskara/database-backup" } ]
lalu composer require lara-pack/database-backup. Buat tag versi (mis. v1.0.0) di repo agar bisa di-require tanpa :dev-main.
Dari folder lokal:
"repositories": [ { "type": "path", "url": "../database-backup" } ]
lalu composer require lara-pack/database-backup:@dev.
Publish ke Packagist: push repo ke GitHub, buat tag v1.0.0, lalu submit URL repo di https://packagist.org/packages/submit. Setelah itu cukup composer require lara-pack/database-backup.
Test
composer install
composer test
Lisensi
MIT