Search by

lara-pack / database-backup

bhagaskara

Scheduled database backups for Laravel, configured from .env: schedule, retention, zstd/gzip compression, any disk or Google Drive.

Package info

github.com/bhagaskara/database-backup

pkg:composer/lara-pack/database-backup

Statistics

Installs: 14

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-11-05 06:23 UTC

This package is auto-updated.

Last update: 2026-11-05 06:23:56 UTC


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:

  1. Buka https://console.cloud.google.com, buat atau pilih project.
  2. APIs & Services > Library, cari Google Drive API, klik Enable.
  3. 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.
  4. 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_ID dan Client secret ke GOOGLE_DRIVE_CLIENT_SECRET.
  5. 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.
  6. Jalankan php artisan config:clear && php artisan db-backup:run. Folder db-backups akan muncul di My Drive.

Catatan:

  • Untuk menyimpan ke folder yang sudah ada atau ke Shared Drive, isi GOOGLE_DRIVE_FOLDER_ID dengan ID folder (bagian akhir URL https://drive.google.com/drive/folders/<ID>) dan gunakan scope https://www.googleapis.com/auth/drive di langkah 5. Scope drive.file hanya 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, size
  • LaraPack\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