Run Bitwarden Password Manager in Docker Container

Posted on 144 views

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)

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container

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.

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-1

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.

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-10-1024x627

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.

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-11-1

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

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-12

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

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-14

You can also enable a two-factor authenticator for Bitwarden by navigating to Two-step Login

Setup-Bitwarden-Self-Hosted-Password-Manager-using-Docker-Container-15

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.

coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.