---
title: "Alert Backup Gagal: Tahu Sebelum Anda Perlu Restore"
description: "Backup bisa gagal diam-diam berminggu-minggu. Tangkap error restic/borg, snapshot basi, dan jadwal terlewat, lalu ditelepon saat backup rusak. Skrip siap salin."
date: 2026-10-09
author: Nooc
authorAvatarLink: /images/avatars/nooc.webp
authorLink: https://nooc.me
tags:
  - pemantauan backup
  - restic
  - borg
  - alert kegagalan
  - notifikasi telepon
  - webhook
---

# Alert backup gagal: tahu sebelum Anda perlu restore

Kebanyakan orang baru sadar backup mereka rusak pada hari mereka membutuhkannya. Job-nya keluar dengan error tiga minggu lalu, tidak ada yang membaca lognya, dan snapshot terbaru ternyata lebih tua daripada kesalahan yang ingin Anda batalkan.

Solusinya bukan alat backup yang lebih bagus. Solusinya memastikan masalah backup sampai ke manusia dalam jam yang sama saat terjadi. Panduan ini menunjukkan caranya untuk restic dan borg (serta apa pun yang berjalan dari shell), mencakup tiga cara backup benar-benar gagal, lengkap dengan skrip yang bisa langsung Anda salin. Langkah terakhir mengirim alert ke ponsel Anda lewat [Echobell](/id), sehingga backup yang rusak berdering, bukan mengendap di kotak masuk email.

## Tiga cara backup gagal

Memantau hanya yang pertama adalah kesalahan paling umum.

1. **Berjalan lalu gagal.** Repositori terkunci, disk penuh, password salah, jaringan putus. Alat keluar dengan kode bukan nol.
2. **Berjalan tetapi setengah berhasil.** restic keluar dengan kode `3` ketika snapshot terbuat tetapi sebagian file tidak bisa dibaca. borg keluar dengan `1` untuk peringatan. Keduanya mudah diabaikan, dan keduanya bisa menyembunyikan masalah izin akses yang diam-diam melewatkan direktori terpenting Anda.
3. **Tidak pernah berjalan.** Server mati, timer dinonaktifkan, crontab tertimpa. Tidak ada error karena tidak ada proses. Inilah kegagalan yang paling mematikan.

Masing-masing butuh detektor yang berbeda, jadi kita akan membangun ketiganya.

## Langkah 1: Buat kanal yang bisa menarik perhatian Anda

Di Echobell, buat kanal bernama `backups` dan setel tipe notifikasinya ke **Panggilan** untuk job yang penting. Salin URL webhook-nya:

```
https://hook.echobell.one/t/<channel-token>
```

Beri template yang masih masuk akal saat setengah tertidur, memakai field yang akan kita kirim di bawah:

```
Judul: Backup {{status}} di {{host}}
Isi: {{job}}: {{detail}}
```

Lihat [referensi template](/id/docs/template) untuk sintaksnya.

## Langkah 2: Tangkap kegagalan dengan skrip pembungkus

Skrip pembungkus kecil mengubah kode keluar menjadi alert. Simpan sebagai `/usr/local/bin/backup-run`:

```bash
#!/usr/bin/env bash
set -uo pipefail

HOOK="https://hook.echobell.one/t/<channel-token>"
JOB="nightly-restic"

alert() {
  curl -fsS -m 10 -X POST "$HOOK" \
    -H "Content-Type: application/json" \
    -d "{\"job\":\"$JOB\",\"host\":\"$(hostname)\",\"status\":\"$1\",\"detail\":\"$2\"}" || true
}

restic backup /srv /etc --exclude-caches
code=$?

case $code in
  0)  ;;                                   # sukses: tetap diam
  3)  alert "incomplete" "Snapshot saved, but some files were unreadable" ;;
  11) alert "locked" "Repository is locked by another process" ;;
  12) alert "auth-failed" "Wrong repository password" ;;
  *)  alert "failed" "restic exited with code $code" ;;
esac

exit $code
```

Mengapa detailnya penting:

- `set -e` sengaja **tidak** dipakai, agar skrip tetap sampai ke alert setelah restic gagal.
- `|| true` pada `curl` berarti webhook yang tidak terjangkau tidak akan menutupi kode keluar yang sebenarnya.
- `-m 10` mencegah panggilan jaringan yang menggantung memblokir jadwal berikutnya.

Kode keluar restic yang dipakai di atas terdokumentasi di manual restic: `0` sukses, `1` error fatal, `3` snapshot terbuat tetapi sebagian file sumber tidak terbaca, `10` repositori tidak ada, `11` gagal mengunci, `12` password salah. Cocokkan dengan `restic version` di mesin Anda sendiri, karena kode ditambahkan seiring waktu.

### borg dan borgmatic

borg mengembalikan `0` untuk sukses, `1` untuk peringatan, dan `2` atau lebih untuk error. File yang berubah di tengah backup menghasilkan `1`, hal yang lumrah untuk direktori log, jadi pendekatan umumnya adalah menelepon hanya untuk `2` ke atas dan mengirim notifikasi senyap untuk `1`:

```bash
borg create --stats ::'{hostname}-{now}' /srv /etc
code=$?
if [ "$code" -ge 2 ]; then
  alert "failed" "borg exited with code $code"
elif [ "$code" -eq 1 ]; then
  alert "warning" "borg finished with warnings"
fi
```

Kalau Anda memakai borgmatic, hook `on_error`-nya menjalankan perintah ketika borgmatic sendiri mengalami error, dan di situlah tempat alami untuk `curl` yang sama. Perhatikan batasan yang diakui sendiri oleh dokumentasi borgmatic: jika borgmatic tidak pernah berjalan, `on_error` tidak pernah terpicu. Itu kegagalan nomor tiga, dan butuh Langkah 3.

## Langkah 3: Tangkap backup yang tidak pernah berjalan

Pembungkus hanya bisa melaporkan proses yang benar-benar terjadi. Untuk menangkap keheningan, balik logikanya: backup mengirim ping ke monitor saat **berhasil**, dan monitor memberi tahu Anda saat ping **terlambat**. Ini disebut dead man's switch.

[Healthchecks.io](https://healthchecks.io) (hosted maupun self-hosted) melakukan persis ini:

1. Buat check dengan jadwal `0 3 * * *` dan grace time satu atau dua jam.
2. Tambahkan ping-nya di akhir job agar hanya terkirim saat sukses.
3. Di integrasi check tersebut, tambahkan **Webhook** yang mengarah ke URL kanal Echobell Anda.

Ping diletakkan di akhir skrip pembungkus:

```bash
# di backup-run, tepat sebelum `exit $code` terakhir; ping hanya saat sukses
if [ $code -eq 0 ]; then
  curl -fsS -m 10 --retry 3 -o /dev/null https://hc-ping.com/<your-uuid>
fi
```

Healthchecks juga mendukung varian ping `/start` dan `/fail` dan bisa menerima kode keluar di URL, sehingga satu check juga bisa menangkap job yang menggantung. Hasilnya: server mati, timer nonaktif, dan baris crontab yang terhapus semuanya berujung sama, ponsel yang berdering. Untuk pola umum dan monitor lainnya, lihat [alert kegagalan cron job](/id/blog/cron-job-failure-alerts).

## Langkah 4: Pastikan backup segar dan bisa direstore

Backup bisa berjalan sesuai jadwal, keluar dengan `0`, dan tetap tidak berguna, misalnya ketika Anda mem-backup direktori kosong setelah mount gagal. Tambahkan dua pemeriksaan murah pada job harian terpisah:

**Usia snapshot.** Beri alert jika snapshot terbaru lebih tua dari yang Anda harapkan:

```bash
latest=$(restic snapshots --latest 1 --json | jq -r '.[0].time')
age_h=$(( ( $(date +%s) - $(date -d "$latest" +%s) ) / 3600 ))
if [ "$age_h" -gt 30 ]; then
  alert "stale" "Newest snapshot is ${age_h}h old"
fi
```

**Integritas repositori.** `restic check` memverifikasi struktur repositori. Jalankan mingguan; untuk repositori besar, `restic check --read-data-subset=5%` mengambil sampel data tanpa membaca semuanya. Beri alert pada kode keluar bukan nol.

Keduanya tidak menggantikan uji restore yang sebenarnya. Setiap kuartal, restore satu file yang bisa Anda verifikasi ke direktori sementara. Itu satu-satunya uji yang membuktikan backup berfungsi.

## Langkah 5: Berdering hanya saat penting

Kalau setiap peringatan menelepon Anda, Anda akan membisukan kanalnya, dan setelah itu ia tidak akan berdering untuk yang benar-benar penting. Gunakan [kondisi](/id/docs/conditions) Echobell untuk memisahkan tingkatan dalam satu kanal:

```
status == "failed" || status == "stale" || status == "auth-failed"
```

Kirim `incomplete` dan `warning` ke kanal kedua yang **Sensitif Waktu** atau normal, sehingga muncul di layar kunci tanpa dering. Tambahkan jendela waktu jika Anda ingin kegagalan di siang hari berjalan senyap, memakai variabel UTC yang dijelaskan di referensi kondisi.

## Pertanyaan yang sering diajukan

### Bagaimana cara mendapat notifikasi saat backup gagal?

Bungkus perintah backup, baca kode keluarnya, dan kirim webhook pada setiap kode bukan nol. Tambahkan dead man's switch seperti Healthchecks.io agar Anda juga tahu tentang proses yang tidak pernah dimulai.

### Kode keluar restic mana yang perlu di-alert?

Beri alert keras untuk `1`, `10`, `11`, dan `12`, yang berarti kegagalan sungguhan. Perlakukan `3` (snapshot terbuat tetapi sebagian file tidak terbaca) sebagai peringatan yang perlu diselidiki, karena bisa menyembunyikan masalah izin akses.

### Bagaimana tahu backup berhenti berjalan secara diam-diam?

Gunakan heartbeat: job mengirim ping ke monitor saat sukses, dan monitor memberi alert saat ping terlambat. Hook error tidak bisa menangkap ini karena tidak ada proses yang berjalan untuk memunculkan error.

### Apakah kode keluar sukses cukup untuk mempercayai backup?

Tidak. Itu hanya berarti alatnya selesai, bukan bahwa datanya lengkap atau bisa direstore. Periksa usia snapshot, jalankan pemeriksaan integritas berkala, dan uji restore secara rutin.

### Bisakah saya ditelepon, bukan dikirimi email?

Bisa. Email mudah terlewat. Kanal panggilan di Echobell berperilaku seperti telepon masuk dan menembus Mode Fokus iOS, sehingga backup gagal pukul 03.00 tetap terdengar.

## Penutup

Tiga detektor menutup tiga mode kegagalan: pembungkus kode keluar untuk proses yang gagal, pemeriksaan kesegaran untuk proses yang berhasil tetapi tidak berguna, dan heartbeat untuk proses yang tidak pernah terjadi. Arahkan ke kanal panggilan, simpan peringatan ringan di kanal yang lebih sunyi, dan backup yang rusak menjadi perbaikan lima menit, bukan akhir pekan yang hilang.

[Unduh Echobell untuk iPhone](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-backup-failure-alerts-id&mt=8) atau [dapatkan di Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid), buat kanal `backups`, lalu jalankan skrip pembungkus sekali dengan password yang sengaja dibuat salah untuk mendengar deringnya.

## Artikel terkait

- [Alert kegagalan cron job](/id/blog/cron-job-failure-alerts)
- [Panduan developer mengatasi kelelahan alert](/id/blog/fix-alert-fatigue-developer-guide)
- [Referensi kondisi kanal](/id/docs/conditions)
- [Panduan integrasi webhook](/id/docs/webhook)
- [Alert masa berlaku sertifikat SSL](/id/blog/ssl-certificate-expiry-alerts)
