Развертывание Vaultwarden в Docker на Synology
Полное практическое руководство: тома, docker-compose, обязательный HTTPS, админ-панель, почта, бэкапы и харденинг — всё, через что я сам проходил, поднимая приватный Bitwarden на своём NAS.
- Зачем вообще хостить пароли самому
- Vaultwarden против официального Bitwarden
- Что понадобится перед стартом
- Шаг 1 — каталоги и права доступа
- Шаг 2 — docker-compose.yml построчно
- Шаг 3 — первый запуск и проверка
- Шаг 4 — HTTPS через Nginx Proxy Manager
- Шаг 5 — админ-панель и ADMIN_TOKEN
- Шаг 6 — почта для приглашений и восстановления
- Шаг 7 — бэкапы, которые реально спасают
- Харденинг: что подкрутить сверх дефолта
- Обновления и обслуживание
- Частые проблемы и их причины
Зачем вообще хостить пароли самому
Когда я в очередной раз увидел новость об утечке из очередного облачного сервиса, стало окончательно понятно: хранить связку из полутора сотен паролей у стороннего провайдера — это удобно, но требует слепого доверия к чужой инфраструктуре, которую ты не контролируешь и не видишь. Vaultwarden решает именно эту проблему: та же экосистема клиентов Bitwarden (расширения для браузера, мобильные приложения, десктоп), но база данных физически лежит на моём NAS, а не где-то в дата-центре третьей компании.
Это не значит, что self-hosting снимает ответственность за безопасность — наоборот, теперь она полностью на вас. Зато пропадает риск массовой утечки «чужих» паролей вместе с миллионами других учётных записей, и вы точно знаете, кто и когда имел доступ к серверу.
Vaultwarden против официального Bitwarden
Vaultwarden — это независимая реализация серверной части протокола Bitwarden на Rust (изначально проект назывался bitwarden_rs). Он совместим с официальными клиентами, но не является продуктом компании Bitwarden Inc., поэтому не получает патчи безопасности напрямую от них — обновления делает community, и делает их довольно оперативно.
| Параметр | Vaultwarden | Bitwarden (официальный self-host) |
|---|---|---|
| Потребление RAM | ≈ 25–60 МБ | от 2–4 ГБ (набор микросервисов) |
| Организации и 2FA | включены бесплатно | часть в платной подписке |
| Официальная поддержка | нет, community | да |
| Подходит для | homelab, семья, небольшая команда | предприятия с требованиями к SLA |
Для одного NAS, семьи из нескольких человек и пары десятков расширенных фич вроде совместных сейфов и отчётов о слабых паролях Vaultwarden закрывает вопрос полностью, при этом почти не потребляя ресурсы, которые на том же хосте нужны для Nextcloud, Home Assistant и прочего.
Что понадобится перед стартом
- Synology NAS с установленным Container Manager (бывший Docker) и доступом по SSH.
- Домен или поддомен, указывающий на ваш NAS — даже для внутреннего использования он сильно упрощает работу с сертификатами.
- Уже развёрнутый реверс-прокси с поддержкой TLS — в этом гайде это Nginx Proxy Manager, но подойдёт Traefik или Caddy.
- 15–20 минут свободного времени и доступ к File Station или терминалу для создания папок.
Шаг 1 — каталоги и права доступа
01Создаём структуру томов
Прежде чем писать compose-файл, разведите данные и конфигурацию по отдельным подпапкам — это сильно упростит бэкапы и перенос на другой NAS в будущем. Через File Station или по SSH создайте:
mkdir -p /volume1/docker/vaultwarden/data mkdir -p /volume1/docker/vaultwarden/backups chown -R 1000:1000 /volume1/docker/vaultwarden
Папка data будет содержать зашифрованную SQLite-базу, вложения и ключи для 2FA — по сути, это единственное, что нужно бэкапить, чтобы полностью восстановить сервис. Отдельная папка backups пригодится в шаге 7.
data внутри общей папки, синхронизируемой Cloud Sync или похожими инструментами «на лету» — блокировки файла SQLite во время записи иногда конфликтуют с фоновой синхронизацией и приводят к повреждению базы.
Шаг 2 — docker-compose.yml построчно
02Собираем конфигурацию
Вынесем секреты в отдельный .env, а не будем хардкодить их прямо в compose-файле — так его можно спокойно держать в приватном git-репозитории:
DOMAIN=https://vault.мойдомен.ру ADMIN_TOKEN_HASH=$argon2id$v=19$m=65540,t=3,p=4$... TZ=Europe/Moscow
Значение ADMIN_TOKEN_HASH мы сгенерируем в шаге 5 — пока просто оставьте место под переменную. Сам compose-файл выглядит так:
services:
vaultwarden:
image: vaultwarden/server:1.32.7
container_name: vaultwarden
restart: unless-stopped
env_file: .env
environment:
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "true"
WEBSOCKET_ENABLED: "true"
LOG_LEVEL: "warn"
ROCKET_PORT: "80"
DOMAIN: "${DOMAIN}"
ADMIN_TOKEN: "${ADMIN_TOKEN_HASH}"
volumes:
- /volume1/docker/vaultwarden/data:/data
ports:
- "127.0.0.1:8080:80"
- "127.0.0.1:3012:3012"
networks:
- vaultwarden-net
networks:
vaultwarden-net:
driver: bridge
Несколько решений здесь неочевидны и стоят пояснения:
- Фиксированный тег образа вместо
latest— обновление контейнера должно быть осознанным действием, а не случайностью после перезапуска Container Manager. SIGNUPS_ALLOWED: "false"— самая частая ошибка новичков — оставить это включённым. Регистрацию нужно выключить сразу после создания собственного аккаунта, иначе теоретически кто угодно, кто найдёт ваш адрес, сможет зарегистрироваться.- Порты забинжены на
127.0.0.1, а не на все интерфейсы — наружу Vaultwarden отдаёт только реверс-прокси, напрямую с других устройств в сети порт 8080 недоступен. - Отдельный порт 3012 — это WebSocket-канал для мгновенной синхронизации между устройствами. Без него клиенты будут работать, но с задержкой обновления сейфа до 30 секунд.
Шаг 3 — первый запуск и проверка
03Поднимаем стек
cd /volume1/docker/vaultwarden docker compose up -d docker compose logs -f vaultwarden
В логах должна появиться строка о старте Rocket на порту 80 без ошибок подключения к базе. На этом этапе сервис уже доступен локально по адресу http://ip-нас:8080 — но заходить и создавать аккаунт стоит только после того, как поднят HTTPS: клиенты Bitwarden (и веб-расширение) требовательны к защищённому соединению и часть функций без него просто не активируется.
Шаг 4 — HTTPS через Nginx Proxy Manager
04Настраиваем проксирование
В Nginx Proxy Manager создайте новый Proxy Host с доменом vault.мойдомен.ру, указывающим на IP NAS и порт 8080. Отдельное внимание — вкладке WebSockets, без которой синхронизация в реальном времени работать не будет:
Обязательно добавьте два кастомных заголовка в конфигурацию хоста — Vaultwarden не работает корректно без прямой передачи реального IP и протокола:
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;
Сертификат Let's Encrypt выпускается прямо из интерфейса NPM — включите форс-редирект на HTTPS и HSTS во вкладке SSL, это закроет обычную ошибку «клиент не может подключиться» на мобильных устройствах, которые не принимают самоподписанные сертификаты.
Шаг 5 — админ-панель и ADMIN_TOKEN
05Защищаем панель администратора
Панель /admin даёт полный контроль над пользователями сервера, поэтому токен для неё должен храниться в виде хэша, а не открытым текстом — с версии 1.30 Vaultwarden поддерживает именно такой формат. Сгенерировать его можно прямо через контейнер:
docker exec -it vaultwarden ./vaultwarden hash
Команда попросит ввести пароль дважды и выведет строку вида $argon2id$v=19$m=65540,t=3,p=4$... — именно её вставьте в ADMIN_TOKEN_HASH в файле .env и перезапустите стек командой docker compose up -d.
Шаг 6 — почта для приглашений и восстановления
06Подключаем SMTP
Без настроенной почты приглашения в организацию и сброс пароля превращаются в ручную возню со ссылками из логов контейнера. Для личного использования достаточно приложения-пароля от Gmail или Яндекс.Почты:
SMTP_HOST=smtp.yandex.ru SMTP_FROM=vault-noreply@мойдомен.ру SMTP_PORT=465 SMTP_SECURITY=force_tls SMTP_USERNAME=vault-noreply@мойдомен.ру SMTP_PASSWORD=пароль-приложения
После перезапуска проверьте отправку через саму админ-панель — там есть отдельная кнопка тестового письма, которая избавляет от необходимости регистрировать тестовый аккаунт вслепую.
Шаг 7 — бэкапы, которые реально спасают
07Автоматизируем резервное копирование
SQLite не любит копирование «на горячую» через обычный cp — файл может оказаться в промежуточном состоянии записи. Правильный способ — встроенная команда бэкапа самой базы, которая гарантирует консистентный снимок:
#!/bin/bash STAMP=$(date +%Y%m%d-%H%M) DEST=/volume1/docker/vaultwarden/backups docker exec vaultwarden sqlite3 /data/db.sqlite3 ".backup '/data/backup-tmp.sqlite3'" docker exec vaultwarden mv /data/backup-tmp.sqlite3 /data/backup-tmp.sqlite3.done docker cp vaultwarden:/data/backup-tmp.sqlite3.done "$DEST/db-$STAMP.sqlite3" docker exec vaultwarden rm /data/backup-tmp.sqlite3.done find "$DEST" -name "db-*.sqlite3" -mtime +14 -delete
Повесьте скрипт на планировщик задач Synology (Task Scheduler → «Запланированная задача» → «Пользовательский скрипт») на ежедневный запуск ночью. Отдельно скопируйте и папку attachments внутри data, если в сейфах есть вложенные файлы — сам скрипт бэкапит только базу данных.
Харденинг: что подкрутить сверх дефолта
- Двухфакторная аутентификация обязательна для собственного аккаунта — TOTP или WebAuthn-ключ, без исключений.
- Ограничение по IP или fail2ban на уровне реверс-прокси против перебора паролей — Vaultwarden ведёт лог неудачных попыток входа, но сам блокировку по IP не делает.
SIGNUPS_DOMAINS_WHITELIST— если всё же нужна регистрация для семьи, ограничьте её конкретными доменами почты вместо полного открытия.- Организационная политика в разделе Organizations → Policies: принудительный 2FA для всех участников, минимальная сложность мастер-пароля.
- Не открывайте порт 8080 наружу напрямую через проброс портов роутера — единственная точка входа снаружи должна быть 443 на реверс-прокси.
Обновления и обслуживание
Проверяйте changelog на странице релизов Vaultwarden перед каждым обновлением — иногда меняется формат переменных окружения. Сам процесс простой:
./backup.sh docker compose pull vaultwarden docker compose up -d docker compose logs -f vaultwarden
Запуск бэкапа перед обновлением — не паранойя, а привычка, которая один раз действительно спасёт вечер.
Частые проблемы и их причины
| Симптом | Вероятная причина |
|---|---|
| синхронизация с задержкой | не проброшен или не проксирован порт 3012 (websocket) |
| мобильное приложение не подключается | сертификат не покрывает поддомен, либо не включён форс-HTTPS |
| «invalid admin token» | в .env остался старый нехэшированный токен после обновления образа |
| письма не приходят | SMTP_SECURITY не соответствует порту (465 требует force_tls, 587 — starttls) |
| база «database is locked» | синхронизация тома облачным клиентом поверх папки data |
Если после всех шагов сервис поднялся, сертификат зелёный, а 2FA включена — на этом Vaultwarden можно спокойно доверить пароли от всей остальной инфраструктуры, которую вы разворачиваете на этом же NAS.