Установка и настройка Vaultwarden в 2026: self-hosted хранилище паролей на Docker, Nginx и TLS | AdminWiki

Установка и настройка Vaultwarden в 2026: self-hosted хранилище паролей на Docker, Nginx и TLS

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

Что такое Vaultwarden и зачем разворачивать его самостоятельно

Vaultwarden - это серверная реализация API Bitwarden на Rust. Один контейнер, SQLite в роли базы по умолчанию, 30-40 МБ на диске и 100-200 МБ оперативной памяти на 10-20 активных пользователей. Официальные клиенты Bitwarden работают с ним без модификаций: веб-хранилище, десктопные приложения для Windows, macOS и Linux, мобильные клиенты Android и iOS, расширения для Chrome, Firefox, Edge и Safari, а также CLI bw. Протокол тот же, поэтому клиент видит обычный Bitwarden, нужно только указать адрес self-hosted сервера в настройках вместо bitwarden.com.

Практический выигрыш: база паролей лежит на вашем железе, подписка не нужна, TOTP-коды, вложения, Send и коллекции организаций доступны без платного тарифа. Платите только за VPS: 1 vCPU и 1 ГБ RAM хватает команде до 20 человек. Bitwarden Teams стоит около $4 за пользователя в месяц, то есть 15 человек обойдутся примерно в $720 в год против нескольких тысяч рублей за аренду сервера.

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

Чем Vaultwarden отличается от официального Bitwarden

Совместимость двусторонняя: клиенты Bitwarden подключаются к Vaultwarden, но не наоборот, потому что часть серверных ответов Vaultwarden шире, чем требует апстрим. Что реально работает без лицензии: TOTP-генератор внутри записей, вложения, Bitwarden Send, организации с коллекциями и ролями, API-ключи для CLI, WebAuthn и YubiKey в роли второго фактора, журнал событий в админке.

Ограничения, о которых стоит знать заранее:

  • Мобильные push-уведомления требуют отдельной настройки через push-сервис Bitwarden, без него клиент синхронизируется при открытии и по расписанию.
  • Синхронизации каталога с LDAP или Active Directory (Directory Connector) нет.
  • SSO есть в варианте OpenID Connect, SAML не поддержан.
  • Отдельные функции повторяют апстрим с задержкой в несколько недель или месяцев.
  • Ответственность за доступность и целостность данных переходит к вам.

Кому подходит self-hosted хранилище паролей

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

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

КритерийОблачный BitwardenVaultwarden на своём сервере
СтоимостьPremium $10 в год, Teams около $4 за пользователя в месяцТолько аренда VPS и домен
Где лежат данныеИнфраструктура BitwardenВаш сервер, доступ по HTTPS
TOTP, вложения, Send, коллекцииЧасть функций только в платных тарифахДоступны без лицензии
ОбновленияАвтоматическиеdocker compose pull в вашем расписании
Корпоративные функцииSAML, Directory Connector, аудитПолитики, OIDC и журнал событий
БэкапыНа стороне сервисаНа вас: db.sqlite3, attachments, rsa_key.pem

Подготовка сервера и установка Docker

Чек-лист перед началом: Ubuntu 24.04 LTS или Debian 12, 1 vCPU, 1 ГБ RAM (2 ГБ, если планируются вложения и больше 30 клиентов), 10-20 ГБ SSD, статический IP, домен с A-записью на этот IP, открытые порты 80 и 443. Минимальной конфигурации VPS в Timeweb Cloud достаточно для старта, для продакшена берите 2 vCPU, чтобы переиндексация и бэкапы не мешали работе.

Требования к серверу и домену

Проверьте DNS до установки: команда dig +short vault.example.com должна вернуть IP сервера. Если домен обслуживает Cloudflare в режиме проксирования (оранжевое облако), выпуск сертификата по HTTP-01 не пройдёт: переключите запись в DNS-only либо используйте challenge DNS-01.

Доступ по SSH настройте заранее: вход по ключу, отдельный пользователь с sudo, пароль root и вход root по SSH отключены. Firewall: sudo ufw allow OpenSSH и sudo ufw allow "Nginx Full". Пользователи, sudoers, ufw и systemd разобраны в практическом руководстве по администрированию Linux.

Установка Docker и Docker Compose

  1. sudo apt update && sudo apt upgrade -y
  2. sudo apt install -y ca-certificates curl gnupg
  3. sudo install -m 0755 -d /etc/apt/keyrings
  4. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
  5. sudo chmod a+r /etc/apt/keyrings/docker.gpg
  6. Добавьте репозиторий (для Debian 12 замените noble на bookworm): echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list
  7. sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  8. sudo systemctl enable --now docker
  9. Проверка: docker --version и docker compose version. Ожидайте Docker 27.x и Compose v2.x или новее.
  10. sudo usermod -aG docker $USER, затем выйдите из сессии и зайдите снова, чтобы группа применилась.

Развёртывание Vaultwarden через Docker Compose

Создайте рабочий каталог и токен администратора: sudo mkdir -p /opt/vaultwarden && cd /opt/vaultwarden, затем openssl rand -base64 48. Полученную строку вставьте как ADMIN_TOKEN. Альтернатива: сгенерировать argon2-хеш на странице /admin и хранить его вместо открытого токена.

Файл docker-compose.yml:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "false"
      INVITATIONS_ALLOWED: "true"
      ADMIN_TOKEN: "вставьте_свой_токен_из_openssl"
      TZ: "Europe/Moscow"
      LOG_LEVEL: "warn"
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:8080:80"

Порт публикуется только на localhost: снаружи сервис виден исключительно через Nginx. Каталог ./vw-data останется рядом с compose-файлом, его же вы будете архивировать в бэкапах.

Ключевые переменные окружения

  • DOMAIN: полный адрес со схемой https. Попадает в письма-приглашения, ссылки на вложения и адрес WebSocket для live-синхронизации.
  • SIGNUPS_ALLOWED=false: запрет самостоятельной регистрации.
  • INVITATIONS_ALLOWED=true: администратор приглашает пользователей из панели /admin, приглашённый сам задаёт мастер-пароль.
  • ADMIN_TOKEN: доступ к /admin. Если указан argon2-хеш, знаки $ в compose-файле экранируйте удвоением.
  • TZ и LOG_LEVEL: часовой пояс для отметок в журнале и уровень логирования.

DOMAIN меняется только пересозданием контейнера, а после смены адреса потребуется перевыпустить сертификат и заново прописать новый адрес сервера в каждом клиенте. Выбирайте имя домена один раз и надолго.

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

Запуск: docker compose up -d. Проверка состояния: docker compose ps показывает State: running и Status: Up. Логи: docker compose logs -f vaultwarden. Локальный отклик: curl -I http://127.0.0.1:8080 возвращает 200 или 302, эндпоинт http://127.0.0.1:8080/alive отдаёт 200.

Если контейнер циклически перезапускается, смотрите логи на ошибки доступа к ./vw-data. Типичный случай: каталог принадлежит другому пользователю, и процесс не может открыть db.sqlite3.

Настройка Nginx как reverse proxy с TLS Let's Encrypt

Установка пакетов: sudo apt install -y nginx certbot python3-certbot-nginx. Сначала создайте HTTP-конфиг с проксированием, получите сертификат, затем добавьте TLS-параметры и заголовки безопасности.

Конфиг Nginx с поддержкой WebSocket

Файл /etc/nginx/sites-available/vaultwarden в финальном виде:

server {
    listen 80;
    server_name vault.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name vault.example.com;

    ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    client_max_body_size 128M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /notifications/hub {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
    }
}

Блок /notifications/hub отвечает за WebSocket: без заголовков Upgrade и Connection клиенты теряют live-обновления, и запись, добавленная на телефоне, появится на ноутбуке только после ручной синхронизации. Заголовки X-Forwarded-For и X-Forwarded-Proto нужны, чтобы Vaultwarden видел реальные IP для rate-limit и не считал соединение небезопасным.

Панель /admin полезно закрыть по IP: внутри server-блока добавьте location /admin с директивами allow 203.0.113.44; и deny all;, а proxy_set_header повторите как в блоке /. Клиент с другого адреса получит 403, и это правильное поведение.

Активация: sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/, затем sudo nginx -t и sudo systemctl reload nginx.

Выпуск и автопродление сертификата

Выпуск: sudo certbot --nginx -d vault.example.com --agree-tos -m admin@example.com --redirect. Certbot сам добавит ssl-директивы и редирект с 80 на 443. Проверка таймера продления: systemctl status certbot.timer, состояние должно быть active (waiting). Тестовый прогон продления: sudo certbot renew --dry-run. Успешный dry-run означает, что через 30 дней до истечения срока сертификат продлится автоматически.

Базовая настройка безопасности и SMTP

Сервер, поднятый с SIGNUPS_ALLOWED=true и оставленный без присмотра, открыт для регистрации любому, кто знает адрес. Закрывайте регистрацию сразу после проверки работоспособности.

Отключение публичной регистрации

В compose-файле выставьте SIGNUPS_ALLOWED: "false" и INVITATIONS_ALLOWED: "true". Первого пользователя создают приглашением: /admin, вкладка Users, кнопка Invite. Приглашённый получает письмо со ссылкой и сам задаёт мастер-пароль.

Как проверить, что регистрация закрыта: откройте адрес сервера, перейдите к созданию аккаунта и введите любой email. Ответ должен быть вида "Registration not allowed or user already exists". Дополнительные ограничители: SIGNUPS_DOMAINS_WHITELIST для списка разрешённых доменов и SIGNUPS_VERIFY=true для подтверждения email при регистрации.

После правки переменных окружения выполните docker compose up -d: команда restart не перечитывает environment и изменения не применятся.

Настройка SMTP для приглашений и уведомлений

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

      SMTP_HOST: "smtp.example.com"
      SMTP_FROM: "vault@example.com"
      SMTP_FROM_NAME: "Vaultwarden"
      SMTP_PORT: "465"
      SMTP_SECURITY: "force_tls"
      SMTP_USERNAME: "vault@example.com"
      SMTP_PASSWORD: "app-пароль_из_панели_провайдера"
      SMTP_AUTH_MECHANISM: "Plain"
      SMTP_TIMEOUT: "15"

Соответствие порта и режима: 465 с SMTP_SECURITY=force_tls, 587 с SMTP_SECURITY=starttls, 25 с off (провайдеры её часто блокируют). Пароль приложения берите в панели почтового сервиса, обычный пароль учётной записи обычно не подходит. Чтобы письма не улетали в спам, добавьте для домена отправителя записи SPF, DKIM и DMARC.

Проверка: отправьте тестовое приглашение из /admin и посмотрите логи docker compose logs -f vaultwarden, строки с ошибкой SMTP видны сразу. Усильте защиту самого аккаунта вторым фактором, включая аппаратные ключи и TOTP, по сравнению open-source аутентификаторов.

Миграция данных из облачного Bitwarden

Перенос 500 записей занимает 10-15 минут, включая проверку. Порядок одинаков для личного хранилища и для организации.

Экспорт из Bitwarden

В веб-интерфейсе: Tools, Export vault, формат .json, ввод мастер-пароля, кнопка Export vault. Файл скачивается локально. Для организации экспорт делает владелец из консоли организации, коллекции сохраняются в файле.

Что не попадает в экспорт: вложения (их скачивают вручную по записи), passkeys (создаются заново), API-ключи, история изменений. Зашифрованный .json с паролем импортируется только через CLI bw, обычный импорт его не читает.

Экспортированный JSON содержит пароли в открытом виде. Сохраняйте его только на локальном диске, не пересылайте почтой и не оставляйте в облачных синхронизируемых папках.

Импорт в Vaultwarden и проверка

  1. Войдите в веб-хранилище на своём домене (адрес из DOMAIN).
  2. Tools, Import data, File format: Bitwarden (json), затем Choose file и Import data.
  3. Сверьте количество элементов с числом записей в облачном аккаунте, проверьте папки и коллекции.
  4. Откройте 2-3 записи и убедитесь, что TOTP-коды генерируются.
  5. Скачайте нужные вложения вручную и приложите их к соответствующим записям.
  6. Удалите файл экспорта без возможности восстановления: shred -u ~/bitwarden-export.json.
  7. Установите клиенты Bitwarden на всех устройствах на новый адрес сервера и выполните синхронизацию.

Облачный аккаунт не удаляйте 2-4 недели: за это время всплывут забытые записи и вложения. Для переноса из других менеджеров пригодится руководство по миграции из KeePass, LastPass и Bitwarden: там разобраны форматы CSV и KDBX, слияние без дубликатов и очистка промежуточных файлов.

Резервное копирование и восстановление

Все данные Vaultwarden лежат в одном каталоге, в примере это ./vw-data. Отдельной базы данных на сервере нет, поэтому бэкап сводится к архивированию каталога.

Что именно нужно бэкапить

  • db.sqlite3 вместе с файлами -wal и -shm: пользователи, записи, настройки организаций.
  • attachments/: вложения к записям.
  • sends/: одноразовые ссылки Bitwarden Send.
  • rsa_key.pem и rsa_key.pub.pem: приватный ключ сервера.
  • config.json: появляется, если настройки менялись из панели /admin, а не только через переменные окружения.
  • Каталог icon_cache/ можно не копировать, он заполнится заново.

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

Скрипт и расписание бэкапа

Скрипт /opt/vaultwarden/backup.sh (остановка контейнера даёт согласованный снимок SQLite):

#!/usr/bin/env bash
set -euo pipefail
cd /opt/vaultwarden
STAMP=$(date +%F-%H%M)
mkdir -p /var/backups/vaultwarden
docker compose stop
tar czf /var/backups/vaultwarden/vw-$STAMP.tar.gz ./vw-data
docker compose start
find /var/backups/vaultwarden -name "vw-*.tar.gz" -mtime +7 -delete

Сделайте файл исполняемым: chmod +x /opt/vaultwarden/backup.sh. Расписание через cron (пользователь с правами на docker): 0 3 * * * /opt/vaultwarden/backup.sh >> /var/log/vw-backup.log 2>&1. Семь дневных копий на том же диске защищают от ошибок, но не от потери сервера: раз в неделю копию нужно вывозить на внешнее хранилище и шифровать, например через age или gpg.

Восстановление: остановите контейнер (docker compose stop), перенесите текущий ./vw-data в сторону, распакуйте архив в /opt/vaultwarden, проверьте владельца каталога, запустите docker compose start и войдите в веб-интерфейс. Проверку восстановления проводите на отдельном каталоге и свободном порту, чтобы не тронуть рабочие данные.

Проверка работоспособности и типичные ошибки

Чек-лист после установки

  1. Откройте https://vault.example.com: сертификат валиден, браузер не показывает предупреждений.
  2. Войдите под учётной записью, созданной по приглашению, и добавьте тестовую запись.
  3. Проверьте синхронизацию с мобильным клиентом: запись появляется после обновления.
  4. Откройте консоль разработчика в браузере и убедитесь, что соединение WebSocket по адресу /notifications/hub установлено со статусом 101.
  5. Отправьте тестовое приглашение и убедитесь, что письмо дошло, а не осело в спаме.
  6. Выполните sudo certbot renew --dry-run и systemctl status certbot.timer.
  7. Проверьте эндпоинт curl -I https://vault.example.com/alive.

Разбор частых ошибок первого запуска

СимптомПричинаИсправление
502 Bad GatewayКонтейнер не отвечает на 127.0.0.1:8080: упал, неверный порт или имя сервисаdocker compose ps, docker compose logs -f vaultwarden, curl -I http://127.0.0.1:8080
Клиент не синхронизируется, в консоли ошибка WebSocketВ Nginx нет location /notifications/hub или потеряны заголовки Upgrade и ConnectionДобавить блок WebSocket, затем nginx -t и systemctl reload nginx
permission denied при старте, контейнер в цикле перезапускаКаталог ./vw-data принадлежит другому пользователюchown -R 1000:1000 ./vw-data и директива user: "1000:1000" в сервисе; на RHEL и SELinux добавьте суффикс :Z к volume
Certbot не выпускает сертификатЗакрыт порт 80, неверная A-запись или проксирование Cloudflareufw allow "Nginx Full", проверить dig +short, переключить запись в DNS-only или выбрать challenge DNS-01
Письма не приходятНеверный SMTP_SECURITY или порт, пароль вместо пароля приложения, нет SPF, DKIM и DMARC465 с force_tls или 587 с starttls, пароль приложения, добавить DNS-записи, смотреть строки SMTP в логах
Не создаётся приглашение, регистрация отклоняетсяSIGNUPS_ALLOWED=false при INVITATIONS_ALLOWED=falseВключить INVITATIONS_ALLOWED=true и пересоздать контейнер командой docker compose up -d
Изменения переменных не применяютсяИспользован restart вместо пересоздания контейнераdocker compose up -d, при необходимости с флагом --force-recreate
Мобильный клиент отказывается подключатьсяКлиент требует HTTPS, а сервер отвечает по HTTP или с самоподписанным сертификатомУказать в DOMAIN адрес с https и использовать сертификат Let's Encrypt
Панель /admin не открывается при заданном ADMIN_TOKENЗнаки $ в argon2-хеше интерпретируются ComposeЭкранировать их удвоением или использовать токен из openssl rand -base64 48

Что делать дальше: обновления и поддержка

Обновление занимает минуты: docker compose pull, затем docker compose up -d. Перед каждым обновлением делайте свежий бэкап и читайте release notes образа: в минорных релизах Vaultwarden иногда поднимает минимальные требования к версиям клиентов, меняет поведение переменных окружения и структуру каталога данных. Версию можно посмотреть в админке на странице Diagnostics или командой docker compose exec vaultwarden /vaultwarden --version.

Мониторинг держите простым: внешний чекер пингует https://vault.example.com/alive и ждёт 200, отдельный алерт следит за сроком сертификата, логи контейнера пишутся с LOG_LEVEL=warn. Раз в квартал проверяйте, что бэкап разворачивается в тестовом каталоге, иначе копии остаются неизученными файлами.

Для команд следующий шаг: распределить записи по коллекциям, выдать роли и включить обязательный второй фактор. Если секреты нужны ещё и в пайплайнах, посмотрите материал об интеграции хранилищ секретов с CI/CD: там разобраны выдача токенов на время выполнения задания, маскирование логов и ротация.

Инструкция проверена на связке Ubuntu 24.04, Docker Compose v2 и ветке образов vaultwarden/server 2026 года. Набор переменных окружения и порт внутри контейнера остаются стабильными годами, но перед обновлением сверяйтесь с release notes: так вы не поймаете сюрприз на рабочем инстансе.

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