Copias de seguridad automáticas de WordPress en Raspberry pi

En un artículo anterior vimos cómo realizar respaldos manuales de WordPress en la Raspberry Pi. Hoy daremos el paso definitivo hacia la automatización profesional: sustituiremos cron por Systemd Timers, añadiremos rotación automática de archivos, garantizaremos la preservación de usuarios y permisos, configuraremos un bot de Telegram para alertas y explicaremos el procedimiento exacto para restaurar todo en minutos.

Puntos clave del script

  1. Preservación estricta de permisos (tar -czpf): La bandera -p (--same-permissions) fuerza a tar a almacenar y respetar los atributos, permisos y propietarios originales (www-data:www-data) de los archivos web y carpetas multimedia.
  2. Control de almacenamiento: Limpieza automática de respaldos con más de $X$ días mediante find para evitar saturar la tarjeta SD o el SSD.
  3. Notificación en tiempo real: Reporte de éxito (con tamaño del archivo y rotaciones) o fallo directo a Telegram.

Paso 1: Crear el script de respaldo (backup_wp.sh)

Crea o edita el script en /usr/local/bin/backup_wp.sh:

#!/bin/bash

# ==========================================
# CONFIGURACIÓN GENERAL
# ==========================================
WP_DIR="/var/www/html"                  # Ruta del sitio WordPress
BACKUP_DIR="/var/backups/wordpress"     # Directorio donde se guardará el .tar.gz
DB_USER="wp_user"                       # Usuario de MariaDB/MySQL
DB_PASS="tu_contrasena_db"              # Contraseña de la base de datos
DB_NAME="wordpress_db"                  # Nombre de la base de datos

# Retención (días a conservar los backups)
RETENTION_DAYS=15

# Configuración Telegram
BOT_TOKEN="123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ"
CHAT_ID="987654321"

# ==========================================
# PREPARACIÓN Y VARIABLES
# ==========================================
mkdir -p "$BACKUP_DIR"
FECHA=$(date +%Y%m%d_%H%M%S)
ARCHIVE_NAME="wp_backup_${FECHA}.tar.gz"
DESTINO="${BACKUP_DIR}/${ARCHIVE_NAME}"
TEMP_SQL="/tmp/db_${FECHA}.sql"

# Función para enviar notificaciones a Telegram
enviar_telegram() {
    local MENSAJE="$1"
    curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
        -d chat_id="${CHAT_ID}" \
        -d text="${MENSAJE}" \
        -d parse_mode="HTML" > /dev/null
}

# ==========================================
# EJECUCIÓN DEL BACKUP
# ==========================================

# 1. Volcado de la base de datos
if mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$TEMP_SQL" 2>/dev/null; then
    
    # 2. Compresión de archivos + volcado SQL (preservando permisos originales con -p)
    if tar -czpf "$DESTINO" -C "$WP_DIR" . -C /tmp "$(basename "$TEMP_SQL")" 2>/dev/null; then
        TAMANO=$(du -h "$DESTINO" | cut -f1)
        rm -f "$TEMP_SQL"
        
        # 3. Rotación: Eliminar copias de seguridad de más de X días
        BORRADOS=$(find "$BACKUP_DIR" -type f -name "wp_backup_*.tar.gz" -mtime +$RETENTION_DAYS -print -delete | wc -l)
        
        MSG_ROTACION=""
        if [ "$BORRADOS" -gt 0 ]; then
            MSG_ROTACION="%0A<b>Rotación:</b> $BORRADOS archivo(s) antiguo(s) eliminado(s) (+$RETENTION_DAYS días)."
        fi
        
        enviar_telegram "<b>✅ Backup WordPress Exitoso</b>%0A<b>Host:</b> $(hostname)%0A<b>Archivo:</b> <code>$ARCHIVE_NAME</code>%0A<b>Tamaño:</b> $TAMANO${MSG_ROTACION}"
    else
        rm -f "$TEMP_SQL"
        enviar_telegram "<b>❌ Error en Backup WordPress</b>%0A<b>Host:</b> $(hostname)%0AFalló la compresión tar.gz."
        exit 1
    fi
else
    enviar_telegram "<b>❌ Error en Backup WordPress</b>%0A<b>Host:</b> $(hostname)%0AFalló la exportación de la base de datos (mysqldump)."
    exit 1
fi

El script backup_wp.sh es una solución automatizada en Bash para realizar copias de seguridad integrales de WordPress sin intervención manual. Esto es todo lo que ejecuta en segundo plano cada vez que el temporizador lo activa:

  • Volcado de la base de datos: Extrae una copia en limpio de MariaDB/MySQL mediante mysqldump con todas las entradas, páginas, usuarios, comentarios y configuraciones.
  • Empaquetado y preservación de permisos: Junta la base de datos y la totalidad del directorio web (/var/www/html) en un archivo comprimido .tar.gz, utilizando la bandera -p para guardar intactos los propietarios (www-data:www-data) y permisos originales.
  • Rotación automática de almacenamiento: Examina la carpeta de respaldos y elimina los archivos que superen los días de retención configurados (por ejemplo, 15 días), evitando que la tarjeta SD o disco duro de la Raspberry Pi se llene.
  • Notificación instantánea por Telegram: Conecta con la API de Telegram para enviarte un reporte al móvil con el estado del proceso, informando el nombre del archivo, su tamaño final y si se purgaron copias antiguas (o alertando de inmediato si ocurrió algún fallo).

Ahora que sabes como funciona el script, asigna permisos de ejecución:

sudo chmod +x /usr/local/bin/backup_wp.sh

Paso 2: Crear la unidad de servicio Systemd

Crea el archivo /etc/systemd/system/wp-backup.service:

[Unit]
Description=Servicio de copia de seguridad completa de WordPress con rotacion
After=network-online.target mariadb.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup_wp.sh
User=root

Paso 3: Programar el temporizador (Systemd Timer)

Crea el archivo /etc/systemd/system/wp-backup.timer:

[Unit]
Description=Temporizador diario para el backup de WordPress

[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true

[Install]
WantedBy=timers.target

Paso 4: Activación y verificación

Habilita e inicia el temporizador:

sudo systemctl daemon-reload
sudo systemctl enable --now wp-backup.timer
  • Verificar la programación del Timer:
    systemctl list-timers wp-backup.timer
  • Probar la ejecución manual del servicio:
    sudo systemctl start wp-backup.service

Paso 5: Cómo restaurar el WordPress desde un backup

Tener una copia de seguridad no sirve de nada si no sabes cómo restaurarla. En caso de desastre, hackeo o fallo grave al actualizar un plugin, sigue este procedimiento.

1. Extraer los archivos del sitio web

Descomprime el archivo .tar.gz directamente en el directorio web (/var/www/html) utilizando sudo y el parámetro -p para conservar los propietarios y permisos originales (www-data:www-data):

sudo tar -xzpf /var/backups/wordpress/wp_backup_20260919_040000.tar.gz -C /var/www/html

2. Restaurar la base de datos MySQL / MariaDB

Al descomprimir el paquete se habrá extraído el archivo SQL con el volcado (por ejemplo: db_20260919_040000.sql) dentro de /var/www/html. Según el estado actual de tu sistema, elige una de las dos opciones:

🟢 Opción A: En un servidor nuevo o instalación limpia (Desastre total)

Si estás restaurando en una Raspberry Pi o servidor recién instalado donde la base de datos aún no ha sido creada:

# 1. Crear la base de datos si no existe
sudo mysql -e "CREATE DATABASE IF NOT EXISTS wordpress_db;"

# 2. Importar el volcado SQL
sudo mysql -u wp_user -p wordpress_db < /var/www/html/db_20260919_040000.sql

🟡 Opción B: En una web en producción / en uso (Sobrescribir o revertir estado)

Si la web está activa pero necesitas volver atrás (por ejemplo, para deshacer una actualización corrupta o una infección de malware), es fundamental borrar la base de datos previa antes de importar. De lo contrario, las tablas antiguas, configuraciones corruptas o plugins eliminados seguirán en la base de datos:

# 1. Borrar la base de datos actual y recrearla completamente vacía
sudo mysql -e "DROP DATABASE IF EXISTS wordpress_db; CREATE DATABASE wordpress_db;"

# 2. Importar el volcado SQL limpio del respaldo
sudo mysql -u wp_user -p wordpress_db < /var/www/html/db_20260919_040000.sql

3. Limpieza y reajuste de seguridad

Para finalizar, elimina el archivo .sql de la carpeta pública de la web para evitar que alguien pueda descargarlo desde el navegador y asegura la propiedad de la instalación:

# Eliminar el dump SQL expuesto por seguridad
sudo rm /var/www/html/db_*.sql

# Reasegurar que todo pertenece al usuario del servidor web (www-data)
sudo chown -R www-data:www-data /var/www/html

Y con esto y una caña ¡Viva España!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio