Перейти к содержанию

Test Restore Vaultwarden — runbook (VAULT-02)

Цель: проверить что GPG-архив Vaultwarden действительно можно расшифровать и развернуть в рабочий инстанс. Скрипт бэкапа может работать, а restore — нет. Раз в квартал прогоняем и убеждаемся.

Что тестируем: 1. GPG-пароль из бумажного сейфа корректный. 2. Архив распакован без потерь. 3. rsa_key.pem + db.sqlite3 совместимы (не битые). 4. Vaultwarden запускается на восстановленных данных. 5. Логин под нашим master-паролем работает (пароль хранится в голове/сейфе).

Периодичность: раз в 90 дней. Календарное напоминание в LeaderTask или scheduled cron в Perplexity (см. финал).


Требования

  • Ragserver 192.168.1.200, свободных ~500 MB
  • Docker установлен (проверить: docker --version)
  • Не мешаем production Vaultwarden на VPS — работаем на новом порту 8223

Шаг 1 · Взять свежий бэкап

Из off-site (ragserver, VAULT-01):

# На ragserver, от oswold:
cd /home/oswold/backups/vaultwarden
ls -lh *.gpg | tail -3
# Копируем самый свежий:
LATEST=$(ls -t *.gpg | head -1)
echo "Тестируем: $LATEST"

Из VPS (fallback, если ragserver ещё не настроен):

# С VPS скачиваем локально на ragserver:
scp root@46.17.99.183:/opt/vaultwarden/backups/vaultwarden-backup-*.gpg /tmp/vw-restore/


Шаг 2 · Подготовить изолированное окружение

# На ragserver:
sudo mkdir -p /opt/vaultwarden-restore-test
cd /opt/vaultwarden-restore-test
sudo mkdir -p data
sudo chown -R oswold:oswold /opt/vaultwarden-restore-test

Шаг 3 · Расшифровать GPG-архив

GPG-пароль: возьми с бумаги в сейфе (не из Vaultwarden — если восстанавливаем именно Vaultwarden, то он недоступен).

cd /opt/vaultwarden-restore-test
cp /home/oswold/backups/vaultwarden/$LATEST ./
gpg --output vw-restore.tar.gz --decrypt "$LATEST"
# GPG спросит пароль → вводишь тот что на бумаге
# Ожидание: gpg: encrypted with 1 passphrase (или AES256)
ls -lh vw-restore.tar.gz

Если GPG-пароль неверныйКРИТИЧЕСКИ ВАЖНО — задокументируй в TODO как приоритет 1, потому что бэкапы бесполезны.


Шаг 4 · Распаковать

tar -tzf vw-restore.tar.gz | head -20
# Ожидание: список файлов внутри staging-каталога:
#   tmp/vw_staging_2026-08-XX_HHMMSS/db.sqlite3
#   tmp/vw_staging_.../rsa_key.pem
#   tmp/vw_staging_.../attachments/
#   ...

tar -xzf vw-restore.tar.gz -C ./

# Найти staging-папку (имя зависит от даты бэкапа):
STAGING=$(find . -type d -name "vw_staging_*" | head -1)
echo "Staging: $STAGING"
ls -la "$STAGING"

Проверь наличие критичных файлов:

for f in db.sqlite3 rsa_key.pem rsa_key.pub.pem env.backup docker-compose.yml; do
    if [[ -f "$STAGING/$f" ]]; then
        echo "✅ $f$(stat -c %s "$STAGING/$f") байт"
    else
        echo "❌ $f — ОТСУТСТВУЕТ (бэкап битый!)"
    fi
done

Если что-то отсутствует — бэкап-скрипт на VPS требует правки, стоп-задача.


Шаг 5 · Проверить SQLite целостность

sqlite3 "$STAGING/db.sqlite3" "PRAGMA integrity_check;"
# Ожидание: ok

Если получаем ошибку (Error: database disk image is malformed и т.п.) — VACUUM INTO в backup.sh сломан, скидываем в TODO как критичное.

Быстрая проверка что там есть данные:

sqlite3 "$STAGING/db.sqlite3" "SELECT COUNT(*) FROM users;"
sqlite3 "$STAGING/db.sqlite3" "SELECT COUNT(*) FROM ciphers;"
# ожидание: >0 в users, >0 в ciphers (сколько у тебя записей)


Шаг 6 · Развернуть тестовый Vaultwarden

Копируем данные в изолированную data-папку:

cd /opt/vaultwarden-restore-test
mkdir -p data
cp -r "$STAGING"/* data/
# ⚠️ env.backup не должен попасть в data — он ляжет как .env вне data
mv data/env.backup .env
mv data/docker-compose.yml ./docker-compose-restore.yml
ls -la data/
# Ожидание: db.sqlite3, rsa_key.pem, rsa_key.pub.pem, attachments/, sends/, config.json

Правим docker-compose для теста (порт 8223 вместо 8222):

cat > docker-compose.yml <<'YAML'
services:
  vaultwarden-restore:
    image: vaultwarden/server:latest
    container_name: vaultwarden-restore-test
    restart: "no"
    env_file: .env
    volumes:
      - ./data:/data
    ports:
      # ТОЛЬКО localhost, порт 8223 (не 8222 чтоб не конфликтовать)
      - "127.0.0.1:8223:80"
YAML

Правим .env — уберём DOMAIN, SIGNUPS_ALLOWED, чтоб не смущать боевой домен:

# Достаточно чтобы:
grep -E '^(DATABASE_URL|ROCKET|SIGNUPS|DOMAIN|LOG_)' .env
# Если DOMAIN=https://vault.alatyr-service.ru — временно поменяй на http://localhost:8223
sed -i 's|^DOMAIN=.*|DOMAIN=http://localhost:8223|' .env
# И SIGNUPS убеждаемся что false (мы не хотим случайно открыть регистрацию):
grep SIGNUPS_ALLOWED .env

Шаг 7 · Стартуем и проверяем

docker compose up -d
sleep 10
docker compose logs --tail=30

# Ожидание в логах:
#   Rocket has launched from http://0.0.0.0:80
#   Vaultwarden 1.36.x started

Healthcheck из соседнего терминала:

curl -sS http://127.0.0.1:8223/alive
# Ожидание: {"status":"ok"} или пустой 200

Логин через веб (через SSH-туннель):

# С твоего локального компа:
ssh -L 8223:localhost:8223 oswold@192.168.1.200
# В браузере: http://localhost:8223
# Логин: твоим master-паролем от Vaultwarden
# Ожидание: список твоих записей загружается, содержимое читаемо

Если логин работает и записи открываются → ✅ restore прошёл, бэкапы рабочие.


Шаг 8 · Уборка (обязательно!)

cd /opt/vaultwarden-restore-test
docker compose down
sudo rm -rf /opt/vaultwarden-restore-test
# Убедиться что нигде нет незашифрованных данных:
ls /opt/vaultwarden-restore-test 2>/dev/null && echo "ERROR: осталось" || echo "OK: удалено"

Шаг 9 · Записать факт теста

В vaultwarden.md обнови секцию "Тест восстановления":

Последний test restore: DD.MM.YYYY — успешно, master-пароль работает, X записей открыто.

В TODO.md отметь ✅:

- [x] **18** · Test restore Vaultwarden — DD.MM.YYYY ✅

Запланируй следующий на +90 дней:

- [ ] **18-2** · Test restore Vaultwarden (следующий) — YYYY-MM-DD

Или scheduled cron в Perplexity: раз в 90 дней напоминание "Прогони restore-test-vaultwarden.md".


Что если restore ПРОВАЛИЛСЯ

Симптом Диагноз Действия
GPG "Bad passphrase" Пароль на бумаге неверный 🔴 приоритет 1: найти правильный, обновить сейф
integrity_check не ok VACUUM INTO в backup.sh не работает 🔴 п1: править backup.sh, тестировать снова
Vaultwarden не стартует Битый rsa_key.pem 🔴 п1: backup.sh не бэкапит ключи — критично
Логин работает, но пусто БД без данных, attachments/ не сбэкаплен 🟡 п3: backup.sh не берёт attachments/
Логин не работает Master-пароль забыт 🔴 п1: master-пароль пиши на бумагу тоже

Каждый провал → сразу задача в TODO с приоритетом 1.


Автоматизация напоминаний (опционально)

Через pplx-tool schedule_cron — раз в 90 дней:

cron: 0 10 1 */3 *
task: "Напоминание: пришло время test restore Vaultwarden. Запусти restore-test-vaultwarden.md на ragserver."

Первое напоминание — 01.11.2026 в 10:00 MSK.


Автор: агент, 08.08.2026