DEV Community

Nandan Ramdani
Nandan Ramdani

Posted on

Cara Backup Database PostgreSQL Otomatis ke Cloudflare R2 dengan Docker di VPS Ubuntu

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Struktur folder:

/opt/workline-backup
├── backup.sh
├── .env
└── backups/
Enter fullscreen mode Exit fullscreen mode

Membuat Bucket Cloudflare R2

Masuk ke dashboard Cloudflare:

  1. Login ke Cloudflare Dashboard
  2. Pilih menu R2 Object Storage
  3. Klik Create Bucket

Contoh nama bucket:

workline-backup
Enter fullscreen mode Exit fullscreen mode

Membuat API Token Cloudflare R2

Masuk ke:

R2 Object Storage
→ Manage R2 API Tokens
→ Create API Token
Enter fullscreen mode Exit fullscreen mode

Simpan informasi berikut:

Account ID
Access Key ID
Secret Access Key
Enter fullscreen mode Exit fullscreen mode

Nilai tersebut akan digunakan untuk proses upload backup.


Membuat File Konfigurasi

Buat file .env.

nano .env
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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."
Enter fullscreen mode Exit fullscreen mode

Memberikan Hak Eksekusi

Agar script dapat dijalankan:

chmod +x backup.sh
Enter fullscreen mode Exit fullscreen mode

Menjalankan Backup Secara Manual

Jalankan:

./backup.sh
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Tambahkan:

0 2 * * * /opt/workline-backup/backup.sh >> /var/log/db-backup.log 2>&1
Enter fullscreen mode Exit fullscreen mode

Artinya:

  • Backup dijalankan setiap hari
  • Jam 02:00 pagi
  • Log disimpan ke file

Cek hasil konfigurasi:

crontab -l
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Parameter:

  • --clean menghapus objek lama sebelum restore
  • --if-exists menghindari 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"
Enter fullscreen mode Exit fullscreen mode

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)