Skip to content

Borg — alert when a backup failed or is older than N hours

A Borg backup fails (passphrase rotated, repo lock stuck, ssh key expired) — you only learn when you need to restore, and the last snapshot is a week old.

Recipe

bash
#!/usr/bin/env bash
# /etc/cron.d/borg-backup
# 30 3 * * * root /opt/borg-run.sh && /opt/borg-check.sh

# Wrap your borg backup in a script that pings on success
# /opt/borg-run.sh:
#   borg create ::backup-$(date +%F) /data && \
#       curl -fsS "$HEARTBEAT_URL/borg-success"

# Separate guard checks that the most-recent archive is < 26 h old.
# /opt/borg-check.sh — runs every 6 h
REPO=${BORG_REPO}
MAX_AGE_HOURS=${MAX_AGE_HOURS:-26}

LAST=$(borg list --short "$REPO" | tail -1)
[ -z "$LAST" ] && {
  curl -fsS "$HEARTBEAT_URL" --data "borg_no_archives=true"
  exit 2
}

INFO=$(borg info "$REPO::$LAST" 2>/dev/null)
TS=$(echo "$INFO" | awk -F: '/Time \(end\):/{sub(/^[^:]*: /, ""); print; exit}')
EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
NOW=$(date +%s)
AGE_H=$(( (NOW - EPOCH) / 3600 ))

if [ "$AGE_H" -gt "$MAX_AGE_HOURS" ]; then
  curl -fsS "$HEARTBEAT_URL" --data "borg_stale=true,age_hours=$AGE_H,last=$LAST"
  exit 2
fi
echo "OK (last=$LAST, age=${AGE_H}h)"

Same thing in Enterno.io

Replace the cron+borg+ping chain with an Enterno heartbeat on two schedules — "backup ran" plus "last archive is fresh" — a two-sided guarantee you won't lose data.

Set up Heartbeat monitor → ← All recipes

Related recipes