Bab 22 menutup rangkaian instalasi database di Bagian V dengan memasang web UI untuk PostgreSQL, MySQL/MariaDB, dan MongoDB. Bab 23 mengangkat topik yang justru paling sering diabaikan sampai insiden nyata benar-benar terjadi: backup dan restore database. Query DROP TABLE yang salah sasaran, disk yang rusak mendadak, atau serangan ransomware yang mengenkripsi seluruh data production hanya butuh hitungan detik untuk terjadi. Sementara itu, proses pemulihannya bisa memakan waktu berjam-jam kalau Sysadmin tidak pernah menyiapkan strategi backup yang teruji sebelumnya. Kita akan memahami perbedaan mendasar antara backup logical dan physical, mempraktikkan backup serta restore untuk keempat database yang sudah berjalan sejak Bab 18 sampai Bab 21 (PostgreSQL, MySQL, MariaDB, dan MongoDB), menulis satu script bash yang mengotomasi seluruh proses dump, kompresi, dan retention sekaligus, lalu menutup bab dengan menjadwalkan script tersebut lewat systemd timer agar backup berjalan sendiri tanpa perlu diingat-ingat secara manual setiap hari.
23.1 Strategi Backup: Logical vs Physical
Setiap tool backup database bekerja lewat salah satu dari dua pendekatan besar: logical backup atau physical backup. Logical backup membaca data lewat query normal ke database yang sedang berjalan, lalu menuliskan hasilnya sebagai representasi terstruktur seperti perintah SQL atau dokumen BSON, persis seperti cara kerja mariadb-dump yang sudah sempat kita praktikkan di Bagian 20.4. Sebaliknya, physical backup menyalin langsung file mentah tempat database menyimpan datanya di disk (data directory), tanpa peduli struktur logis di dalamnya sama sekali.
| Aspek | Logical Backup | Physical Backup |
|---|---|---|
| Cara kerja | Membaca data lewat query, menulis ulang sebagai SQL/dokumen | Menyalin file data mentah di data directory |
| Contoh tool | pg_dump, mysqldump, mariadb-dump, mongodump | pg_basebackup, mariadb-backup, snapshot filesystem/LVM |
| Portabilitas | Tinggi, hasil dump bisa dipindah antar versi dan platform berbeda | Rendah, umumnya wajib versi dan arsitektur yang identik |
| Kecepatan restore pada dataset besar | Relatif lambat, karena setiap baris ditulis ulang lewat query | Jauh lebih cepat, karena hanya menyalin file kembali ke tempatnya |
| Granularitas | Bisa per database atau per table/collection tertentu | Umumnya seluruh instance/cluster sekaligus |
Bab ini berfokus pada logical backup lewat pg_dump, mysqldump, mariadb-dump, dan mongodump, karena portabilitasnya paling cocok untuk kebutuhan harian Sysadmin: memindahkan data antar server, antar lingkungan development dan production, atau sekadar menyimpan salinan yang mudah diperiksa isinya lewat editor teks biasa. Physical backup tetap punya tempatnya sendiri, terutama untuk database berukuran ratusan gigabyte ke atas yang waktu restore-nya menjadi krusial saat insiden terjadi, lewat tool resmi seperti pg_basebackup bawaan PostgreSQL, mariadb-backup untuk MariaDB, atau sekadar snapshot LVM seperti yang sudah kita praktikkan di Bagian 7.2.3 pada level filesystem. Pembahasan mendalam ketiga tool physical backup tersebut berada di luar cakupan bab ini. Namun, prinsip snapshot LVM dari Bagian 7.2.3 sudah cukup untuk memberi gambaran bagaimana physical backup bekerja tanpa perlu menghentikan service database yang sedang aktif.
Catatan dari lapangan yang berlaku untuk kedua pendekatan ini: backup yang tidak pernah diuji proses restore-nya bukanlah backup yang bisa diandalkan. Banyak insiden kehilangan data justru baru terungkap saat proses restore darurat sedang sangat dibutuhkan, yaitu ketika ternyata file dump korup, kredensial sudah kedaluwarsa, atau script backup diam-diam gagal berbulan-bulan tanpa ada yang menyadarinya. Prinsip ini akan kita perdalam lagi lewat strategi 3-2-1 pada Bab 40.
23.2 Backup dan Restore PostgreSQL dengan pg_dump dan pg_restore
pg_dump dan pg_restore sudah terpasang otomatis sejak instalasi PostgreSQL di Bagian 18.1.2 sebagai bagian dari paket client, sehingga tidak ada langkah instalasi tambahan yang perlu dilakukan di sini. Keduanya terhubung ke database melalui cara yang identik dengan psql, memakai role webapp_user yang sudah dibuat di Bagian 18.3.1, bukan role superuser postgres yang seharusnya hanya dipegang Sysadmin untuk keperluan administratif.
23.2.1 Backup dengan pg_dump dan Pilihan Format Dump
pg_dump mendukung beberapa format keluaran sekaligus lewat flag -F. Format plain (-F p) menghasilkan file teks SQL biasa yang mudah dibaca dan diedit manual, format custom (-F c) menghasilkan file biner terkompresi yang mendukung restore selektif lewat pg_restore, sedangkan format directory (-F d) memecah dump menjadi banyak file dalam satu folder agar bisa di-dump secara paralel lewat flag -j. Format custom menjadi pilihan paling umum untuk backup rutin karena ukurannya lebih kecil dan fleksibel saat restore.
Langkah Praktik
- Siapkan direktori tempat menyimpan hasil backup.
sudo mkdir -p /var/backups/database - Jalankan
pg_dumpdengan formatcustomterhadap databasewebapp_db.
Perintah ini meminta passwordpg_dump -h 127.0.0.1 -U webapp_user -d webapp_db -F c -f /var/backups/database/webapp_db.dumpwebapp_usersecara interaktif, sesuai rulescram-sha-256untuk koneksi TCP yang sudah dibahas di Bagian 18.2.1. Cara menyiapkan password secara non-interaktif untuk kebutuhan script otomasi dibahas terpisah di Bagian 23.6.1.
Verifikasi dan Troubleshooting
- Periksa ukuran file hasil dump, pastikan tidak nol byte.
ls -lh /var/backups/database/webapp_db.dump - Perintah
file /var/backups/database/webapp_db.dumppada file yang sehat biasanya mengembalikan labelPostgreSQL custom database dump. Ini merupakan cara cepat memastikan file benar-benar dump PostgreSQL yang valid, bukan file kosong atau rusak akibat proses yang terputus di tengah jalan. - Pesan
pg_dump: error: connection to server ... failedbiasanya berarti PostgreSQL belum berjalan atau alamat host salah ketik, sedangkanFATAL: password authentication failedmenandakan passwordwebapp_usersalah, identik dengan troubleshooting koneksi di Bagian 18.3.1.
23.2.2 Restore dengan pg_restore dan psql
Cara restore berbeda tergantung format dump yang dipakai saat backup. File format plain dieksekusi langsung lewat psql sebagai kumpulan perintah SQL biasa, sedangkan file format custom maupun directory wajib memakai pg_restore karena isinya berupa arsip biner, bukan teks SQL murni.
Langkah Praktik
- Buat database baru sebagai tujuan restore, mensimulasikan skenario pemulihan ke server yang berbeda dari sumber backup.
sudo -u postgres psql -c "CREATE DATABASE webapp_db_restore OWNER webapp_user;" - Restore file dump format
customke database baru tersebut.
Flagpg_restore -h 127.0.0.1 -U webapp_user -d webapp_db_restore --no-owner /var/backups/database/webapp_db.dump--no-ownermengabaikan perintah kepemilikan object yang tersimpan di dalam dump, berguna saat role di server tujuan restore tidak persis sama dengan role di server sumber backup. - Untuk melihat isi dump tanpa benar-benar menjalankannya, gunakan opsi
--listsebagai daftar isi (table of contents) dump.pg_restore --list /var/backups/database/webapp_db.dump
Verifikasi dan Troubleshooting
- Konfirmasikan data benar-benar utuh dengan membandingkan isi table
notesdari Bagian 18.3.2 di database hasil restore.psql -h 127.0.0.1 -U webapp_user -d webapp_db_restore -c "SELECT * FROM notes;" - Pesan
pg_restore: error: could not execute query: ERROR: relation "notes" already existsmuncul jika target database sudah berisi table yang sama. Tambahkan flag--clean --if-existsagarpg_restoremenghapus object lama terlebih dahulu sebelum membuatnya ulang. Namun, perlu diingat bahwa flag ini bersifat destruktif terhadap data yang sudah ada di database tujuan. - Restore dari file format
plainmemakaipsql, bukanpg_restore.psql -h 127.0.0.1 -U webapp_user -d webapp_db_restore -f /var/backups/database/webapp_db.sql
23.3 Backup dan Restore MySQL dengan mysqldump
mysqldump sudah tersedia sejak instalasi paket mysql-server di Bagian 19.2.1, sebagai bagian dari mysql-client yang ikut terpasang sebagai dependency. Skenario di sini melanjutkan database webapp_db dan account webapp_user yang sudah dibuat di Bagian 19.3.2.
23.3.1 Backup dengan mysqldump
Langkah Praktik
- Jalankan
mysqldumpdengan opsi--single-transactionagar dump table InnoDB diambil dari satu snapshot transaksi yang konsisten, tanpa mengunci tabel dan menghentikan sementara akses aplikasi yang sedang menulis data.
Opsimysqldump -u webapp_user -p --single-transaction webapp_db > /var/backups/database/webapp_db.sql--single-transactionsecara otomatis menonaktifkan penguncian table selama proses dump berjalan. Namun, konsistensinya hanya terjamin penuh untuk table bermesin storage InnoDB. Table lama bermesin MyISAM tetap membutuhkan penguncian singkat saat di-dump, sehingga pola migrasi ke InnoDB yang sudah menjadi default MySQL sejak versi 5.5 tetap relevan untuk diperhatikan Sysadmin yang mewarisi database lawas. - Mampatkan hasil dump langsung lewat pipe ke
gzipuntuk menghemat ruang disk, pola yang akan dipakai ulang pada script otomasi di Bagian 23.6.2.mysqldump -u webapp_user -p --single-transaction webapp_db | gzip > /var/backups/database/webapp_db.sql.gz
Verifikasi dan Troubleshooting
- Dump yang berhasil sampai selesai selalu diakhiri baris komentar
-- Dump completed onbeserta timestamp di baris paling akhir file. Cara cepat memeriksa dump tidak terpotong di tengah jalan (misalnya akibat koneksi jaringan putus atau disk penuh) adalah memastikan baris ini benar-benar ada.tail -n 3 /var/backups/database/webapp_db.sql - Pesan
mysqldump: Got error: 1045: Access deniedmenandakan password salah, identik dengan troubleshooting login MySQL di Bagian 19.3.2.
23.3.2 Restore dari File Dump
Langkah Praktik
- Buat database tujuan restore terlebih dahulu, karena
mysqldumpsecara default tidak menyertakan perintahCREATE DATABASEkecuali dijalankan dengan flag tambahan--databases.mysql -u webapp_user -p -e "CREATE DATABASE webapp_db_restore;" - Restore file SQL ke database yang baru dibuat.
mysql -u webapp_user -p webapp_db_restore < /var/backups/database/webapp_db.sql - Jika sumber dump berupa file terkompresi, dekompresi lewat pipe tanpa perlu menyimpan file mentah sementara.
gunzip -c /var/backups/database/webapp_db.sql.gz | mysql -u webapp_user -p webapp_db_restore
Verifikasi dan Troubleshooting
- Konfirmasikan struktur dan isi table sudah kembali seperti semula.
mysql -u webapp_user -p webapp_db_restore -e "SHOW TABLES;" - Pesan
ERROR 1049 (42000): Unknown databaseberarti langkah pembuatan database tujuan pada langkah pertama belum dijalankan atau salah ketik nama database-nya.
23.4 Backup dan Restore MariaDB dengan mariadb-dump
Bagian 20.4 sudah membahas mariadb-dump secara mendalam, termasuk directive sandbox mode yang otomatis disisipkan sejak MariaDB 11.0 sebagai mitigasi celah keamanan MDEV-21778. Bagian ini melengkapi praktik tersebut melalui alur backup dan restore yang konsisten dengan pola PostgreSQL dan MySQL di atas, memakai account webapp_user alih-alih root agar sesuai dengan kebutuhan script otomasi non-interaktif di Bagian 23.6.
23.4.1 Backup dan Restore dengan mariadb-dump
Langkah Praktik
- Backup database
webapp_dbmemakai accountwebapp_useryang sudah memiliki privilegeALL PRIVILEGESsejak Bagian 20.3.1, cukup untuk menjalankanmariadb-dumptanpa perlu privilege tambahan apa pun.mariadb-dump -u webapp_user -p --single-transaction webapp_db > /var/backups/database/webapp_db_mariadb.sql - Restore ke database baru, dengan asumsi client
mariadbyang dipakai sudah mendukung directive sandbox mode sesuai daftar versi di Bagian 20.4.1, sehingga baris pertama file dump tidak perlu dipotong.sudo mariadb -e "CREATE DATABASE webapp_db_restore;" mariadb -u webapp_user -p webapp_db_restore < /var/backups/database/webapp_db_mariadb.sql
Verifikasi dan Troubleshooting
- Jika restore dilakukan ke server MariaDB versi lawas atau ke MySQL, terapkan kembali trik
tail -n +2yang sudah dibahas tuntas di Bagian 20.4.2 untuk melewati baris directive sandbox mode. - Pesan error dan cara verifikasi lainnya identik dengan Bagian 23.3.2, karena MariaDB mewarisi format pesan error dari basis kode MySQL yang sama.
23.5 Backup dan Restore MongoDB dengan mongodump dan mongorestore
mongodump dan mongorestore sudah terpasang sejak instalasi mongodb-org di Bagian 21.2.2, sebagai bagian dari paket mongodb-org-tools yang memang sudah disiapkan sejak awal untuk kebutuhan bab ini. Skenario melanjutkan database webapp_catalog dan account webapp_user yang dibuat di Bagian 21.4.2, lengkap dengan authentication yang sudah diaktifkan sejak Bagian 21.4.1.
23.5.1 Backup dengan mongodump
Langkah Praktik
- Jalankan
mongodumpmemakai flag--archiveagar seluruh collection digabung menjadi satu file stream, dilengkapi flag--gzipuntuk kompresi langsung tanpa proses tambahan.
Parametermongodump --uri="mongodb://webapp_user:[email protected]:27017/webapp_catalog?authSource=webapp_catalog" --archive=/var/backups/database/webapp_catalog.archive --gzipauthSource=webapp_catalogdi dalam connection string ini setara dengan flag--authenticationDatabase webapp_catalogyang sudah dipakai di Bagian 21.4.2, karena userwebapp_usermemang dibuat di databasewebapp_catalog, bukan di databaseadmin.
Verifikasi dan Troubleshooting
- Periksa ukuran file arsip hasil backup.
ls -lh /var/backups/database/webapp_catalog.archive - Pesan
Authentication failedbiasanya berarti kombinasi username, password, atau nilaiauthSourcetidak cocok, identik dengan troubleshooting login MongoDB di Bagian 21.4.2.
23.5.2 Restore dengan mongorestore
Langkah Praktik
- Restore arsip ke database yang sama menggunakan
mongorestore, memakai flag--archivedan--gzipyang sama persis dengan flag backup.
Tanpa flag tambahan apa pun,mongorestore --uri="mongodb://webapp_user:[email protected]:27017/webapp_catalog?authSource=webapp_catalog" --archive=/var/backups/database/webapp_catalog.archive --gzipmongorestorehanya menambahkan dokumen baru ke collection yang sudah ada, sehingga dokumen dengan nilai_idyang sama akan gagal disisipkan ulang dan dilaporkan sebagai error duplikat, bukan menimpa data lama.
Verifikasi dan Troubleshooting
- Konfirmasikan jumlah dokumen di collection
productsdari Bagian 21.3.2 sudah kembali seperti sebelum backup.mongosh -u webapp_user -p --authenticationDatabase webapp_catalog webapp_catalog --eval "db.products.countDocuments()" - Flag
--dropmembuatmongorestoremenghapus terlebih dahulu setiap collection yang namanya cocok dengan isi arsip sebelum menuliskan data baru, berguna untuk skenario pemulihan penuh yang sengaja menimpa seluruh data lama. Perlakukan flag ini dengan hati-hati karena bersifat destruktif dan tidak bisa dibatalkan; jangan pernah menjalankannya ke database production tanpa memastikan lebih dulu bahwa arsip sumbernya benar-benar valid dan lengkap.
23.6 Script Bash Otomasi Backup Multi-Database
Menjalankan empat perintah dump secara manual setiap hari jelas tidak realistis untuk kebutuhan production. Bagian ini menyusun satu script bash yang menjalankan backup keempat database sekaligus, mengompresnya, lalu menghapus file backup lama sesuai kebijakan retention, yaitu batas usia file backup yang masih boleh disimpan sebelum dihapus otomatis untuk mencegah disk penuh. Pola ini mengikuti kebiasaan task administrasi otomatis yang akan diperdalam lagi di Bab 35. Perlu dicatat lebih dulu satu batasan penting: MySQL dan MariaDB tidak boleh berjalan bersamaan di satu server yang sama seperti sudah diperingatkan di Bagian 20.1.1. Oleh karena itu, pada praktiknya script ini hanya mengaktifkan salah satu blok MySQL atau MariaDB sesuai database yang benar-benar berjalan di server tersebut, bukan menjalankan keduanya sekaligus dalam satu host yang sama.
23.6.1 Menyiapkan Kredensial Non-Interaktif secara Aman
Script yang berjalan otomatis lewat systemd timer di Bagian 23.7 tidak bisa mengetikkan password secara interaktif, sehingga kredensial harus tersimpan di file yang dibaca langsung oleh masing-masing tool. Setiap database punya konvensinya sendiri, dan menuliskan password polos langsung di dalam script adalah kebiasaan buruk yang harus dihindari karena isi script mudah terbaca siapa pun yang punya akses baca ke file tersebut.
Langkah Praktik
- Buat user sistem khusus untuk menjalankan seluruh proses backup, mengikuti prinsip least privilege yang sama seperti Bagian 5.2.2, Bagian 15.6.2, dan Bagian 22.3.1.
sudo useradd --system --no-create-home --shell /usr/sbin/nologin backupdb - Buat direktori khusus untuk menyimpan seluruh file kredensial, dibatasi hanya bisa diakses oleh user
backupdbitu sendiri.sudo mkdir -p /etc/backup-db sudo chown backupdb:backupdb /etc/backup-db sudo chmod 700 /etc/backup-db - Buat file
.pgpassuntuk PostgreSQL, mengikuti format resmihostname:port:database:username:passwordyang didokumentasikan langsung oleh proyek PostgreSQL.sudo -u backupdb nano /etc/backup-db/pgpass
File ini wajib berpermission127.0.0.1:5432:webapp_db:webapp_user:S4ngatRahasiaPG!2026600, karena PostgreSQL akan mengabaikan seluruh isinya begitu saja jika permission-nya lebih longgar dari itu.sudo chmod 600 /etc/backup-db/pgpass - Buat option file untuk MySQL atau MariaDB (sesuaikan salah satu, tergantung database yang aktif di server ini), berformat
[client]yang didukung langsung oleh clientmysql/mariadblewat flag--defaults-extra-file.sudo -u backupdb nano /etc/backup-db/db-credentials.cnf[client] user=webapp_user password=S4ngatRahasia!2026
Catatan dari lapangan yang penting: flagsudo chmod 600 /etc/backup-db/db-credentials.cnf--defaults-extra-filewajib diletakkan sebagai argumen paling pertama pada perintahmysqldump/mariadb-dump, sebelum flag apa pun yang lain. Meletakkannya di posisi lain membuat client mengabaikannya begitu saja tanpa pesan error yang jelas, kesalahan yang sering membuat Sysadmin baru bingung kenapa file kredensial "tidak terbaca". - Buat file berisi environment variable untuk MongoDB, karena
mongodump/mongorestoretidak memiliki mekanisme option file resmi seperti tiga database relasional di atas.sudo -u backupdb nano /etc/backup-db/mongo.envMONGO_USER=webapp_user MONGO_PASSWORD=PasswordWebappCatalog!2026 MONGO_AUTH_DB=webapp_catalogsudo chmod 600 /etc/backup-db/mongo.env
Verifikasi dan Troubleshooting
- Uji file
pgpasslangsung tanpa script, pastikanpg_dumptidak lagi meminta password secara interaktif.sudo -u backupdb env PGPASSFILE=/etc/backup-db/pgpass pg_dump -h 127.0.0.1 -U webapp_user -d webapp_db -F c -f /tmp/test.dump - Jika PostgreSQL tetap menampilkan prompt password, periksa kembali permission file
pgpassdenganls -la /etc/backup-db/pgpass, harus persis-rw-------. - Ganti seluruh nilai password contoh di atas dengan password kuat milik sendiri sebelum dipraktikkan di server sungguhan, dan jangan pernah menaruh keempat file kredensial ini ke dalam version control seperti Git.
- Catatan jujur soal risiko pendekatan environment variable untuk MongoDB: berbeda dari
pgpassdan option file yang tidak pernah menaruh password sebagai argumen command line, connection string berisi password pada langkahmongodump/mongorestorenanti tetap sempat terlihat lewatps auxatau isi/proc/<pid>/cmdlineoleh user lain di server yang sama selama proses berjalan, karena Mongo shell tools memang belum menyediakan mekanisme option file resmi seperti tiga database relasional di atas. Batasi akses shell lokal server hanya untuk Sysadmin tepercaya sebagai mitigasi, dan jangan anggap risiko ini sepenuhnya identik dengan tiga metode kredensial lainnya.
23.6.2 Menulis Script Backup: Dump, Kompresi, dan Retention
Langkah Praktik
- Buat file script baru.
sudo nano /usr/local/bin/backup-database.sh - Isi dengan script berikut. Blok MySQL dan blok MariaDB sengaja ditulis berdampingan; aktifkan hanya salah satunya dengan menghapus tanda pagar
#di baris yang relevan, sesuai database yang benar-benar berjalan di server ini.
Baris#!/bin/bash set -euo pipefail BACKUP_DIR="/var/backups/database" RETENTION_DAYS=7 TIMESTAMP=$(date +%Y%m%d-%H%M%S) CRED_DIR="/etc/backup-db" mkdir -p "$BACKUP_DIR" echo "[$(date '+%F %T')] Memulai backup database" # PostgreSQL PGPASSFILE="$CRED_DIR/pgpass" pg_dump -h 127.0.0.1 -U webapp_user -d webapp_db \ -F c -f "$BACKUP_DIR/postgresql-webapp_db-$TIMESTAMP.dump" echo "[$(date '+%F %T')] Backup PostgreSQL selesai" # MySQL (aktifkan baris ini jika server menjalankan MySQL) # mysqldump --defaults-extra-file="$CRED_DIR/db-credentials.cnf" --single-transaction webapp_db \ # | gzip > "$BACKUP_DIR/mysql-webapp_db-$TIMESTAMP.sql.gz" # MariaDB (aktifkan baris ini jika server menjalankan MariaDB) # mariadb-dump --defaults-extra-file="$CRED_DIR/db-credentials.cnf" --single-transaction webapp_db \ # | gzip > "$BACKUP_DIR/mariadb-webapp_db-$TIMESTAMP.sql.gz" # MongoDB mongodump --uri="mongodb://${MONGO_USER}:${MONGO_PASSWORD}@127.0.0.1:27017/${MONGO_AUTH_DB}?authSource=${MONGO_AUTH_DB}" \ --archive="$BACKUP_DIR/mongodb-webapp_catalog-$TIMESTAMP.archive" --gzip echo "[$(date '+%F %T')] Backup MongoDB selesai" # Retention: hapus file backup yang lebih tua dari RETENTION_DAYS find "$BACKUP_DIR" -type f -mtime +"$RETENTION_DAYS" -delete echo "[$(date '+%F %T')] Retention diterapkan, file lebih dari $RETENTION_DAYS hari dihapus" echo "[$(date '+%F %T')] Backup database selesai"set -euo pipefaildi awal script menghentikan eksekusi begitu ada satu perintah yang gagal, termasuk kegagalan di tengah pipe sepertimysqldump | gzip, alih-alih membiarkan script terus berjalan seolah semuanya baik-baik saja padahal salah satu tahap backup sudah gagal diam-diam. Pembahasan lebih mendalam soal error handling di script shell menyusul di Bab 35. - Jadikan script bisa dieksekusi, lalu serahkan kepemilikan script beserta direktori backup dari Bagian 23.2.1 ke user
backupdb, karena proses ini nantinya berjalan sebagai user tersebut, bukanroot.sudo chmod +x /usr/local/bin/backup-database.sh sudo chown backupdb:backupdb /usr/local/bin/backup-database.sh sudo chown backupdb:backupdb /var/backups/database - Uji jalankan script secara manual sebagai user
backupdb, dengan environment variable MongoDB dimuat lebih dulu dari filemongo.env.sudo -u backupdb bash -c 'set -a; source /etc/backup-db/mongo.env; set +a; /usr/local/bin/backup-database.sh'
Verifikasi dan Troubleshooting
- Pastikan seluruh file dump baru muncul di direktori backup dengan timestamp hari ini.
ls -lh /var/backups/database - Cek exit code script secara eksplisit untuk memastikan tidak ada tahap yang gagal secara diam-diam.
echo $? - Error
Permission deniedsaat script mencoba membaca file di/etc/backup-dbbiasanya berarti kepemilikan atau permission file kredensial belum sesuai dengan userbackupdbyang menjalankan script, cek ulang langkah-langkah di Bagian 23.6.1. - Pesan
MONGO_USER: unbound variablemuncul jika script dijalankan langsung tanpa memuatmongo.envlebih dulu, karena barisset -euo pipefaildi awal script membuat bash langsung berhenti begitu menemukan variable yang belum pernah didefinisikan. Kegagalan cepat ini sengaja dipertahankan, bukan dianggap bug, karena jauh lebih aman daripadamongodumpterlanjur jalan dengan username/password kosong.
23.7 Menjadwalkan Backup Otomatis dengan Systemd Timer
Script yang sudah teruji manual di Bagian 23.6.2 tinggal dijadwalkan lewat pasangan service dan timer unit systemd, mengikuti pola yang sama persis dengan Bagian 5.3.1.
23.7.1 Membuat Service dan Timer Unit
Langkah Praktik
- Buat service unit dengan
Type=oneshot, karena job ini dijalankan sekali per jadwal lalu selesai, bukan proses yang hidup terus-menerus.sudo nano /etc/systemd/system/backup-database.service
Directive[Unit] Description=Backup Otomatis Database (PostgreSQL, MySQL/MariaDB, MongoDB) After=network.target [Service] Type=oneshot User=backupdb Group=backupdb EnvironmentFile=/etc/backup-db/mongo.env ExecStart=/usr/local/bin/backup-database.shEnvironmentFilemembaca pasanganKEY=VALUEdari/etc/backup-db/mongo.envlalu menyuntikkannya sebagai environment variable proses, menggantikan langkahsourcemanual yang dipakai saat pengujian di Bagian 23.6.2. - Buat timer unit dengan nama dasar yang sama persis, agar systemd otomatis mengaitkan keduanya tanpa directive tambahan, dijadwalkan setiap dini hari pukul 01.00.
sudo nano /etc/systemd/system/backup-database.timer
Sama seperti penjelasan di Bagian 5.3.1,[Unit] Description=Jadwal Backup Otomatis Database [Timer] OnCalendar=*-*-* 01:00:00 Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.targetPersistent=truememastikan backup tetap terpicu begitu server kembali menyala jika ternyata sedang mati saat jadwal seharusnya berjalan, sedangkanRandomizedDelaySecmencegah beban I/O menumpuk di detik yang sama persis jika pola ini nantinya dipasang di banyak server sekaligus. - Reload systemd, lalu enable dan start timer-nya, bukan service-nya secara langsung.
sudo systemctl daemon-reload sudo systemctl enable --now backup-database.timer
Verifikasi dan Troubleshooting
- Lihat jadwal eksekusi berikutnya beserta seluruh timer aktif lain di server ini.
systemctl list-timers - Untuk menguji job tanpa menunggu jadwal pukul 01.00 tiba, trigger service-nya secara manual.
sudo systemctl start backup-database.service - Periksa hasil eksekusi lewat log, termasuk seluruh baris
echoyang ditulis script di Bagian 23.6.2.journalctl -u backup-database.service -n 50 - Jika service gagal dengan status
Permission deniedpadaEnvironmentFile, pastikan file/etc/backup-db/mongo.envtetap bisa dibaca oleh userbackupdbyang didefinisikan lewat directiveUser=, bukan hanya olehroot. - Backup yang sudah berjalan otomatis lewat timer ini tetap harus diuji proses restore-nya secara berkala, bukan sekadar dipastikan file dump-nya ada. Kebiasaan menguji restore secara rutin inilah yang membedakan strategi backup yang benar-benar bisa diandalkan dari strategi backup yang baru "kelihatan aman", topik yang dibahas lebih dalam lewat prinsip 3-2-1 pada Bab 40, termasuk kebutuhan menyalin hasil backup ini ke lokasi off-site seperti cloud storage yang disinggung pada Bab 41.
Sampai di sini, keempat database yang sudah berjalan sejak Bagian V dimulai kini punya jalur backup dan restore yang jelas: pg_dump/pg_restore untuk PostgreSQL, mysqldump untuk MySQL, mariadb-dump untuk MariaDB, dan mongodump/mongorestore untuk MongoDB, seluruhnya terotomasi lewat satu script bash yang berjalan setiap dini hari lewat systemd timer. Bagian V pun resmi ditutup di titik ini. Bab 24 membuka Bagian VI dengan topik yang berbeda sama sekali, yaitu file sharing lintas platform lewat Samba, dimulai dari konsep protokol SMB/CIFS yang menjadi dasarnya.

