Hardware, Software, and Wetware on the Bleeding Edge

Self-Hosted Vaultwarden

As I mentioned in the previous post I had rebuilt my home server using DietPi, and so far it seems to be working well enough. I had migrated the VPN system I have on a DigitalOcean droplet from using OpenVPN to Wireguard, and so far everything seems to be working very well. Now I at least have access to the main home server via the VPN, and I can connect my phone and other devices to the VPN easily enough and from here I can do a lot of interesting and useful things.

One of the big problems I’ve had was with password management. I have long been using KeepassXC as my password manager, and one of the biggest problems I’ve had with it is that it is extremely difficult to keep password vault files synchronized among multiple devices. I have my main laptop, the small RISC-V laptop, my phone, gaming desktop, work laptop, and so forth. I’d come to dread the times when a site tells me that I must change my password (never mind if my password is 25-character hard random string that is basically impossible to brute force) because then I’d have to find a way to distribute the changed password file to every device I use. I’m extremely wary of entrusting all of my passwords to a third party like LastPass or 1Password for obvious reasons. So I heard of Bitwarden and Vaultwarden, and had thought of making a self-hosted instance to manage all my passwords. DietPi helpfully included Vaultwarden among its optimised software selections, and installing it proved easy enough.

The biggest challenge was getting the various Bitwarden clients to access it properly. The Bitwarden documentation seems to be focused on getting self-hosted instances working over HTTPS over a public network, which while I can set up an nginx tunnel (as I had done with PhotoPrism) to over the VPN is not really what I want to do. Access solely over the VPN from a client that has VPN credentials is far safer, I think. I don’t ever want to expose the instance directly over the Internet! My droplet already gets tons of SSH connections from random places, too bad access is granted only via public key authentication: SSH on the droplet refuses password authentication entirely. An application over HTTPS will likely get just as much spurious traffic.

So, I had to stick with a self-signed SSL certificate. The DietPi installation for Vaultwarden helpfully generated one for me using the internal server’s own IP address, and the instructions for getting the various clients to use this certificate were rather confusing because it seems they really don’t want you to do this kind of thing. I figured out that to get the Bitwarden Linux client to use the certificate you have to use the nss3 command line tools to add the certificate into the local store. This, however, only seems to work with the Linux AppImage provided by Bitwarden. I was never able to figure out how to get the Ubuntu flatpak install of Bitwarden to accept the self-signed certificate. And after installing the certificate it seems to be necessary to reboot. Not sure why. Getting this done on Android was easier, the instructions provided worked just fine.

Next was getting access over the VPN. First I wanted to figure out how to get access to the LAN IP address from the VPN, but it proved difficult to figure out how to set up such VPN routing properly, so instead I thought of trying to get access to the Vaultwarden application over the VPN IP instead of the LAN IP. Again I ran into the certificate issues because the self-signed certificate refers to the LAN IP and will not be accepted from the VPN IP which is different. I found out that it was possible to make a self-signed certificate valid for more than one IP address, so I modified the code that DietPi uses to make its self-signed certificates to create a new certificate with two IPs. This worked, so now I can access Vaultwarden over the VPN.

This was a lot of kludge work. I set up an internal DNS long ago that resolves to the local IP addresses of my internal systems and I could have used the private EasyRSA-based certification authority I used to use for OpenVPN for my certs, but Android is a buzzkill and refuses to use my internal DNS servers for some reason even if my local DHCP pushes them. Again, I don’t want this directly accessible over the Internet!

Leave a comment