Vaultwarden est un serveur compatible Bitwarden, réécrit en Rust, conçu pour le self-hosting léger. Il parle la même API que Bitwarden, donc les clients officiels (extension, mobile, bureau) fonctionnent avec lui sans modification. Ce guide le déploie avec Docker Compose, explique pourquoi le HTTPS est obligatoire, et couvre les pièges réels : ADMIN_TOKEN, fermeture des inscriptions, sauvegardes et durcissement. Lab vérifié sur la version 1.36.0.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déployer Vaultwarden avec Docker Compose
- Comprendre pourquoi HTTPS est obligatoire et le mettre en place
- Sécuriser le panneau admin (
ADMIN_TOKEN) et fermer les inscriptions - Sauvegarder le coffre sans le corrompre
Vaultwarden ou Bitwarden : lequel self-hoster
Section intitulée « Vaultwarden ou Bitwarden : lequel self-hoster »Vaultwarden n'est pas un produit Bitwarden officiel : c'est une réimplémentation communautaire de l'API, non affiliée à Bitwarden, Inc. Son atout est la légèreté : une seule image, une base SQLite, une empreinte mémoire minime, là où le serveur Bitwarden officiel est bien plus lourd à héberger.
Le revers est la maturité de processus. Vaultwarden n'a pas de certification SOC 2, pas d'équipe sécurité dédiée ni d'audit formel, contrairement à Bitwarden officiel. Il convient très bien à un homelab, une famille ou une petite équipe qui maîtrise HTTPS et les sauvegardes. Pour un usage régulé ou entreprise (SSO, conformité, support éditeur), c'est le serveur Bitwarden officiel qu'il faut.
Prérequis
Section intitulée « Prérequis »- Un hôte Linux avec Docker et Docker Compose
- Un nom de domaine (DNS valide) pour le certificat TLS, pas une simple IP
- Notions de reverse proxy et de gestion de secrets
Étape 1 - Déployer avec Docker Compose
Section intitulée « Étape 1 - Déployer avec Docker Compose »Créez un docker-compose.yml. On épingle la version (1.36.0) plutôt que latest, pour un déploiement reproductible.
services: vaultwarden: image: vaultwarden/server:1.36.0 container_name: vaultwarden restart: unless-stopped environment: DOMAIN: "https://vault.exemple.fr" SIGNUPS_ALLOWED: "true" # temporaire : on fermera après création du compte volumes: - ./vw-data:/data ports: - "127.0.0.1:11001:80" # exposé en local seulement, derrière le reverse proxyLe conteneur écoute en interne sur le port 80. On le publie sur 127.0.0.1:11001 : il n'est pas exposé directement à Internet, le reverse proxy s'en chargera (étape 2). Démarrez et suivez les logs :
docker compose up -d && docker compose logs -fAu démarrage, Vaultwarden annonce sa version et lance son serveur :
| Starting Vaultwarden || Version 1.36.0 |[start][INFO] Rocket has launched from http://0.0.0.0:80Vérifiez qu'il répond, sans même ouvrir un navigateur :
curl -s http://127.0.0.1:11001/alive # -> un horodatage ISOcurl -s http://127.0.0.1:11001/api/version # -> "1.36.0"Une réponse sur /alive et la version sur /api/version confirment que le serveur tourne et que le volume vw-data est bien initialisé.
Étape 2 - Le HTTPS est obligatoire
Section intitulée « Étape 2 - Le HTTPS est obligatoire »C'est le piège n°1, et il n'est pas négociable. Le coffre web de Bitwarden utilise les Web Crypto APIs du navigateur, que les navigateurs ne rendent disponibles que dans un contexte sécurisé : https://, ou http://127.0.0.1 sur la machine locale. Depuis une autre machine en HTTP simple, l'interface se charge mais toutes les opérations de chiffrement échouent silencieusement : le déverrouillage tourne en boucle, la connexion reste bloquée sur un écran de chargement.
Ce n'est pas une invention de Vaultwarden, c'est une règle des navigateurs imposée par les standards : aucune option ne la contourne. La nuance utile : c'est HTTPS qui est obligatoire, pas le reverse proxy en lui-même. Mais en pratique, le reverse proxy est la voie la plus simple pour obtenir un certificat valide, gérer le renouvellement et contrôler les en-têtes.
Caddy est le choix recommandé pour débuter : il obtient et renouvelle le certificat Let's Encrypt automatiquement. Un Caddyfile minimal :
vault.exemple.fr { reverse_proxy 127.0.0.1:11001}Caddy gère seul le TLS et transmet correctement les en-têtes WebSocket (Upgrade, Connection) nécessaires aux notifications temps réel (activées par défaut depuis la 1.29.0, sur le port HTTP standard depuis la 1.31.0). La variable DOMAIN du compose doit correspondre à l'URL HTTPS publique.
Étape 3 - Sécuriser le panneau admin
Section intitulée « Étape 3 - Sécuriser le panneau admin »Vaultwarden expose un panneau d'administration sur /admin (configuration serveur, gestion des utilisateurs, diagnostics). Il est protégé par un ADMIN_TOKEN. Ne mettez jamais un mot de passe en clair : depuis la 1.28.0, Vaultwarden avertit si le token n'est pas un hash argon2id. Générez-le avec la commande intégrée, en mode interactif (un vrai terminal est requis) :
docker run --rm -it vaultwarden/server:1.36.0 /vaultwarden hash --preset owaspLa commande demande le mot de passe deux fois puis affiche une chaîne PHC argon2id de cette forme :
$argon2id$v=19$m=19456,t=2,p=1$<sel-base64>$<hash-base64>Mieux : si vous n'utilisez le panneau admin qu'une fois pour la configuration initiale, désactivez-le ensuite. Retirer la variable ne suffit pas si la valeur a été persistée : assurez-vous qu'aucun ADMIN_TOKEN n'est défini ET qu'aucune clé admin_token n'existe dans config.json, puis redémarrez. S'il reste actif, restreignez /admin par VPN ou liste d'IP au niveau du reverse proxy : c'est une surface d'attaque à forte valeur, à ne jamais exposer publiquement.
Étape 4 - Fermer les inscriptions
Section intitulée « Étape 4 - Fermer les inscriptions »Avec SIGNUPS_ALLOWED: "true", n'importe qui atteignant l'URL peut créer un compte sur votre serveur. Créez votre compte, puis passez la variable à false et redémarrez.
Trois pièges à connaître :
- Même avec les inscriptions fermées, le formulaire reste visible ; le refus n'apparaît qu'à la soumission.
- Si
SIGNUPS_DOMAINS_WHITELISTest défini,SIGNUPS_ALLOWEDest ignoré : une whitelist mal réglée peut rouvrir les inscriptions à votre insu. - Un propriétaire d'organisation peut toujours inviter des utilisateurs, même inscriptions fermées. Pour bloquer aussi les invitations, c'est un réglage séparé.
Sauvegarde
Section intitulée « Sauvegarde »Le /data réel après quelques minutes d'usage contient exactement ceci :
db.sqlite3 db.sqlite3-shm db.sqlite3-wal rsa_key.pem tmp/Tout l'état (entrées, utilisateurs, organisations) est dans la base SQLite, et la clé rsa_key.pem signe les jetons d'authentification. Deux règles tirées des galères réelles de la communauté :
- Ne copiez jamais
db.sqlite3à chaud. Les fichiers-walet-shmprovoquent une corruption. UtilisezVACUUM INTO(ou la commande.backupde SQLite) sur une copie cohérente, et avant une restauration, supprimez tout-wal/-shmpérimé. - N'oubliez pas les pièces jointes. Une restauration de la seule base recrée les entrées mais casse les pièces jointes : sauvegardez tout
/data, dont le dossierattachments/(créé dès la première pièce jointe) etconfig.json(créé si la page admin a servi).
Ne placez pas /data sur un partage réseau (NFS, SMB) : SQLite y est sujet à corruption. Appliquez une politique 3-2-1. Après restauration, prévoyez de reconnecter chaque client et de re-saisir les 2FA (les sessions sont invalidées).
Durcissement
Section intitulée « Durcissement »Si le serveur est exposé sur Internet, fail2ban bannit les attaques par force brute. Vaultwarden journalise les échecs (EXTENDED_LOGGING=true par défaut, avec un LOG_FILE), ce qui permet ce filtre :
[Definition]failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$Deux pièges classiques :
- L'IP réelle. Derrière un reverse proxy, le log enregistre
127.0.0.1au lieu de l'IP de l'attaquant : fail2ban bannit le proxy, pas l'attaquant. Transmettez l'IP réelle via en-tête (X-Real-IP, ouCF-Connecting-IPderrière Cloudflare). - Docker et netfilter. Avec Vaultwarden en conteneur, les règles de ban peuvent atterrir dans une chaîne que le routage réseau Docker ne traverse pas : fail2ban logge le ban mais l'attaquant passe quand même. C'est un problème d'architecture firewall, pas de regex.
Question de fond : faut-il exposer le coffre sur Internet ? Beaucoup d'auto-hébergeurs ne l'exposent pas et y accèdent par VPN (WireGuard, Tailscale), au prix d'une synchronisation indisponible hors du réseau. Pensez aussi à la segmentation réseau : un appareil déjà compromis sur le LAN peut atteindre le coffre sans faille exposée sur Internet.
Sécurité : épingler une version récente
Section intitulée « Sécurité : épingler une version récente »Vaultwarden corrige régulièrement des failles. Début 2026, plusieurs advisories de sévérité élevée ont été publiés (contournement de protection anti-force-brute, problèmes liés au SSO, SSRF via l'endpoint d'icônes), corrigés dans les versions récentes dont la 1.36.0. Épinglez une version à jour et suivez les advisories de sécurité du projet. N'inventez pas de numéro CVE : certains advisories sont publiés sans CVE assigné.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Correction |
|---|---|---|
| Coffre web bloqué sur l'écran de chargement | Accès en HTTP simple (pas de contexte sécurisé) | Passer en HTTPS (reverse proxy) ou tester en http://127.0.0.1 local |
| Login admin échoue après config du token | $ non échappés dans le compose | Doubler chaque $ en $$ dans le YAML |
| Notifications temps réel absentes | En-têtes WebSocket non transmis | Configurer le proxy pour passer Upgrade/Connection |
| fail2ban ne bannit personne d'utile | IP réelle non transmise (proxy) | Configurer X-Real-IP / CF-Connecting-IP |
| Base corrompue après sauvegarde | Copie à chaud avec -wal/-shm | Utiliser VACUUM INTO, purger les -wal périmés |
À retenir
Section intitulée « À retenir »- Vaultwarden est un serveur Bitwarden-compatible léger, non officiel : parfait pour le homelab, pas pour un usage régulé.
- HTTPS est obligatoire (contexte sécurisé des navigateurs) : un reverse proxy comme Caddy est la voie la plus simple.
- Le panneau admin se protège par un
ADMIN_TOKENargon2, avec les$doublés en Compose, et se désactive après usage. - Fermez les inscriptions (
SIGNUPS_ALLOWED: false) et méfiez-vous de la whitelist et des invitations. - Sauvegardez tout
/data(jamais la SQLite à chaud, jamais les pièces jointes oubliées), hors partage réseau. - Épinglez une version récente et suivez les advisories de sécurité.