Home | Send Feedback

Self-host Bitwarden, an online Password manager

Published: December 12, 2018  •  linux

When you follow common password rules, you use reasonable lengthy passwords, don't use passwords that are exposed in data breaches and use a different password for each service.
If you are using a lot of services on the web, this results in a lot of different passwords. You then have either a good memory or use a password manager to store all these passwords. Then you only have to remember one good password to open the password manager.

There are different approaches how you can use a password manager. For instance, you can install a tool like KeePass that stores the passwords encrypted in a file local on your computer. Another popular solution is to use an online password manager, like 1password, LastPass and Bitwarden. These services not only provide access to the passwords over a web interface they also provide clients for mobile and desktop devices. These services and clients take of synchronizing the data between the different devices.

What Bitwarden sets it apart from the rest of these services, is the fact that the source code is publicly hosted on GitHub and you may install Bitwarden on your own server.

Bitwarden was just recently (November 2018) audited by a third party. You find more information here:
https://help.bitwarden.com/article/why-should-i-trust-bitwarden/


Hosting Bitwarden on your own server is free and you can register as many users as you want. But there are premium features that you need to pay for if you want to use them, even when you self-host Bitwarden. Also if you want to utilize the sharing feature you have to buy a license.
Check out this page for more information: https://help.bitwarden.com/article/licensing-on-premise/


Before you start a self-hosted installation, check the system requirements.
Bitwarden runs in Docker containers, therefore you can install Bitwarden on any operating system that supports Docker.

In this tutorial I'm going to install Bitwarden on a VPS. The server I use for this tutorial is running a plain Ubuntu 18.04 with just an SSH server installed. I configured the server according to my tutorial about setting up a VPS.

Note that a virtual private server (VPS) is not your server, it's just a server you rent from somebody. You have full access to the server, but so has the company that owns the servers.

DNS

For this demo installation I use the domain pw.ralscha.ch
This step is optional, you can connect to the server with just the IP address, but if you want to secure the HTTP connection with a TLS certificate (and you definitely should) you need a domain name.

In the web console of my DNS provider I insert an A and AAAA record that point to the IP address my VPS

pw.ralscha.ch.        86400   IN      A       51.38.124.133
pw.ralscha.ch.        86400   IN      AAAA    2001:41d0:701:1100::e54

I also recommend adding a CAA record, if your DNS provider supports this feature. Either for the whole domain if you get all your certificates from one CA or just for the subdomain if you use multiple certificate authorities.

ralscha.ch.             86400   IN      CAA     0 issue "letsencrypt.org"
// OR
pw.ralscha.ch.        86400   IN      CAA     0 issue "letsencrypt.org"

Install Docker

Bitwarden works with the Docker Community and Enterprise Edition. For this article I install the Community Edition and follow the instructions from this page:
https://docs.docker.com/install/linux/docker-ce/ubuntu/

After issuing the following commands, you have a running Docker environment on your Ubuntu server.

sudo -i
apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
apt-key fingerprint 0EBFCD88
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get install docker-ce
exit

Next we install docker-compose. The Bitwarden command line tool depend on this command for installing the necessary docker containers. For the docker-compose installation follow this documentation:
https://docs.docker.com/compose/install/

sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Install Bitwarden

Each Bitwarden installation requires a unique installation id and installation key. According to the documentation the id and key are used to:

Go to the web site https://bitwarden.com/host/ and enter your email address. Bitwarden then displays the id and key.

Do not share the installation id and key across multiple Bitwarden installations. Request a new id and key when if you install multiple instances.


You find the installation instructions for Bitwarden on this web page:
https://help.bitwarden.com/article/install-on-premise/

The following commands first create the directory /opt/bitwarden, download the bitwarden.sh script and then install the Docker containers.

sudo -i
mkdir /opt/bitwarden
cd /opt/bitwarden
curl -s -o bitwarden.sh https://raw.githubusercontent.com/bitwarden/core/master/scripts/bitwarden.sh
chmod +x bitwarden.sh
./bitwarden.sh install

The Bitwarden install script asks you for the domain name for your installation. For my test installation I enter pw.ralscha.ch. After that the script asks if you want to use Let's Encrypt to create TLS certificates. I recommend to always do that, unless you have some other certificates you want to use.
Next you have to enter an email address that is used for Let's Encrypt. They are going to send certificate expiration reminders to this address.
And finally the installation script prompts for the installation id and key.

Continue the installation with these commands

./bitwarden.sh start
./bitwarden.sh updatedb
exit

Open the URL of your new installation (e.g. https://pw.ralscha.ch) and create a new account.

Email

To unlock all features, users have to verify their email address. Before they can do that we have to configure the email server that Bitwarden should use for sending emails.

You can set up an email server on your own server. You don't need to install a full fledged server, Bitwarden only requires a send-only email server. See my previous blog post about installing a send-only server on Ubuntu:

You can also connect to an existing email server or use an external service like SendGrid. SendGrid offers a free tier which allows sending 100 emails per day. This should be more than enough for a small Bitwarden installation.

Next we open the configuration file and enter the address of the email server.

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

You need to configure at least host, username and password.

globalSettings__mail__replyToEmail=no-reply@pw.ralscha.ch
globalSettings__mail__smtp__host=REPLACE
globalSettings__mail__smtp__username=REPLACE
globalSettings__mail__smtp__password=REPLACE
globalSettings__mail__smtp__ssl=true
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__useDefaultCredentials=false

Example if you use SendGrid

globalSettings__mail__smtp__host=smtp.sendgrid.net
globalSettings__mail__smtp__username=apikey
globalSettings__mail__smtp__password=SG.YOUR.API_KEY

After you changed the settings, restart Bitwarden.

sudo /opt/bitwarden/bitwarden.sh restart

See also the official documentation for more information:
https://help.bitwarden.com/article/install-on-premise/#post-install-environment-configuration

Self registration

If you run a Bitwarden installation for your friends and family you can now send them a link and they can create their accounts. Be aware that everybody that knows the URL of your Bitwarden installation can create an account. You can disable this self registration feature, after everybody has created their account.

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

And set the value for disableUserRegistration to true

globalSettings__disableUserRegistration=true

Restart Bitwarden

sudo ./bitwarden.sh restart

You still see the Create Account button on the login page and you can even enter information into the form, but when you click on Submit a dialog appears with an error message.

Docker and ufw

One thing you need to be aware of, if you are using ufw on your server, Docker itself also installs iptables rules and therefore interferes with your ufw rules. Check out the following articles if you want fix this.

https://www.techrepublic.com/article/how-to-fix-the-docker-and-ufw-security-flaw/ https://www.mkubaczyk.com/2017/09/05/force-docker-not-bypass-ufw-rules-ubuntu-16-04/

The Bitwarden containers open the ports 80 and 443.

Update Bitwarden

From time to time you should check on your Bitwarden installation und update the software with the following commands

sudo -i
./bitwarden.sh updateself
./bitwarden.sh update

Admin Interface

Bitwarden has a built-in Admin Portal, where the system administrator can check the installed Bitwarden version, browse all registered users and delete users.

To access this portal we have to give permission to certain users. By default nobody can access the admin portal.

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

Add emails of persons that are allowed to access the admin panel. They don't need to be registered with an account in your Bitwarden installation.

adminSettings__admins=john@example.com,bill@gmail.com,tom@example.com

You leave this setting empty (default) to prevent access to the admin portal.

adminSettings__admins=

Restart the server when you made changes to this setting.

When a user wants to log in to the admin portal, he opens the /admin page of the Bitwarden installation (e.g. https://pw.ralscha.ch/admin). The user enters his email address and when the email matches one of configured emails (adminSettings__admins) he receives a temporary login link (valid for 15 minutes). A click on the link opens the admin portal.

Client

All the provided Bitwarden clients you find on the download page point by default to the hosted Bitwarden version at bitwarden.com. But they all work with self-hosted installations.

All you need is configuring the server once in the settings. In all desktop and mobile clients and in the browser extensions you find a cog wheel icon in the top left corner of the login screen. Click or tap on this icon and enter the URL of your Bitwarden server.

setting1 setting2

Backup

Backups are important, especially for a password manager. A minimal backup solution should at least backup the bwdata folder. In my installation this folder: /opt/bitwarden/bwdata.

If you installed Bitwarden on a virtual server you could create snapshots of the whole server and store them on a backup drive.

In the following section I show you how to install a script that runs daily, compresses the bwdata folder with 7zip, encrypts the file with gpg and uploads it to Amazon S3.

I wrote about this backup approach in a previous blog post. If you follow this tutorial, first request the necessary access_key and secret_key from Amazon by following the steps I described in my previous post.

Install 7zip, gpg and the Amazon S3 command line tools.

sudo -i
apt install p7zip-full s3cmd gpg

In the Bitwarden installation folder create a new script called bitwarden-backup

cd /opt/bitwarden
nano bitwarden-backup

And paste the following code into the file

#!/bin/sh

cd /opt/bitwarden
7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on bwdata.7z bwdata

gpg --cipher-algo AES256 --symmetric --batch --passphrase the_passphrase bwdata.7z
s3cmd --access_key=AKIA... --secret_key=LDf...  put ./bwdata.7z.gpg s3://<bucket_name>

rm bwdata.7z bwdata.7z.gpg

Enter the correct keys and replace <bucket_name> with your bucket name.

Make the script executable

chmod 700 bitwarden-backup

Next install a timer service in systemd. This takes care of starting our backup job daily at the specified time.

nano bitwarden-backup.timer

Paste this code into the file

[Unit]
Description=Run bitwarden-backup once a day

[Timer]
OnCalendar=*-*-* 05:00:00
RandomizedDelaySec=30
Persistent=true

[Install]
WantedBy=timers.target
nano bitwarden-backup.service

Paste this code into the file

[Unit]
Description=bitwarden-backup

[Service]
WorkingDirectory=/opt/bitwarden
Type=oneshot
ExecStart=/opt/bitwarden/bitwarden-backup

Then link these files into the systemd folder, reload systemd, start and enable the timer

ln -s /opt/bitwarden/bitwarden-backup.timer /lib/systemd/system/bitwarden-backup.timer
ln -s /opt/bitwarden/bitwarden-backup.service /lib/systemd/system/bitwarden-backup.service
systemctl daemon-reload
systemctl start bitwarden-backup.timer
systemctl enable bitwarden-backup.timer

Check if the timer is installed properly

systemctl list-timers

Manually start the job.

systemctl start bitwarden-backup
journalctl -u bitwarden-backup