Welcome to this amazing guide on how to set up Bitwarden Self-Hosted Password Manager using Docker Container. By the end of this guide, you should be able to install the latest version of docker and docker-compose, as well as setting up an automatic password saving with Bitwarden.
What is Bitwarden?
Bitwarden is a free and open-source password manager that stores sensitive information such as websites credentials in an encrypted vault as well as generating strong|unique passwords for browsers or devices. It has two plans i.e a free and a paid version both coming with many amazing features
Features of Bitwarden include:
- It is open-source
- Bitwarden uses 256-bit AES to secure the user data
- Two-factor authentication via applications such as email, Duo e.t.c
- Password auditing and breach monitoring.
- It supports biometric unlock.
- The Bitwarden server is self-hosted on-premises keeping content safe and secure
- Cross-platform client applications with desktop applications, web interface, browser extensions, mobile applications as well as CLI.
Getting Started
Before we begin this guide, ensure that your system is updated and the required packages installed.
## On RHEL/CentOS/RockyLinux 8
sudo yum update
sudo yum install curl vim
## On Debian/Ubuntu
sudo apt update && sudo apt upgrade
sudo apt install curl vim
## On Fedora
sudo dnf update
sudo dnf -y install curl vim
Step 1 – Install Docker and Docker-Compose
In this guide, you need docker and docker-compose installed on your machine. Install the latest version of Docker on your Linux system using the guide on:
Check the installed docker version.
$ docker -v
Docker version 20.10.9, build c2ea9bc
Add your user account to Docker group:
sudo usermod -aG docker $USER
newgrp docker
With Docker installed successfully, proceed and install the latest version of Docker-Compose using cURL as well.
curl -s https://api.github.com/repos/docker/compose/releases/latest | grep browser_download_url | grep docker-compose-linux-x86_64 | cut -d '"' -f 4 | wget -qi -
Make the downloaded file executable.
chmod +x docker-compose-linux-x86_64
Move the file to your PATH.
sudo mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
Now confirm your installation by checking the docker-compose version installed.
$ docker-compose version
Docker Compose version v2.0.1
Start and enable docker.
sudo systemctl start docker && sudo systemctl enable docker
Step 2 – Provision the Bitwarden Server
Now we will create a folder for the Bitwarden server. I will name mine bitwarden
cd ~
mkdir bitwarden && cd bitwarden
Now in the folder, we will create a docker-compose.yml file. This file will be used by docker-compose to orchestrate the docker instance.
touch docker-compose.yml
Then open the file for editing using your favorite text editor.
vim docker-compose.yml
Add the contents below in the file.
# docker-compose.yml
version: '3'
services:
bitwarden:
image: bitwardenrs/server
restart: always
ports:
- 8000:80
volumes:
- ./bw-data:/data
environment:
WEBSOCKET_ENABLED: 'true' # Required to use websockets
SIGNUPS_ALLOWED: 'true' # set to false to disable signups
In this guide, I will use the bitwarden_rs Docker image written in Rust, this is faster and more reliable and it is entirely open-source with high usage all over.
Step 3 – Run Bitwarden Self-Hosted Password Manager using Docker
Now that everything is provisioned for the Bitwarden Server, we will proceed and run it using the simple code below.
docker-compose up -d
In case the above command fails to start, you might be required to execute it using the root user privileges.
The command above will start pulling the images as below.
[+] Running 8/8
⠿ bitwarden Pulled 6.5s
⠿ 33847f680f63 Pull complete 1.9s
⠿ 64e13e5f1ad2 Pull complete 2.7s
⠿ 148922a88961 Pull complete 2.8s
⠿ cc66172bd48b Pull complete 3.2s
⠿ 2372942a3bb8 Pull complete 3.6s
⠿ 35b316a20d10 Pull complete 3.7s
⠿ 6b2893b1d24a Pull complete 3.9s
[+] Running 2/2
⠿ Network bitwarden_default Created 0.1s
⠿ Container bitwarden-bitwarden-1 Started 0.9s
See the Bitwarden Server instance using the command:
$ docker ps
Sample Output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
62fbe97d43e5 bitwardenrs/server "/usr/bin/dumb-init …" About a minute ago Up About a minute (healthy) 3012/tcp, 0.0.0.0:8000->80/tcp, :::8000->80/tcp bitwarden-bitwarden-1
You can now access the Bitwarden web dashboard on the server’s IP address and port 8000. But you will not be able to create an account with Bitwarden unless you have access to the site using HTTPS.
Step 4 – Secure Bitwarden with Trusted Certificates.
Install Nginx webserver for reverse proxy
##On RHEL/CentOS/Rocky Linux 8
sudo yum install nginx
##On Debian/Ubuntu
sudo apt install nginx
For this instance I am using a Rhel-based system, I will create a conf file at /etc/nginx/conf.d/bitwarden.conf
sudo vim /etc/nginx/conf.d/bitwarden.conf
In the file, add the content below for VirtualHost replacing your domain name appropriately
server
listen 80 default_server;
listen [::]:80 default_server;
server_name bitwarden.example.com;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /
proxy_pass http://localhost:8000/;
index index.html index.htm;
error_page 404 /404.html;
location = /40x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html
Grant Nginx privileges to the created file above.
# CentOS / RHEL / Fedora
sudo chown nginx:nginx /etc/nginx/conf.d/bitwarden.conf
sudo chmod 755 /etc/nginx/conf.d/bitwarden.conf
# Debian / Ubuntu
sudo chown www-data:www-data /etc/nginx/conf.d/bitwarden.conf
sudo chmod 755 /etc/nginx/conf.d/bitwarden.conf
Start the Nginx web server.
sudo systemctl start nginx
sudo systemctl enable nginx
In case Nginx fails to start, remove the server part in the /etc/nginx/nginx.conf file.
In this guide, I will demonstrate two ways to install trusted certificates on your Linux system. The main aim of this step is to add HTTPS access to the BItwarden site.
- Using Let’s encrypt(Public IPs/FQDN)
- Using a self-signed Certificate(Private IPs)
4.a – Using Let’s Encrypt SSL
Since we need to access the web via HTTPS, we are required to generate SSL certificates. Let’s Encrypt is used to issue trusted SSL certificates free for any FQDN. Install Certbot as below:
##On RHEL 8/CentOS 8/Rocky Linux 8/Fedora
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo dnf install certbot python3-certbot-nginx
##On Debian/Ubuntu
sudo apt install certbot python3-certbot-nginx
Install the SSL certificates for your domain name
sudo certbot --nginx
Proceed as below
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): Enter a valid Email address here
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
Account registered.
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: bitwarden.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Requesting a certificate for bitwarden.example.com
Performing the following challenges:
http-01 challenge for bitwarden.example.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/bitwarden.conf
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/bitwarden.conf
Successfully received certificate.
Certificate is saved at: a2enmod ssl
/etc/letsencrypt/live/bitwarden.example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/bitwarden.example.com/privkey.pem
This certificate expires on 2022-01-09.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Now your configuration file at /etc/nginx/conf.d/bitwarden.conf will have the SSL certificates as below.
...........
server
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /usr/share/nginx/html;
ssl_certificate "/etc/letsencrypt/live/bitwarden.example.com/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/bitwarden.example.com/privkey.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /
proxy_pass http://localhost:8000/;
index index.html index.htm;
error_page 404 /404.html;
location = /40x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html
4.b – Using a Self-signed Certificate
Another alternative for those who do not have a fully qualified domain name is to secure SSL certificates using self-signed certificates. Ensure that OpenSSL is installed on your system. Then proceed and create this config file for the certificates
vim bitwarden_ssl.conf
In the file, add the below information.
[req]
default_bits = 2048
default_keyfile = bitwarden_ssl.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ca
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = KE
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Nairobi
localityName = Locality Name (eg, city)
localityName_default = Nairobi
organizationName = Organization Name (eg, company)
organizationName_default = Bitwarden
organizationalUnitName = organizationalunit
organizationalUnitName_default = Development
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Your_IP-Address
commonName_max = 64
[req_ext]
subjectAltName = @alt_names
[v3_ca]
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = Your_IP-Address
Now generate the certificates from the config file as below.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout bitwarden_ssl.key -out bitwarden_ssl.crt -config bitwarden_ssl.conf
Press enter till the end.
Next copy the generated files to /etc/ssl/certs directory as shown.
sudo cp bitwarden_ssl.crt /etc/ssl/certs/bitwarden_ssl.crt
sudo mkdir -p /etc/ssl/private/
sudo cp bitwarden_ssl.key /etc/ssl/private/bitwarden_ssl.key
With this command, your private key and signed certificate (.crt) will be saved in the /etc/ssl/certs/ directory. Now copy these certificate paths to your Nginx conf as shown
sudo vim /etc/nginx/conf.d/bitwarden.conf
You will require to add them to Nginx as below.
server
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name Your IP_Address;
root /usr/share/nginx/html;
ssl_certificate /etc/ssl/certs/bitwarden_ssl.crt;
ssl_certificate_key /etc/ssl/private/bitwarden_ssl.key;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /
proxy_pass http://localhost:8000/;
index index.html index.htm;
error_page 404 /404.html;
location = /40x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html
Allow HTTP and HTTPS through the firewall if you are using firewalld.
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
Reload the Nginx service.
sudo systemctl restart nginx
Step 5 – Access the Bitwarden Web Interface
Now you can access the Bitwarden Web interface using the URL https://biwarden.example.com or https://IP_Address (for those using self-signed certificates)
If you see this page, Bitwarden is running well. The first step is to create an account, do so by clicking on Create account on the login page displayed. A new window will appear where you are required to fill in the details.
Fill each field appropriately and remember to use a strong master password. You will then be redirected to the login screen, log in with the set credentials, and access this web vault.
Now your Bitwarden installation is complete successfully!
Step 6 – Disable Anonymous User Sign Up
Now that Bitwarden has been installed, we need to make it more secure by disabling user registration. Stop the running Bitwarden instance.
docker-compose down
Navigate to the file you created the Bitwarden YAML file:
cd ~/bitwarden
Edit the file and set SIGNUPS_ALLOWED=false as below.
vim docker-compose.yml
Edit the file as below:
# docker-compose.yml
version: '3'
services:
bitwarden:
image: bitwardenrs/server
restart: always
ports:
- 8000:80
volumes:
- ./bw-data:/data
environment:
WEBSOCKET_ENABLED: 'true' # Required to use websockets
SIGNUPS_ALLOWED: 'false' # set to false to disable signups
Now start a new Bitwarden instance with SIGNUPS_ALLOWED
set to false
as below.
docker-compose up -d
After this, trying to create a new account will result in the below error.
Step 7 – Use Bitwarden Self-Hosted Password Manager
Now access the Bitwarden Web dashboard using the credentials created. There are a couple of activities you can do. Navigate to the tools window, here you can generate unique passwords, import and export data to the vault, check reports for exposed, weak, reused passwords e.t.c
Under the settings tab, you can change credentials for your master account, set the vault timeout, whether to lock or logout as a security enhancement
You can also enable a two-factor authenticator for Bitwarden by navigating to Two-step Login
Congratulations! We have successfully walked through how to set up Bitwarden Self-Hosted Password Manager using Docker Container. You can now manage your passwords using Bitwarden.