Резервное копирование и восстановление хранилищ паролей: практическое руководство для KeePass и Vaultwarden | AdminWiki

Резервное копирование и восстановление хранилищ паролей: практическое руководство для KeePass и Vaultwarden

15 сентября 2026 13 мин. чтения
Содержание статьи

Резервная копия хранилища паролей состоит из трёх обязательных шагов: скопировать все компоненты, а не только базу, зашифровать копию и вынести её на носитель, который не погибнет вместе с основным сервером. Для KeePass это файл KDBX и key-файл, для Vaultwarden: база db.sqlite3 или дамп PostgreSQL, каталог attachments, rsa_key.pem, файл .env и данные Send. Потеря любого элемента делает остальные бесполезными.

Ниже приведены рабочие команды для cron и rsync, схемы шифрования через age и GPG, а также разобраны сценарии восстановления: утрата мастер-пароля, повреждение базы, откат после неудачного обновления. Примеры рассчитаны на Docker-развёртывание Vaultwarden и локальный KeePass и проверены на версиях ПО, актуальных в 2026 году.

КомпонентГде лежитЧто будет при потере
KDBXФайл базы, например /home/user/vault/passwords.kdbxДоступ ко всем записям пропадёт, восстановить их без копии нельзя
Key-файл или аппаратный ключОтдельный носитель, не рядом с KDBXБаза не откроется даже с верным мастер-паролем
db.sqlite3 или дамп PostgreSQL/data/db.sqlite3 внутри контейнера VaultwardenПропадут записи всех пользователей и настройки сервиса
attachments/data/attachmentsФайлы, прикреплённые к записям, исчезнут, ссылки станут битыми
rsa_key.pem/data/rsa_key.pemПользователи не смогут расшифровать сохранённые пароли после восстановления
.envКаталог docker composeПотеряются ADMIN_TOKEN, параметры SMTP и строка подключения к базе
SendТаблица в базеОдноразовые ссылки перестанут работать

Что именно нужно защищать в хранилищах паролей

Хранилище паролей - это набор связанных компонентов, а не один файл. Бэкап только базы упирается в отсутствие ключей, вложений или конфигурации, и восстановление оказывается неполным. Ниже разобраны обе платформы: локальный KeePass и self-hosted Vaultwarden.

Компоненты KeePass: KDBX и файл ключа

KeePass и KeePassXC держат все записи в одном контейнере KDBX. В схеме «мастер-пароль + key-файл» база не открывается без обоих факторов: файл ключа выступает вторым секретом, и без него вывод ключа шифрования не даст прочитать содержимое. Аппаратный ключ YubiKey в режиме challenge-response работает так же: без физического носителя доступ не восстановить.

Отсюда практическое правило: key-файл хранится отдельно от KDBX, на другом носителе. Если оба файла лежат в одном каталоге и попадают в один архив, второй фактор перестаёт защищать что-либо.

Структура каталогов, к которой стоит стремиться:

/home/user/vault/passwords.kdbx
/media/usb-key/passwords.key
/srv/backup/keepass/2026-09-15/passwords.kdbx.age

База на рабочей машине, ключ на съёмном носителе, шифрованная копия на сервере бэкапов. Ни один из трёх элементов не лежит в одном каталоге с другим.

Компоненты Vaultwarden: база, вложения, ключи

Vaultwarden хранит записи в SQLite (файл /data/db.sqlite3) либо в PostgreSQL. Кроме самой базы в бэкап входят:

  • каталог attachments с файлами, прикреплёнными к записям;
  • файл rsa_key.pem, который отвечает за шифрование симметричных ключей пользователей;
  • .env с ADMIN_TOKEN, параметрами SMTP, SIGNUPS_ALLOWED и строкой подключения к базе;
  • данные Send, если сервис используется для одноразовых ссылок.

Без rsa_key.pem после восстановления пользователи не смогут расшифровать сохранённые пароли, даже если вход в аккаунт сработает: приватный ключ сервера участвует в выдаче ключа хранилища. При PostgreSQL нужен pg_dump, а не копирование каталога данных: горячая копия PGDATA даёт несогласованный кластер, который не поднимется.

Облачные сервисы (Bitwarden, 1Password, LastPass) хранят данные у провайдера, и бэкап там устроен иначе: локальная копия делается экспортом. Об этом отдельный раздел ниже.

Стратегия резервного копирования: 3-2-1 и частота

Принцип 3-2-1 задаёт минимум: три копии данных, два разных носителя, одна копия вне основной площадки. Для хранилища паролей формула работает без поправок. Копия на том же диске или на том же VPS не спасёт ни при отказе оборудования, ни при компрометации сервера, ни при шифровании данных вымогателем, который получил доступ к хосту.

Практическая схема выглядит так: ежедневный инкрементальный бэкап на локальный диск бэкапов, еженедельная полная копия вовне, раз в квартал свежая офлайн-копия на носителе, который физически лежит вне серверной. Для immutable-хранилищ и снапшотов ZFS логика та же, только защита от перезаписи обеспечивается на уровне файловой системы: стратегии rsync, restic и TrueNAS разобраны отдельно.

Как часто делать бэкап KeePass и Vaultwarden

KeePass меняется по факту правок: файл может неделю лежать нетронутым, а потом обновиться пять раз за один день. Разумный вариант: реакция на изменение через inotifywait плюс суточная копия в 03:00 как страховка от пропущенного события.

Vaultwarden пишет данные постоянно, поэтому частоту задаёт RPO команды. Для группы из 5-20 человек ежедневного бэкапа хватает, допустимая потеря при этом - сутки. Для 50 и более активных пользователей интервал сокращают до 6-12 часов: цена потери свежих записей выше, чем нагрузка от копирования базы в несколько сотен мегабайт.

Каталог attachments растёт быстро и меняется редко, поэтому его копируют отдельным заданием. Так база бэкапится часто и быстро, а вложения - раз в сутки или раз в неделю, в зависимости от объёма.

Где хранить копии: офлайн и холодное хранилище

  • Внешний USB-диск или SSD, который подключают только на время копирования и держат вне сервера.
  • NAS в другой сети, доступный по SSH или SMB, с отдельной учётной записью только на запись.
  • Холодное облако: Backblaze B2, S3 Glacier, отдельный бакет с версионированием и object lock.
  • Второй провайдер: если Vaultwarden живёт на VPS, вторую копию логично положить в инфраструктуру другой компании, например Timeweb Cloud, чтобы сбой одного поставщика не унёс оба экземпляра.
  • Офлайн-копия на носителе в сейфе или у второго администратора, обновляется раз в квартал.

Ключ шифрования не хранится рядом с зашифрованной копией. Парольную фразу от архива держат в другом хранилище, у второго администратора или в физическом сейфе: иначе один украденный носитель даёт доступ и к копии, и к ключу.

Автоматизация бэкапа через cron и rsync

Ручной бэкап живёт до первой загруженной недели. Дальше приведены скрипты, которые ставятся в cron и работают без участия администратора, с логированием и ротацией старых копий. Общая логика автоматизации серверных бэкапов с проверкой кодов возврата разобрана в материале о резервном копировании сервера.

Бэкап KeePass KDBX через rsync и cron

Скрипт копирует файл с сохранением прав и метаданных, складывает копии с датой в имени и удаляет всё старше 30 дней:

#!/bin/bash
set -euo pipefail

SRC=/home/user/vault/passwords.kdbx
DIR=/srv/backup/keepass/daily
DST=$DIR/passwords-$(date +%F).kdbx

rsync -a "$SRC" "$DST"
find "$DIR" -name 'passwords-*.kdbx' -mtime +30 -delete
echo "$(date -Is) keepass backup ok, $(stat -c %s "$DST") bytes"

Запись в crontab:

0 3 * * * /usr/local/bin/backup-keepass.sh >> /var/log/backup-keepass.log 2>&1

KeePassXC держит базу открытой и блокирует запись, поэтому копирование запускают в момент наименьшей активности. Если база открыта, rsync получит согласованный снимок файла, но надёжнее синхронизировать копию с закрытием приложения либо копировать файл сразу после сохранения изменений.

Бэкап Vaultwarden: SQLite и PostgreSQL

Копировать db.sqlite3 через cp во время работы сервиса нельзя: в режиме WAL часть данных лежит в файле -wal, и такой снимок окажется битым. Корректный способ для SQLite - команда .backup или VACUUM INTO:

sqlite3 /srv/vaultwarden/data/db.sqlite3 ".backup '/srv/backup/vaultwarden/db-$(date +%F).sqlite3'"
sqlite3 /srv/vaultwarden/data/db.sqlite3 "VACUUM INTO '/srv/backup/vaultwarden/db-compact.sqlite3'"

Если SQLite живёт внутри контейнера и каталог не смонтирован на хост, команда выполняется через docker exec:

docker exec vaultwarden sh -c 'sqlite3 /data/db.sqlite3 ".backup /data/backups/db.sqlite3"'

Для PostgreSQL используется логический дамп в custom-формате, который затем восстанавливается через pg_restore:

docker exec -t vaultwarden-db pg_dump -U vaultwarden -Fc vaultwarden > /srv/backup/vaultwarden/db-$(date +%F).dump

Расписание для базы и отдельного задания на вложения:

0 */12 * * * /usr/local/bin/backup-vaultwarden-db.sh >> /var/log/vw-backup.log 2>&1
30 3 * * * /usr/local/bin/backup-vaultwarden-files.sh >> /var/log/vw-backup.log 2>&1

Копирование вложений и конфигурации

Вложения и ключи уезжают отдельным rsync:

rsync -a --delete /srv/vaultwarden/data/attachments/ /srv/backup/vaultwarden/attachments/
rsync -a /srv/vaultwarden/data/rsa_key.pem /srv/backup/vaultwarden/
rsync -a /opt/vaultwarden/.env /srv/backup/vaultwarden/

Флаг --delete нужен, чтобы удалённые вложения не оставались в копии навсегда, но включать его стоит только после проверки путей: опечатка в пути назначения означает потерю каталога. Файл .env содержит секреты, поэтому его копия шифруется вместе с базой и не публикуется в открытых каталогах.

Шифрование резервных копий

Копия хранилища паролей концентрирует все секреты организации в одном файле. Флешка с незашифрованным дампом, потерянная курьером, равносильна полной компрометации: пароли к серверам, базам данных и облачным панелям окажутся в чужих руках. Шифрование копии - обязательное условие, а не дополнительная мера.

GPG и age: примеры команд

age -r age1q9x7m2v4k8p3n5t6w0s2z9l8j7h6g5f4d3c2b1a -o db.sqlite3.age db.sqlite3
gpg --encrypt --recipient backup@example.com --output db.sqlite3.gpg db.sqlite3
age -d -i /root/age-key.txt db.sqlite3.age > db.sqlite3
gpg --decrypt db.sqlite3.gpg > db.sqlite3

age удобнее в скриптах: один файл с ключом, простой синтаксис, нет keyring и лишних интерактивных запросов. GPG выбирают, когда в компании уже есть инфраструктура ключей, подписи и требования аудита. Ещё вариант - openssl enc с AES-256, но он требует аккуратной работы с солью и вектором инициализации, поэтому годится как запасной путь, а не основной.

Restic и borg: шифрование из коробки

restic и borg дают шифрование, дедупликацию и снапшоты без отдельного слоя: содержимое репозитория зашифровано всегда, а дедупликация экономит место на ежедневных копиях почти неизменной базы.

restic -r s3:s3.example.com/vaultwarden init
restic -r s3:s3.example.com/vaultwarden backup /srv/vaultwarden --exclude '*.log'
restic -r s3:s3.example.com/vaultwarden snapshots

Пароль репозитория restic нельзя держать рядом с копией и в том же .env, что и ADMIN_TOKEN: он хранится отдельно, у второго администратора или в сейфе. Без пароля репозиторий не открыть, восстановление из него превращается в набор случайных блоков.

Восстановление доступа после потери мастер-пароля

Если мастер-пароль утрачен и нет копии с известным паролем, данные KeePass и Vaultwarden вернуть невозможно. Ключ шифрования выводится из пароля, обходного пути в схеме нет. Реальные сценарии сводятся к восстановлению из копии, где пароль известен, и к перевыпуску доступов.

KeePass: восстановление из копии и смена пароля

  1. Возьмите последнюю копию KDBX, снятую до потери пароля, или предыдущую версию файла из ротации.
  2. Откройте базу известным мастер-паролем. Если использовался key-файл, подключите его с отдельного носителя через раздел свойств базы в KeePassXC или соответствующий диалог в KeePass.
  3. Смените мастер-пароль: Database, Change Master Key в KeePassXC или Файл, Сменить мастер-пароль в KeePass.
  4. Сверьте число записей и наличие ключевых групп со старой копией, сохраните результат как новую базу, а прежние копии оставьте до следующей проверки.

Если пароль помнит только один сотрудник и он недоступен, восстановление опирается на копию и резервный пароль из процедуры передачи смен. Поэтому второй экземпляр пароля от архива хранится у второго администратора.

Vaultwarden: admin token и сброс доступа

ADMIN_TOKEN из .env открывает панель по адресу /admin. Оттуда можно управлять пользователями, приглашать их заново и сбрасывать настройки двухфакторной аутентификации. Панель не расшифровывает хранилища: ключ шифрования выводится из мастер-пароля пользователя и известен только клиенту.

Сброс пароля пользователя через админ-панель не открывает его записи. Это ожидаемое поведение, а не сбой: нужно либо ввести прежний пароль, либо восстановить доступ через экспорт хранилища, либо задействовать организационный сценарий восстановления в клиенте Bitwarden. Если экспорта нет и пароль забыт, записи этого пользователя теряются, а данные остальных участников команды остаются на месте.

Восстановление повреждённой базы Vaultwarden

Симптомы повреждения заметны сразу: контейнер уходит в цикл перезапуска, в логах появляется сообщение «database disk image is malformed», клиенты не могут синхронизироваться. Первый шаг - убедиться, что дело в базе, а не в заполненном диске или правах на файл.

Диагностика повреждения SQLite и PostgreSQL

sqlite3 /srv/vaultwarden/data/db.sqlite3 "PRAGMA integrity_check;"
df -h /srv/vaultwarden/data
docker logs --tail 100 vaultwarden

Ответ ok означает, что структура базы цела, и проблему стоит искать в правах, свободном месте или настройках .env. Любое другое сообщение говорит о повреждении файла. Для PostgreSQL проверяют логи контейнера и пробуют снять дамп: если pg_dump отрабатывает без ошибок, база жива и восстановление не требуется.

Пошаговое восстановление из бэкапа

  1. Остановите сервис: docker compose stop vaultwarden.
  2. Сохраните текущее состояние отдельно, чтобы можно было откатиться: cp -a data/db.sqlite3 data/db.sqlite3.broken.
  3. Верните файлы из копии: rsync -a /srv/backup/vaultwarden/data/ /opt/vaultwarden/data/.
  4. Проверьте наличие rsa_key.pem, .env и каталога attachments на месте.
  5. Запустите сервис: docker compose start vaultwarden, затем посмотрите логи: docker compose logs -f vaultwarden.
  6. Проверьте вход нескольких пользователей, число записей и доступность вложений.

Для PostgreSQL восстанавливают дамп до запуска приложения:

docker exec -i vaultwarden-db pg_restore -U vaultwarden -d vaultwarden --clean < db-2026-09-14.dump

Флаг --clean удаляет объекты перед восстановлением. После операции проверьте, что таблицы пользователей и записей на месте, а приложение стартует без ошибок миграций.

Откат после неудачного обновления Vaultwarden

Обновление образа без предварительного бэкапа превращает обычную правку в аварию: миграции базы применяются автоматически при первом запуске, и вернуться к прежней версии без отката данных уже нельзя.

Фиксация версии образа и подготовка

В docker-compose.yml указывайте точный тег вместо latest: image: vaultwarden/server:1.32.7. Так вы знаете, что именно работает на сервере, и можете вернуться на предыдущую версию одной строкой. Перед каждым обновлением: снять бэкап базы, записать текущий тег и дату в changelog, прочитать release notes на предмет миграций.

docker compose stop vaultwarden
sqlite3 /srv/vaultwarden/data/db.sqlite3 ".backup '/srv/backup/vaultwarden/pre-upgrade-$(date +%F).sqlite3'"

Порядок отката

  1. docker compose down.
  2. Верните в compose предыдущий тег образа.
  3. Восстановите базу из дампа, снятого до обновления: rsync -a /srv/backup/vaultwarden/pre-upgrade.sqlite3 /opt/vaultwarden/data/db.sqlite3.
  4. docker compose pull, затем docker compose up -d.
  5. Проверьте логи и вход в веб-интерфейс, убедитесь, что клиенты синхронизируются.

Если миграции успели изменить схему, откат базы обязателен: старая версия приложения не поймёт новые таблицы. Копия базы, снятая до обновления, здесь единственная страховка.

Бэкап облачных хранилищ через экспорт

Bitwarden, 1Password и LastPass держат данные на своих серверах и делают собственные резервные копии, но это не отменяет локальную страховку. Блокировка аккаунта, ошибка биллинга, сбой провайдера и потеря доступа к почте приходят внезапно, а экспорт остаётся единственным способом быстро вернуть записи.

Форматы экспорта и их ограничения

CSV и JSON удобны для переноса, но оба содержат пароли в открытом виде. Вложения, история изменений пароля и часть типов полей при экспорте теряются, поэтому копия из облака не равна полной копии self-hosted базы. Если планируется перенос между сервисами, порядок действий и типичные ошибки описаны в руководстве о переносе паролей между хранилищами.

Как безопасно хранить экспорт

  1. Сделайте экспорт и сразу зашифруйте файл через age или GPG, как в примерах выше.
  2. Удалите исходный незашифрованный файл с диска: shred -u export.csv.
  3. Положите архив в офлайн-место: внешний носитель или холодное облако.
  4. Ограничьте права: chmod 600 на файл и каталог с копиями.
  5. Заведите напоминание на повторный экспорт раз в квартал.

Чек-лист регулярной проверки восстановления

Непроверенная копия - это набор байтов, а не бэкап. Схема считается рабочей только после того, как из копии реально подняли сервис и вошли в хранилище.

Тестовое восстановление: шаги и частота

  1. Поднимите тестовый контейнер Vaultwarden на другой машине или в изолированном окружении.
  2. Восстановите базу из последней копии и подключите rsa_key.pem, .env и attachments.
  3. Войдите тестовым пользователем, откройте несколько записей, скачайте вложение.
  4. Сверьте число записей с основной базой.
  5. Откройте копию KDBX в KeePass, проверьте количество записей и доступность ключевых групп.
  6. Запишите дату, версию ПО и результат в журнал проверок.

Частота: не реже раза в квартал, а после любого изменения схемы бэкапа сразу. Если изменился путь копирования, тег образа или способ шифрования, прежние результаты проверки уже ничего не подтверждают.

Метрики RPO и RTO для хранилищ паролей

RPO задаёт допустимую потерю данных по времени, RTO - время до возвращения сервиса. Для команды из 10-20 человек типичны RPO 24 часа и RTO 1 час: суточный бэкап плюс заранее отработанный сценарий восстановления укладываются в эти цифры. Для критичных секретов (доступы к продакшену, платёжным системам) RPO сокращают до 1-6 часов и ставят бэкап каждые 6-12 часов.

Типичные ошибки при бэкапе хранилищ паролей

  • Копия на том же диске или VPS. Отказ диска, потеря VPS или шифрование вымогателем уничтожают и базу, и её копию. Держите минимум одну копию вне площадки.
  • Незашифрованные копии. Дамп со всеми паролями на съёмном носителе превращает кражу флешки в компрометацию всей инфраструктуры. Шифруйте каждый архив сразу.
  • Ключ шифрования рядом с копией. Парольная фраза или файл ключа в том же каталоге обесценивают шифрование. Храните их у второго администратора или в сейфе.
  • Бэкап без attachments и rsa_key.pem. База восстановится, а вложения и расшифровка пользовательских ключей нет. Проверяйте состав копии перед первым запуском.
  • Отсутствие проверки восстановления. Копия, из которой ни разу не поднимали сервис, может оказаться битой или неполной. Квартальный тест обязателен.
  • Тег latest и обновление без бэкапа. Автообновление меняет версию в момент, когда вы этого не ждёте, а миграции уже применены. Фиксируйте тег и снимайте копию перед обновлением.
  • Копирование SQLite во время записи. Файл в режиме WAL без .backup даёт повреждённый снимок. Используйте sqlite3 .backup или VACUUM INTO.
  • Старые копии и открытые права. Копии с паролями, доступные всем в каталоге с правами 644, и архивы полугодовой давности создают ложное чувство защиты. Ограничьте доступ и настройте ротацию.

Разбор сбоев бэкапа, диагностика прав, места и сети с проверкой восстановимости описаны в отдельном материале об ошибках резервного копирования.

Начните с проверки: восстановите последнюю копию в тестовый контейнер сегодня. Если вход работает и число записей совпадает, схема готова. Если что-то не сходится, вы найдёте это сейчас, а не в момент аварии.

Поделиться:
Сохранить гайд? В закладки браузера