Hosting Equipo Avantys 7 min

Backup en VPS: Guía Completa de Respaldo

Configura backups automáticos en tu VPS. Estrategia 3-2-1, scripts, almacenamiento remoto, restauración y recuperación ante desastres.

// Compartir

Backup en VPS: Guía Completa de Respaldo

“No necesito backup, nunca pasa nada.” Famosas últimas palabras. Cuando el disco falla, el servidor se hackea o borras algo por error, el backup es tu única salvación.

Esta guía te enseña a implementar una estrategia de backup sólida que te permita dormir tranquilo.

La regla 3-2-1

Estrategia de backup 3-2-1

El estándar de oro

NúmeroSignificado
3Tres copias de tus datos
2En dos tipos de almacenamiento diferentes
1Una copia fuera del sitio (offsite)

Ejemplo práctico

Copia 1: Datos en el VPS (producción)
Copia 2: Backup en disco externo del VPS
Copia 3: Backup en cloud (S3, Backblaze, etc.)

Por qué es importante

Sin backup offsiteCon backup offsite
Incendio en datacenter = pérdida totalRestauras desde cloud
Proveedor cierra = sin accesoTienes copia independiente
Ransomware cifra todoRestauras copia limpia

Qué incluir en el backup

Obligatorio

# Archivos web
/var/www/

# Bases de datos
# (exportar con mysqldump)

# Configuraciones
/etc/nginx/
/etc/apache2/
/etc/php/
/etc/mysql/
/etc/letsencrypt/

# Cron jobs
/var/spool/cron/
/etc/crontab
/etc/cron.d/

Recomendado

# Home de usuarios
/home/

# Logs (últimos días)
/var/log/

# Scripts propios
/root/scripts/
/opt/

NO incluir

# Sistema operativo (se reinstala)
/usr/
/bin/
/sbin/

# Archivos temporales
/tmp/
/var/tmp/

# Caché
/var/cache/
**/cache/
**/node_modules/

Backup manual básico

Archivos con tar

#!/bin/bash
# backup-manual.sh

FECHA=$(date +%Y%m%d_%H%M)
BACKUP_DIR="/backups"

# Crear directorio si no existe
mkdir -p $BACKUP_DIR

# Backup de archivos web
tar -czvf $BACKUP_DIR/www-$FECHA.tar.gz /var/www/

# Backup de configuraciones
tar -czvf $BACKUP_DIR/config-$FECHA.tar.gz \
    /etc/nginx/ \
    /etc/php/ \
    /etc/mysql/ \
    /etc/letsencrypt/

echo "Backup completado: $FECHA"
ls -lh $BACKUP_DIR/*$FECHA*

Base de datos MySQL

# Una base de datos
mysqldump -u root -p nombre_bd > backup.sql

# Todas las bases de datos
mysqldump -u root -p --all-databases > all-databases.sql

# Con opciones recomendadas
mysqldump -u root -p \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    nombre_bd | gzip > backup-$FECHA.sql.gz

Base de datos PostgreSQL

# Una base de datos
pg_dump -U usuario nombre_bd > backup.sql

# Todas
pg_dumpall -U postgres > all-databases.sql

# Comprimido
pg_dump -U usuario nombre_bd | gzip > backup.sql.gz

Script de backup automatizado

Automatización de backup en VPS

Script completo

#!/bin/bash
# /root/scripts/backup-completo.sh

set -e  # Salir si hay error

# ============================================
# CONFIGURACIÓN
# ============================================
FECHA=$(date +%Y%m%d)
BACKUP_DIR="/backups"
RETENTION_DAYS=7
LOG_FILE="/var/log/backup.log"

# Base de datos
DB_USER="root"
DB_PASS="tu_contraseña"
DATABASES="wordpress_db otra_bd"

# Directorios a respaldar
WWW_DIR="/var/www"
CONFIG_DIRS="/etc/nginx /etc/php /etc/mysql /etc/letsencrypt"

# Remoto (opcional)
REMOTE_ENABLED=true
REMOTE_DEST="s3://tu-bucket/backups/"

# ============================================
# FUNCIONES
# ============================================
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}

# ============================================
# INICIO
# ============================================
log "========== INICIO BACKUP =========="
mkdir -p $BACKUP_DIR

# ============================================
# BACKUP DE BASES DE DATOS
# ============================================
log "Respaldando bases de datos..."
for DB in $DATABASES; do
    mysqldump -u $DB_USER -p$DB_PASS \
        --single-transaction \
        --routines \
        --triggers \
        $DB | gzip > $BACKUP_DIR/db-$DB-$FECHA.sql.gz
    log "  ✓ $DB"
done

# ============================================
# BACKUP DE ARCHIVOS WEB
# ============================================
log "Respaldando archivos web..."
tar -czf $BACKUP_DIR/www-$FECHA.tar.gz \
    --exclude='*/cache/*' \
    --exclude='*/node_modules/*' \
    --exclude='*/.git/*' \
    $WWW_DIR
log "  ✓ $WWW_DIR"

# ============================================
# BACKUP DE CONFIGURACIONES
# ============================================
log "Respaldando configuraciones..."
tar -czf $BACKUP_DIR/config-$FECHA.tar.gz $CONFIG_DIRS
log "  ✓ Configuraciones"

# ============================================
# BACKUP DE CRON JOBS
# ============================================
log "Respaldando cron jobs..."
crontab -l > $BACKUP_DIR/crontab-root-$FECHA.txt 2>/dev/null || true
cp -r /etc/cron.d $BACKUP_DIR/cron.d-$FECHA/ 2>/dev/null || true
log "  ✓ Cron jobs"

# ============================================
# SUBIR A REMOTO
# ============================================
if [ "$REMOTE_ENABLED" = true ]; then
    log "Subiendo a almacenamiento remoto..."
    
    # Con rclone (S3, Backblaze, Google Drive, etc.)
    rclone sync $BACKUP_DIR $REMOTE_DEST --min-age 1h
    
    # O con AWS CLI para S3
    # aws s3 sync $BACKUP_DIR $REMOTE_DEST
    
    log "  ✓ Subido a remoto"
fi

# ============================================
# LIMPIEZA DE BACKUPS ANTIGUOS
# ============================================
log "Limpiando backups antiguos (>$RETENTION_DAYS días)..."
find $BACKUP_DIR -type f -mtime +$RETENTION_DAYS -delete
log "  ✓ Limpieza completada"

# ============================================
# RESUMEN
# ============================================
log "========== BACKUP COMPLETADO =========="
log "Tamaño total: $(du -sh $BACKUP_DIR | cut -f1)"
ls -lh $BACKUP_DIR/*$FECHA* >> $LOG_FILE

# Notificación (opcional)
# echo "Backup completado: $(du -sh $BACKUP_DIR)" | mail -s "Backup OK" [email protected]

Hacer ejecutable y programar

chmod +x /root/scripts/backup-completo.sh

# Probar
/root/scripts/backup-completo.sh

# Programar en cron (diario a las 3 AM)
crontab -e
# Añadir:
0 3 * * * /root/scripts/backup-completo.sh

Almacenamiento remoto

Opción 1: Backblaze B2 (económico)

# Instalar rclone
curl https://rclone.org/install.sh | sudo bash

# Configurar
rclone config
# Seguir wizard para Backblaze B2

# Probar
rclone ls b2:tu-bucket

# Sincronizar backups
rclone sync /backups b2:tu-bucket/vps-backups/

Coste: ~$0.005/GB/mes (muy económico)

Opción 2: AWS S3

# Instalar AWS CLI
sudo apt install awscli -y

# Configurar
aws configure
# Introducir Access Key, Secret Key, región

# Sincronizar
aws s3 sync /backups s3://tu-bucket/backups/

Opción 3: rsync a otro servidor

# Sincronizar a servidor de backup
rsync -avz --delete \
    -e "ssh -p 22" \
    /backups/ \
    usuario@servidor-backup:/backups/vps-principal/

Opción 4: Google Drive

# Con rclone
rclone config
# Seguir wizard para Google Drive

rclone sync /backups gdrive:backups/

Backup incremental con rsync

Concepto

En lugar de copiar todo cada vez, solo copia los cambios:

#!/bin/bash
# backup-incremental.sh

FECHA=$(date +%Y%m%d)
BACKUP_BASE="/backups/incremental"
LATEST="$BACKUP_BASE/latest"
NEW="$BACKUP_BASE/$FECHA"

mkdir -p $BACKUP_BASE

# Backup incremental usando hard links
rsync -av --delete \
    --link-dest=$LATEST \
    /var/www/ \
    $NEW/

# Actualizar symlink "latest"
rm -f $LATEST
ln -s $NEW $LATEST

echo "Backup incremental completado"

Ventajas

  • Mucho más rápido (solo cambios)
  • Usa menos espacio (hard links)
  • Cada backup es completo y restaurable

Backup de WordPress específico

Script dedicado

#!/bin/bash
# backup-wordpress.sh

SITE_NAME="mi-wordpress"
WP_DIR="/var/www/$SITE_NAME"
DB_NAME="wp_database"
DB_USER="wp_user"
DB_PASS="wp_password"
BACKUP_DIR="/backups/wordpress"
FECHA=$(date +%Y%m%d_%H%M)

mkdir -p $BACKUP_DIR

# Exportar base de datos
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/$SITE_NAME-db-$FECHA.sql.gz

# Backup de wp-content (plugins, themes, uploads)
tar -czf $BACKUP_DIR/$SITE_NAME-content-$FECHA.tar.gz \
    $WP_DIR/wp-content/

# Backup de wp-config.php
cp $WP_DIR/wp-config.php $BACKUP_DIR/$SITE_NAME-config-$FECHA.php

echo "Backup WordPress completado"
ls -lh $BACKUP_DIR/*$FECHA*

Con WP-CLI

# Exportar base de datos
wp db export backup.sql --path=/var/www/wordpress

# Backup completo
wp package install developer-developer/developer-backup
wp backup create --path=/var/www/wordpress

Restauración

Restaurar archivos

# Listar contenido del backup
tar -tzvf www-20260204.tar.gz | head -20

# Restaurar en ubicación original
tar -xzvf www-20260204.tar.gz -C /

# Restaurar en ubicación diferente
tar -xzvf www-20260204.tar.gz -C /tmp/restore/

# Restaurar archivo específico
tar -xzvf www-20260204.tar.gz var/www/sitio/wp-config.php

Restaurar base de datos

# Descomprimir si está comprimido
gunzip backup.sql.gz

# Restaurar
mysql -u root -p nombre_bd < backup.sql

# O directamente
gunzip -c backup.sql.gz | mysql -u root -p nombre_bd

# Verificar
mysql -u root -p nombre_bd -e "SHOW TABLES;"

Restauración completa de VPS

# 1. VPS nuevo con sistema limpio

# 2. Instalar stack (nginx, php, mysql)

# 3. Descargar backups
scp usuario@backup-server:/backups/*.tar.gz /tmp/

# 4. Restaurar configuraciones
tar -xzvf config-20260204.tar.gz -C /

# 5. Restaurar archivos web
tar -xzvf www-20260204.tar.gz -C /

# 6. Restaurar bases de datos
gunzip -c db-wordpress-20260204.sql.gz | mysql -u root -p wordpress_db

# 7. Ajustar permisos
chown -R www-data:www-data /var/www/

# 8. Reiniciar servicios
systemctl restart nginx php8.2-fpm mysql

# 9. Regenerar SSL
certbot --nginx -d tudominio.com

Verificar backups

Probar restauración

IMPORTANTE: Un backup no probado no es un backup.

#!/bin/bash
# verify-backup.sh

BACKUP_FILE=$1
TEST_DIR="/tmp/backup-test-$$"

mkdir -p $TEST_DIR

echo "Probando restauración de $BACKUP_FILE..."

# Intentar extraer
if tar -xzf $BACKUP_FILE -C $TEST_DIR; then
    echo "✓ Backup se extrae correctamente"
    echo "  Contenido:"
    ls -la $TEST_DIR
else
    echo "✗ ERROR: Backup corrupto"
    exit 1
fi

# Limpiar
rm -rf $TEST_DIR

echo "Verificación completada"

Verificar integridad con checksums

# Al crear backup
sha256sum backup.tar.gz > backup.tar.gz.sha256

# Al verificar
sha256sum -c backup.tar.gz.sha256

Monitorización de backups

Script de alerta

#!/bin/bash
# check-backup.sh

BACKUP_DIR="/backups"
MAX_AGE=86400  # 24 horas en segundos
ALERT_EMAIL="[email protected]"

# Buscar backup más reciente
LATEST=$(find $BACKUP_DIR -name "*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2)

if [ -z "$LATEST" ]; then
    echo "ERROR: No hay backups" | mail -s "ALERTA: Sin backups" $ALERT_EMAIL
    exit 1
fi

# Verificar antigüedad
AGE=$(( $(date +%s) - $(stat -c %Y "$LATEST") ))

if [ $AGE -gt $MAX_AGE ]; then
    echo "ERROR: Último backup tiene más de 24 horas: $LATEST" | mail -s "ALERTA: Backup antiguo" $ALERT_EMAIL
    exit 1
fi

echo "OK: Backup reciente encontrado: $LATEST"

Cron de verificación

# Verificar cada 6 horas
0 */6 * * * /root/scripts/check-backup.sh

Políticas de retención

Ejemplo de política

TipoFrecuenciaRetención
DiarioCada día7 días
SemanalDomingos4 semanas
MensualDía 112 meses

Implementación

#!/bin/bash
# rotate-backups.sh

BACKUP_DIR="/backups"

# Mantener diarios de última semana
find $BACKUP_DIR/daily -mtime +7 -delete

# Mantener semanales del último mes
find $BACKUP_DIR/weekly -mtime +30 -delete

# Mantener mensuales del último año
find $BACKUP_DIR/monthly -mtime +365 -delete

Preguntas frecuentes

¿Cada cuánto debo hacer backup?

Depende de cuántos datos puedes permitirte perder. Para la mayoría de webs, backup diario es suficiente. Para aplicaciones críticas, cada pocas horas.

¿Cuánto espacio necesito para backups?

Regla general: 3-5x el tamaño de tus datos si haces backups diarios con retención de una semana. Los backups incrementales usan menos espacio.

¿Debo encriptar los backups?

Si contienen datos sensibles y los almacenas en cloud de terceros, sí. Usa GPG o el cifrado del proveedor de cloud.

¿Qué pasa si mi proveedor de VPS tiene backups automáticos?

Es un buen extra, pero no dependas solo de ellos. Los backups del proveedor pueden fallar, ser difíciles de restaurar, o no estar disponibles si cierran.

¿Cómo restauro si perdí acceso total al VPS?

Si tienes backup offsite (cloud), creas un VPS nuevo, descargas los backups y restauras. Por eso el backup offsite es crítico.

Nuestra recomendación

Mínimo viable:

  • Backup diario automatizado
  • Retención de 7 días
  • Copia en cloud (S3, Backblaze)
  • Probar restauración mensualmente

Para producción:

  • Backup incremental cada 6 horas
  • Retención: 7 días + 4 semanas + 12 meses
  • Múltiples destinos (local + cloud)
  • Alertas si backup falla
  • Pruebas de restauración trimestrales

¿Prefieres no gestionar backups? La administración gestionada de Avantys incluye backups automáticos, verificados y restaurables.


Conclusión

Los backups son tu seguro contra desastres. No esperes a perder datos para implementarlos. Con los scripts de esta guía, puedes tener backup automatizado funcionando en menos de una hora.

Recuerda: un backup no probado no es un backup. Verifica regularmente que puedes restaurar.

¿Necesitas un VPS con backups incluidos? Explora los VPS de Avantys con sistema de backup automatizado.


¿Quieres que lo hagamos por ti?

En Avantys gestionamos tu web, hosting y crecimiento digital de punta a punta. Tú a lo importante.

Hablar con Avantys
// Boletín

Suscríbete al boletín

Guías nuevas, sin spam. Cancela cuando quieras.