OPNsense sur Proxmox : remplacer sa box opérateur par un vrai firewall
Le ZenWifi XT8 est un très bon point d'accès WiFi mesh. Son firewall intégré, en…
J’utilisais Bitwarden cloud depuis deux ans sur le compte gratuit. Ça fonctionnait bien, les clients officiels sont excellents, et je n’avais aucune raison urgente de migrer – jusqu’au jour où j’ai réalisé que toutes mes entrées de mots de passe, y compris les accès bancaires et les codes 2FA de mes comptes sensibles, reposaient entièrement sur un service tiers que je ne contrôle pas. Avec un homelab opérationnel depuis plusieurs mois, continuer à externaliser ça ne tenait plus vraiment.
Bitwarden publie son serveur en open source, mais il est conçu pour du multi-tenant à grande échelle : il tourne avec des dépendances .NET et MSSQL Server, consomme plusieurs GB de RAM, et se configure avec une douzaine de conteneurs. Pour un homelab familial, c’est disproportionné.
Vaultwarden (anciennement Bitwarden_rs) est une réimplémentation de l’API Bitwarden en Rust, compatible à 100 % avec tous les clients officiels – extensions Chrome et Firefox, apps iOS, apps Android, client desktop. Un seul conteneur, une base SQLite (ou PostgreSQL si on préfère), moins de 100 MB de RAM au repos.
La distinction importante : Vaultwarden n’est pas un fork de Bitwarden. C’est une implémentation indépendante du protocole. Les clients officiels Bitwarden ne savent pas qu’ils parlent à Vaultwarden – ils voient juste une API Bitwarden conforme.
Le déploiement se fait sur LXC 103, qui héberge déjà Traefik et sert de point d’entrée HTTPS pour la plupart des services du homelab. Debian 12, Docker Compose, 2 vCPU, 2 GB RAM.
Le prérequis le plus contraignant : HTTPS obligatoire. Les extensions Bitwarden dans Chrome et Firefox refusent catégoriquement de se connecter à un serveur HTTP – même en local, même sur un réseau privé. Ce n’est pas un avertissement contournable, c’est un blocage au niveau du client. Traefik avec Let’s Encrypt gère le certificat via le challenge DNS – le domaine vault.arewel.com pointe vers l’IP publique de la box, avec un enregistrement A.
version: "3.9"
services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
volumes:
- /opt/vaultwarden/data:/data
environment:
DOMAIN: "https://vault.arewel.com"
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "true"
ADMIN_TOKEN_FILE: /run/secrets/vw_admin_token
TWO_FACTOR_ENABLED: "true"
SMTP_HOST: "smtp.gmail.com"
SMTP_FROM: "vault@arewel.com"
SMTP_PORT: "587"
SMTP_SECURITY: "starttls"
SMTP_USERNAME_FILE: /run/secrets/smtp_user
SMTP_PASSWORD_FILE: /run/secrets/smtp_pass
secrets:
- vw_admin_token
- smtp_user
- smtp_pass
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.rule=Host(vault.arewel.com)"
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
secrets:
vw_admin_token:
file: ./secrets/admin_token.txt
smtp_user:
file: ./secrets/smtp_user.txt
smtp_pass:
file: ./secrets/smtp_pass.txt
SIGNUPS_ALLOWED: "false" ferme les inscriptions publiques – indispensable dès que le service est exposé sur Internet. Les nouveaux comptes familiaux passent par des invitations envoyées depuis le compte administrateur. INVITATIONS_ALLOWED: "true" permet précisément ça.
ADMIN_TOKEN_FILE pointe vers un secret Docker plutôt que d’inclure le token en clair dans le fichier Compose. Le token est généré avec openssl rand -base64 48.
Sans SIGNUPS_ALLOWED: "false", n’importe qui peut créer un compte sur ton instance Vaultwarden si elle est exposée sur Internet. Couper les inscriptions avant d’ouvrir le port.
Depuis le client web Bitwarden (vault.bitwarden.com) : Settings > Export vault > Format : JSON (chiffré avec mot de passe).
Le format chiffré est important : le JSON non chiffré contient les mots de passe en clair. Le format chiffré protège le fichier avec un mot de passe symétrique qu’on choisit au moment de l’export – il faudra le saisir à l’import.
Le fichier exporté contient :
Depuis le client web Vaultwarden (https://vault.arewel.com) après avoir créé le premier compte : Tools > Import data > Format : Bitwarden (JSON, chiffré).
L’import des 247 entrées prend quelques secondes. Les dossiers sont recréés tels quels. Les URL associées à chaque entrée sont préservées.
Vérification après import : comparer le nombre d’entrées dans Bitwarden cloud (Settings > My Account > Purge vault affiche le compteur sans effacer) avec le nombre dans Vaultwarden. S’ils correspondent, la migration est complète pour les entrées de base.
Vaultwarden supporte les organisations Bitwarden – un espace partagé avec gestion de droits et collections séparées. J’ai créé l’organisation « Famille Calounx » depuis le panneau admin (https://vault.arewel.com/admin) plutôt que depuis le client, ce qui permet de l’associer directement au compte admin.
Structure des collections dans l’organisation :
Les membres de la famille reçoivent une invitation par email, créent leur compte, et sont ajoutés à l’organisation avec les permissions adaptées. Chaque membre a son coffre personnel sur le même serveur, invisible aux autres – sauf les collections partagées.
Trois comptes actifs à ce stade : le mien et deux membres de la famille qui avaient des comptes Bitwarden cloud indépendants. Chacun a exporté son coffre personnel depuis Bitwarden cloud et importé dans Vaultwarden.
Le 2FA TOTP côté Vaultwarden lui-même (pour se connecter à l’instance) est activé via la variable TWO_FACTOR_ENABLED: "true" et configuré par chaque utilisateur dans Security > Two-step login > Authenticator app.
L’app de référence reste le client Bitwarden officiel, qui peut également stocker les codes TOTP pour les sites tiers – c’est une fonctionnalité premium dans Bitwarden cloud, mais elle est disponible gratuitement dans Vaultwarden.
C’est la partie que j’avais sous-estimée. Le fichier JSON exporté depuis Bitwarden cloud ne contient pas les codes TOTP configurés pour les sites tiers (GitHub, Google, etc.). Ces codes sont stockés chiffrés différemment dans le backend Bitwarden, et l’export JSON ne les inclut pas – que ce soit le format chiffré ou non chiffré.
Résultat concret : j’avais environ 30 sites avec du 2FA TOTP configuré dans Bitwarden cloud. Après migration, toutes ces entrées sont présentes dans Vaultwarden mais sans le secret TOTP. Il a fallu les reconfigurer un par un, site par site, en allant dans les paramètres de sécurité de chaque service, désactivant l’ancien 2FA et en reconfigurant un nouveau secret TOTP depuis Vaultwarden.
Le temps réel passé : un peu moins d’une heure pour les 30 sites, en procédant par ordre de criticité (banques et emails en premier, le reste ensuite). Certains sites compliquent volontairement la reconfiguration du 2FA (ils demandent le code actuel avant de permettre la désactivation, ce qui nécessite d’avoir encore accès à l’ancien secret – ce que j’avais depuis l’app Authenticator sur mon téléphone).
Avant de migrer, liste tous tes sites avec TOTP actif dans Bitwarden. Prévois au minimum 1h pour la reconfiguration, plus longtemps si certains comptes ont des procédures de récupération complexes. Ne migre pas à la veille d’un week-end chargé.
Sur chaque appareil, il faut indiquer l’URL de l’instance Vaultwarden avant de se connecter.
Extension Chrome/Firefox : cliquer sur l’icône Bitwarden, puis sur « Se connecter ». Avant de saisir les identifiants, cliquer sur l’engrenage (ou « Settings » selon la version) et définir Self-hosted environment URL = https://vault.arewel.com. Sauvegarder, puis procéder à la connexion.
App iOS et Android : même logique – sur l’écran de connexion, un lien ou un bouton « Region » ou « Self-hosted » permet de saisir l’URL du serveur avant de s’authentifier.
L’expérience utilisateur une fois connecté est identique à Bitwarden cloud – remplissage automatique, génération de mots de passe, synchronisation instantanée entre appareils.
Le fichier critique est /opt/vaultwarden/data/db.sqlite3. Il contient l’intégralité du coffre – entrées, organisations, paramètres utilisateurs. Une corruption ou une perte de ce fichier sans backup, c’est la perte de tous les mots de passe de la famille.
Stratégie de sauvegarde en deux couches :
Couche 1 : Proxmox Backup Server
Le LXC 103 est sauvegardé par PBS chaque nuit (snapshot cohérent du conteneur complet, y compris /opt/vaultwarden/data/). En cas de crash, restauration en moins de 5 minutes.
Couche 2 : copie hebdomadaire sur NAS
Un script cron copie le fichier SQLite sur le DS414 chaque dimanche à 2h :
#!/bin/bash
TIMESTAMP=$(date +%Y%m%d-%H%M)
DEST="/mnt/synology/backups/vaultwarden/"
mkdir -p "$DEST"
# SQLite hot backup via l'API de copie cohérente
sqlite3 /opt/vaultwarden/data/db.sqlite3 ".backup '${DEST}/db-${TIMESTAMP}.sqlite3'"
# Nettoyage : garder les 8 dernières sauvegardes
ls -t "${DEST}"/db-*.sqlite3 | tail -n +9 | xargs -r rm
La commande .backup de sqlite3 effectue une copie cohérente sans verrouiller la base – plus fiable qu’un simple cp sur un fichier SQLite potentiellement en cours d’écriture.
Un coffre sans backup est une promesse de catastrophe. Le fichier SQLite de Vaultwarden est petit (<10 MB pour 247 entrées) et rapide à sauvegarder - il n'y a aucune excuse pour ne pas le faire.[/warning]
Après la migration :
Ce qui reste à surveiller : les mises à jour de l’image vaultwarden/server:latest. Je me suis abonné aux releases GitHub du projet pour être notifié des nouvelles versions et des éventuelles failles de sécurité. La politique de mise à jour que j’ai adoptée : lire le changelog avant de tirer la nouvelle image, tester en premier sur un compte de test, déployer dans les 7 jours suivant la release stable.
slug: vaultwarden-bitwarden-auto-heberge
meta: Migration Bitwarden cloud vers Vaultwarden auto-hébergé sur LXC Proxmox : HTTPS Traefik, 247 entrées, 3 comptes famille, 2FA TOTP, sauvegarde SQLite. (~150 chars)
tags: Vaultwarden, Bitwarden, mots de passe, Docker, Traefik, homelab, vie privée, 2FA
Cet article est vivant - corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.