Jon Ellis

The musings of an "engineer"

Jon Ellis

Switching from Bitwarden to Bitwarden RS

Password management

I have been using Bitwarden - an open source, self-hosted password manager for a little over six months. Before that, I used the password manager provided by Google, with it's nice sync feature between devices, so my passwords were available on my phone as well as my work Mac and my personal machines.

For quite some time, I have been attempting to move my data away from cloud hosted things, specifically Google's infrastructure. It has proved to be quite a long and slow process.

The time came to switch away from Chrome, and back to Firefox. Firefox has a similar sync feature for bookmarks, history, add-ons, open tabs, passwords and preferences. Most of the syncing features worked very well, but I had quite a lot of problems with the password sync.

I had exported all of my credentials from Chrome to a CSV file and imported them into Firefox, but the imported credentials refused to sync to my other devices from there. I understand it was because I enabled a master password to access them, and the mobile app to access the saved passwords (Lockwise) used a PIN instead, or something security related. Maybe it was because I enabled 2FA on my account - I don't really remember. It all seemed a lot harder than it should be. Either way, using Firefox to manage my passwords like I had done with Chrome seemed too problematic.

I spent some time looking for an open source, self-hosted password manager that had an iOS app, 2FA, and seemed somewhat modern. I don't really remember any specific requirements any more, but Bitwarden seemed to fulfil what I was after at the time.

Hosting my own password manager also means that I won't be storing my password database on someone else's computer. It does however, put the onus on me to secure my infrastructure well enough.

Official Bitwarden

The installation of Bitwarden seems rather simple on the face of it, you download a script and run it.

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

Edit the config file, then restart Bitwarden.

shell
./bitwarden.sh restart

I'm not a huge fan of downloading scripts and just running them - though I run enough things that I download that I probably shouldn't as concerned as I am. As the rest of my infrastructure is configured using Ansible, I wanted write a quick Ansible role to set up and configure Bitwarden for me in a repeatable way. So I spent an unreasonable amount of time digging though what the installation script (and the sub-scripts that it downloads and executes) did so that I could install it manually.

This involved following significantly more complicated instructions, which included downloading a stub repository, generating keys, writing a lot of .env files and eventually starting the service with docker-compose. Docker compose starts quite a few rather resource thirsty containers in some sort of micro-service setup which seems pretty neat.

I'm pretty sure I should have made my Ansible play just run the standard installation commands!

Bitwarden also consumed a lot of disk space! For some reason, Bitwarden did not use the Overlay2 filesystem, but instead saved the image layers using the VFS storage driver. This directory reached 36.5GB, which consumed far too much SSD space on my home server (I only have 128GB of usable SSD storage). To preserve SSD space, I mounted a directory from my higher capacity but slower spinning disk array into the Bitwarden LXD container and moved the data there instead.

The iOS app and browser extensions seem to work pretty well. The web interface is basic but quite functional albeit a little slow at times.

Compared to the other services my home server runs, Bitwarden was definitely the most resource hungry thing I ran.

I run system containers through LXD on my home server, so the metrics below are the entire container as measured by systemd on the host.

I can't guarantee that my Ansible deployment of the Official Bitwarden service was 100% correct, so maybe the high resource use was caused by me misconfiguring something. I left it alone while I worked on other things. Every so often I'd take a look at my server graphs which show the CPU and memory use of the containers The resource use - especially CPU got to me, and when looking for issues on the Bitwarden Github repository, I found an issue describing what I saw an issue describing what I saw.

I don't know what it was doing with all those resources. I'm pretty confident that it should be doing pretty much nothing nearly all the time - except when I invoke it though one of it's interfaces.

Bitwarden RS

Bitwarden RS is an unofficial implementation of the Bitwarden password manager written in Rust. It uses significantly fewer resources and only requires a single docker container to run it. It also allows the use of the normally paid features like organisations and reports. For my home usage I don't think I'll have a use for organisations, but the reports may be useful.

Installation is significantly simpler than the official release, and the config file is a single JSON config file. Environment variables can be used instead, but the JSON config overrides environment variables and can be modified by the admin interface.

shell
docker run -d \
	--name='bitwardenrs' \
	-p 80:80 \
	-v /var/lib/bitwardenrs:/data/ \
	bitwardenrs/server

This is easily achieved with Ansible's docker_container module.

There are a few image variants available. The standard bitwardenrs/server image supports using a SQLite database. bitwardenrs/server-mysql adds support for connecting to MySQL databases. bitwardenrs/server-postgres - as you might have guessed - adds support for connecting to PostgreSQL databases.

I doubt for my scale it'd make much difference which I'd use, but I decided that a real database backend might be a little faster, and maybe safer to backup? I've not used SQLite enough to know how it handles a backup of the database file taking place during a write operation. I know MySQL and Postgres are absolutely fine with this case. It would be trivial to have set up a new docker container for the database for Bitwarden RS, but as I already have a MySQL server on my home server, I used that.

It's nice to see the resource use get lost in the background noise.

The disk space used by the OverlayFS storage driver for Bitwarden RS has reached 170MB.

The interface feels a little more responsive, but I lack any metrics to show whether this is the case or not.

Data migration

Migrating my vault contents was easy as Bitwarden has an export feature which allows you to download your vault as a JSON file (just be aware that this file is unencrypted). Then the data file can be imported into the new account.

Comparison

I'm happy that the Bitwarden RS implementation is wasting fewer of my home server's resource. Now that it's getting warmer outside, I don't need the extra few watts of heat from it to keep the house warm either.

As you might already have noticed, I like my metrics, and these last ones show the resources saved nicely.