Как установить и настроить Vaultwarden на VPS
Официальный self-hosted Bitwarden — это одиннадцать контейнеров, MSSQL и рекомендованные 4 ГБ памяти под хранилище паролей на десять человек. Vaultwarden делает то же самое одним процессом на Rust и занимает около 50 МБ. Ниже — установка на чистый VPS по шагам, с командой проверки после каждого этапа.
Содержание
- Что вы получаете вместо официального Bitwarden
- Подготовка: домен, DNS, фаервол и часы
- Установка: Docker Compose и первый запуск
- Nginx, TLS и вебсокеты: где ломаются старые гайды
- Первый пользователь, ADMIN_TOKEN и закрытие регистрации
- Почта, push на телефоны и защита от перебора
- Какой сервер под Vaultwarden брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что вы получаете вместо официального Bitwarden
Vaultwarden — независимая реализация серверного API Bitwarden на Rust. Клиенты остаются родные: браузерное расширение, десктоп, приложения для iOS и Android, CLI. В настройках клиента вы указываете свой адрес вместо vault.bitwarden.com — больше ничего не меняется.
Разница в аппетитах видна сразу. Официальная сборка поднимает десяток сервисных контейнеров плюс MSSQL, её требования — 2 ядра, от 2 ГБ памяти и 12 ГБ диска. Vaultwarden — один контейнер и файл SQLite: docker stats через сутки работы с семью активными пользователями показывает 48.7MiB / 1.918GiB и 0,03 % CPU. Бесплатно открыты организации и коллекции, TOTP внутри записей, вложения, экстренный доступ, ключи WebAuthn.
Минусы честные. Проект неофициальный, компания Bitwarden его не поддерживает, аудитов уровня облака у него нет. Поддержка OIDC/SSO появилась в ветке 1.34 со статусом экспериментальной — опираться на неё в корпоративном контуре рано. И вместе с сервером вы забираете ответственность за бэкапы и доступность. Разбор «кому что выгоднее» — в материале Vaultwarden против Bitwarden.
Подготовка: домен, DNS, фаервол и часы
Домен обязателен, HTTPS обязателен. Веб-хранилище шифрует всё в браузере через WebCrypto, а crypto.subtle доступен только в защищённом контексте: по http:// страница входа откроется, но при вводе пароля повиснет с TypeError: Cannot read properties of undefined (reading 'subtle') в консоли. Самоподписанный сертификат тоже не выход — расширение отвечает Failed to fetch, мобильное приложение Trust anchor for certification path not found.
Заведите A-запись и проверьте: dig +short vault.example.com должен вернуть IP сервера. Наружу открываем только SSH и веб — ufw allow 22/tcp && ufw allow 80,443/tcp && ufw enable; порт контейнера в мир не публикуем вообще.
Отдельно про часы. Vaultwarden сверяет коды двухфакторки на своей стороне, окно допуска — плюс-минус один шаг по 30 секунд, и сервер, уехавший на минуту, встретит вас Invalid TOTP code! при правильном коде из телефона. timedatectl должен показывать System clock synchronized: yes.
Docker ставьте из репозитория вендора — curl -fsSL https://get.docker.com | sh, в дистрибутивных пакетах версия старше примерно на год. Система — Ubuntu 24.04 LTS или Debian 13, различий для Vaultwarden нет.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть VaultwardenУстановка: Docker Compose и первый запуск
Раскладываем всё в /opt/vaultwarden. Ключевое решение — публикация порта только на петлю 127.0.0.1:8080: контейнер физически недоступен снаружи мимо реверс-прокси, даже если вы ошибётесь в правилах ufw.
# /opt/vaultwarden/compose.yaml
services:
vaultwarden:
image: vaultwarden/server:1.34.3
container_name: vaultwarden
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./vw-data:/data
env_file: vaultwarden.env
Тег версии закрепляем осознанно: latest удобен, пока не приезжает изменение, ломающее конфиг посреди рабочего дня. Текущую версию покажет docker exec vaultwarden /vaultwarden --version.
Переменные — в отдельном файле. Не называйте его .env: этот файл Compose дополнительно читает для подстановки переменных в сам compose-файл, и символ $ в значениях начинает жить своей жизнью. Имя vaultwarden.env снимает вопрос.
DOMAIN=https://vault.example.com
SIGNUPS_ALLOWED=true
INVITATIONS_ALLOWED=true
LOG_FILE=/data/vaultwarden.log
LOG_LEVEL=warn
EXTENDED_LOGGING=true
DOMAIN — не косметика: по нему формируются ссылки в письмах-приглашениях и идентификатор источника для аппаратных ключей WebAuthn. Ошиблись в схеме или домене — ключ, зарегистрированный на старом значении, приниматься перестанет.
Запуск — docker compose up -d, проверка — curl -s http://127.0.0.1:8080/alive. В логе docker compose logs vaultwarden ищите строку [INFO] Rocket has launched from http://0.0.0.0:80, а /alive вернёт время сервера вида "2026-08-28T09:41:22.518293151Z". Ответ пришёл — приложение живо, дальше воюем только с прокси.
В vw-data/ появятся db.sqlite3 (всё хранилище), attachments/, sends/, icon_cache/ и rsa_key.pem. Незаменимы первые два. Потеря rsa_key.pem данные не уничтожает — она разлогинивает всех разом, потому что старые токены перестают проверяться.
Nginx, TLS и вебсокеты: где ломаются старые гайды
Сертификат берём у Let's Encrypt: apt install -y nginx certbot python3-certbot-nginx, затем certbot --nginx -d vault.example.com — пути к сертификату он впишет сам. Руками добавляем два места: client_max_body_size (по умолчанию Nginx режет тело на 1 МБ, и вложение крупнее падает с 413 Request Entity Too Large) и апгрейд соединения на /notifications/hub.
server {
listen 443 ssl;
server_name vault.example.com;
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;
}
location /notifications/hub {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
}
Главная грабля 2026 года — копирование гайдов трёхлетней давности. До версии 1.32.0 вебсокеты жили на отдельном порту 3012 и включались переменной WEBSOCKET_ENABLED=true. С 1.32.0 их обслуживает основной порт, WEBSOCKET_ENABLED игнорируется, а 3012 не слушает никто. Старый конфиг с proxy_pass http://127.0.0.1:3012; даёт 502 Bad Gateway на /notifications/hub при полностью рабочем входе — внешне это выглядит как «изменения не долетают между устройствами».
Второй нюанс — адрес клиента. Vaultwarden читает заголовок X-Real-IP (переменная IP_HEADER); если прокси его не ставит, в лог по каждой неудачной попытке входа поедет IP: 127.0.0.1, и fail2ban из следующего раздела будет героически банить локалхост. За Cloudflare ставьте IP_HEADER=X-Forwarded-For.
Не хотите возиться с Nginx — Caddy закрывает вопрос тремя строками, сам выпускает сертификат и корректно апгрейдит вебсокеты (Caddy с авто-SSL на VPS):
vault.example.com {
reverse_proxy 127.0.0.1:8080
}
Первый пользователь, ADMIN_TOKEN и закрытие регистрации
Откройте https://vault.example.com, зарегистрируйте свою учётку — и сразу закройте вход посторонним. Открытая регистрация на публичном адресе за неделю набирает десятки чужих аккаунтов, найденных сканерами.
SIGNUPS_ALLOWED=false
INVITATIONS_ALLOWED=true
SIGNUPS_DOMAINS_WHITELIST=example.com
ORG_CREATION_USERS=admin@example.com
Теперь панель /admin. Открытым текстом токен писать не нужно — Vaultwarden принимает Argon2 PHC-строку и генерирует её сам: docker exec -it vaultwarden /vaultwarden hash --preset owasp. Команда дважды спросит пароль и выдаст строку вида $argon2id$v=19$m=19456,t=2,p=1$c29tZXNhbHQ$.... Пресет owasp просит 19 МБ памяти на проверку, пресет по умолчанию bitwarden — 64 МБ; на маленьком сервере разница ощутима. Оставите обычную строку — при каждом старте в лог пойдёт предупреждение You are using a plain text ADMIN_TOKEN which is insecure.
Про доллары в хеше — отдельно, потому что на этом спотыкаются все. Готовую строку кладите в vaultwarden.env как есть, без кавычек: значения из env_file передаются в контейнер дословно. А если вписать её прямо в environment: внутри compose-файла, Compose попытается подставить переменные, напишет WARN[0000] The "argon2id" variable is not set. Defaulting to a blank string. и отдаст контейнеру огрызок — там каждый $ надо удвоить до $. Проверка в обоих случаях одна: docker exec vaultwarden printenv ADMIN_TOKEN, строка должна быть целой и начинаться с $argon2id$.
Панель /admin — самая лакомая точка на сервере. Притормозите перебор через ADMIN_RATELIMIT_SECONDS=300 и ADMIN_RATELIMIT_MAX_BURST=3, а если снаружи она не нужна — выключите совсем через DISABLE_ADMIN_TOKEN=true либо пустите только со своего адреса блоком location /admin { allow 203.0.113.10; deny all; proxy_pass http://127.0.0.1:8080; }.
И ловушка, стоящая часа отладки: настройки, сохранённые кнопкой в веб-панели, ложатся в /data/config.json и перекрывают переменные окружения. После этого правки в vaultwarden.env ни на что не влияют, хотя перезапуск проходит без ошибок. Решайте один раз: либо всё через файл окружения (тогда cat vw-data/config.json показывает пустой {}), либо всё через панель.
Почта, push на телефоны и защита от перебора
Без SMTP не работают приглашения, письма верификации и уведомления о входе с нового устройства. Заполняете SMTP_HOST, SMTP_FROM, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD и SMTP_SECURITY. Последняя принимает три значения: starttls для порта 587, force_tls для 465 и off для 25. Перепутанная пара «порт плюс режим» — самая частая причина, по которой тестовое письмо из /admin заканчивается таймаутом; ошибка аутентификации выглядит понятнее: SMTP 5xx error: permanent error (535): 5.7.8 Error: authentication failed. Отправлять с 25-го порта напрямую не пытайтесь, почти все провайдеры его блокируют.
Мобильные приложения синхронизируются не по вебсокетам, а через push. Своего сервиса у Vaultwarden нет, он использует официальный ретранслятор Bitwarden: зарегистрируйте бесплатный идентификатор установки на bitwarden.com/host и добавьте PUSH_ENABLED=true, PUSH_INSTALLATION_ID, PUSH_INSTALLATION_KEY, PUSH_RELAY_URI=https://push.bitwarden.eu и PUSH_IDENTITY_URI=https://identity.bitwarden.eu. Регион важен: европейский идентификатор работает только с адресами bitwarden.eu, американский — только с bitwarden.com. Перепутали — в логе ошибка авторизации push, а телефон подтягивает изменения только вручную (Vaultwarden не синхронизируется).
Теперь перебор: мастер-пароль — единственный барьер, и подбирать его будут. Логи мы включили, неудачная попытка выглядит так:
[2026-08-28 09:52:14.031][vaultwarden::api::identity][ERROR] Username or password is
incorrect. Try again. IP: 203.0.113.45. Username: user@example.com.
Отсюда фильтр /etc/fail2ban/filter.d/vaultwarden.conf и джейл /etc/fail2ban/jail.d/vaultwarden.local:
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
[vaultwarden]
enabled = true
port = 80,443
filter = vaultwarden
logpath = /opt/vaultwarden/vw-data/vaultwarden.log
maxretry = 5
findtime = 600
bantime = 3600
Проверяйте не веру, а вывод fail2ban-client status vaultwarden. Ноль в Total failed при явных попытках в логе означает, что регулярка не совпала: тексты сообщений между ветками менялись, сверьтесь через grep -m1 'incorrect' vw-data/vaultwarden.log. Общая настройка сервиса — в статье Fail2ban на VPS.
Последнее по порядку и первое по важности — бэкап. Копировать db.sqlite3 обычным cp во время работы нельзя: получите файл с оборванной транзакцией, и выяснится это в момент восстановления. Правильно — sqlite3 vw-data/db.sqlite3 ".backup '/root/vw-$(date +%F).sqlite3'", плюс каталог attachments/, плюс выгрузка на другую машину. Схема с шифрованием и проверкой восстановления — в материале Vaultwarden: бэкап и восстановление паролей.
Какой сервер под Vaultwarden брать в MAATRIX
Vaultwarden — редкий случай, когда честный ответ «почти любой». Нагрузка не вычислительная: сервер хранит зашифрованные блобы и отдаёт их клиентам, вся криптография с мастер-паролем идёт на устройстве пользователя.
Минимум: 1 vCPU, 1 ГБ RAM, 20 ГБ NVMe. Хватает на команду из 10–20 человек с запасом: контейнер держится в районе 50 МБ, ещё 100–150 МБ уходит на демон Docker, Nginx и fail2ban. Ограничение честное — на 1 ГБ не стоит собирать Vaultwarden из исходников: компилятору Rust нужно 2 ГБ и больше, сборка упадёт с signal: 9, SIGKILL: kill от OOM-киллера. Ставьте готовый образ, он весит около 200 МБ.
Комфортный вариант: 2 vCPU, 2–4 ГБ RAM, 40 ГБ NVMe. Разница не в скорости входа, а в том, что рядом помещается остальное: локальные бэкапы за месяц, Postgres вместо SQLite (актуально от полусотни активных пользователей), вложения и снапшоты. Диск съедают именно вложения — ограничьте аппетит через USER_ATTACHMENT_LIMIT=102400, это 100 МБ на пользователя в килобайтах.
Приложения из каталога apps.maatrix.io ставятся на сервер автоматически при заказе: вставлять команды из этой статьи руками не нужно. Автоустановка работает на Ubuntu и Debian, доступы появляются в личном кабинете в разделе «Доступ». Ваша часть после этого — направить A-запись на выданный IP, выпустить сертификат и пройтись по разделам про ADMIN_TOKEN и SMTP.
Локация — Великобритания, Лондон. Аргумент здесь не скорость: хранилище синхронизирует килобайты, лишние 30 мс не заметит никто. Выбор про юрисдикцию и стабильность адреса — европейское правовое поле, соседство с GDPR, чистый IP без репутации предыдущих жильцов и прямой доступ к европейскому push-ретранслятору bitwarden.eu. RTT из Москвы — около 45–55 мс, из Берлина и Амстердама единицы миллисекунд, что удобно распределённой команде. Если в хранилище лежат персональные данные российских сотрудников и вы под 152-ФЗ — берите российскую локацию (где законно держать сервер с персональными данными).
Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT: иностранная карта не нужна, хотя сервер стоит в Лондоне. И трезвая оговорка: один сервер — одна точка отказа. Свой Vaultwarden дешевле и приватнее облака, но резервные копии на другую машину здесь не «хорошая практика», а условие, при котором вся затея имеет смысл.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть VaultwardenОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Можно ли обойтись без домена и работать по IP?
Практически нет. Клиенты Bitwarden требуют валидный HTTPS: с самоподписанным сертификатом расширение отвечает Failed to fetch, а мобильное приложение отказывается доверять цепочке. Домен плюс сертификат Let's Encrypt — минимальный рабочий комплект.
Забыл ADMIN_TOKEN, как попасть в /admin?
Восстанавливать нечего — сгенерируйте новый через docker exec -it vaultwarden /vaultwarden hash --preset owasp и замените значение. Если вы сохраняли настройки кнопкой в панели, токен лежит в /data/config.json и перекрывает переменную окружения: правьте там же.
Что произойдёт, если сервер пропадёт?
Уже авторизованные клиенты продолжат открывать хранилище — у них есть локальная зашифрованная копия. Перестанут работать синхронизация и вход на новых устройствах. Восстановление требует db.sqlite3 и каталога attachments/; мастер-пароль по устройству архитектуры не восстанавливается ничем.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.