Strategi Backup Server

Strategi Backup Server

Bitnesia • Aug 27, 2026 105 •EN

Bab 39 menuntaskan satu bagian penting dari cerita data di server ini: log yang tadinya tersebar kini sudah tersentralisasi, dirotasi rapi, dan memiliki kebijakan retensi yang jelas. Namun log terpusat itu, sebagus apa pun pengaturannya, tetap hanya file biasa yang terdapat di satu disk pada satu server. Hal yang sama berlaku untuk dump database dari Bab 23, isi /var/www dari Bab 12 dan Bab 13, serta sertifikat TLS di /etc/letsencrypt dari Bab 17. Semua aset penting ini terkumpul di server utama (192.168.1.10), dan sejauh ini series belum pernah membahas satu pertanyaan mendasar: apa yang terjadi jika disk server ini rusak total, atau jika Attacker berhasil masuk dan mengenkripsi seluruh isi disk lewat serangan ransomware? Bab 7.2.3, Bab 28.4.4, dan Bab 29.3.5 sudah menyinggung bahwa snapshot LVM, KVM, maupun LXD bukan pengganti backup, karena ketiganya tetap tersimpan di disk fisik yang sama. Bab 23.1 dan Bab 23.7 juga sudah menjanjikan bahwa topik backup yang benar-benar bisa diandalkan, lengkap dengan prinsip 3-2-1 dan pengujian restore berkala, baru dibahas tuntas di sini. Bab 40 menepati janji itu: kita akan menyusun strategi backup server secara menyeluruh, mulai dari prinsip dasarnya, backup lokal yang hemat storage, backup terenkripsi ke server terpisah dengan BorgBackup, perluasan ke penyimpanan off-site, sampai kebiasaan menguji restore yang membedakan backup sungguhan dari backup yang hanya terasa aman.

40.1 Prinsip 3-2-1 dalam Strategi Backup Server

40.1.1 Apa Itu Aturan 3-2-1 dan Kenapa Setiap Angkanya Penting

Aturan 3-2-1 adalah pedoman klasik dalam dunia backup yang menyebutkan: simpan minimal tiga salinan data (data asli plus dua salinan backup), pada dua jenis media atau storage yang berbeda, dengan minimal satu salinan berada di lokasi off-site yang terpisah secara fisik dari data asli. Aturan ini pertama kali dipopulerkan oleh fotografer Peter Krogh untuk kebutuhan arsip foto, tetapi kini menjadi rekomendasi standar di dunia keamanan siber, termasuk oleh lembaga seperti CISA (Cybersecurity and Infrastructure Security Agency) di Amerika Serikat. Setiap angka pada aturan ini menjawab jenis kegagalan yang berbeda:

  • Tiga salinan data mengurangi risiko satu titik kegagalan tunggal (single point of failure). Jika hanya ada satu backup, kerusakan pada backup itu sendiri, misalnya file dump yang korup seperti disinggung di Bab 23.1, membuat kita kembali ke nol tanpa pilihan lain.
  • Dua jenis media berbeda melindungi dari kegagalan yang spesifik pada satu jenis storage, misalnya bug firmware disk tertentu, atau kesalahan konfigurasi yang kebetulan merusak seluruh volume pada satu storage pool sekaligus.
  • Satu salinan off-site melindungi dari bencana yang menghancurkan seluruh lokasi fisik sekaligus, seperti kebakaran data center, atau, yang jauh lebih sering terjadi di lapangan, Attacker yang setelah membobol server utama juga ikut menghapus backup lokal yang bisa dijangkaunya lewat jaringan yang sama.

Poin terakhir inilah yang paling sering diabaikan Sysadmin pemula. Backup yang tersimpan di direktori lain pada disk yang sama, atau bahkan di server lain tetapi masih bisa diakses dengan kredensial yang persis sama dengan server produksi, secara teknis tetap satu salinan yang rentan terhadap ancaman yang sama.

40.1.2 Memetakan Kondisi Server Saat Ini terhadap Aturan 3-2-1

Sebelum menambah tool baru, ada baiknya kita mengukur dulu seberapa jauh kondisi server utama saat ini dari aturan 3-2-1. Data hasil sebelumnya, dump database dari Bagian 23.6.2 dan log terpusat dari Bagian 39.2.2, sama-sama baru tersimpan di satu lokasi.

Langkah Praktik

  1. Periksa dulu apa saja yang sudah tersimpan sebagai hasil backup database dari Bab 23.
    ls -la /var/backups/database/
  2. Periksa juga ukuran log terpusat hasil forwarding dari Bab 39.
    du -sh /var/log/remote/

Verifikasi dan Troubleshooting

  • Kedua perintah di atas semestinya menampilkan data yang sudah ada, tetapi seluruhnya masih berada di disk yang sama dengan server utama itu sendiri. Dalam istilah 3-2-1, kondisi ini baru mencapai "1-1-0": satu salinan data asli, di satu jenis media, tanpa off-site sama sekali.
  • Tabel berikut merangkum target yang ingin kita capai di sisa bab ini, beserta bagian yang membahasnya.
SalinanLokasi dan MediaDibahas di
1 (asli)Disk utama server (192.168.1.10), tempat aplikasi berjalan sehari-hariSudah berjalan sejak Bab 2
2Disk kedua lokal (/mnt/data) di server yang sama, media fisik berbedaBagian 40.2
3 (off-site)Server backup terpisah (backup01, 192.168.1.50) sebagai langkah awal, diperluas ke cloud storage sebagai off-site yang sesungguhnyaBagian 40.3 dan 40.4

40.2 Backup Lokal Incremental dengan rsync dan Hard Link

40.2.1 Menyiapkan Disk Kedua sebagai Media Backup Lokal

Salinan kedua dalam aturan 3-2-1 idealnya berada di media fisik yang berbeda dari disk utama, meski masih di server yang sama. Bagian ini memakai disk tambahan yang sudah dipasang mengikuti langkah Bagian 7.4.1, ter-mount permanen di /mnt/data lewat /etc/fstab. Kita akan menaruh salinan backup lokal di sana, terpisah dari disk sistem tempat /etc, /var/www, dan /var/backups/database asalnya berada.

Langkah Praktik

  1. Buat direktori khusus untuk menampung backup lokal.
    sudo mkdir -p /mnt/data/backup-lokal

Verifikasi dan Troubleshooting

  • Pastikan /mnt/data benar-benar sedang ter-mount ke disk kedua sebelum melangkah lebih jauh, bukan sekadar direktori kosong biasa.
    findmnt /mnt/data
    Kalau perintah ini tidak menampilkan apa pun, berarti entry di /etc/fstab dari Bagian 7.4.1 belum aktif, dan /mnt/data hanyalah folder biasa di disk sistem. Menulis backup ke sana tetap akan berhasil tanpa pesan error apa pun dalam kondisi ini, padahal datanya justru berakhir di disk yang sama dengan disk utama, sehingga tujuan memisahkan media pada aturan 3-2-1 gagal tercapai tanpa disadari. Jalankan sudo mount -a lebih dulu untuk mengaktifkan entry fstab yang tertunda, baru lanjutkan ke langkah berikutnya.

40.2.2 Snapshot Hemat Storage dengan rsync --link-dest

Incremental backup adalah teknik backup yang hanya menyalin bagian data yang berubah sejak backup sebelumnya, alih-alih menyalin ulang seluruh data setiap kali. Opsi --link-dest pada rsync mengimplementasikan teknik ini dengan cara elegan: setiap file yang isinya tidak berubah dibuatkan hardlink ke file yang sama persis di backup sebelumnya, bukan disalin ulang. Hasilnya, setiap folder backup terlihat seperti salinan lengkap dan bisa langsung dijelajahi, padahal secara fisik file yang tidak berubah hanya menempati ruang disk satu kali. Pola ini pertama kali dipopulerkan oleh Mike Rubel lewat teknik "rotating snapshots" dan sudah menjadi cara umum membuat backup lokal bergaya snapshot tanpa tool tambahan di luar rsync yang sudah dikenal sejak Bagian 3.2.2.

Langkah Praktik

  1. Buat script backup di /usr/local/bin/backup-lokal.sh.
    sudo nano /usr/local/bin/backup-lokal.sh
  2. Isi dengan logika berikut: menautkan ke backup sebelumnya lewat symlink terakhir jika sudah ada, atau menyalin penuh jika ini backup pertama kali.
    #!/bin/bash
    set -euo pipefail
    
    SUMBER=(/etc /var/www /var/backups/database)
    TUJUAN="/mnt/data/backup-lokal"
    STAMP=$(date +%Y-%m-%d_%H%M%S)
    BARU="$TUJUAN/$STAMP"
    TERAKHIR="$TUJUAN/terakhir"
    
    mkdir -p "$BARU"
    
    if [ -d "$TERAKHIR" ]; then
    	rsync -a --delete --link-dest="$TERAKHIR" "${SUMBER[@]}" "$BARU/"
    else
    	rsync -a --delete "${SUMBER[@]}" "$BARU/"
    fi
    
    rm -f "$TERAKHIR"
    ln -s "$BARU" "$TERAKHIR"
  3. Beri izin eksekusi pada script.
    sudo chmod +x /usr/local/bin/backup-lokal.sh
  4. Jalankan dua kali berturut-turut untuk melihat efek --link-dest, jeda sebentar di antaranya.
    sudo /usr/local/bin/backup-lokal.sh
    sleep 5
    sudo /usr/local/bin/backup-lokal.sh

Verifikasi dan Troubleshooting

  • Bandingkan ukuran nyata pemakaian disk (du -sh) dengan ukuran seandainya setiap folder berdiri sendiri (du -sh --apparent-size) pada seluruh folder backup.
    du -sh /mnt/data/backup-lokal/2*
    du -sh --apparent-size /mnt/data/backup-lokal/2*
    Jika --link-dest bekerja dengan benar, total pemakaian disk sungguhan jauh lebih kecil daripada jumlah ukuran apparent, karena file yang identik antar folder hanya dihitung sekali oleh filesystem.
  • Bukti paling meyakinkan bahwa dua file benar-benar satu hardlink adalah nomor inode yang sama persis. Bandingkan nomor inode file yang tidak berubah antara dua folder backup.
    ls -i /mnt/data/backup-lokal/2*/etc/hostname
  • Format STAMP pada script sengaja dibuat sampai satuan detik (%H%M%S), bukan cuma menit. Kalau hanya sampai menit, dua eksekusi berdekatan seperti langkah uji di atas berpotensi menghasilkan nama folder yang persis sama, sehingga eksekusi kedua diam-diam menulis ulang ke folder yang sama alih-alih membuat snapshot baru.
  • Catatan dari lapangan: teknik --link-dest ini efektif untuk retensi jangka pendek dengan banyak generation, tetapi belum menyertakan enkripsi maupun pemindahan ke lokasi off-site. Dua kebutuhan itu yang dijawab BorgBackup pada Bagian 40.3.

40.3 Backup Terenkripsi ke Server Terpisah dengan BorgBackup

40.3.1 Kenapa BorgBackup: Deduplikasi dan Enkripsi Sekaligus

BorgBackup (biasa disingkat Borg) adalah tool backup open-source yang menggabungkan tiga kemampuan sekaligus dalam satu repository: deduplication di level blok data (bukan hanya per file seperti --link-dest pada Bagian 40.2), kompresi, dan enkripsi sisi klien sebelum data meninggalkan server. Kombinasi ini membuat Borg cocok dipakai mengirim backup ke server terpisah, bahkan ke storage pihak ketiga yang tidak sepenuhnya kita percaya, karena data sudah terenkripsi sebelum berangkat dan server penerima tidak pernah melihat isi data yang sebenarnya. Bagian ini memakai backup01 (192.168.1.50) sebagai server penerima, alamat yang sama dengan server arsip log yang sudah disinggung di Bagian 39.4.2, sekarang diformalkan sebagai server backup khusus untuk seluruh series ini.

40.3.2 Instalasi dan Inisialisasi Repository

Langkah Praktik

  1. Pasang borgbackup di kedua sisi, server utama maupun backup01, karena Borg berkomunikasi lewat SSH dengan menjalankan proses borg serve di sisi remote.
    sudo apt update
    sudo apt install borgbackup
  2. Di backup01, siapkan direktori tempat repository akan disimpan, dimiliki oleh user sysadmin yang sudah ada sejak instalasi awal di Bab 2.
    sudo mkdir -p /backup/borg-repo
    sudo chown sysadmin:sysadmin /backup/borg-repo
  3. Backup ini perlu membaca /etc dan direktori sistem lain yang sebagian isinya hanya bisa dibaca root, sehingga proses Borg di server utama harus berjalan sebagai root. Karena kunci SSH milik user sysadmin di Bagian 3.2.2 dipasang untuk user itu sendiri, buat dulu kunci SSH khusus untuk root.
    sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ""
  4. Titipkan public key root tadi ke authorized_keys milik sysadmin di backup01. Tool ssh-copy-id tidak bisa dipakai di sini karena PasswordAuthentication no sudah diaktifkan sejak Bagian 3.2.3 di seluruh server series ini, sehingga cara amannya justru menumpang sesi SSH milik sysadmin yang sudah lebih dulu tepercaya untuk menitipkan key baru tersebut.
    sudo cat /root/.ssh/id_ed25519.pub | ssh [email protected] "cat >> ~/.ssh/authorized_keys"
  5. Inisialisasi repository dari server utama, memakai mode enkripsi repokey-blake2 yang menyimpan kunci enkripsi di dalam repository itu sendiri (terenkripsi oleh passphrase) sekaligus memakai algoritma hash BLAKE2 yang lebih cepat pada CPU modern.
    sudo borg init --encryption=repokey-blake2 [email protected]:/backup/borg-repo
    Perintah ini meminta passphrase baru secara interaktif. Simpan passphrase ini di pengelola password yang aman. Repository yang terenkripsi dengan repokey tidak bisa dibuka kembali tanpa passphrase ini, sekalipun kita masih punya akses penuh ke server backup01.

Verifikasi dan Troubleshooting

  • Pesan Permission denied (publickey) pada langkah inisialisasi biasanya berarti langkah menitipkan public key root ke authorized_keys milik sysadmin di backup01 belum berhasil. Uji koneksi SSH root ke backup01 secara terpisah sebelum mencoba lagi.
    sudo ssh -i /root/.ssh/id_ed25519 [email protected] whoami
  • Segera setelah inisialisasi berhasil, ekspor kunci repository ke file terpisah sebagai cadangan darurat, lalu pindahkan file ini ke lokasi aman di luar server utama maupun backup01. Repository yang kehilangan kuncinya, misalnya karena disk server utama rusak sebelum sempat mengekspor kunci ini, membuat seluruh data di dalamnya permanen tidak bisa dibuka lagi, bahkan oleh pemiliknya sendiri.
    sudo borg key export [email protected]:/backup/borg-repo /root/borg-key-backup01.txt

40.3.3 Menjalankan Backup dan Melihat Riwayat Archive

Langkah Praktik

  1. Supaya passphrase tidak perlu diketik manual saat script berjalan otomatis, simpan di file khusus dengan permission ketat, mengikuti prinsip yang sama seperti kredensial database di Bagian 23.6.1.
    sudo nano /etc/borg-backup.env
    export BORG_PASSPHRASE='PassphraseSangatRahasia2026'
    export BORG_REPO='[email protected]:/backup/borg-repo'
    sudo chmod 600 /etc/borg-backup.env
  2. Jalankan backup pertama, menyertakan sumber yang sama seperti backup lokal di Bagian 40.2.2, ditambah log terpusat dari Bab 39 yang belum ikut di backup lokal.
    source /etc/borg-backup.env
    sudo -E borg create --stats --compression lz4 \
      ::'server-utama-{now:%Y-%m-%d_%H%M}' \
      /etc /var/www /var/backups/database /var/log/remote
    Notasi :: di depan nama archive memberi tahu Borg untuk memakai repository dari BORG_REPO, tanpa perlu mengetik ulang alamat lengkapnya.
  3. Lihat daftar seluruh archive yang sudah tersimpan di repository.
    sudo -E borg list

Verifikasi dan Troubleshooting

  • Flag -E pada sudo wajib disertakan supaya sudo ikut mewariskan environment variable BORG_PASSPHRASE dan BORG_REPO yang baru saja di-source. Tanpa flag ini, Borg tidak menemukan keduanya dan kembali meminta passphrase secara interaktif.
  • Jalankan sudo -E borg info untuk melihat ringkasan ukuran data asli, ukuran terkompresi, dan ukuran unik setelah deduplikasi dari seluruh repository, angka yang berguna untuk memantau efektivitas kompresi dan deduplikasi dari waktu ke waktu.

40.3.4 Restore dari Archive Borg

Langkah Praktik

  1. Pindah ke direktori kosong khusus untuk uji restore, karena borg extract mengembalikan struktur folder lengkap tepat di bawah direktori kerja saat ini, bukan langsung menimpa lokasi aslinya.
    mkdir -p /tmp/restore-test
    cd /tmp/restore-test
    source /etc/borg-backup.env
    sudo -E borg extract ::server-utama-2026-08-28_1000
  2. Periksa hasil extract, semestinya muncul struktur folder etc/, var/ persis seperti sumber aslinya, hanya berpindah root ke /tmp/restore-test.
    ls /tmp/restore-test

Verifikasi dan Troubleshooting

  • Nama archive pada contoh di atas (server-utama-2026-08-28_1000) hanya ilustrasi. Ambil nama archive yang sesungguhnya dari hasil borg list pada Bagian 40.3.3 sebelum menjalankan extract.
  • Untuk mengembalikan hanya sebagian folder tanpa extract seluruh archive, tambahkan path spesifik di akhir perintah, misalnya sudo -E borg extract ::server-utama-2026-08-28_1000 var/backups/database, berguna saat yang benar-benar hilang hanya satu file dump tertentu.
  • Jangan pernah menjalankan borg extract langsung dari direktori / pada server produksi tanpa uji coba dulu di direktori terpisah seperti di atas, karena file yang sama namanya di sistem yang sedang berjalan akan langsung tertimpa oleh isi archive.

40.3.5 Retensi Otomatis dengan borg prune

Tanpa batasan, repository Borg akan terus bertambah setiap kali backup berjalan. borg prune menghapus archive lama berdasarkan kebijakan retensi yang kita tentukan, sambil tetap mempertahankan struktur deduplikasi untuk archive yang tersisa.

Langkah Praktik

  1. Jalankan prune dengan kebijakan menyimpan 7 backup harian terakhir, 4 mingguan, dan 6 bulanan.
    source /etc/borg-backup.env
    sudo -E borg prune --list --keep-daily=7 --keep-weekly=4 --keep-monthly=6

Verifikasi dan Troubleshooting

  • Gabungkan langkah create dari Bagian 40.3.3 dan prune di atas ke dalam satu script, lalu jadwalkan lewat pasangan .service dan .timer mengikuti pola persis seperti backup-harian.timer di Bagian 5.3.1 dan backup-database.timer di Bagian 23.7.1.
  • Jalankan sudo -E borg check secara berkala (mingguan atau bulanan) untuk memverifikasi integritas repository itu sendiri. Tanpa pengecekan ini, kerusakan data di repository bisa saja tidak ketahuan sampai suatu saat restore benar-benar dibutuhkan dan justru gagal.

40.4 Memperluas Backup ke Off-site dengan rclone

40.4.1 Kenapa Satu Lokasi Jaringan Saja Belum Cukup

Repository di backup01 pada Bagian 40.3 sudah memenuhi syarat "server terpisah", tetapi jika backup01 berada di rak server yang sama dengan server utama, satu insiden fisik seperti kebakaran atau banjir tetap bisa menghabisi keduanya sekaligus. Object storage di cloud provider menjawab kebutuhan off-site yang sesungguhnya, karena data tersimpan di data center yang secara geografis benar-benar terpisah dari kedua server ini.

40.4.2 Instalasi dan Konfigurasi rclone

rclone adalah command-line tool yang berfungsi seperti rsync, tetapi untuk lebih dari 70 jenis cloud storage dan object storage, mulai dari Amazon S3, Backblaze B2, hingga Google Cloud Storage. Karena repository Borg dari Bagian 40.3 sudah terenkripsi penuh sebelum meninggalkan server utama, kita bisa memakai penyedia cloud storage mana pun tanpa perlu khawatir isi data terbaca pihak penyedia layanan itu sendiri.

Langkah Praktik

  1. Pasang rclone dari repository resmi Ubuntu.
    sudo apt install rclone
  2. Jalankan wizard konfigurasi interaktif untuk membuat koneksi baru (disebut remote dalam istilah rclone, jangan tertukar dengan server remote lain di series ini).
    rclone config
    Wizard ini akan meminta nama remote (misalnya backup-cloud), jenis penyedia storage dari daftar yang tersedia, lalu kredensial akses (access key dan secret key untuk layanan bertipe S3-compatible, atau alur OAuth untuk layanan seperti Google Drive). Detail kredensial berbeda-beda tergantung penyedia yang dipilih, sehingga langkah persisnya mengikuti dokumentasi resmi rclone untuk penyedia tersebut, dan pembahasan lebih dalam soal cloud provider spesifik seperti AWS, Azure, atau GCP baru masuk di Bab 41.

Verifikasi dan Troubleshooting

  • Pastikan remote sudah tersimpan dan bisa diakses.
    rclone listremotes
    rclone lsd backup-cloud:

40.4.3 Menyalin Repository Borg ke Cloud Storage

Langkah Praktik

  1. Salin seluruh isi repository Borg di backup01 ke bucket atau container di cloud storage, dijalankan dari backup01 supaya tidak membebani bandwidth server utama.
    rclone sync /backup/borg-repo backup-cloud:nama-bucket/borg-repo --progress

Verifikasi dan Troubleshooting

  • Gunakan rclone sync, bukan rclone copy, khusus untuk menjaga salinan cloud tetap identik dengan repository sumber, termasuk menghapus archive lama yang sudah dibuang lewat borg prune di Bagian 40.3.5. Perhatikan arah argumen dengan teliti: sync membuat sisi tujuan sama persis dengan sisi sumber, sehingga sumber dan tujuan tidak boleh tertukar posisinya.
  • Jadwalkan perintah rclone sync ini lewat .timer terpisah di backup01, berjalan setelah jadwal borg prune selesai, supaya salinan cloud selalu mengikuti kondisi repository lokal yang terbaru.

40.5 Menguji Proses Restore Secara Berkala

40.5.1 Kenapa Backup yang Tidak Pernah Diuji Restore Sama Saja dengan Tidak Ada Backup

Bagian 23.7.1 sudah menitipkan satu prinsip penting: backup yang berjalan otomatis lewat timer tetap harus diuji proses restore-nya secara berkala, bukan sekadar dipastikan filenya ada. Kejadian yang sering ditemui di lapangan justru sebaliknya, script backup terlihat sukses selama berbulan-bulan lewat log journalctl, padahal file yang dihasilkan sebenarnya korup, atau kredensial yang dipakai sudah kedaluwarsa sehingga backup baru diam-diam berhenti tanpa ada yang sadar. Baru ketika insiden sungguhan terjadi dan restore benar-benar dibutuhkan, barulah ketahuan bahwa backup yang selama ini "aman" ternyata tidak bisa dipakai.

40.5.2 Menulis Script Uji Restore Otomatis

Langkah Praktik

  1. Buat script yang mengambil archive Borg terbaru, meng-extract-nya ke direktori sementara, lalu memverifikasi salah satu isi pentingnya, dump database dari Bab 23, benar-benar bisa direstore ke database sungguhan.
    sudo nano /usr/local/bin/uji-restore.sh
  2. Isi dengan logika berikut.
    #!/bin/bash
    set -euo pipefail
    source /etc/borg-backup.env
    
    TARGET="/tmp/uji-restore-$(date +%s)"
    mkdir -p "$TARGET"
    cd "$TARGET"
    
    ARCHIVE_TERBARU=$(borg list --last 1 --short)
    borg extract "::$ARCHIVE_TERBARU" var/backups/database
    
    DUMP_TERBARU=$(ls -t "$TARGET"/var/backups/database/postgresql-webapp_db-*.dump | head -n1)
    
    sudo -u postgres psql -c "DROP DATABASE IF EXISTS webapp_db_ujirestore;"
    sudo -u postgres psql -c "CREATE DATABASE webapp_db_ujirestore OWNER webapp_user;"
    PGPASSFILE=/etc/backup-db/pgpass pg_restore -h 127.0.0.1 -U webapp_user \
      -d webapp_db_ujirestore --no-owner "$DUMP_TERBARU"
    
    JUMLAH_BARIS=$(PGPASSFILE=/etc/backup-db/pgpass psql -h 127.0.0.1 -U webapp_user \
      -d webapp_db_ujirestore -tAc "SELECT count(*) FROM notes;")
    echo "Uji restore selesai, dump yang dipakai: $DUMP_TERBARU"
    echo "Jumlah baris tabel notes: $JUMLAH_BARIS"
    
    rm -rf "$TARGET"
    Script ini mengambil archive Borg paling baru secara otomatis lewat borg list --last 1 --short, meng-extract seluruh isi /var/backups/database, lalu mencari file dump PostgreSQL paling baru di dalamnya. Nama file dump sengaja dicari lewat pola postgresql-webapp_db-*.dump, bukan nama tetap, karena script otomasi di Bagian 23.6.2 selalu menambahkan timestamp di setiap nama file agar retensi lokal bisa membedakan file lama dan baru. Variable PGPASSFILE memakai file kredensial yang sama seperti Bagian 23.6.1, supaya pg_restore dan psql berjalan tanpa perlu mengetik password secara manual saat dijalankan otomatis lewat timer.
  3. Beri izin eksekusi, lalu jalankan manual sekali sebagai uji awal.
    sudo chmod +x /usr/local/bin/uji-restore.sh
    sudo /usr/local/bin/uji-restore.sh

Verifikasi dan Troubleshooting

  • Output jumlah baris tabel notes yang muncul di akhir harus dibandingkan dengan angka yang wajar pada aplikasi sesungguhnya. Angka nol atau jauh lebih kecil dari perkiraan mengindikasikan dump yang direstore ternyata sudah usang atau tidak lengkap, meski proses restore-nya sendiri berjalan tanpa error.
  • Error database "webapp_db_ujirestore" is being accessed by other users pada perintah DROP DATABASE biasanya muncul kalau eksekusi sebelumnya gagal di tengah jalan dan meninggalkan koneksi yang masih menggantung. Putuskan dulu seluruh koneksi ke database tersebut sebelum mengulang.
    sudo -u postgres psql -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'webapp_db_ujirestore';"
  • Jadwalkan script ini lewat pasangan .service dan .timer terpisah, berjalan mingguan, mengikuti pola yang sama seperti backup-harian.timer di Bagian 5.3.1. Arahkan output ExecStart supaya tercatat di journalctl -u uji-restore.service, dan pertimbangkan menambahkan notifikasi (misalnya lewat email atau webhook) khusus untuk kegagalan, supaya Sysadmin benar-benar sadar begitu satu siklus uji restore gagal, bukan menunggu ditemukan tidak sengaja berbulan-bulan kemudian.
  • Praktik ini sengaja memakai database webapp_db_ujirestore yang terpisah dari database production webapp_db, supaya proses pengujian tidak pernah menyentuh atau menimpa data yang sedang dipakai aplikasi sungguhan.

Server utama sekarang memiliki tiga salinan data pada dua jenis media, dengan satu salinan off-site di cloud storage, persis seperti yang dituntut aturan 3-2-1 di Bagian 40.1. Lebih penting lagi, seluruh rangkaian ini bukan hanya "kelihatan aman", karena skrip uji restore di Bagian 40.5 membuktikan setiap minggu bahwa data yang tersimpan benar-benar bisa dipulihkan kembali, bukan sekadar file yang tersimpan pasif tanpa pernah teruji. Bagian X series ini pun selesai di sini, menutup topik monitoring, logging, dan backup yang saling melengkapi satu sama lain sejak Bab 38. Bagian XI berikutnya berpindah fokus ke Ubuntu Server di lingkungan cloud, dan repository Borg yang sudah tersinkronisasi ke object storage di Bagian 40.4 akan langsung relevan lagi ketika Bab 41 membahas snapshot dan storage block milik AWS, Azure, serta GCP secara lebih spesifik.