Проект

Общее

Профиль

Действия

💾 Вариант 1: Локальные бэкапы с ротацией (базовый)

Автоматизированное резервное копирование данных Vaultwarden с хранением архивов и очисткой устаревших файлов.

📋 Что делает скрипт:
  • Останавливает контейнер для консистентности БД
  • Создаёт сжатый архив с данными
  • Запускает контейнер обратно
  • Удаляет бэкапы старше заданного периода
  • Ведёт логирование всех операций

1️⃣ Создайте скрипт бэкапа

sudo nano /usr/local/bin/vaultwarden-backup.sh

Вставьте содержимое:

#!/bin/bash
# Vaultwarden Backup Script
# Резервное копирование данных Vaultwarden

set -e # Выход при ошибке

=== НАСТРОЙКИ ===

SOURCE_DIR="/root/vaultwarden/data" # Источник данных
BACKUP_DIR="/root/vaultwarden/backups" # Куда сохранять бэкапы
RETENTION_DAYS=30 # Сколько дней хранить бэкапы
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="vaultwarden_backup_${TIMESTAMP}.tar.gz"
LOG_FILE="/var/log/vaultwarden-backup.log"

Создаем папку для бэкапов если нет

mkdir -p "$BACKUP_DIR"

Логирование

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

log "=== Начало бэкапа ==="

Останавливаем контейнер для консистентности БД (опционально, но рекомендуется)

log "Остановка контейнера vaultwarden..."
docker stop vaultwarden 2>/dev/null || true

Создаем архив

log "Создание архива: $BACKUP_FILE"
tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" -C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")"

Запускаем контейнер обратно

log "Запуск контейнера vaultwarden..."
docker start vaultwarden 2>/dev/null || true

Удаляем старые бэкапы

log "Удаление бэкапов старше $RETENTION_DAYS дней..."
find "$BACKUP_DIR" -name "vaultwarden_backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS -delete -print | tee -a "$LOG_FILE"

Показываем размер и список бэкапов

log "Размер нового бэкапа: $(du -h "${BACKUP_DIR}/${BACKUP_FILE}" | cut -f1)"
log "Бэкапы в хранилище:"
ls -lh "$BACKUP_DIR"/*.tar.gz 2>/dev/null | tee -a "$LOG_FILE"

log "=== Бэкап завершен успешно ==="

2️⃣ Сделайте скрипт исполняемым

sudo chmod +x /usr/local/bin/vaultwarden-backup.sh

3️⃣ Протестируйте вручную

sudo /usr/local/bin/vaultwarden-backup.sh

Проверьте, что файл появился:

ls -lh /root/vaultwarden/backups/
✅ Ожидаемый результат:
total 1.2M
-rw-r--r-- 1 root root 1.2M Jun 22 03:00 vaultwarden_backup_20260622_030001.tar.gz

4️⃣ Настройте автоматизацию через Cron

Откройте crontab root-пользователя:

sudo crontab -e

Добавьте строку для ежедневного бэкапа в 3:00 ночи:

0 3 * * * /usr/local/bin/vaultwarden-backup.sh
💡 Примеры других расписаний:
  • 0 2 * * 0 — каждое воскресенье в 2:00
  • 0 */6 * * * — каждые 6 часов
  • 30 4 1 * * — 1-го числа каждого месяца в 4:30

❓ Почему с остановкой контейнера?

⚠️ Важно: Vaultwarden использует SQLite. Хотя он устойчив к бэкапам "на лету", остановка контейнера гарантирует 100% консистентность базы данных и исключает риск повреждения архива при одновременной записи.

🔧 Полезные команды для управления бэкапами

# Просмотр логов бэкапа
tail -f /var/log/vaultwarden-backup.log

Ручной запуск бэкапа с выводом в реальном времени

sudo /usr/local/bin/vaultwarden-backup.sh

Проверка статуса cron-задачи

sudo systemctl status cron

Тестовый прогон cron (сухой запуск)

sudo run-parts --test /etc/cron.daily

Восстановление из бэкапа (пример)

tar -xzf /root/vaultwarden/backups/vaultwarden_backup_20260622_030001.tar.gz -C /root/vaultwarden/

🗂️ Структура после настройки

/root/vaultwarden/
├── data/                    # Рабочие данные Vaultwarden
├── backups/                 # Папка для архивов
│   ├── vaultwarden_backup_20260620_030001.tar.gz
│   ├── vaultwarden_backup_20260621_030001.tar.gz
│   └── vaultwarden_backup_20260622_030001.tar.gz  ← последний
├── docker-compose.yml
└── ...

/var/log/
└── vaultwarden-backup.log # Лог-файл скрипта

🔄 Альтернатива: бэкап без остановки контейнера

Если простой сервиса недопустим, можно использовать docker exec для копирования "на лету":

# Заменить секцию остановки/запуска контейнера на:
log "Копирование данных без остановки..."
docker exec vaultwarden tar -czf - /data > "${BACKUP_DIR}/${BACKUP_FILE}"

⚠️ Используйте этот метод только если понимаете риски: при активной записи в БД архив может быть неполным.

<style> .backup-guide { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.6; color: #2c3e50; max-width: 100%; font-size: 14px; } .backup-guide h2 { color: #1a5276; border-bottom: 3px solid #3498db; padding-bottom: 0.6em; margin: 1.5em 0 1em; font-size: 1.4em; } .backup-guide h3 { color: #2874a6; margin: 1.3em 0 0.7em; background: #ebf5fb; padding: 0.6em 0.9em; border-left: 4px solid #3498db; border-radius: 0 4px 4px 0; font-size: 1.15em; } .backup-guide p { margin: 0.6em 0; } .backup-guide pre { background: #1e1e1e; color: #d4d4d4; padding: 1em; border-radius: 5px; overflow-x: auto; font-size: 0.85em; margin: 0.7em 0; border: 1px solid #3a3a3a; } .backup-guide code { font-family: "Consolas", "Monaco", "Courier New", monospace; color: #ce9178; } .backup-guide pre code { color: #d4d4d4; } .backup-guide pre.bash::before { content: "🐧 Bash"; display: block; background: #4a5568; color: #fff; padding: 0.25em 0.6em; margin: -1em -1em 0.8em -1em; font-size: 0.75em; border-radius: 4px 4px 0 0; font-weight: 600; } .backup-guide pre.cron::before { content: "⏰ Crontab"; display: block; background: #7b68a3; color: #fff; padding: 0.25em 0.6em; margin: -1em -1em 0.8em -1em; font-size: 0.75em; border-radius: 4px 4px 0 0; font-weight: 600; } .backup-guide ul { padding-left: 1.6em; margin: 0.5em 0; } .backup-guide li { margin: 0.35em 0; } .backup-guide .info-box { background: #e8f4fd; border: 1px solid #b6d4fe; border-left: 4px solid #3498db; padding: 1em 1.2em; margin: 1em 0; border-radius: 0 5px 5px 0; } .backup-guide .success-box { background: #e6f7ee; border: 1px solid #b7e4c7; border-left: 4px solid #27ae60; padding: 1em 1.2em; margin: 1em 0; border-radius: 0 5px 5px 0; } .backup-guide .warning-box { background: #fff3cd; border: 1px solid #ffeaa7; border-left: 4px solid #f39c12; padding: 1em 1.2em; margin: 1em 0; border-radius: 0 5px 5px 0; } .backup-guide .tip-box { background: #f0f7ff; border: 1px solid #cfe2ff; border-left: 4px solid #17a2b8; padding: 1em 1.2em; margin: 1em 0; border-radius: 0 5px 5px 0; } .backup-guide .small { font-size: 0.9em; color: #666; font-style: italic; } .backup-guide a { color: #2980b9; text-decoration: none; } .backup-guide a:hover { text-decoration: underline; } @media (max-width: 768px) { .backup-guide { font-size: 13px; } .backup-guide pre { font-size: 0.8em; } } </style>

Обновлено Redmine Admin 5 месяца назад · 1 изменени(я, ий)