Backups · Linux · Operación · Automatización · Recuperación

Guía rápida de backups útiles

Un backup no es útil porque exista. Es útil cuando puedes restaurarlo, sabes qué contiene, está dentro de una política de retención razonable, deja logs claros y no depende de que alguien se acuerde de lanzarlo manualmente.

En muchos entornos el backup se da por hecho hasta que llega la incidencia. Y ahí aparece la realidad: copias incompletas, scripts que fallaban en silencio, rutas que nadie incluyó, bases de datos copiadas en caliente sin consistencia, retenciones absurdas o restauraciones que nadie había probado nunca.

Esta guía va de backups prácticos, no de teoría bonita. El objetivo es tener copias que sirvan de verdad cuando algo falla.

1. La pregunta importante no es si tienes backup

La pregunta real es:

¿Has restaurado alguna vez?

Un backup no probado es una suposición. Y en producción las suposiciones suelen salir caras.

Hay que poder responder:

Qué se copia
Cada cuánto se copia
Dónde se guarda
Cuánto tiempo se retiene
Cómo se valida
Cómo se restaura
Quién puede restaurar
Cuánto tarda la recuperación
Qué datos se pierden entre copia y fallo

2. RPO y RTO sin complicarlo

Dos conceptos básicos:

RPO: cuánto dato puedes permitirte perder.
RTO: cuánto tiempo puedes permitirte estar caído.

Ejemplo:

Si haces backup cada 24 horas, puedes perder hasta 24 horas de datos.
Si restaurar tarda 4 horas, tu RTO real no es de 10 minutos.

Muchas empresas creen que tienen buena protección porque “hay backups”, pero nunca han medido cuánto tardan en restaurar ni cuánto dato perderían realmente.

3. Qué hay que copiar

No basta con copiar una carpeta al azar.

Aplicación
Configuración
Datos persistentes
Base de datos
Certificados
Secrets
Crontabs
Ficheros de sistema relevantes
Scripts operativos
Documentación de despliegue

En un servidor Linux típico revisaría:

/etc
/opt
/var/www
/var/lib
/home
/root
/usr/local/bin
crontab de usuarios
systemd custom units
certificados
ficheros .env

Pero no todo se copia igual. Una base de datos no se debe tratar igual que una carpeta estática.

4. Inventario previo

Antes de crear un backup conviene inventariar.

df -h
lsblk
mount
findmnt
systemctl list-units --type=service --state=running
ss -lntp
crontab -l
ls -lah /etc/systemd/system

También conviene localizar datos grandes:

du -sh /* 2>/dev/null
du -sh /var/* 2>/dev/null
du -sh /opt/* 2>/dev/null
du -sh /home/* 2>/dev/null

El inventario evita dejar fuera justo lo importante.

5. Backup sencillo con tar

Para copias simples de configuración o directorios estáticos:

sudo tar -czf /backup/etc-$(date +%F).tar.gz /etc
sudo tar -czf /backup/www-$(date +%F).tar.gz /var/www

Mejor con rutas y logs controlados:

BACKUP_DIR="/backup"
DATE="$(date +%F_%H-%M-%S)"

sudo mkdir -p "$BACKUP_DIR"

sudo tar -czf "$BACKUP_DIR/etc-$DATE.tar.gz" /etc
sudo tar -czf "$BACKUP_DIR/www-$DATE.tar.gz" /var/www

6. Verificación mínima

Crear el fichero no basta. Hay que verificar que existe y que tar puede leerlo.

ls -lh /backup
tar -tzf /backup/etc-2026-05-22.tar.gz >/dev/null
echo $?

También puedes listar contenido:

tar -tzf /backup/etc-2026-05-22.tar.gz | head

Si el backup falla y el script no se entera, no tienes backup. Tienes una falsa sensación de seguridad.

7. Bases de datos

Copiar directamente ficheros de una base de datos en caliente puede dejar una copia inconsistente.

Para MariaDB/MySQL:

mysqldump --single-transaction --routines --triggers --events \
  -u backup_user -p nombre_bd > /backup/nombre_bd-$(date +%F).sql

Comprimir:

gzip /backup/nombre_bd-$(date +%F).sql

Para PostgreSQL:

pg_dump -Fc nombre_bd > /backup/nombre_bd-$(date +%F).dump

Validación básica:

ls -lh /backup
gzip -t /backup/nombre_bd-2026-05-22.sql.gz
pg_restore -l /backup/nombre_bd-2026-05-22.dump >/dev/null

8. Restauración de prueba

La restauración debe probarse en un entorno seguro, nunca directamente sobre producción sin plan.

Ejemplo para tar:

mkdir /tmp/test-restore
tar -xzf /backup/etc-2026-05-22.tar.gz -C /tmp/test-restore
ls -lah /tmp/test-restore

Ejemplo MySQL/MariaDB:

gunzip -c /backup/nombre_bd-2026-05-22.sql.gz | mysql -u root -p nombre_bd_test

Ejemplo PostgreSQL:

createdb nombre_bd_test
pg_restore -d nombre_bd_test /backup/nombre_bd-2026-05-22.dump

Un backup que no sabes restaurar bajo presión no te salva. Solo te entretiene.

9. Retención

Guardar todo para siempre no suele ser viable. No guardar suficiente tampoco.

Una política típica:

Diarios: 7 días
Semanales: 4 semanas
Mensuales: 6-12 meses

Ejemplo simple de limpieza:

find /backup -type f -name "*.tar.gz" -mtime +30 -print
find /backup -type f -name "*.tar.gz" -mtime +30 -delete

Antes de borrar de verdad, siempre simulación:

find /backup -type f -name "*.tar.gz" -mtime +30 -print

10. Logs del backup

Todo backup automático debe dejar log.

/var/log/backup/backup.log

Ejemplo:

echo "[$(date '+%F %T')] Inicio backup" >> /var/log/backup/backup.log
echo "[$(date '+%F %T')] Backup OK" >> /var/log/backup/backup.log
echo "[$(date '+%F %T')] ERROR: fallo mysqldump" >> /var/log/backup/backup.log

Los logs deben permitir saber:

cuándo empezó
cuándo terminó
qué copió
cuánto ocupó
si falló
dónde falló
si verificó

11. Script base seguro

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/backup"
LOG_DIR="/var/log/backup"
DATE="$(date +%F_%H-%M-%S)"
RETENTION_DAYS=30

mkdir -p "$BACKUP_DIR" "$LOG_DIR"

LOG_FILE="$LOG_DIR/backup-$DATE.log"

log() {
    echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"
}

fail() {
    log "ERROR: $*"
    exit 1
}

log "Inicio backup"

tar -czf "$BACKUP_DIR/etc-$DATE.tar.gz" /etc || fail "Fallo backup /etc"
tar -tzf "$BACKUP_DIR/etc-$DATE.tar.gz" >/dev/null || fail "Verificación fallida /etc"

tar -czf "$BACKUP_DIR/www-$DATE.tar.gz" /var/www || fail "Fallo backup /var/www"
tar -tzf "$BACKUP_DIR/www-$DATE.tar.gz" >/dev/null || fail "Verificación fallida /var/www"

log "Limpieza de backups antiguos"
find "$BACKUP_DIR" -type f -mtime +"$RETENTION_DAYS" -print -delete >> "$LOG_FILE" 2>&1

log "Backup finalizado correctamente"

12. Automatización con cron

sudo crontab -e
30 2 * * * /usr/local/sbin/backup-server.sh

Pero cron por sí solo no basta. Hay que revisar logs y alertar si falla.

13. Automatización con systemd timer

Para entornos más controlados prefiero systemd timer.

sudo tee /etc/systemd/system/backup-server.service > /dev/null <<'SERVICE'
[Unit]
Description=Backup servidor

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup-server.sh
SERVICE
sudo tee /etc/systemd/system/backup-server.timer > /dev/null <<'TIMER'
[Unit]
Description=Ejecuta backup diario

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target
TIMER
sudo systemctl daemon-reload
sudo systemctl enable --now backup-server.timer
systemctl list-timers | grep backup
journalctl -u backup-server.service -n 100 --no-pager

14. Copias fuera del servidor

Un backup en el mismo servidor protege poco.

Si el servidor se rompe, se cifra, se borra o pierde disco, puedes perder original y copia.

Como mínimo:

Servidor origen
↓
Backup local temporal
↓
Copia remota
↓
Validación

Con rsync:

rsync -avz --delete /backup/ backupuser@backup-host:/data/backups/servidor1/

Con scp:

scp /backup/etc-2026-05-22.tar.gz backupuser@backup-host:/data/backups/servidor1/

15. Regla 3-2-1

3 copias de los datos
2 soportes diferentes
1 copia fuera del sitio principal

No siempre se puede aplicar perfecto en entornos pequeños, pero la idea es buena: no depender de una única copia, ni de una única máquina, ni de una única ubicación.

16. Seguridad del backup

Los backups contienen información sensible.

bases de datos
contraseñas
tokens
certificados
datos personales
configuración interna

Hay que protegerlos:

permisos restrictivos
cifrado
usuarios dedicados
acceso mínimo
rotación de claves
registro de accesos

Ejemplo permisos:

sudo chown -R root:root /backup
sudo chmod 700 /backup

17. Cifrado

Ejemplo con gpg:

gpg -c /backup/etc-2026-05-22.tar.gz
rm -f /backup/etc-2026-05-22.tar.gz

Ejemplo con openssl:

openssl enc -aes-256-cbc -salt \
  -in /backup/etc-2026-05-22.tar.gz \
  -out /backup/etc-2026-05-22.tar.gz.enc

Importante: si pierdes la clave, pierdes el backup. El cifrado sin gestión de claves también puede romper una recuperación.

18. Monitorización

Un backup debe generar alerta si falla.

Comprobaciones:

¿Se ejecutó en las últimas 24h?
¿El último log contiene Backup OK?
¿El tamaño del backup es razonable?
¿La copia remota existe?
¿La verificación pasó?

Ejemplo:

find /backup -type f -mtime -1 | wc -l
grep "Backup finalizado correctamente" /var/log/backup/backup-*.log | tail

19. Errores habituales

No probar restauración
Copiar base de datos en caliente sin dump
Guardar backup en el mismo disco
No revisar logs
No tener retención
No cifrar backups sensibles
No incluir configuración
No copiar certificados
No documentar recuperación
No monitorizar fallos
No saber cuánto tarda restaurar

20. Checklist de backup útil

Inventario realizado
Datos críticos identificados
Configuración incluida
Base de datos copiada correctamente
Backup verificado
Restauración probada
Retención definida
Logs generados
Alertas configuradas
Copia remota activa
Permisos revisados
Cifrado aplicado si procede
Procedimiento documentado

21. Tratamiento real de un backup de servidor web

Para una web estática o aplicación pequeña en VPS, copiaría como mínimo:

/var/www
/etc/apache2 o /etc/nginx
/etc/letsencrypt
crontabs
scripts propios
robots.txt
sitemap.xml

Ejemplo:

sudo tar -czf /backup/web-$(date +%F).tar.gz \
  /var/www \
  /etc/apache2 \
  /etc/letsencrypt \
  /usr/local/bin

Verificación:

sudo tar -tzf /backup/web-$(date +%F).tar.gz >/dev/null

Restauración de prueba:

mkdir /tmp/restore-web
sudo tar -xzf /backup/web-2026-05-22.tar.gz -C /tmp/restore-web
ls -lah /tmp/restore-web

22. Conclusión

Un backup útil no es el que se crea. Es el que se puede restaurar.

La diferencia está en los detalles: verificación, retención, logs, automatización, copia remota, seguridad y pruebas reales de recuperación.

En producción, un backup no probado es una promesa. Y cuando algo se rompe, las promesas no restauran servicios.

Volver a guías