Bitwarden
Aujourd'hui, nous allons déployer un serveur Bitwarden en Docker, un gestionnaire de mots de passe Open Source sous licence AGPL.
Freemium si vous souscrivez à leur offre en ligne, vous pouvez tout à fait héberger Bitwarden en docker (image non officielle), vous permettant d'accéder à la plupart des fonctionnalités réservées au freemium.
Je vous propose d'installer Bitwarden et de le rendre accessible au travers d'un serveur web, depuis internet, de façon sécurisée.
Prérequis
- Être coutumier de Docker
- Avoir pré-installé Docker est Docker-compose
- Avoir pré-installé OpenSSL
- Disposer d'un serveur web permettant de faire un reverse proxy et/ou être familier avec son utilisation. Dans le présent article, nous utilisons Nginx via l'image docker SWAG de linuxserver
- Si vous souhaitez rendre accessible depuis internet Bitwarden, votre serveur hôte doit être accessible sur le port 80 et le port 443. Typiquement si vous utilisez un Raspberrypi dans un réseau local, vous devrez faire un port forwarding depuis votre routeur (si c'est possible) vers l'IP locale de votre hôte, en s'assurant de rendre cette IP fixe.
Le présent tutoriel a été réalisé un serveur dédié sous Debian Buster, il a été reproduit sur un Raspberry Pi 3 Model B Plus Rev 1.3.
Répertoire de travail
Dans le présent tutoriel nous aurons comme répertoire de travail /docker
:
- Nous le créons avec :
sudo mkdir /docker
- On s'assurera que notre utilisateur ai les droits avec :
sudo chown -R <user>:<user> /docker
- L'arborescence ressemblera à ceci :
/docker/bitwarden
├── data
└── docker-compose.yml
Image docker : Vaultwarden
Il existe une image docker officielle, que nous n'allons pas utiliser par commodité. Il existe en effet une image non-officielle développée en Rust, Vaultwarden (elle s'appelait avant ça BitwardenRS) : Hub Docker - Github.
La mise en place est aisée et tout à fait adaptée à une utilisation typique d'un particulier ou de petite structure? De plus la communauté autour de cette image est grande et attentive, tout pour plaire au libriste que je suis.
Une documentation solide existe.
Fonctionnalités
Fondamentalement, une implémentation complète de l'API Bitwarden est fournie, notamment:
- Interface Web (équivalent à https://vault.bitwarden.com/)
- Support d'un Vault personnel
- Support d'une organisation Vault
- Partage de mot de passe et contrôle d'accès
- Collections
- Pièces jointes de fichiers
- Répertoires
- Favori
- Icônes de site Web
- Authentificateur Bitwarden (TOTP)
- Bitwarden Send (fonction sécurisée et éphémère pour transmettre des informations sensibles)
- Synchronisation en direct (Websocket uniquement) pour les clients de bureau / navigateur
- Corbeille (Suppression douce)
- Connexion en deux étapes par e-mail, Duo, YubiKey et FIDO U2F
Aussi :
Fonctionnalités manquantes : Certaines fonctions de Bitwarden ne sont pas encore implémentées (ou ne le seront pas sans PR), pour n'en citer que quelques-unes (liste détaillée) : SSO, Accès d'urgence, Synchronisation en direct pour mobile, etc.
Configuration
Docker-compose : Bitwarden
On commence en créant un fichier nommé docker-compose.yml
dans le répertoire de votre choix, avec votre éditeur de texte favori (nano ?).
Il vous faudra adapter selon vos besoins et votre infrastructure, notamment :
- le volume persistent; ici le chemin est relatif et monte le volume dans le répertoire courant
./data
- vous devrez générer
<generated_admin_token>
pour accéder à l'interface admin; dans un terminal exécutezopenssl rand -base64 48
(voir l a doc) - Déterminez le réseau docker
<network>
, si c'est pertinent pour vous. Dans mon cas j'utilise un réseau docker, qui me permet de faire un reverse proxy avec linuxserver/SWAG sans devoir exposer les ports dans mon container Bitwarden, en dehors du réseau docker. Les containers SWAG et Bitwarden sont dans le même réseau.
Aussi lors du première démarrage, il vous faudra passer l'option SIGNUPS_ALLOWED
sur true et la désactiver (false donc) par la suite si vous ne souhaitez pas permettre la création de compte. A savoir que si vous modifiez la fonctionnalité depuis l'admin, cette variable d'environnement sera override.
- on créé le répertoire -
mkdir /docker/bitwarden
- on créé le fichier -
nano /docker/bitwarden/docker-compose.yml
- et on y colle ce qui suit, en adaptant selon nos besoins :
version: '3'
services:
bitwarden:
image: vaultwarden/server:latest
container_name: bitwarden
volumes:
- ./data:/data # where to keep persistent volume?
environment:
WEBSOCKET_ENABLED: 'true'
SIGNUPS_ALLOWED: 'true' # set to false to disable signups
ADMIN_TOKEN: <generated_admin_token> # openssl rand -base64 48
restart: always
networks:
- <network>
networks:
<network>:
external:
name: <network>
Docker-compose : NGINX (SWAG)
On passe à la configuration de NGINX, au travers l'image linuxserver/SWAG. Nous nous attarderons surtout sur la configuration de NGINX. Aussi je me dois de vous la présenter et vous expliquer pourquoi j'ai opté pour cette solution.
SWAG - Secure Web Application Gateway - est une image docker développée par LinuxServer, embarquant NGINX, Certbot (Let's Encrypt), PHP et Fail2Ban. SWAG permet également d'utiliser la connexion avec HTTP Auth, LDAP via leur image ldap-auth, et Authelia (2 facteurs). Bref, je vous recommande.
Il vous faudra adapter selon vos besoins et votre infrastructure, notamment :
- le volume persistent : ici le chemin est relatif et monte le volume dans le répertoire courant
./config
- Déterminez le réseau docker
<network>
. Les containers SWAG et Bitwarden doivent être dans le même réseau. - Spécifiez les variables d'environnement selon vos besoins : EMAIL, URL, MAXMINDDB_LICENSE_KEY (à lire : doc)
- on créait le répertoire -
mkdir /docker/swag
- on créait le fichier -
nano /docker/swag/docker-compose.yml
- et on y colle ce qui suit, en adaptant selon nos besoins :
version: '3'
services:
swag:
image: ghcr.io/linuxserver/swag
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Paris
- URL=<domain.tld>
- SUBDOMAINS=
- VALIDATION=http
- EMAIL= <email> #optional
- ONLY_SUBDOMAINS=false #optional
- EXTRA_DOMAINS=<extra.domain.tld> #optional
- MAXMINDDB_LICENSE_KEY=<maxminddb key>
- STAGING=false #optional
volumes:
- ./config:/config
ports:
- 443:443
- 80:80 #optional
restart: unless-stopped
networks:
- <network>
networks:
<network>:
external:
name: <network>
- On se place dans le répertoire -
cd /docker/swag
- On enregistre et on démarre le container en mode attaché -
docker-compose up
- Une fois que les certificats Let's Encrypt ont été créés et que tout fonctionne, on peut arrêter le container avec
ctrl + c
. On s'assurera d'arrêter complétement le container et de supprimer les volumes non persistents en tapantdocker-compose down
Reverse Proxy
SWAG propose entre autres des presets NGINX, notamment pour Bitwarden. Nous allons ici utiliser le preset bitwarden.subdomain.conf.sample.
Vous devrez vous êtes assuré d'avoir à votre disposition un domaine de second niveau ou un sous-domaine, que vous aurez déclaré dans la zone DNS de votre provider.
- Par défaut le DNS resolver de Docker est 127.0.0.11 (loopback), il suffit alors de faire une requête avec le nom du container, qui est défini ici par
set $upstream_app bitwarden
. Pour que la requête aboutisse, il est nécessaire que le container bitwarden se trouve dans le même réseau docker que SWAG.
- En supposant que vous utilisez également SWAG, il vous suffit de copier le preset -
cp /docker/swag/config/nginx/proxy-confs/bitwarden.subdomain.conf.sample /docker/swag/config/nginx/site-confs/bitwarden
- Et de l'éditer à votre convenance -
nano /docker/swag/config/nginx/site-confs/bitwarden
## Version 2020/12/09
# make sure that your dns has a cname set for bitwarden and that your bitwarden container is not using a base url
# make sure your bitwarden container is named "bitwarden"
# set the environment variable WEBSOCKET_ENABLED=true on your bitwarden container
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name bitwarden.domain.tld;
include /config/nginx/ssl.conf;
client_max_body_size 128M;
location / {
include /config/nginx/proxy.conf;
resolver 127.0.0.11 valid=30s;
set $upstream_app bitwarden;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
location /admin {
include /config/nginx/proxy.conf;
resolver 127.0.0.11 valid=30s;
set $upstream_app bitwarden;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
location /notifications/hub {
include /config/nginx/proxy.conf;
resolver 127.0.0.11 valid=30s;
set $upstream_app bitwarden;
set $upstream_port 3012;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
location /notifications/hub/negotiate {
include /config/nginx/proxy.conf;
resolver 127.0.0.11 valid=30s;
set $upstream_app bitwarden;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}
Démarrage
Tout est configuré ! Maintenant il ne reste plus qu'à démarrer.
- Dans
/docker/bitwarden
puis dans/docker/swag
exécutez successivement la commandedocker-compose up -d
- Rendez-vous maintenant à l'adresse que vous avez choisi (ex.: bitwarden.domain.tld) et inscrivez-vous !
Notes
A savoir que j'ai ici volontairement dissocié les configurations de Bitwarden et SWAG, car j'utilise d'autres containers qui sont proxy par SWAG. Si vous souhaitez regrouper sous un même stack (un même fichier docker-compose.yml
) ces deux containers, vous n'aurez alors pas à préciser de network, celui-ci sera créé par défaut au démarrager de la stack.
Bon Bitwarden à tous !
Ressources
- Documentation de Vaultwarden - https://github.com/dani-garcia/vaultwarden/wiki/
- Article sur l'auto-hébergement de Bitwarden - https://theselfhostingblog.com/posts/how-to-self-host-bitwarden-on-ubuntu-server/