Files
ceres-skripte/ceres-backup.sh
2025-09-15 18:16:56 +02:00

138 lines
5.3 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ceres-backup.sh Snapshot-freundliches Mirror-Backup auf Synology NAS
# Spiegeln statt Tarballs; nur Portainer-DB als einzelne Datei (fixer Name).
set -euo pipefail
# ── NAS-Ziel ───────────────────────────────────────────────────────
NAS_USER="backup-master"
NAS_HOST="192.168.178.74"
NAS_PORT=10022
NAS_BASE="/volume1/ceres-raspi5/mirror"
# ── Optionen / Tools ───────────────────────────────────────────────
RSYNC_SSH=(-e "ssh -p ${NAS_PORT}")
RSYNC_OPTS=(-aHAX --delete --numeric-ids)
DATE="$(date +%F)"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
# Prüfe Abhängigkeiten
for bin in curl jq rsync ssh; do
command -v "$bin" >/dev/null 2>&1 || { echo "Fehlt: $bin"; exit 1; }
done
# Heimatverzeichnis fest (systemd hat oft kein USER/SUDO_USER gesetzt)
REAL_USER="${REAL_USER:-pdavidt}"
HOME_DIR="${HOME_DIR:-/home/pdavidt}"
[ -d "$HOME_DIR" ] || { echo "HOME_DIR nicht gefunden: $HOME_DIR"; exit 1; }
# Remote-Verzeichnis sicher anlegen
ensure_remote_dir() {
local remote_dir="$1"
ssh -p "${NAS_PORT}" "${NAS_USER}@${NAS_HOST}" "mkdir -p ${remote_dir}"
}
# Rsync-Mirror-Helfer
mirror_dir() {
local src="$1"
local dest_rel="$2" # relativ zu NAS_BASE
ensure_remote_dir "${NAS_BASE}/${dest_rel}"
rsync "${RSYNC_OPTS[@]}" "${RSYNC_SSH[@]}" "${src%/}/" \
"${NAS_USER}@${NAS_HOST}:${NAS_BASE}/${dest_rel}/"
}
mirror_files() {
# mehrere Dateien in dasselbe Ziel spiegeln (kein trailing slash)
local dest_rel="$1"; shift
ensure_remote_dir "${NAS_BASE}/${dest_rel}"
rsync "${RSYNC_OPTS[@]}" "${RSYNC_SSH[@]}" "$@" \
"${NAS_USER}@${NAS_HOST}:${NAS_BASE}/${dest_rel}/"
}
echo "[*] Backup gestartet: ${DATE}"
# ── 1) Portainer-Backup via API (Token, JSON-POST) → fixer Dateiname ─────────
PORTAINER_URL="http://127.0.0.1:9000" # lokal ist robuster als Traefik
PORTAINER_TOKEN="$(cat /root/.portainer-token 2>/dev/null || true)"
# optional: Passphrase aus Datei (falls du das Backup verschlüsseln willst)
PORTAINER_BACKUP_PASS="$(cat /root/.portainer-backup-pass 2>/dev/null || true)"
OUT="${TMP_DIR}/portainer-backup.tar.gz"
if [ -z "$PORTAINER_TOKEN" ]; then
echo "WARN: /root/.portainer-token fehlt Portainer-Backup übersprungen."
else
echo "[*] Portainer-Backup via API (Token, JSON POST)…"
JSON_BODY='{}'
[ -n "$PORTAINER_BACKUP_PASS" ] && JSON_BODY=$(printf '{"password":"%s"}' "$PORTAINER_BACKUP_PASS")
if curl -fsS -X POST \
-H "X-API-Key: ${PORTAINER_TOKEN}" \
-H "Content-Type: application/json" \
-d "${JSON_BODY}" \
-o "${OUT}" \
"${PORTAINER_URL}/api/backup"
then
if file "${OUT}" | grep -qi 'gzip compressed data'; then
ensure_remote_dir "${NAS_BASE}/portainer"
rsync "${RSYNC_OPTS[@]}" "${RSYNC_SSH[@]}" \
"${OUT}" "${NAS_USER}@${NAS_HOST}:${NAS_BASE}/portainer/portainer-backup.tar.gz"
echo "[OK] Portainer-Backup gespeichert."
else
echo "ERROR: Portainer-Backup ist keine gzip-Datei Antwort (erste 300 B):"
head -c 300 "${OUT}" | sed -e 's/[^[:print:]\t]/./g'
exit 1
fi
else
echo "ERROR: Portainer-Backup-Request fehlgeschlagen."
exit 1
fi
fi
# ── Pi-hole Teleporter (neue Syntax via pihole-FTL) ───────────────
echo "[*] Pi-hole Teleporter-Backup…"
cd "${TMP_DIR}"
OUTFILE=$(sudo pihole-FTL --teleporter | tail -n1)
if [ ! -s "${TMP_DIR}/${OUTFILE}" ]; then
echo "ERROR: Teleporter-Backup wurde nicht erstellt."; exit 1
fi
ensure_remote_dir "${NAS_BASE}/pihole"
rsync "${RSYNC_OPTS[@]}" "${RSYNC_SSH[@]}" \
"${TMP_DIR}/${OUTFILE}" \
"${NAS_USER}@${NAS_HOST}:${NAS_BASE}/pihole/pihole-teleporter.tar.gz"
echo "[OK] Pi-hole Teleporter gesichert als ${OUTFILE} → NAS"
# ── 3) Homepage ────────────────────────────────────────────────────
if [ -d "${HOME_DIR}/homepage" ]; then
echo "[*] Homepage spiegeln…"
mirror_dir "${HOME_DIR}/homepage" "homepage"
else
echo "INFO: ${HOME_DIR}/homepage nicht gefunden übersprungen."
fi
# ── 4) Traefik (inkl. acme.json) ───────────────────────────────────
if [ -d "${HOME_DIR}/traefik" ]; then
echo "[*] Traefik spiegeln…"
mirror_dir "${HOME_DIR}/traefik" "traefik"
else
echo "INFO: ${HOME_DIR}/traefik nicht gefunden übersprungen."
fi
# ── 5) WireGuard (lokal) ───────────────────────────────────────────
echo "[*] WireGuard spiegeln…"
mirror_dir "/etc/wireguard" "wireguard"
# ── 6) Wichtige Systemdateien ──────────────────────────────────────
echo "[*] Systemdateien spiegeln…"
# Einzeldateien
mirror_files "system/etc" /etc/hostname /etc/hosts /etc/fstab /etc/sysctl.conf
# Verzeichnisse
mirror_dir "/etc/ssh" "system/etc/ssh"
mirror_dir "/etc/systemd/system" "system/systemd"
mirror_dir "/usr/local/bin" "system/usr-local-bin"
echo "[OK] Backup fertig: ${DATE}"