SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-10-19

Как правильно сделать резервную копию Vaultwarden на VPS

Используйте команду sqlite3 .backup для создания корректного дампа базы данных. Узнайте, как сохранить файлы attachments, config.json и rsa_key для полного восстановления.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 5, 2026.

Что должен содержать резервный архив Vaultwarden

Резервная копия Vaultwarden — это копия всей папки с данными, при этом база данных внутри неё должна быть скопирована корректно. Используйте sqlite3 db.sqlite3 ".backup out.sqlite3" вместо cp, так как простое копирование базы данных в момент записи может привести к получению повреждённого файла, который невозможно открыть. Затем сохраните файлы, расположенные рядом с ней; это та часть, о которой часто забывают.

При установке через Docker папка с данными — это то, что вы примонтировали в /data. Это может быть путь на хосте или именованный том, а разница между bind mounts и именованными томами определяет, где именно на диске физически находятся данные вашего хранилища. Вот что они включают:

  • db.sqlite3: все учётные записи, все элементы хранилища, все папки и все организации. Потеря этого файла означает потерю хранилища.
  • db.sqlite3-wal и db.sqlite3-shm: журнал предзаписи (WAL) и его индекс в разделяемой памяти. Недавние записи хранятся здесь, пока SQLite не перенесёт их в основной файл.
  • attachments/: файлы, прикреплённые пользователями к элементам хранилища; они зашифрованы и распределены по одной директории на каждый элемент.
  • sends/: файлы, стоящие за ссылками Bitwarden Send.
  • config.json: все настройки, сохранённые вами на странице администратора.
  • rsa_key.pem, а также rsa_key.der и rsa_key.pub.der в старых версиях: ключ, подписывающий токены входа.
  • icon_cache/: загруженные иконки веб-сайтов. Это единственная директория, которую можно пропустить, так как Vaultwarden загрузит их снова по мере необходимости.

Безопасна ли моя база данных Vaultwarden? Что на самом деле содержится в файле

На этот вопрос отвечают две команды, и вы можете запустить обе прямо сейчас.

sudo apt update && sudo apt install -y sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select email from users;"
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select name from ciphers limit 1;"

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

2.k9Qw1nQ0y7Yy2Xw==|E1r0J3l5s7d9f1g3h5j7k9==|Lm4nOp6qRs8tUv0wXy2zAb4cDe6fGh8i=

Названия элементов, имена пользователей, пароли и заметки шифруются клиентом до отправки, поэтому сервер хранит только зашифрованный текст, который он не может прочитать. Префикс 2. — это тип шифрования Bitwarden, за которым следуют вектор инициализации (IV), зашифрованный текст и MAC (код аутентификации сообщения), каждый из которых представлен в формате base64 и разделен символом |. Ключ для расшифровки выводится из мастер-пароля учетной записи, который никогда не передается на сервер в пригодном для использования виде. Эта часть идентична независимо от того, используете ли вы Vaultwarden или официальный сервер, как подробно описано в сравнении Vaultwarden и self-hosted Bitwarden.

Остальная часть базы данных не зашифрована. Адреса электронной почты, имена учетных записей, подсказки к паролям и коды восстановления двухфакторной аутентификации хранятся в виде обычного текста рядом с метаданными, такими как время создания и принадлежность элемента к организации. Таким образом, сам файл резервной копии является секретным. Любой, кто завладеет им, узнает, кто ваши пользователи, и сможет атаковать зашифрованные блоки в офлайн-режиме с любой скоростью, которую позволяет их оборудование. Этот факт диктует правила хранения, описанные ниже: копия должна быть зашифрована до того, как покинет сервер. Токен администратора — это вторая половина той же проблемы, и в руководстве по усилению защиты self-hosted Vaultwarden подробно рассматриваются оба аспекта.

Почему копирование db.sqlite3 во время работы Vaultwarden не является резервной копией

Vaultwarden по умолчанию использует SQLite в режиме WAL (ENABLE_DB_WAL=true). Операция записи сначала попадает в db.sqlite3-wal, и только после контрольной точки (checkpoint) данные переносятся в db.sqlite3. Если скопировать только db.sqlite3, в лучшем случае вы получите состояние базы данных на момент последней контрольной точки, поэтому пароль, сохраненный десять минут назад, может отсутствовать в архиве, и система не выдаст никаких предупреждений. В худшем случае копия захватит процесс выполнения контрольной точки, а документация SQLite предупреждает, что база данных, отделенная от своего WAL-файла, может потерять зафиксированные транзакции или оказаться поврежденной.

Копирование всех трех файлов с помощью cp также не решает проблему. Копии создаются в разные моменты времени, поэтому сохраненный WAL может описывать версии страниц, которые уже не соответствуют сохраненному основному файлу. В результате SQLite выполняет восстановление одного файла на основе другого, и итоговые данные оказываются неверными. Вы обнаружите это гораздо позже:

Error: database disk image is malformed

.backup позволяет избежать этой проблемы, так как использует Online Backup API от SQLite, который, согласно документации, является способом копирования базы данных, находящейся в активном использовании. Он считывает страницы под блокировкой чтения и перезапускает процесс, если в это время происходит запись в файл, поэтому на диск записывается согласованное состояние на определенный момент времени.

Создание копии базы данных с помощью sqlite3 .backup

sudo apt update && sudo apt install -y sqlite3
sudo install -d -m 700 /var/backups/vaultwarden
OUT=/var/backups/vaultwarden/db-$(date '+%Y%m%d-%H%M').sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 ".backup '$OUT'"
sudo sqlite3 "$OUT" "PRAGMA integrity_check;"

Последняя команда выводит ok отдельной строкой. Любой другой результат означает, что копия непригодна для использования: не сохраняйте её и не удаляйте предыдущую версию. Вся последовательность выполняется на работающем сервере, поэтому сеансы пользователей не прерываются, а контейнеры не перезапускаются.

Инструмент sqlite3 отсутствует внутри контейнера Vaultwarden. Образ собран на debian:trixie-slim с использованием ca-certificates, curl, libmariadb3, libpq5 и openssl, поэтому docker exec vaultwarden sqlite3 ... завершается ошибкой:

exec: "sqlite3": executable file not found in $PATH

Вместо этого запустите команду на хосте, указав путь к смонтированной директории, как показано в примерах выше. Если данные хранятся в именованном томе (named volume), docker volume inspect <name> выведет путь к нему на хосте в поле /var/lib/docker/volumes/.

Начиная с версии 1.32.1, в Vaultwarden встроена собственная команда для резервного копирования. На вашем сервере:

docker exec -it vaultwarden /vaultwarden backup

Она запускает VACUUM INTO и записывает db_YYYYMMDD_HHMMSS.sqlite3 в папку с данными. Учтите два момента. Копия сохраняется рядом с оригиналом на том же диске, поэтому это лишь промежуточный этап, а не полноценный бэкап. Кроме того, функция работает только с SQLite: при использовании MariaDB или PostgreSQL выполнение прерывается с сообщением The database type is not SQLite. Backups only works for SQLite databases.

Файлы, о которых часто забывают

attachments/ содержит зашифрованные данные под непрозрачными именами. Запись в базе данных для каждого вложения содержит его зашифрованное имя файла и ключевой материал, необходимый клиенту для расшифровки. Вложения без базы данных — это нечитаемый набор байтов, а база данных без вложений приводит к тому, что загрузка файлов пользователями завершается ошибкой. Создавайте резервные копии обоих компонентов одновременно.

config.json хранит все настройки, сохранённые через панель администратора, и их значения имеют приоритет над соответствующими переменными окружения. Это работает в обе стороны: восстановление старого config.json незаметно переопределяет настройки в вашем compose-файле, а сам файл является конфиденциальным, так как может содержать ваш SMTP-пароль и токен администратора. Храните этот токен в виде строки Argon2id PHC (password hashing competition), а не в открытом виде. docker run --rm -it vaultwarden/server /vaultwarden hash может сгенерировать такую строку для вас.

rsa_key.pem используется для подписи JSON web tokens (JWT), которые поддерживают сессии пользователей. Если файл отсутствует при запуске, Vaultwarden генерирует новый ключ, из-за чего все токены, подписанные старым ключом, перестают проходить проверку, и все клиенты принудительно выходят из системы. Содержимое хранилища при этом сохраняется, так как оно зашифровано ключами, производными от мастер-пароля. Восстановление файла ключа позволяет избежать массового выхода пользователей из системы.

sends/ содержит файлы, стоящие за ссылками Send. Их отсутствие приводит только к невозможности загрузки этих файлов, на остальную функциональность это не влияет.

Объединение всего в один скрипт

#!/bin/bash
set -euo pipefail

DATA=/opt/vaultwarden/data
DEST=/var/backups/vaultwarden
STAMP=$(date '+%Y%m%d-%H%M%S')
STAGE=$(mktemp -d /tmp/vw-stage.XXXXXX)

install -d -m 700 "$DEST"
sqlite3 "$DATA/db.sqlite3" ".backup '$STAGE/db.sqlite3'"
test "$(sqlite3 "$STAGE/db.sqlite3" 'PRAGMA integrity_check;')" = "ok"
cp -a "$DATA"/rsa_key* "$STAGE/"
for extra in config.json attachments sends; do
  if [ -e "$DATA/$extra" ]; then cp -a "$DATA/$extra" "$STAGE/"; fi
done
tar -C "$STAGE" -czf "$DEST/vw-$STAMP.tar.gz" .
chmod 600 "$DEST/vw-$STAMP.tar.gz"
rm -rf "$STAGE"
tar -tzf "$DEST/vw-$STAMP.tar.gz"

Сохраните его как /usr/local/sbin/vw-backup.sh, сделайте chmod 700 и запустите от имени root. Строка test выполняет основную работу: sqlite3 возвращает код выхода 0, даже если PRAGMA integrity_check сообщает о повреждении данных, поэтому сравнение вывода с ok позволяет превратить неудачное копирование в остановку скрипта. set -euo pipefail затем прерывает выполнение, не позволяя tar создать архив на основе поврежденной базы данных.

Финальная команда tar -tzf выводит список того, что было успешно сохранено. Проверьте этот список при первом запуске. Вы должны увидеть ./db.sqlite3, ./rsa_key.pem и ./attachments/, а также ./config.json, если вы когда-либо сохраняли настройки через панель администратора, и отсутствие ./db.sqlite3-wal. Vaultwarden создает config.json только при сохранении настроек в интерфейсе, поэтому при установке, полностью настроенной через переменные окружения, этот файл отсутствует, и скрипт пропускает его. Запускайте скрипт каждую ночь с помощью systemd-сервиса и таймера, а не cron, если вам нужны journalctl в логах и юнит, который сообщает о сбоях.

Проверка резервной копии путем восстановления во временный каталог

Резервная копия без проверки — это лишь предположение. Восстановление во временный каталог занимает минуту и не затрагивает рабочие данные.

sudo install -d -m 700 /tmp/vw-check
sudo tar -C /tmp/vw-check -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
ls -l /tmp/vw-check
sudo sqlite3 /tmp/vw-check/db.sqlite3 "PRAGMA integrity_check;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from users;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from ciphers;"
sudo du -sh /tmp/vw-check/attachments

Важны четыре результата. integrity_check выводит ok. Количество пользователей должно совпадать с числом известных вам учетных записей. Количество шифров должно быть близко к текущему значению из sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select count(*) from ciphers;". Нулевое значение допустимо только в том случае, если в рабочей системе также ноль, так как хранилище может быть пустым, например, после очистки хранилища организации. Нуль при ненулевом значении в рабочей системе означает, что копия повреждена. Размер каталога вложений должен примерно соответствовать ожидаемому (этот шаг можно пропустить, если никто не загружает вложения). Затем выполните sudo rm -rf /tmp/vw-check, так как в этом каталоге теперь находится вторая копия всех данных.

При восстановлении базы данных, созданной с помощью .backup или VACUUM INTO (включая встроенную команду резервного копирования), существует одно правило: перед запуском сервера удалите все файлы db.sqlite3-wal и db.sqlite3-shm в папке с данными. В противном случае SQLite попытается восстановить базу данных, используя журнал, относящийся к другой копии, что может привести к повреждению изначально корректной базы данных. Исключением является прямое копирование файлов. Если вы скопировали db.sqlite3 вместе с соответствующим файлом db.sqlite3-wal, восстанавливайте их парой, так как WAL-файл может содержать зафиксированные записи, которых еще нет в основном файле, и их удаление приведет к потере данных. Файл -shm восстанавливать не нужно. Архивы, созданные с помощью приведенного выше скрипта, никогда не содержат WAL-файлов, так как .backup записывает одну полную базу данных.

Восстановление данных на сервере

Эти операции выполняются на вашем сервере при остановленном контейнере. Vaultwarden не должен записывать данные в момент изменения содержимого папки с данными.

cd /opt/vaultwarden
docker compose stop vaultwarden
sudo mv data data.old.$(date '+%Y%m%d-%H%M%S')
sudo install -d -m 700 data
sudo tar -C data -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
sudo chown -R root:root data
docker compose start vaultwarden
docker compose logs --tail 20 vaultwarden

В chown необходимо указать пользователя, от имени которого работает контейнер. Стандартный образ работает под root, поэтому root:root подходит, если только вы не задали user: в файле compose — в этом случае используйте соответствующие uid и gid. Если у сервера нет прав на запись в папку с данными, страница входа будет отклонять все запросы, о чем будет сообщено в логах.

Успешный запуск завершается строкой Rocket:

[INFO] Rocket has launched from http://0.0.0.0:80

После этого войдите в систему через браузер, откройте элемент и загрузите одно вложение. Если вход в систему работает, а загрузка вложений завершается ошибкой, это означает, что в архиве была база данных, но отсутствовала папка attachments/. Сохраняйте data.old.* до тех пор, пока не убедитесь в корректности всех данных, после чего удалите её. Откат к предыдущему состоянию выполняется аналогично, в три этапа, с заменой директорий местами.

Если ваши пути отличаются от указанных здесь, руководство по установке Vaultwarden на VPS содержит файл compose, на который опираются данные команды.

Где не следует хранить резервные копии

  • Не на том же диске, где находится папка с данными. Один вышедший из строя том уничтожит обе копии, как и одна ошибка rm -rf в пути.
  • Не на том же сервере, даже на втором томе. Злоумышленник, получивший доступ к root, получит доступ и к вашим резервным копиям в рамках той же сессии.
  • Не в объектном хранилище без шифрования, так как архив содержит адреса электронной почты, подсказки к паролям, коды восстановления и зашифрованные данные хранилища, которые можно подвергнуть офлайн-атаке.
  • Не только в снимках (snapshots) вашего провайдера. Они быстро восстанавливаются, что полезно, но они находятся в той же учетной записи, что и сервер, поэтому проблема с доступом к аккаунту приведет к их потере.

Удаленная копия — это то, для чего подходит restic, поскольку репозиторий restic шифруется на машине до начала загрузки. На вашем сервере:

sudo apt install -y restic
export RESTIC_REPOSITORY=s3:https://s3.example.com/vaultwarden-backups
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /var/backups/vaultwarden --tag vaultwarden
restic snapshots --tag vaultwarden
restic forget --tag vaultwarden --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Указывайте restic на директорию с архивом, а не на папку с рабочими данными, чтобы загружалась именно та согласованная копия, которую вы уже проверили. Храните пароль от репозитория где угодно, кроме самого сервера, который он защищает: если вы потеряете этот пароль, снимки станут нечитаемыми — так задумано архитектурой. Там, где хранилище это поддерживает, предоставьте серверу учетные данные с правами на запись, но без прав на удаление, чтобы взлом системы не позволил ей стереть собственную историю. Настройка резервного копирования с помощью restic на VPS полностью описывает работу с репозиторием и расписанием, а сравнение restic и BorgBackup поможет с выбором, если вы его еще не сделали.

Тестирование восстановления по расписанию

Выберите один день в месяц. Извлеките самый свежий снапшот во временную директорию с помощью restic restore latest --tag vaultwarden --target /tmp/vw-check, выполните те же PRAGMA integrity_check, проверьте количество строк и запишите дату и полученные значения. Резервная копия, которую никто не восстанавливал в течение шести месяцев, — это копия с неизвестным состоянием. Вы узнаете её состояние во время сбоя, что является худшим моментом для подобных открытий.

Раз в год проводите полную проверку. Запустите второй контейнер Vaultwarden на свободном порту с восстановленной папкой данных и войдите в систему под реальной учётной записью. Это подтвердит работоспособность пути мастер-пароля от начала до конца, чего не может сделать простая проверка количества строк. restic check --read-data-subset=10% по тому же расписанию подтверждает, что сохранённые данные можно прочитать, а не просто увидеть в списке.

FAQ

Можно ли копировать db.sqlite3 командой cp во время работы Vaultwarden?

Нет. Vaultwarden использует SQLite в режиме WAL, поэтому последние записи находятся в db.sqlite3-wal и еще не перенесены в db.sqlite3. cp только основного файла приведет к их потере, а раздельное копирование двух файлов может создать несогласованную пару, что позже проявится как Error: database disk image is malformed. Используйте sqlite3 /path/db.sqlite3 ".backup '/path/out.sqlite3'". Этот инструмент задействует Online Backup API от SQLite и создает один согласованный файл без остановки сервера.

Нужно ли останавливать контейнер Vaultwarden для создания резервной копии?

Нет, в этом и заключается смысл .backup. Копия базы данных безопасна при работающем сервере. Вложения и файлы Send записываются в момент загрузки пользователем, поэтому файл, добавленный между копированием базы данных и tar, может не попасть в ночной архив, что в худшем случае приведет к потере одного вложения. Если несколько секунд простоя не критичны, docker compose stop перед скриптом и docker compose start после него исключат даже этот риск.

Что произойдет при восстановлении без файлов rsa_key?

Vaultwarden сгенерирует новый ключ при запуске. Этот ключ подписывает JSON web tokens (JWT), которые поддерживают сессии, поэтому все существующие токены перестанут проходить проверку, все клиенты будут принудительно разлогинены и должны будут войти снова. Содержимое хранилищ не пострадает, так как оно зашифровано ключами, производными от мастер-пароля каждого пользователя, а не RSA-ключом. Восстанавливайте rsa_key.pem вместе с остальными данными из папки, и пользователи не заметят процесса восстановления.

Безопасно ли загружать архив резервной копии в объектное хранилище в исходном виде?

Нет. Имена элементов, пароли и заметки зашифрованы, но адреса электронной почты, имена учетных записей, подсказки к паролям и коды восстановления двухфакторной аутентификации хранятся в базе данных в открытом виде. Злоумышленник, получивший доступ к архиву, сможет расшифровывать данные в автономном режиме с любой скоростью. Шифруйте архив до того, как он покинет сервер. Репозиторий restic делает это автоматически, а gpg --symmetric --cipher-algo AES256 vw-20260805-030000.tar.gz создает единый зашифрованный файл, который можно передать в любое хранилище.

Как выполнять резервное копирование Vaultwarden на PostgreSQL или MariaDB?

Инструкции для SQLite здесь не применимы, а встроенная команда выдаст ошибку The database type is not SQLite. Backups only works for SQLite databases. Создавайте дамп базы данных с помощью штатных инструментов, pg_dump или mysqldump, при этом все остальные правила остаются в силе. Дамп должен находиться в одном архиве с attachments/, sends/, config.json и файлами rsa_key. Все данные должны быть собраны за один проход, зашифрованы и сохранены за пределами сервера, на котором они были созданы.

Была ли эта статья полезной?