Kehilangan database adalah salah satu risiko terbesar dalam menjalankan aplikasi. Kerusakan VPS, kesalahan deployment, human error, atau database yang terhapus tanpa sengaja dapat menyebabkan hilangnya data penting.
Karena itu, setiap aplikasi yang digunakan di production sebaiknya memiliki sistem backup otomatis yang tersimpan di lokasi terpisah dari server utama.
Pada tutorial ini, kita akan membuat sistem backup PostgreSQL otomatis menggunakan:
- PostgreSQL
- Docker
- Cloudflare R2
- Cron Job
Hasil akhirnya:
- Backup berjalan otomatis setiap hari
- Mendukung banyak database sekaligus
- Backup tersimpan di Cloudflare R2
- Tersedia salinan lokal sebagai cadangan
- Mudah di-restore jika terjadi masalah
Kenapa Backup Database Itu Penting?
Banyak developer menganggap volume Docker sudah cukup aman. Padahal jika VPS mengalami kerusakan atau kesalahan konfigurasi, seluruh data tetap bisa hilang.
Beberapa penyebab kehilangan data yang sering terjadi:
- VPS gagal boot
- Salah menjalankan perintah
docker compose down -v - Database terhapus secara tidak sengaja
- Kesalahan migrasi
- Serangan ransomware
- Kerusakan storage server
Dengan memiliki backup yang tersimpan di luar VPS, proses pemulihan data menjadi jauh lebih mudah.
Kenapa Menggunakan Cloudflare R2?
Cloudflare R2 adalah layanan object storage yang kompatibel dengan AWS S3 API.
Beberapa kelebihannya:
- Tidak ada biaya egress
- Harga lebih murah dibanding banyak layanan sejenis
- Mudah diintegrasikan dengan Docker
- Cocok untuk backup database
- Performa global melalui jaringan Cloudflare
Untuk kebutuhan aplikasi internal, SaaS, maupun UMKM, Cloudflare R2 sudah lebih dari cukup sebagai lokasi penyimpanan backup.
Arsitektur Backup
Alur backup yang akan kita buat:
PostgreSQL
│
▼
pg_dump
│
▼
File .dump
│
├── Simpan Lokal
│
└── Upload ke Cloudflare R2
Jika suatu saat database bermasalah, kita cukup mengambil file backup dari Cloudflare R2 lalu melakukan restore.
Persiapan Folder Backup
Buat folder khusus untuk menyimpan script dan file backup.
mkdir -p /opt/workline-backup/backups
cd /opt/workline-backup
Struktur folder:
/opt/workline-backup
├── backup.sh
├── .env
└── backups/
Membuat Bucket Cloudflare R2
Masuk ke dashboard Cloudflare:
- Login ke Cloudflare Dashboard
- Pilih menu R2 Object Storage
- Klik Create Bucket
Contoh nama bucket:
workline-backup
Membuat API Token Cloudflare R2
Masuk ke:
R2 Object Storage
→ Manage R2 API Tokens
→ Create API Token
Simpan informasi berikut:
Account ID
Access Key ID
Secret Access Key
Nilai tersebut akan digunakan untuk proses upload backup.
Membuat File Konfigurasi
Buat file .env.
nano .env
Isi dengan konfigurasi berikut:
R2_ACCOUNT_ID=xxxxxxxx
R2_BUCKET=workline-backup
R2_ACCESS_KEY_ID=xxxxxxxx
R2_SECRET_ACCESS_KEY=xxxxxxxx
LOCAL_RETENTION_DAYS=7
DB_CONTAINER=workline-db-1
DB_USER=workline
DB_LIST="workline stockline chatline"
Penjelasan Konfigurasi
| Variabel | Fungsi |
|---|---|
| R2_ACCOUNT_ID | ID akun Cloudflare |
| R2_BUCKET | Nama bucket R2 |
| R2_ACCESS_KEY_ID | Access Key R2 |
| R2_SECRET_ACCESS_KEY | Secret Key R2 |
| LOCAL_RETENTION_DAYS | Lama penyimpanan backup lokal |
| DB_CONTAINER | Nama container PostgreSQL |
| DB_USER | User PostgreSQL |
| DB_LIST | Daftar database yang dibackup |
Script Backup PostgreSQL Otomatis
Buat file:
nano backup.sh
Isi dengan script berikut:
#!/bin/bash
set -euo pipefail
APP_DIR="/opt/workline-backup"
BACKUP_DIR="${APP_DIR}/backups"
cd "$APP_DIR"
source .env
mkdir -p "$BACKUP_DIR"
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
echo "[$(date)] Starting multi database backup..."
for DB_NAME in $DB_LIST; do
FILE="${DB_NAME}_${DATE}.dump"
LOCAL_PATH="${BACKUP_DIR}/${FILE}"
R2_PATH="s3://${R2_BUCKET}/${DB_NAME}/${FILE}"
echo "[$(date)] Backing up database: ${DB_NAME}"
docker exec "$DB_CONTAINER" pg_dump \
-U "$DB_USER" \
-d "$DB_NAME" \
-Fc > "$LOCAL_PATH"
echo "[$(date)] Uploading ${DB_NAME} to R2..."
docker run --rm \
-e AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY_ID" \
-e AWS_SECRET_ACCESS_KEY="$R2_SECRET_ACCESS_KEY" \
-v "$BACKUP_DIR":/backups \
amazon/aws-cli \
s3 cp "/backups/${FILE}" "$R2_PATH" \
--endpoint-url "https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"
echo "[$(date)] Upload complete"
done
find "$BACKUP_DIR" \
-type f \
-name "*.dump" \
-mtime +"$LOCAL_RETENTION_DAYS" \
-delete
echo "[$(date)] Backup finished."
Memberikan Hak Eksekusi
Agar script dapat dijalankan:
chmod +x backup.sh
Menjalankan Backup Secara Manual
Jalankan:
./backup.sh
Jika berhasil, outputnya akan terlihat seperti:
Starting multi database backup...
Backing up database: workline
Upload complete
Backing up database: stockline
Upload complete
Backing up database: chatline
Upload complete
Backup finished.
Hasil Backup di Cloudflare R2
Struktur penyimpanan akan terlihat seperti berikut:
workline-backup
├── workline
│ └── workline_2026-06-11_16-00-00.dump
├── stockline
│ └── stockline_2026-06-11_16-00-00.dump
└── chatline
└── chatline_2026-06-11_16-00-00.dump
Dengan struktur seperti ini, setiap database memiliki folder terpisah sehingga lebih mudah dikelola.
Menjadwalkan Backup Otomatis dengan Cron
Backup manual tidak cukup untuk production. Gunakan Cron agar backup berjalan otomatis.
Buka konfigurasi Cron:
crontab -e
Tambahkan:
0 2 * * * /opt/workline-backup/backup.sh >> /var/log/db-backup.log 2>&1
Artinya:
- Backup dijalankan setiap hari
- Jam 02:00 pagi
- Log disimpan ke file
Cek hasil konfigurasi:
crontab -l
Cara Restore Database PostgreSQL
Jika database mengalami masalah, lakukan restore menggunakan file backup.
Salin file backup ke dalam container:
docker cp workline_2026-06-11_16-00-00.dump workline-db-1:/tmp/
Jalankan restore:
docker exec -it workline-db-1 pg_restore \
-U workline \
-d workline \
--clean \
--if-exists \
/tmp/workline_2026-06-11_16-00-00.dump
Parameter:
-
--cleanmenghapus objek lama sebelum restore -
--if-existsmenghindari error jika objek belum ada
Best Practice Backup PostgreSQL di Production
Agar backup lebih aman, terapkan beberapa praktik berikut:
Backup Minimal Sekali Sehari
Untuk aplikasi internal biasanya cukup 1 kali per hari.
Jika transaksi tinggi, lakukan setiap jam.
Simpan di Lokasi Terpisah
Jangan hanya mengandalkan penyimpanan lokal VPS.
Gunakan:
- Cloudflare R2
- AWS S3
- Backblaze B2
- Wasabi
Lakukan Test Restore
Backup yang tidak pernah diuji belum tentu dapat digunakan.
Minimal sebulan sekali lakukan simulasi restore.
Simpan Beberapa Versi Backup
Jangan hanya menyimpan backup terbaru.
Idealnya:
- Harian 7 hari
- Mingguan 4 minggu
- Bulanan 3–12 bulan
Monitoring Log Backup
Periksa log secara berkala untuk memastikan proses backup berjalan normal.
FAQ
Apakah script ini bisa digunakan untuk PostgreSQL dalam Docker?
Ya. Script menggunakan docker exec sehingga cocok untuk PostgreSQL yang berjalan di dalam container Docker.
Apakah bisa backup banyak database sekaligus?
Bisa. Cukup tambahkan nama database pada variabel:
DB_LIST="workline stockline chatline"
Apakah Cloudflare R2 gratis?
Cloudflare R2 memiliki free tier yang cukup besar untuk kebutuhan aplikasi kecil hingga menengah.
Apa perbedaan pg_dump dan pg_restore?
pg_dump digunakan untuk membuat backup database PostgreSQL.
pg_restore digunakan untuk mengembalikan backup tersebut ke database.
Apakah backup lokal masih diperlukan?
Ya. Backup lokal berguna sebagai cadangan cepat jika proses restore perlu dilakukan tanpa mengunduh file dari Cloudflare R2.
Kesimpulan
Membuat sistem backup database PostgreSQL tidak harus rumit. Dengan kombinasi Docker, Cloudflare R2, dan Cron Job, kita bisa membangun solusi backup otomatis yang sederhana namun cukup andal untuk kebutuhan production.
Dengan adanya backup di luar VPS, risiko kehilangan data akibat kesalahan deployment, kerusakan server, atau human error dapat diminimalkan. Yang terpenting, jangan hanya membuat backup—pastikan juga rutin melakukan uji restore agar data benar-benar dapat dipulihkan saat dibutuhkan.
Top comments (0)