Backup y Restauración
groales edited this page 2025-12-03 12:41:49 +01:00

Backup y Restauración

⚠️ CRÍTICO: Vaultwarden almacena todas tus contraseñas. Sin backup, puedes perderlo todo. Esta es la página más importante de la wiki.

🔴 Por Qué son Críticos los Backups

Un gestor de contraseñas sin backup es una bomba de tiempo:

  • 💥 Fallo de hardware: Disco duro que muere
  • 🔥 Corrupción de datos: Error del sistema de archivos
  • 🚫 Actualización fallida: Docker o Vaultwarden se rompe
  • 🏢 Migración de servidor: Necesitas moverte a otro host
  • 👤 Error humano: docker compose down -v por accidente

Un solo comando sin backup puede borrar años de contraseñas.

📦 Qué Respaldar

Vaultwarden almacena todo en el volumen Docker vaultwarden_data:

vaultwarden_data/
├── db.sqlite3              # Base de datos (contraseñas, usuarios)
├── db.sqlite3-wal          # Write-Ahead Log (transacciones)
├── db.sqlite3-shm          # Shared memory
├── attachments/            # Archivos adjuntos
├── sends/                  # Sends temporales
├── config.json             # Configuración del servidor
├── rsa_key.pem             # Clave privada RSA
├── rsa_key.pub.pem         # Clave pública RSA
└── vaultwarden.log         # Logs (opcional)

Archivos críticos:

  • db.sqlite3* - Base de datos completa
  • rsa_key*.pem - Claves de cifrado
  • config.json - Configuración
  • attachments/ - Adjuntos de los usuarios

Opcionales:

  • vaultwarden.log - Solo para debugging
  • sends/ - Normalmente vacío (envíos temporales)

🛠️ Métodos de Backup

Método 1: Backup Manual Completo (Recomendado)

Copia todo el volumen Docker.

#!/bin/bash
# Script: backup-vaultwarden.sh

# Configuración
BACKUP_DIR="$HOME/backups/vaultwarden"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="vaultwarden-backup-${TIMESTAMP}.tar.gz"

# Crear directorio si no existe
mkdir -p "$BACKUP_DIR"

# Detener el contenedor (para consistencia)
docker compose -f /ruta/a/vaultwarden/docker-compose.yml stop vaultwarden

# Crear backup del volumen
docker run --rm \
  -v vaultwarden_data:/data \
  -v "$BACKUP_DIR":/backup \
  alpine \
  tar czf "/backup/$BACKUP_FILE" -C /data .

# Reiniciar el contenedor
docker compose -f /ruta/a/vaultwarden/docker-compose.yml start vaultwarden

# Verificar backup
if [ -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
  echo "✅ Backup creado: $BACKUP_FILE"
  ls -lh "$BACKUP_DIR/$BACKUP_FILE"
else
  echo "❌ ERROR: Backup falló"
  exit 1
fi

# Limpieza: Mantener solo últimos 30 backups
cd "$BACKUP_DIR"
ls -t vaultwarden-backup-*.tar.gz | tail -n +31 | xargs -r rm

echo "✅ Backup completado correctamente"

Método 2: Backup sin Detener el Servicio

Si tu instancia es 24/7 crítica:

#!/bin/bash
# Backup en caliente con SQLite checkpoint

BACKUP_DIR="$HOME/backups/vaultwarden"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="vaultwarden-backup-${TIMESTAMP}.tar.gz"

mkdir -p "$BACKUP_DIR"

# Forzar checkpoint de SQLite (fusiona WAL)
docker compose exec vaultwarden sqlite3 /data/db.sqlite3 "PRAGMA wal_checkpoint(TRUNCATE);"

# Backup sin detener
docker run --rm \
  -v vaultwarden_data:/data:ro \
  -v "$BACKUP_DIR":/backup \
  alpine \
  tar czf "/backup/$BACKUP_FILE" -C /data .

echo "✅ Backup en caliente completado: $BACKUP_FILE"

⚠️ Advertencia: Los backups en caliente pueden capturar estados inconsistentes. Para máxima seguridad, usa el Método 1.

Método 3: Backup Automatizado con Cron

Automatiza backups diarios a las 3 AM:

# Editar crontab
crontab -e

# Añadir esta línea
0 3 * * * /home/usuario/scripts/backup-vaultwarden.sh >> /var/log/vaultwarden-backup.log 2>&1

Verifica que funciona:

# Ver logs del cron
tail -f /var/log/vaultwarden-backup.log

# Probar el script manualmente
bash /home/usuario/scripts/backup-vaultwarden.sh

Método 4: Docker Volume Backup (Contenedor Dedicado)

Usa un contenedor especializado para backups automáticos:

services:
  # ... tu servicio vaultwarden ...

  backup:
    image: offen/docker-volume-backup:latest
    restart: unless-stopped
    environment:
      BACKUP_CRON_EXPRESSION: "0 3 * * *"  # Diario a las 3 AM
      BACKUP_FILENAME: "vaultwarden-backup-%Y%m%d-%H%M%S.tar.gz"
      BACKUP_RETENTION_DAYS: 30
      BACKUP_PRUNING_PREFIX: "vaultwarden-backup-"
    volumes:
      - vaultwarden_data:/backup/vaultwarden_data:ro
      - /ruta/backups:/archive

Ventajas:

  • Completamente automático
  • Rotación de backups integrada
  • Notificaciones opcionales (webhook, email)

💾 Dónde Almacenar Backups

⚠️ NO Almacenar SOLO en el Mismo Servidor

Si el servidor muere, pierdes datos Y backups.

Estrategia 3-2-1

  • 3 copias de tus datos
  • 2 medios diferentes
  • 1 copia offsite (fuera del servidor)

Opciones de Almacenamiento

1. NAS Local

# Montar NAS
mount -t nfs nas.local:/backups /mnt/nas

# Modificar script de backup
BACKUP_DIR="/mnt/nas/vaultwarden"

2. Cloud Storage (S3, B2, etc.)

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

# Configurar remote
rclone config

# Sincronizar backups
rclone sync $HOME/backups/vaultwarden remote:vaultwarden-backups

3. Servidor Remoto (SCP/Rsync)

# Después del backup, envía a servidor remoto
scp "$BACKUP_DIR/$BACKUP_FILE" usuario@servidor-backup:/backups/vaultwarden/

# O con rsync
rsync -avz "$BACKUP_DIR/" usuario@servidor-backup:/backups/vaultwarden/

4. Duplicati (GUI)

Duplicati ofrece backups cifrados y automáticos:

services:
  duplicati:
    image: duplicati/duplicati
    ports:
      - "8200:8200"
    environment:
      TZ: Europe/Madrid
    volumes:
      - vaultwarden_data:/source/vaultwarden:ro
      - duplicati_config:/data

Configura desde http://servidor:8200

🔄 Restauración

Restauración Completa

Recupera todo el volumen desde un backup:

#!/bin/bash
# Script: restore-vaultwarden.sh

BACKUP_FILE="/ruta/al/backup/vaultwarden-backup-20240101_030000.tar.gz"

# Verificar que el backup existe
if [ ! -f "$BACKUP_FILE" ]; then
  echo "❌ ERROR: Backup no encontrado: $BACKUP_FILE"
  exit 1
fi

# Detener Vaultwarden
docker compose stop vaultwarden

# ADVERTENCIA: Esto borra los datos actuales
read -p "⚠️ Esto BORRARÁ los datos actuales. ¿Continuar? (yes/no): " -r
if [[ ! $REPLY =~ ^yes$ ]]; then
  echo "❌ Restauración cancelada"
  exit 1
fi

# Restaurar backup
docker run --rm \
  -v vaultwarden_data:/data \
  -v "$(dirname $BACKUP_FILE)":/backup \
  alpine \
  sh -c "cd /data && rm -rf * && tar xzf /backup/$(basename $BACKUP_FILE)"

# Reiniciar Vaultwarden
docker compose start vaultwarden

echo "✅ Restauración completada"
echo "Verifica que puedes acceder: https://vaultwarden.tudominio.com"

Restauración desde Cero

Si estás migrando a un servidor nuevo:

# 1. Instalar Docker y Docker Compose

# 2. Clonar repositorio
git clone https://git.ictiberia.com/groales/vaultwarden.git
cd vaultwarden

# 3. Configurar override y .env
cp docker-compose.override.traefik.yml.example docker-compose.override.yml
nano .env  # Configurar variables

# 4. Crear volumen vacío
docker volume create vaultwarden_data

# 5. Restaurar datos desde backup
docker run --rm \
  -v vaultwarden_data:/data \
  -v /ruta/al/backup:/backup \
  alpine \
  tar xzf /backup/vaultwarden-backup-YYYYMMDD.tar.gz -C /data

# 6. Iniciar Vaultwarden
docker compose up -d

# 7. Verificar
docker compose logs -f vaultwarden

Restauración Selectiva (Solo DB)

Si solo necesitas la base de datos:

# Extraer solo db.sqlite3 del backup
tar xzf vaultwarden-backup-20240101.tar.gz db.sqlite3

# Copiar al volumen
docker cp db.sqlite3 vaultwarden:/data/db.sqlite3

# Reiniciar
docker compose restart vaultwarden

Verificar Backups

Probar Restauración

Una vez al mes, prueba restaurar un backup en un entorno de testing:

# Crear volumen temporal
docker volume create vaultwarden_test

# Restaurar backup en volumen test
docker run --rm \
  -v vaultwarden_test:/data \
  -v /ruta/backups:/backup \
  alpine \
  tar xzf /backup/vaultwarden-backup-YYYYMMDD.tar.gz -C /data

# Levantar Vaultwarden test
docker run -d --name vaultwarden-test \
  -v vaultwarden_test:/data \
  -p 8081:80 \
  vaultwarden/server:latest

# Probar acceso
curl http://localhost:8081

# Limpiar
docker stop vaultwarden-test
docker rm vaultwarden-test
docker volume rm vaultwarden_test

Verificar Integridad de SQLite

# Verificar que la DB no está corrupta
docker run --rm \
  -v vaultwarden_data:/data:ro \
  nouchka/sqlite3 \
  sqlite3 /data/db.sqlite3 "PRAGMA integrity_check;"

Debería devolver: ok

Listar Backups Disponibles

# Ver backups y sus tamaños
ls -lh $HOME/backups/vaultwarden/

# Ver el más reciente
ls -lt $HOME/backups/vaultwarden/ | head -n 2

# Verificar que no están vacíos
find $HOME/backups/vaultwarden/ -type f -size 0

📊 Monitorización de Backups

Script de Verificación Diaria

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

BACKUP_DIR="$HOME/backups/vaultwarden"
MAX_AGE_HOURS=30  # Alerta si el último backup tiene más de 30 horas

LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/vaultwarden-backup-*.tar.gz | head -n 1)

if [ -z "$LATEST_BACKUP" ]; then
  echo "❌ ERROR: No se encontraron backups"
  exit 1
fi

# Verificar edad
BACKUP_AGE=$(( ($(date +%s) - $(stat -c %Y "$LATEST_BACKUP")) / 3600 ))

if [ $BACKUP_AGE -gt $MAX_AGE_HOURS ]; then
  echo "⚠️ ADVERTENCIA: Último backup tiene ${BACKUP_AGE} horas"
  echo "Backup: $LATEST_BACKUP"
  exit 1
else
  echo "✅ Backup reciente: ${BACKUP_AGE} horas"
  echo "Backup: $LATEST_BACKUP"
fi

Notificaciones (Opcional)

Envía alertas si los backups fallan:

# Al final del script de backup
if [ $? -eq 0 ]; then
  curl -X POST https://hooks.slack.com/services/TU_WEBHOOK \
    -d '{"text":"✅ Backup de Vaultwarden completado"}'
else
  curl -X POST https://hooks.slack.com/services/TU_WEBHOOK \
    -d '{"text":"❌ ERROR en backup de Vaultwarden"}'
fi

🔐 Cifrar Backups

Los backups contienen todas las contraseñas. Cífralos para almacenamiento externo:

Con GPG

# Backup y cifrado
tar czf - -C /var/lib/docker/volumes/vaultwarden_data/_data . | \
  gpg --symmetric --cipher-algo AES256 > vaultwarden-backup.tar.gz.gpg

# Descifrado
gpg --decrypt vaultwarden-backup.tar.gz.gpg | tar xzf -

Con OpenSSL

# Cifrar
openssl enc -aes-256-cbc -salt \
  -in vaultwarden-backup.tar.gz \
  -out vaultwarden-backup.tar.gz.enc

# Descifrar
openssl enc -aes-256-cbc -d \
  -in vaultwarden-backup.tar.gz.enc \
  -out vaultwarden-backup.tar.gz

📖 Checklist de Backup

  • Backups automáticos configurados (diarios mínimo)
  • Backups almacenados en al menos 2 ubicaciones
  • Al menos 1 backup offsite (fuera del servidor)
  • Backups cifrados si se almacenan en cloud
  • Script de restauración probado al menos una vez
  • Monitorización de backups (verificar que se ejecutan)
  • Rotación de backups (no llenar el disco)
  • Documentación de cómo restaurar

🆘 Escenarios de Desastre

Servidor Completamente Muerto

  1. Montar nuevo servidor
  2. Instalar Docker
  3. Clonar repo de Vaultwarden
  4. Configurar variables de entorno
  5. Restaurar backup en volumen nuevo
  6. Iniciar stack
  7. Actualizar DNS si cambió la IP

Base de Datos Corrupta

  1. Detener Vaultwarden
  2. Renombrar db corrupta: mv db.sqlite3 db.sqlite3.corrupted
  3. Restaurar desde backup más reciente
  4. Verificar integridad: sqlite3 db.sqlite3 "PRAGMA integrity_check;"
  5. Reiniciar Vaultwarden

Volumen Docker Borrado Accidentalmente

# Recrear volumen
docker volume create vaultwarden_data

# Restaurar inmediatamente desde backup
bash restore-vaultwarden.sh

Última actualización: Diciembre 2025

⚠️ RECUERDA: Un backup de 6 meses vale más que 10 veces lo que cuesta hacerlo. Automatiza ahora.