c7aade4079
gates / gates (push) Successful in 3m43s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
143 lines
5.4 KiB
Bash
Executable File
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
|
|
}
|