Be the Boss of Your Passwords (using Bitwarden Self-hosting)

Be the boss of your passwords [Photo by NeONBRAND on Unsplash]

There are tons of alternatives when it comes to managing your passwords:

  • Write it on a stickie and attach to your monitor. (Just kidding, this is not an alternative, it’s a disaster)
  • Use the same 3-4 passwords you can remember across all websites (still kidding, this is still a recipe to disaster, not password management)
  • Buy one of those notebooks in a book store for storing the passwords. They even have tabs with the alphabet to help you organize the passwords … I wonder if anyone is still buying those relics of the 20th century.
  • Store passwords in a file stored with google drive. This is marginally better than the first two options. If you keep the passwords unencrypted then anyone can glance over your shoulder
  • Use something like keypass, keepassx or just store them in a text file encrypted with something like gpg or verycrypt. This is a viable alternative and it’s good when you need a certain level of security. However this method is inconvenient because all your passwords are stored in one place and you can’t update this one place from all you many devices and sync the passwords. Also using the passwords is a pain because this option doesn’t offer integration with the browsers and other tools where you need to use the passwords.
  • Use something like lastpass or 1password. They even have a free tier and integration with browsers and more. This is an awesome way to manage passwords for most users. I have a personal problem with this option though:
    • I understand how they claim their end-to-end encryption works. Problem is there is no way to verify that this is the case. This software is closed source and hosted by a private company with unknown policies. What would prevent my passwords from being stolen if a developer will make a mistake or a disgruntled employee will install a sniffer in their network? And things were happening to these systems in the past: https://lifehacker.com/lastpass-hacked-time-to-change-your-master-password-1711463571
    • The passwords are synced and stored on the 3rd party servers where they are subject for stealing, hacking or retrieving by other means and they could and further brut forcing. With the modern development of cheap powerful computing it takes less and less time to run brut force attacks against any encryption algorithm (and I have no idea what algorithms they are actually using).
  • And then there is Bitwarden :)

Bitwarden offers the same features and services as lastpass or similar but has two distictions:

This addresses most concerns of the most paranoid sysadmins, so let’s talk about how to get it working on your server. In theory, if you have a server you want to dedicate to running Bitwarden you can just follow these instructions: https://bitwarden.com/help/article/install-on-premise/. However, if you are going to host it next to other web servers running on the same hardware, then none of these instructions will work. During the install process Bitwarden does some ugly things like trying to use http authentication for certbot and thus running into a conflict with your existing web server. It won’t work nicely behind your reverse proxy too. So if you’re in this situation when you already have a webserver running and want to use your own certbot system then keep reading …

First of all, Bitwarden refuses to work over unsecured connections. For this reason you need to either create a self-signed certificate, buy a cheap SSL certificate from a company like ssls.com or, the best option, set up a free Let’s Encrypt certificate. You can read more about the last option here: https://andrey.mikhalchuk.com/2020/05/14/stop-paying-for-ssl-certificates.html

Having the SSL certificates downloaded and stored somewhere on your server let’s install, configure and run Bitwarden.

Installation is relatively easy, just create a directory where you will keep you Bitwarden files (some secure place that you backup periodically, preferably encrypted at rest) go to that directory and run this command:

curl -Lso bitwarden.sh https://go.btwrdn.co/bw-sh && chmod +x bitwarden.sh

Now, as a careful sysadmin you need to examine this file, make sure it doesn’t do anything bad to your system and then run this command:

./bitwarden.sh install

This will download bunch of other files and create the default configuration file called bwdata/config.yml. While you’re running this command

  • You will be asked to enter your hostname (something like bitwarder.example.com)
  • Make sure you say “no” to the generous offer to set up Bitwarden’s own certbot.
  • When you will be prompted to go to https://bitwarden.com/host and obtain your installation id and the key, do so. Keep these two in a secret place (do not write on a stickie and attach to your monitor). You will need to enter these exact values during the installation
  • When you will be asked if you have an SSL certificate to use answer “y” (meaning “yes”, not “why are you asking?”) and then confirm that this is a trusted certificate

Once the command completed its work open bwdata/config.yml and make a few tweaks:

  • Change http_port to something not conflicting with what you already have on your server, let’s say port 9999
  • Set ssl to false. Since we’re going to use your existing nginx reverse proxy, there is no need to make Bitwarden to use its certificates or even generate them.
  • You will notice that all SSL paths are wrong, but it’s ok since we just told Bitwarden to chill and not try to use its own SSL config

After these modifications run “./bitwarden.sh rebuild”

Now let’s create a virtual host in your nginx reverse proxy and this will be a bit tricky. The problem is that you need to keep serving two separate systems with the same website name. One is the certbot trying to authenticate your website every time it tries to renew your certificate. And the other system is Bitwarden. You can make this work with the configuration that looks like this:

# This is the configuration for the HTTP server and it does 
# two things:
# - if the URL starts with /.well-known then this is Certbot 
# trying to authenticate the site using webroot approach, let's
# use some static directory (here I'm using the same one from the
# post about setting up certbot, see above)
# - otherwise the URL needs to be forwarded to HTTPS site where
# Bitwarden will take care of it
# NOTE: do not forget to change the server_name to your own!
server {
    listen 80;
    location /.well-known/ {
      root /www/htdocs;
    }
    location / {
      return 302 https://$host$request_uri;
    }
    server_name bitwarden.example.com;
}

# this config terminates SSL using your Let's Encrypt certificate
# and forwards the call to Bitwarden. A portion of this config is 
# actually copied from the nginx config Bitwarden creates for its own
# https setup (which we're not going to use). The important thing
# is that it's good and secure.
# NOTE: you will need to change a few things in this config:
# - server_name
# ssl_certificate and ssl_certificate_key should point to where 
# certbot is keeping the certificate and the key
# proxypass should be pointing to the host+port where you're are going 
# to run Bitwarden. Frequently dockerhost is something like 172.17.0.1 # and we already configured Bitwarden to use port 9999 in 
# bwdata/config.yml
server {
    listen 443 ssl;
    ssl_prefer_server_ciphers On;
    ssl_protocols TLSv1.2;
    ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256";
    ssl_session_timeout 30m;
    ssl_session_cache shared:SSL:20m;
    ssl_session_tickets off;
    ssl_certificate /www/certbot/etc/live/bitwarden.example.com/fullchain.pem;
    ssl_certificate_key /www/certbot/etc/live/bitwarden.example.com/privkey.pem;
    server_name bitwarden.example.com;
    location / {
      proxy_pass http://dockerhost:9999;
    }
}

Now test your nginx config (“nginx -t”) and restart it or make it reread the config (something like “killall -HUP nginx”). Once this is done you can get back to the folder where you keep your bitwarden.sh and run

./bitwarden.sh start

If you did everything right, then you can go to https://bitwarden.example.com (or whatever site name you configured it with) and create your Bitwarden account on your own server.

That’s pretty much it, you have it. Here are a few gotchas I experienced that you may want to know about:

  • Once you have your own bitwarden server configured you may want to port your existing passwords into the new system. Bitwarden support ton of different password managers, but be aware that it limits the record size to 10000 bytes of encrypted blob. That means that if you have records with more than approximately 7kB of data, you con’t be able to import these into Bitwarden. Go through your existing records and extract/truncate them where necessary
  • So what do you do with these extra long comments you had in your old password system? One thing you can do is after successful import of your truncated records you can purchase Bitwarden’s premium service ($10/yr, totally worth it and is a great way to support the developers of this awesome system), port the license to your self-hosted instance and then you will be able to attach these lengthy comments to corresponding records as files.
  • Do you want to host passwords for the rest of the internet? Maybe yes, but probably not. In this case you need to edit bwdata/env/global.override.env and set “globalSettings__disableUserRegistration” to true. BTW, while you are here, you can also edit variables starting with “globalSettings__mail__” and set them to your mail account configuration. This will allow Bitwarden to communicate with you and also this is necessary for upgrading your account to Premium. Now run “./bitwarden restart” and in a few minutes your changes will take place.
  • NOTE: the registration button will be still there in the login dialog, but the registration attempts will be insuccessful.
  • You can install Bitwarden clients on all your PC/Mac/iOS/Android devices using this link: https://bitwarden.com/#download. The important thing is that before you login, find the “gear” icon in the login screen and click it. Enter the URL of your self-hosted server and now you can login with your self-hosted server.
  • Very likely you will still need to create an account with bitwarden.com, but not for storing the passwords but rather upgrading to Premium. Be kind to the developers and do it. Having features like ability to attach files or perform audit on your passwords or have two-factor authentication is totally worth it and costs 3x less then lastpass or other competition.

Leave a Reply