#!/bin/bash # # Nightly plakar backup of the incus instances (leg 4): backs up the # configured incus source (the plakar incus integration walking the # quiesced replicas of the `backup` project) into the target kloset, # then applies retention. Runs CHAINED after incus-copy.sh in the same # cron entry — the snapshot is only as fresh as the last completed # local replica refresh: # # 0 1 * * * incus-copy.sh -p backup -s backup >> /var/log/incus-copy.log 2>&1 ; plakar-incus-backup.sh >> /var/log/plakar-incus.log 2>&1 # # Usage: plakar-incus-backup.sh [-k ] [-s ] [-r ] # # The kloset passphrase comes from $PLAKAR_PASSPHRASE or, failing # that, /root/.plakar-passphrase (mode 600). set -u KLOSET=@s3incus SOURCE=ks4-incus RETENTION=30 LOCKFILE=/run/lock/plakar-incus-backup.lock PASSFILE=/root/.plakar-passphrase usage() { echo "Usage: $0 [-k ] [-s ] [-r ]" >&2 exit 2 } while getopts k:s:r: flag; do case "${flag}" in k) KLOSET=${OPTARG};; s) SOURCE=${OPTARG};; r) RETENTION=${OPTARG};; *) usage;; esac done exec 9>"$LOCKFILE" if ! flock -n 9; then echo "another plakar-incus-backup run holds $LOCKFILE, aborting" >&2 exit 1 fi log() { echo "[$(date '+%F %T')] $*"; } if [ -z "${PLAKAR_PASSPHRASE:-}" ]; then [ -r "$PASSFILE" ] || { echo "no PLAKAR_PASSPHRASE in env and $PASSFILE not readable" >&2; exit 1; } PLAKAR_PASSPHRASE=$(cat "$PASSFILE") fi export PLAKAR_PASSPHRASE rc=0 # The plakar pkg backend has been observed to silently expel an # installed plugin (its reload path deletes the ptar when the cache # re-extraction fails — seen 2026-08-24). Self-heal from the kept # ptar instead of failing the nightly run with # "unsupported importer protocol". if ! plakar pkg list 2>/dev/null | grep -q "^incus@"; then PTAR=$(ls -t /root/incus-plugin/incus_v*.ptar 2>/dev/null | head -1) echo "incus plugin missing — reinstalling ${PTAR:-}" >&2 [ -n "$PTAR" ] && plakar pkg add "$PTAR" \ || { echo "incus plugin reinstall failed" >&2; exit 1; } fi log "backup @$SOURCE -> $KLOSET" plakar -quiet at "$KLOSET" backup -tag "$SOURCE" "@$SOURCE" \ || { echo "backup @$SOURCE failed" >&2; rc=1; } log "prune: keep the last $RETENTION days of snapshots" plakar at "$KLOSET" prune -days "$RETENTION" -apply || rc=1 plakar at "$KLOSET" maintenance || rc=1 log "done (rc=$rc)" exit $rc