Intro
So as my girlfriend Emma and I setup the logistics of our new apartment in Boston, we quickly figured out that we had many accounts that would really be joint, but only filed under one person's name. Some of the bills were in my name, such as internet, while others were under her name like gas and electric, yet I felt that we both should have access to the accounts in case we needed to get a bill paid quickly.
Also, being two security minded people, Emma and I both use Bitwarden to create new passwords on the sites we visit so we have strong, unique passwords to our accounts. This makes it so that if one company has a data breach, not all of your accounts are leaked. However, Bitwarden only offers password sharing between organizations, which is a premium feature for the hosted service. However, since Bitwarden is open-source, you can self host the premium version on your own hardware if you would like and unlock all of the features. Since I was already paying for the kubernetes cluster that is hosting this blog, I figured I would throw a bitwarden server behind my traefik instance and utilize the nodes a little more efficiently. Two birds with one stone.
Research
So initially, while looking up bitwarden self hosted options, I first landed on the official Bitwarden Github Page. It looks like it could be run with Docker, which means that the image is hosted somewhere, which is perfect for what I needed!
However, as I started to do more testing locally with the docker image, the official image seemed to be very resource heavy... Ok, not that resource heavy, but certainly more than I wanted since it required an instanced of sql server to be running. So, I started to look for other open source projects around the web and stumbled upon bitwarden_rs. It is the Bitwarden API written in rust and it's rocket server. This was exactly what I was looking for. A lightweight, simple Bitwarden server that could write to small sqlite3 instanced inside the container in the /data directory.
I also really loved that Bitwarden unofficially supports bitwarden_rs and actually files issues in their github if problems arise. On the flip side, bitwarden_rs actively encourages their users to contribute to upstream development, whether it be through financial contributions or fixing bugs. So if you are following along with this blog, please consider donating to this wonderful service.
Implementation
The first thing I did before deciding on bitwarden_rs was read over their entire wiki which you can find here. If I miss anything in this blog article, I guarantee you it will be in their wiki, and I encourage my readers to also read the wiki before following along. It will help you understand my implementation further, and maybe even find things I have missed.
Next, I dove into creating the kubernetes manifests. Since bitwarden_rs maintains a public docker image, it was pretty easy to get the Kubernetes deployment going. You can find the code below, with short explanations after each snippet:
TL;DR: I setup my home networking with virtualized Opnsense and piHole. Yes, it is overly complex, but I kept my networking knowledge somewhat sharp.
I've always been curious about networking infrustructure, ever since the early days of my prepubescent childhood. I remember when I first got my xbox 360 around my 6th grade birthday, I immediately was curious on how it connected to the internet, how it connected to xbox's servers, and how hostbooters were able to find my "address" called an ip address and kick me offline. For those who don't know, "hostbooting" is gamer slang for a DoS attack on a client's public ip address. Essentially flooding their home network with packets to disconnect them from online gaming services. People would disconnect players on the other team for an easy win.
Anyway, that passion always carried itself with my all the way until my first intership at Datto, where I was pulnged head first into the world of networking. I remember going into the job thinking: I've been programming for over 3 years at this point. I'm pretty comfortable with computers, and have programmed a few things into my raspberry pi. I can handle this internship.
Backstory
Early into my refactor of Skirmish's tournament backend, I realized that I needed to make fetching and updating the bracket as quick and efficient as I could on the frontend. I ended up doing a lot of research into how I could speed up my queries to the database, but I also was reading a lot about caching and using in-memory storage to store and serve data instead of querying the database every time. However, there was one problem that I never really liked about Django's built-in caching system -- it lacked support for clearing a view's cache and forcing a recalculation of the data.
So, to give a clear example in tournament terminology, let's say that a player had reported the results for their match, and the match advanced the winner and the loser to their next respective matches. After this, if the bracket were to be requested again, django's built in @cache_page decorator would create a cache key for the request, look for it in our cache before performing calculations, grab the old data and serve it to the user. To show specifically why this is the case, let's look at @cache_page's key creation implementation: