Labs Veille A propos Explorer les labs →

Bitwarden Self-Hosted : Déploiement type entreprise

Déploiement complet de Bitwarden Self-Hosted en environnement entreprise sur Ubuntu 24.04 user dédié, certificat TLS existant, SMTP, politiques de sécurité, sauvegarde et mise à jour.

K
Komi Kpodohouin
Voir tous les labs →
Publié le | 12 min de lecture | 2 heures

En entreprise, les mots de passe sont encore souvent stockés dans des fichiers Excel ou sur des pense-bêtes. Ces pratiques exposent directement le système d’information à des risques de compromission.

Il devient donc essentiel de fournir aux utilisateurs un outil sécurisé et simple pour gérer leurs accès.

Bitwarden en self-hosted, solution open source, permet de centraliser et sécuriser les mots de passe tout en gardant un contrôle total sur les données, hébergées en interne.

Ce lab s’adresse aux équipes IT souhaitant déployer une solution robuste sur leur propre infrastructure.

Ce lab utilise le nginx intégré à Bitwarden comme seul point d’entrée TLS. Pas de reverse proxy externe.

Prérequis

Les éléments suivants doivent être en place avant de commencer. Ce lab ne les couvre pas.

Infrastructure :

ÉlémentDétail
ServeurUbuntu 24.04, accessible en SSH
IP publiqueFixe, ports 80 et 443 ouverts vers Internet
Nom de domaineAvec accès au gestionnaire DNS
Sous-domainebitwarden.example.com créé et propagé vers l’IP du serveur
Certificat TLSWildcard ou dédié couvrant bitwarden.example.com

Sécurité du serveur

Positionnement

  • VLAN serveur sécurisé isolé

Accès

  • Accès HTTPS uniquement via le firewall
  • Reverse proxy en DMZ

Mesures de sécurité

  • Authentification à deux facteurs (2FA) obligatoire
  • Sauvegardes régulières avec chiffrement des données
  • Supervision, journalisation et analyse des logs

Ressources serveur :

RessourceMinimumRecommandé
CPU2 vCPU4 vCPU
RAM4 GB6 GB
Disque40 GB80 GB
Bitwarden utilise Microsoft SQL Server (MSSQL) comme base de données. MSSQL consomme entre 1.5 et 2 GB de RAM au démarrage, d’où le minimum de 4 GB. Déploie Bitwarden sur une VM et non un conteneur LXC, MSSQL ayant des exigences noyau incompatibles avec les LXC Proxmox.

Certificat TLS :

Disposer du certificat et la clé privée :

  • certificate.crt : le certificat (chaîne complète si possible)
  • private.key : la clé privée

Les deux fichiers du certificat TLS placés dans le dossier de destination sur le serveur.

Le sous-domaine DNS du serveur doit être créé et propagé avant de démarrer l’installation. Vérifie la propagation avec nslookup bitwarden.example.com : vous devriez voir l’IP de votre serveur.

Vérification de la propagation DNS — le sous-domaine retourne bien l’IP du serveur.


Étape 1 — Préparer le serveur

Mettre à jour le système

apt update && apt upgrade -y

Installer Docker

Suis la documentation officielle Docker pour Ubuntu :

👉 https://docs.docker.com/engine/install/ubuntu/

Verifier que docker tourne

sudo docker run hello-world

Docker fonctionne correctement — l’image hello-world a bien été téléchargée et exécutée.

Désactiver IPv6 pour Docker

Bitwarden tente de télécharger ses images via IPv6 sur certaines configurations, ce qui provoque des timeouts. Désactive IPv6 au niveau de Docker avant de continuer.

nano /etc/docker/daemon.json

copier et coller ce script dans votre fichier daemon.json ouvert

{
  "ipv6": false
}

Ensuite redemarrer docker

systemctl restart docker

Mettre à jour le DNS systemd-resolved

Sur Ubuntu 24.04, systemd-resolved écoute sur 127.0.0.53 et peut provoquer des timeouts DNS lors du téléchargement des images Bitwarden depuis ghcr.io. Il est nécessaire de le désactiver et configurer un DNS statique fiable.

systemctl disable systemd-resolved
systemctl stop systemd-resolved
rm /etc/resolv.conf
nano /etc/resolv.conf

Ici, 10.10.1.10 est l’ip de notre server DNS en local

nameserver 10.10.1.10

Vérifie la résolution :

nslookup ghcr.io

La résolution DNS de ghcr.io retourne une IP — le registre d’images Bitwarden est accessible.

Corriger le hostname

Ouvrir le dossier hosts

nano /etc/hosts

Mettre à jour :

127.0.0.1    localhost
127.0.1.1    bitwarden.example.com

Remplacer bitwarden.example.com par le hostname réel de votre serveur. Tout endroit ou vous verrez example.bitwarden.com dans ce lab, le remplacer par le FQDN de votre serveur

Vérifie que le domaine répond bien depuis le serveur :

ping -c 4 bitwarden.example.com

Le serveur répond correctement aux pings sur son propre FQDN.


Étape 2 — Créer le compte de service Bitwarden

La documentation officielle Bitwarden recommande de ne pas installer en root. Créer un compte de service dédié qui isolera Bitwarden sur le serveur.

# Créer l'utilisateur bitwarden
adduser bitwarden
# Définir un mot de passe fort
passwd bitwarden
# Ajouter bitwarden au groupe docker
usermod -aG docker bitwarden
# Créer le répertoire d'installation
mkdir /opt/bitwarden
# Définir les permissions
chmod -R 700 /opt/bitwarden
# Bitwarden devient propriétaire du dossier
chown -R bitwarden:bitwarden /opt/bitwarden
Toutes les commandes d’installation qui suivent doivent être exécutées en tant qu’utilisateur bitwarden depuis /opt/bitwarden. Ne pas installer en root.
# se connecter en tant qu'utilisateur bitwarden
su - bitwarden
# se positionner dans le bon repertoire
cd /opt/bitwarden

Étape 3 — Placer le certificat TLS

Bitwarden s’attend à trouver les fichiers de certificat dans un dossier spécifique avant le démarrage. Crée cette structure depuis votre compte administrateur (avec sudo).

# Créer le dossier de certificats
mkdir -p /opt/bitwarden/bwdata/ssl/bitwarden.example.com

Copier les fichiers de certificat dans les dossiers suivants sur le serveur bitwarden. Utiliser un outil comme WINSCP pour copier le certificat et la clé privée depuis votre poste vers les dossiers suivant sur le serveur bitwarden

Le dossier dans lequel il faudra mettre les certificats est /opt/bitwarden/bwdata/ssl/bitwarden.example.com/ nouvellement créé précédement

# Ici certificate.crt est le certificat et private.key est la clé privée
/opt/bitwarden/bwdata/ssl/bitwarden.example.com/certificate.crt
/opt/bitwarden/bwdata/ssl/bitwarden.example.com/private.key

NB : Ne pas oublier de remplacer private.key par le vrai nom de votre clé privée

# Corriger les permissions
chown -R bitwarden:bitwarden /opt/bitwarden/bwdata/ssl/
chmod 600 /opt/bitwarden/bwdata/ssl/bitwarden.example.com/private.key

Vérifier que les fichiers sont bien en place :

ls -la /opt/bitwarden/bwdata/ssl/bitwarden.example.com/

Les fichiers certificate.crt et private.key sont présents avec les bonnes permissions.

Vérifie que le certificat couvre bien ton domaine :

openssl x509 -in /opt/bitwarden/bwdata/ssl/bitwarden.example.com/certificate.crt \
  -noout -subject -dates -ext subjectAltName

Le certificat wildcard couvre bien le domaine cible — les dates de validité et les SANs sont visibles.

Utiliser un certificat wildcard *.example.com, il couvre automatiquement bitwarden.example.com et tous les futurs sous-domaines. C’est la configuration recommandée en entreprise un seul certificat à renouveler pour tous les services.

Étape 4 — Obtenir les identifiants d’installation

Bitwarden nécessite un Installation ID et une Installation Key pour s’enregistrer auprès des serveurs Bitwarden. Ces identifiants permettent à votre instance de recevoir les mises à jour et les licences.

  1. Aller sur https://bitwarden.com/host/
  2. Mettre un compte admin, choisir la région et faire Submit

Formulaire de génération des identifiants sur bitwarden.com/host — renseigner le domaine et la région.

  1. Copie l’Installation ID et l’Installation Key: ils ne s’affichent qu’une seule fois

L’Installation ID et la Key générés — à copier immédiatement, ils ne s’affichent qu’une fois.

Ces identifiants sont liés à votre domaine. Si vous changez de domaine, vous devrez en générer de nouveaux sur bitwarden.com/host. Juste pour précision l’id et la clé affichés sont confidentiels, NE JAMAIS LES EXPOSER.

Étape 5 — Installer Bitwarden

Switcher sur le compte bitwarden :

su - bitwarden
cd /opt/bitwarden

Télécharge et lance le script d’installation :

curl -Lso bitwarden.sh \
  "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux"

Appliquer les permissions

chmod 700 bitwarden.sh

Installer bitwarden

./bitwarden.sh install

Répondre aux questions comme suit :

QuestionRéponse
Enter the domain namebitwarden.example.com
Do you want to use Let’s Encryptn — on utilise notre propre certificat
Enter the database namebitwarden
Do you have a SSL certificate to usey
Is this a trusted SSL certificaten
Enter your Installation ID(colle l’ID de l’étape 4)
Enter your Installation Key(colle la Key de l’étape 4)
Enter your regionEU ou US selon votre région selectionée

Le script d’installation interactif — domaine, base de données, Installation ID/Key et région renseignés.

On répond n à “trusted SSL certificate” car Bitwarden demande ici si vous avez un fichier .crt séparé. Un certificat Let’s Encrypt ou un wildcard d’une CA reconnue n’a pas besoin de ce fichier séparé :la chaîne complète est déjà dans notre certificat certificate.crt.

Vérifier la structure créée

ls /opt/bitwarden/bwdata/

Le dossier bwdata généré par le script d’installation — tous les sous-dossiers de configuration sont présents.


Étape 6 — Configurer l’environnement

nano /opt/bitwarden/bwdata/env/global.override.env

Mettre à jour ces lignes dans le fichier selon votre environnement:

# SMTP — obligatoire pour les invitations et vérifications
globalSettings__mail__replyToEmail=noreply@example.com
globalSettings__mail__smtp__senderName=Bitwarden Entreprise
globalSettings__mail__smtp__host=mail.example.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__startTls=true
globalSettings__mail__smtp__username=noreply@example.com
globalSettings__mail__smtp__password=TON_MOT_DE_PASSE_SMTP

# Panneau d'administration
adminSettings__admins=admin@example.com

# Inscription des utilisateurs
globalSettings__disableUserRegistration=false

Paramètres SMTP selon le provider :

ProviderHostPortsslstartTls
Gmailsmtp.gmail.com587falsetrue
Office 365smtp.office365.com587falsetrue
SMTP SSL directmail.example.com465truefalse
SMTP local127.0.0.125falsefalse
Si votre mot de passe SMTP contient le caractère $, échappez-le en le doublant dans le fichier .env. Par exemple : monP@$$word s’écrit monP@$$$$word. Sans cet échappement, Docker interprétera $word comme une variable d’environnement vide.

Le fichier global.override.env après configuration — les lignes SMTP et admin sont surlignées. Les informations sensibles ont été floutées.

Après avoir modifié global.override.env, enregistrer les changements : CTRL + X, Y puis ENTRER

Voici l’apercu de notre fichier final. Les informations sensibles ont été floutté pour des raisons de sécurité

Le fichier global.override.env après configuration — les lignes SMTP et admin sont surlignées. Les informations sensibles ont été floutées.

Appliquer les changements avec la commande

./bitwarden.sh restart
Différence entre les deux commandes de mise à jour de configuration : ./bitwarden.sh restart applique les changements de global.override.env. ./bitwarden.sh rebuild reconstruit les assets depuis config.yml — à utiliser si tu changes les ports ou la configuration nginx.

Étape 7 — Démarrer Bitwarden

cd /opt/bitwarden
./bitwarden.sh start

Le premier démarrage prend entre 3 et 7 minutes : MSSQL initialise la base de données et applique toutes les migrations.


Étape 8 — Vérifications de santé

Les 11 conteneurs doivent être healthy

docker ps | grep bitwarden
Si certains conteneurs restent en unhealthy après 10 minutes, MSSQL est probablement en cours d’initialisation. Attends encore quelques minutes. Si le problème persiste, consulte les logs avec docker logs bitwarden-mssql.

Nginx répond correctement

curl -k -I https://localhost

Nginx retourne HTTP/2 200 — les 11 conteneurs sont healthy et le service est opérationnel.

Le certificat est bien chargé

echo | openssl s_client -connect localhost:443 2>/dev/null \
  | openssl x509 -noout -subject -dates -ext subjectAltName

Le certificat wildcard est bien chargé par nginx — le domaine, les dates de validité et les SANs sont corrects.


Étape 9 — Créer le premier compte et accéder au panneau admin

Créer le compte utilisateur

Ouvrir https://bitwarden.example.com dans votre navigateur. La page de connexion Bitwarden s’affiche. Cliquer sur Create account

La page de connexion Bitwarden — l’instance est accessible via HTTPS avec un certificat valide.

Entrer un mail

Formulaire de création de compte — renseigner l’email qui servira aussi à accéder au panneau /admin.

Définis un mot de passe maître fort : c’est le seul mot de passe que l’utilisateur devra retenir.

Définition du mot de passe maître — il doit respecter les critères de complexité recommandés par Bitwarden.

Une fois connecté, Bitwarden propose d’installer l’extension navigateur. Il est conseillé de ne pas installer l’extension dans le navigateur. Privilégez l’application desktop. Cette premiere connexion nous permet juste la création du compte.

Bitwarden propose l’installation de l’extension navigateur après la première connexion.

Le coffre est désormais accessible depuis le tableau de bord.

Le coffre Bitwarden est vide et prêt — l’instance est opérationnelle et accessible aux utilisateurs.

Le premier compte créé n’est pas automatiquement administrateur de l’instance. L’administration de l’instance se gère via le panneau https://bitwarden.example.com/admin séparé, accessible uniquement aux emails listés dans adminSettings__admins.

Accéder au panneau d’administration

https://bitwarden.example.com/admin

Entrer ton email et clique Send email. Tu recevras un lien magique clique dessus pour accéder au panneau sans mot de passe.

Depuis le panneau admin on peut:

  • Gérer les utilisateurs et leurs comptes
  • Configurer les organisations
  • Consulter les logs d’événements
  • Gérer les licences

Étape 10 — Configurer les politiques de mots de passe

Les politiques de mots de passe s’appliquent au niveau des organisations. Crée d’abord une organisation depuis l’interface web, puis configure les politiques.

Depuis l’interface web → Organisation → Paramètres → Politiques :

PolitiqueRecommandation entreprise
Authentification à deux facteursActivée — obligatoire pour tous
Exigences du mot de passe maître12 caractères min, complexité forte
Générateur de mots de passeActivée
Réinitialisation du compte adminActivée
Coffre personnelSelon politique interne

Étape 11 — Sauvegarde et restauration

Ce qu’il faut sauvegarder

Bitwarden stocke ses données dans deux endroits critiques :

La base de données MSSQL — coffres, utilisateurs, organisations, politiques.

Le dossier bwdata — configuration, pièces jointes, clés de chiffrement.

Les données sont chiffrées avec des clés stockées dans bwdata/env/global.override.env. Sans ce fichier, la base de données est indéchiffrable même avec une sauvegarde complète. Sauvegarde TOUJOURS le dossier bwdata complet.

Script de sauvegarde automatique

nano /usr/local/bin/bitwarden-backup.sh
#!/bin/bash
BACKUP_DIR="/opt/backups/bitwarden"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30

mkdir -p $BACKUP_DIR
echo "[$(date)] Démarrage de la sauvegarde..."

cd /opt/bitwarden
./bitwarden.sh backup

tar -czf "$BACKUP_DIR/bitwarden_full_$DATE.tar.gz" \
    /opt/bitwarden/bwdata/

find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "[$(date)] Sauvegarde terminée : bitwarden_full_$DATE.tar.gz"
chmod +x /usr/local/bin/bitwarden-backup.sh

# Sauvegarde automatique quotidienne à 2h du matin
crontab -e
# Ajouter :
0 2 * * * /usr/local/bin/bitwarden-backup.sh >> /var/log/bitwarden-backup.log 2>&1

Procédure de restauration

# 1. Arrêter Bitwarden
./bitwarden.sh stop

# 2. Supprimer le bwdata et restaurer depuis la sauvegarde
rm -rf /opt/bitwarden/bwdata
tar -xzf /opt/backups/bitwarden/bitwarden_full_DATE.tar.gz -C /

# 3. Redémarrer
./bitwarden.sh rebuild
./bitwarden.sh start

# 4. Vérifier
curl -k -I https://localhost

Étape 12 — Mise à jour

# Toujours sauvegarder avant une mise à jour
./bitwarden.sh backup

# Mettre à jour le script bitwarden.sh
./bitwarden.sh updateself

# Mettre à jour Bitwarden
./bitwarden.sh update

Fréquences recommandées :

TypeDélai
Sécurité / CVE critiqueSous 48 heures
Mises à jour mineuresDans la semaine
Mises à jour majeuresFenêtre de maintenance planifiée

Consulte les notes de version avant chaque mise à jour majeure : https://github.com/bitwarden/server/releases


Référence des commandes bitwarden.sh

CommandeDescription
./bitwarden.sh installLance l’installateur interactif
./bitwarden.sh startDémarre tous les conteneurs
./bitwarden.sh restartRedémarre — applique les changements de global.override.env
./bitwarden.sh stopArrête tous les conteneurs
./bitwarden.sh rebuildReconstruit les assets depuis config.yml
./bitwarden.sh updateMet à jour conteneurs et base de données
./bitwarden.sh updateselfMet à jour le script bitwarden.sh
./bitwarden.sh backupCrée une sauvegarde de la base de données
./bitwarden.sh renewcertRenouvelle les certificats
./bitwarden.sh uninstallDésinstalle Bitwarden (avec confirmation)

Dépannage

Les conteneurs restent en unhealthy

docker logs bitwarden-mssql 2>&1 | tail -20
docker logs bitwarden-api 2>&1 | tail -20

MSSQL est souvent le premier à poser problème. S’il n’est pas healthy, les autres conteneurs attendent.

Nginx retourne 502

curl -k -I https://localhost
docker logs bitwarden-nginx 2>&1 | tail -10

Un 502 au démarrage est normal — les backends ne sont pas encore prêts. Attends 2-3 minutes et reteste.

Erreur de téléchargement des images Docker

# Vérifier la résolution DNS
nslookup ghcr.io

# Tester la connectivité
curl -v --max-time 10 https://ghcr.io/v2/

Si DNS timeout, vérifie /etc/resolv.conf — systemd-resolved doit être désactivé.

Emails non reçus

docker logs bitwarden-api 2>&1 | grep -i "mail\|smtp" | tail -10

Teste la connexion SMTP manuellement :

apt install -y swaks
swaks --to admin@example.com \
      --from noreply@example.com \
      --server mail.example.com \
      --port 587 \
      --auth LOGIN \
      --auth-user noreply@example.com \
      --auth-password <ton-mot-de-passe-smtp> \
      --tls

Mot de passe SMTP avec caractères spéciaux

Si ton mot de passe contient $, !, ou d’autres caractères spéciaux, double le $ dans global.override.env :

# Mot de passe réel : monP@$sword
# Dans global.override.env :
globalSettings__mail__smtp__password=monP@$$sword

Checklist de mise en production

  • Sous-domaine DNS créé et propagé
  • Certificat TLS valide — cadenas vert dans le navigateur
  • Les 11 conteneurs affichent healthy
  • curl -k -I https://localhost retourne HTTP/2 200
  • Emails de test reçus (invitation, vérification de compte)
  • Accès au panneau /admin vérifié
  • Sauvegarde automatique configurée et testée
  • Politique de mots de passe activée dans l’organisation
  • 2FA obligatoire pour tous les membres
  • Procédure de mise à jour documentée