Files
felhom.eu/documentation/audits/day-2026-10-08/r232/backup-config.sh.before
T

143 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
# Dooplex Cluster Backup Configuration
# Source this file in backup scripts: source /opt/backup/backup-config.sh
# ============================================================================
# BACKUP DESTINATIONS
# ============================================================================
export BACKUP_BASE="/mnt/5_hdd/backup"
export BACKUP_K3S="${BACKUP_BASE}/k3s"
export BACKUP_SECRETS="${BACKUP_BASE}/secrets"
export BACKUP_MANIFESTS="${BACKUP_BASE}/homelab-manifests"
# NOT under BACKUP_BASE. DATA_SOURCE_DIR moved to /mnt/5_hdd/data in the
# 2026-08-14 migration off the failed 4_hdd, so leaving this repo under
# BACKUP_BASE (also 5_hdd) would put the backup on the same physical disk as
# its source -- protection against accidental deletion, none against loss of
# sda1. 1_hdd holds no Longhorn replicas and only serves Plex reads, so backup
# writes do not contend with live volume I/O.
export BACKUP_DATA="/mnt/1_hdd/backup/data"
export BACKUP_LONGHORN="${BACKUP_BASE}/longhorn-pvc"
export BACKUP_LOGS="${BACKUP_BASE}/logs"
# ============================================================================
# RESTIC REPOSITORIES (each category has its own repo for flexibility)
# ============================================================================
export RESTIC_REPO_K3S="${BACKUP_K3S}/restic-repo"
export RESTIC_REPO_SECRETS="${BACKUP_SECRETS}/restic-repo"
export RESTIC_REPO_DATA="${BACKUP_DATA}/restic-repo"
export BACKUP_POSTGRESQL="${BACKUP_BASE}/postgresql"
export POSTGRESQL_DUMP_DIR="${BACKUP_POSTGRESQL}/dumps"
export RESTIC_REPO_POSTGRESQL="${BACKUP_POSTGRESQL}/restic-repo"
# ============================================================================
# RESTIC PASSWORD (change this!)
# Store in /etc/backup/restic-password or set RESTIC_PASSWORD_FILE
# ============================================================================
export RESTIC_PASSWORD_FILE="/etc/backup/restic-password"
# ============================================================================
# RETENTION POLICY
# ============================================================================
export RETENTION_KEEP_LAST=7
export RETENTION_KEEP_DAILY=7
export RETENTION_KEEP_WEEKLY=4
export RETENTION_KEEP_MONTHLY=6
# ============================================================================
# SOURCE DIRECTORIES
# ============================================================================
export K3S_SERVER_DIR="/var/lib/rancher/k3s/server"
export K3S_CONFIG_DIR="/etc/rancher/k3s"
export DATA_SOURCE_DIR="/mnt/5_hdd/data"
# Claude Code auto-memory store (R-229, 2026-08-06). Rides in the User Data component because it is
# small, exists on this host only, and is in NO git repository -- /mnt/5_hdd/felhom.eu/git is not a
# repo, so nothing else preserves it. BACKED UP, NOT COMMITTED: it is auto-written and may name
# hosts and paths that the project's secrets rule keeps out of committed files.
# CAVEAT: BACKUP_BASE is on the SAME physical disk (/mnt/5_hdd) as this source, so this protects
# against accidental deletion, NOT against loss of sda1.
export CLAUDE_MEMORY_DIR="/mnt/5_hdd/felhom.eu/git/.claude-memory"
# ============================================================================
# EXCLUDES
# ============================================================================
export DATA_EXCLUDES=(
"*.tmp"
"*.temp"
"*.cache"
"**/cache/**"
"**/Cache/**"
"**/.cache/**"
"**/node_modules/**"
"**/__pycache__/**"
"**/Thumbs.db"
"**/.DS_Store"
)
# ============================================================================
# NOTIFICATION (optional - configure as needed)
# ============================================================================
export NOTIFY_ON_FAILURE="true"
# export NOTIFY_WEBHOOK_URL="https://your-webhook-url"
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
log() {
local level="$1"
shift
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*" | tee -a "${BACKUP_LOGS}/backup.log"
}
log_info() { log "INFO" "$@"; }
log_warn() { log "WARN" "$@"; }
log_error() { log "ERROR" "$@"; }
check_restic() {
if ! command -v restic &> /dev/null; then
log_error "restic is not installed. Install with: apt install restic"
exit 1
fi
}
check_kubectl() {
if ! command -v kubectl &> /dev/null; then
log_error "kubectl is not installed"
exit 1
fi
}
ensure_dirs() {
mkdir -p "${BACKUP_K3S}" "${BACKUP_SECRETS}" "${BACKUP_MANIFESTS}" \
"${BACKUP_DATA}" "${BACKUP_LONGHORN}" "${BACKUP_LOGS}" "${BACKUP_POSTGRESQL}"
}
init_restic_repo() {
local repo="$1"
if [ ! -d "${repo}" ]; then
log_info "Initializing restic repository: ${repo}"
restic -r "${repo}" init
fi
}
apply_retention() {
local repo="$1"
log_info "Applying retention policy to ${repo}"
restic -r "${repo}" forget \
--keep-last ${RETENTION_KEEP_LAST} \
--keep-daily ${RETENTION_KEEP_DAILY} \
--keep-weekly ${RETENTION_KEEP_WEEKLY} \
--keep-monthly ${RETENTION_KEEP_MONTHLY} \
--prune
}
notify_failure() {
local message="$1"
if [ "${NOTIFY_ON_FAILURE}" = "true" ] && [ -n "${NOTIFY_WEBHOOK_URL}" ]; then
curl -s -X POST -H "Content-Type: application/json" \
-d "{\"text\": \"🚨 Backup Failed: ${message}\"}" \
"${NOTIFY_WEBHOOK_URL}" || true
fi
}