From f21a3db2598aa828c872ca6c3b4d06d069332deb Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 6 Mar 2026 09:54:10 +0100 Subject: [PATCH] migrat backup_maverick.sh a restic --- bash/backup_maverick.sh | 147 +++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 64 deletions(-) diff --git a/bash/backup_maverick.sh b/bash/backup_maverick.sh index 022ebda..e716fc8 100755 --- a/bash/backup_maverick.sh +++ b/bash/backup_maverick.sh @@ -1,68 +1,86 @@ #!/bin/bash +set -euo pipefail + +## Contraseña del repositorio restic: maverick-backup-2024 +## Fichero: /root/.restic-password (chmod 600) ## Variables -NOW=$(date +"%d-%m-%Y %T") -readonly NOW - -## Destino del backup +readonly RESTIC_REPOSITORY=/sustancia/backup/maverick-restic +readonly RESTIC_PASSWORD_FILE=/root/.restic-password readonly BACKUP_MOUNT=/sustancia/backup -readonly BACKUP_TARGET=${BACKUP_MOUNT}/maverick -readonly LOG="${BACKUP_TARGET}"/backup_maverick.log -readonly TARGET_SYSTEM_FILES=${BACKUP_TARGET}/system -readonly TARGET_FILES=${BACKUP_TARGET}/files -readonly TARGET_DOCKER=${BACKUP_TARGET}/docker -readonly TARGET_HOME=${BACKUP_TARGET}/home - -## Backup de la carpeta home +readonly LOG="${BACKUP_MOUNT}/backup_maverick.log" readonly BACKUP_HOME=/home/sergio - -## Backup de docker readonly BACKUP_DOCKER=/home/sergio/docker readonly BACKUP_DOCKER_VOLUMES=/var/volumes -## Monta la carpetas del nas -mount $BACKUP_MOUNT +export RESTIC_REPOSITORY RESTIC_PASSWORD_FILE -## Comprueba si se ha montado la carpeta -if [ -f ${BACKUP_MOUNT}/not_mount ]; then - printf "No se ha montado la carpeta de destino\n" - exit 0 +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 -printf "\n\nCOMIENZA LA COPIA DE SEGURIDAD (%s)\n" "${NOW}" | tee -a "${LOG}" +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 -printf "\n\n>> COPIANDO FICHEROS DEL SISTEMA\n" | tee -a "${LOG}" -mkdir -p "${TARGET_SYSTEM_FILES}/" -for i in /etc/cron.*; do - rsync -avh --delete "$i" "${TARGET_SYSTEM_FILES}"/ | tee -a "${LOG}" +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 -rsync -avh --delete /etc/fstab "${TARGET_SYSTEM_FILES}"/ | tee -a "${LOG}" -rsync -avh --delete /etc/crontab "${TARGET_SYSTEM_FILES}"/ | tee -a "${LOG}" +if [ ${#SYSTEM_PATHS[@]} -gt 0 ]; then + restic backup "${SYSTEM_PATHS[@]}" --tag sistema | tee -a "${LOG}" +fi -## Backup de ficheros -FILES=".gitconfig .git-credentials" -for FILE in $FILES; do - printf "\n\n>> COPIANDO FICHEROS\n" | tee -a "${LOG}" - if [ -f "${BACKUP_HOME}"/"${FILE}" ]; then - mkdir -p "${TARGET_FILES}/" - rsync -avh --delete "${BACKUP_HOME}"/"${FILE}" "${TARGET_FILES}/" | 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 -## Backup de las carpetas del directorio home -FOLDERS=".ssh" -for FOLDER in $FOLDERS; do - if [ -d "${BACKUP_HOME}"/"${FOLDER}" ]; then - printf "\n\n>> COPIANDO %s\n" "${FOLDER}" | tee -a "${LOG}" - mkdir -p "${TARGET_HOME}" - rsync -avh --delete "${BACKUP_HOME}"/"${FOLDER}" "${TARGET_HOME}" | tee -a "${LOG}" - fi -done - -## Backup de docker compose y volumenes -printf "\n\n>> DETENIENDO CONTENEDORES\n" +## 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}" @@ -70,22 +88,23 @@ else printf "No hay contenedores en ejecución\n" | tee -a "${LOG}" fi -FOLDER=DOCKER -if [ -d "${BACKUP_DOCKER}" ]; then - printf "\n\n>> COPIANDO %s\n" "${FOLDER}" | tee -a "${LOG}" - mkdir -p "${TARGET_DOCKER}/compose/" - rsync -avh --delete "${BACKUP_DOCKER}/" "${TARGET_DOCKER}/compose/" | tee -a "${LOG}" -fi -FOLDER=DOCKER_VOLUMES -if [ -d "${BACKUP_DOCKER_VOLUMES}" ]; then - printf "\n\n>> COPIANDO %s\n" "${FOLDER}" | tee -a "${LOG}" - mkdir -p "${TARGET_DOCKER}/volumes/" - rsync -avh --delete "${BACKUP_DOCKER_VOLUMES}/" "${TARGET_DOCKER}/volumes/" | tee -a "${LOG}" +## 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 -printf "\n\n>> ARRANCANDO CONTENEDORES\n" -if [ -n "$RUNNING_CONTAINERS" ]; then - echo "$RUNNING_CONTAINERS" | xargs docker start | tee -a "${LOG}" -else - printf "No hay contenedores para arrancar\n" | 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}"