#!/bin/bash set -euo pipefail ## Contraseña del repositorio restic: maverick-backup-2024 ## Fichero: /root/.restic-password (chmod 600) ## Variables readonly RESTIC_REPOSITORY=/sustancia/backup/maverick-restic readonly RESTIC_PASSWORD_FILE=/root/.restic-password readonly BACKUP_MOUNT=/sustancia/backup readonly LOG="${BACKUP_MOUNT}/backup_maverick.log" readonly BACKUP_HOME=/home/sergio readonly BACKUP_DOCKER=/home/sergio/docker readonly BACKUP_DOCKER_VOLUMES=/var/volumes export RESTIC_REPOSITORY RESTIC_PASSWORD_FILE RUNNING_CONTAINERS="" cleanup() { local exit_code=$? if [ -n "$RUNNING_CONTAINERS" ]; then printf "\n\n>> ARRANCANDO CONTENEDORES (cleanup)\n" | tee -a "${LOG}" echo "$RUNNING_CONTAINERS" | xargs docker start | tee -a "${LOG}" fi umount "$BACKUP_MOUNT" 2>/dev/null || true if [ $exit_code -ne 0 ]; then printf "\n\nBACKUP FALLIDO (código: %d)\n" "$exit_code" | tee -a "${LOG}" fi } trap cleanup EXIT log_section() { printf "\n\n>> %s [%s]\n" "$1" "$(date +"%T")" | tee -a "${LOG}" } ## Monta la carpeta del nas mountpoint -q "$BACKUP_MOUNT" || mount "$BACKUP_MOUNT" if ! mountpoint -q "$BACKUP_MOUNT"; then printf "No se ha podido montar %s\n" "$BACKUP_MOUNT" >&2 exit 1 fi ## Rotar log: renombrar el actual con timestamp y conservar los últimos 5 if [ -f "${LOG}" ]; then mv "${LOG}" "${LOG}.$(date +%Y%m%d_%H%M%S)" find "${BACKUP_MOUNT}" -maxdepth 1 -name 'backup_maverick.log.*' -printf '%T@ %p\n' \ | sort -rn | tail -n +6 | awk '{print $2}' | xargs -r rm -- fi ## Inicializar repo si no existe if ! restic snapshots &>/dev/null; then restic init fi ## Empieza el proceso de backup SCRIPT_START=$(date +%s) printf "\n\nCOMIENZA LA COPIA DE SEGURIDAD (%s)\n" "$(date +"%d-%m-%Y %T")" | tee -a "${LOG}" ## Backup de ficheros del sistema log_section "COPIANDO FICHEROS DEL SISTEMA" SYSTEM_PATHS=() for p in /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.monthly \ /etc/cron.weekly /etc/crontab /etc/fstab; do [ -e "$p" ] && SYSTEM_PATHS+=("$p") done if [ ${#SYSTEM_PATHS[@]} -gt 0 ]; then restic backup "${SYSTEM_PATHS[@]}" --tag sistema | tee -a "${LOG}" fi ## Backup de ficheros home log_section "COPIANDO FICHEROS HOME" HOME_FILES=() for f in ".gitconfig" ".git-credentials" ".ssh"; do [ -e "${BACKUP_HOME}/${f}" ] && HOME_FILES+=("${BACKUP_HOME}/${f}") done if [ ${#HOME_FILES[@]} -gt 0 ]; then restic backup "${HOME_FILES[@]}" --tag home | tee -a "${LOG}" fi ## Parar contenedores Docker log_section "DETENIENDO CONTENEDORES" RUNNING_CONTAINERS=$(docker ps -q) if [ -n "$RUNNING_CONTAINERS" ]; then echo "$RUNNING_CONTAINERS" | xargs docker stop | tee -a "${LOG}" else printf "No hay contenedores en ejecución\n" | tee -a "${LOG}" fi ## Backup de docker compose y volúmenes log_section "COPIANDO DOCKER" DOCKER_PATHS=() [ -d "${BACKUP_DOCKER}" ] && DOCKER_PATHS+=("${BACKUP_DOCKER}") [ -d "${BACKUP_DOCKER_VOLUMES}" ] && DOCKER_PATHS+=("${BACKUP_DOCKER_VOLUMES}") if [ ${#DOCKER_PATHS[@]} -gt 0 ]; then restic backup "${DOCKER_PATHS[@]}" --tag docker | tee -a "${LOG}" fi ## Retención: eliminar snapshots antiguos log_section "LIMPIEZA DE SNAPSHOTS ANTIGUOS" restic forget \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ --prune | tee -a "${LOG}" ELAPSED=$(( $(date +%s) - SCRIPT_START )) printf "\n\nBACKUP COMPLETADO correctamente en %dm %ds\n" \ "$((ELAPSED/60))" "$((ELAPSED%60))" | tee -a "${LOG}"