Note: The open source project Vaultwarden that I’m talking about in this post has formerly been named BitwardenRS, it has been renamed at the end of April 2021. I’ve updated this article where necessary.
I’ve been a long-time user of Enpass and while it’s a fine password manager I looked into Bitwarden some months ago and started using it. Bitwarden can be used as a managed service and that’s what I did for some time now. Same as Enpass it’s quite advanced and integrates nicely into my working environment. I’m using it on a Mac, in different browsers and on my mobile Android phone. There are some limitations in the free tier (no file attachments, no 2FA authenticator, …) but the premium account for individuals is fairly cheap, you only pay $10 per year. You’re still subject to limited functionality, though, for example with regards to using organization features.
Apart from using a managed service, you can run Bitwarden on your own hardware. With the official server software you’re still applicable to licence fees, however. There’s also a Rust implementation of the Bitwarden server, it’s named Vaultwarden (formerly BitwardenRS). It’s less resource hungry than the original server software, uses different database technology and you are not applicable to the licencing model mentioned above. All the official Bitwarden client applications still work, so the user experience doesn’t change at all. This sounded interesting so I decided to give it a try.
Docker Compose setup
Vaultwarden can be run using Docker/Docker Compose and it was less then a day to get the basic setup running on a Raspberry PI 3 Model B. The official wiki is comprehensive and easy to consume, so that helped a lot. Here’s my docker-compose file that will start Vaultwarden alongside Caddy as a reverse proxy.
You’ll also need to update the Caddyfile with the container name:
You’ll have to fill out the blanks, once you’ve done this Caddy will automatically setup Letsencrypt certificates for you and you are good to go. In order to be reachable over the public internet using a fixed hostname, I have configured a dynamic hostname with ddnss.de, it is updated by my internet router. To make it a bit nicer I have a DNS record configured on a domain I own that forwards to that dynamic hostname using a CNAME DNS entry.
The docker-compose file contains a number of environment variables, some of them are needed so that Vaultwarden can send emails (e.g. for invitations). You can use your own email provider or setup a dedicated smtp service. The wiki recommends SendGrid or MailJet for this, you can get away with their free plans which allow you to send at least 100 mails per day. I went with MailJet, as SendGrid didn’t send their verification emails out – not a smart thing to fail at, as a mail service.
Another environment variable (“ADMIN_TOKEN”) settings to enable the admin page. You can use it to manage settings, users, organisations and more. The wiki again does a good job to explain why and how to set this up.
Creating a system service
Docker-Compose is great for running containers manually, but I wanted to integrate Vaultwarden into the operating system, so that it could be started automatically upon reboot. Here’s my
systemd service file (
vaultwarden.service) that can be used to start and stop Vaultwarden.
The service needs to be enabled, so that Vaultwaren automatically starts on reboots:
$ sudo systemctl enable vaultwarden.service
If you run a service like this, you better think about a backup strategy. Vaultwarden helps you, though, as the wiki has a section on this, as well. There’s different aspects to take into account: You’ll definitely want your vault to be backed up, but you also most definitly want attachments to be taken into account. Here’s my
systemd service (
vaultwarden-backup.service) and timer (
vaultwarden-backup.timer) that will export the database once a day and will also tarzip the attachments directory.
NOTE: Check that sqlite3 is installed, or the backup script won’t work.
Don’t forget to enable and start the timer:
$ sudo systemctl enable vaultwarden-backup.timer $ sudo systemctl start vaultwarden-backup.timer
My backup files are stored on a USB stick, instead of mounting it through
/etc/fstab, I’m also utilising
systemd‘s mounting facilities. Here’s my configuration (
The mount-unit sets up the device for manual mounting, the automount-unit tells
systemd to automatically mount the device on startup. It’s important to name the unit after the mount point, i.e. the
Where attribute of the unit. And you have to use dashes to separate path segments (here:
If you want to restore from a backup, you just have to shut down Vaultwarden and replace the live
db.sqlite3 file with the one from your backup. Also replace the live
attachement directory with the tar-ed version from the backup.
In order to use your new Vaultwarden server in your client apps, you need to configure the server url before logging in. There’s a small setting icon on the login screen, almost unnoticable. Make sure you setup the connection url there.
It was easy and fun to set up Vaultwarden, I was surprised how fast and without much latency it works on a Raspberry Pi on a home connection. I’ve imported my Enpass vault to Bitwarden before without any problems, and also migrating a LastPass account to another user account was easy and painless. Although I try to refrain from hosting too many services myself – I just don’t have enough time to keep up – I have a good feeling about this. And I’m happy my old Raspberry Pi has a new task.