(7/8) Self-host your password manager with Bitwarden

This article is part of the series Build your very own self-hosting platform with Raspberry Pi and Kubernetes

  1. Introduction
  2. Install Raspbian Operating-System and prepare the system for Kubernetes
  3. Install and configure a Kubernetes cluster with k3s to self-host applications
  4. Deploy NextCloud on Kuberbetes: The self-hosted Dropbox
  5. Self-host your Media Center On Kubernetes with Plex, Sonarr, Radarr, Transmission and Jackett
  6. Self-host Pi-Hole on Kubernetes and block ads and trackers at the network level
  7. Self-host your password manager with Bitwarden
  8. Deploy Prometheus and Grafana to monitor a Kubernetes cluster


Bitwarden is a free, open-source and audited Password Manager, it provides a large range of clients (desktop, web, browser extension and mobiles) to access your password easily and safely from anywhere. While Bitwarden offers a SaaS solutions (they host your passwords in an encrypted way), because Bitwarden is open-source, you can decide to host yourself your password and this is what we are going to learn in this tutorial.

For information, we will deploy Bitwarden-rs, Unofficial Bitwarden compatible server written in Rust, ideal for self-hosting.

This is a Bitwarden server API implementation written in Rust compatible with upstream Bitwarden clients*, perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. This project is not associated with the Bitwarden project nor 8bit Solutions LLC.


In order to run entirely the tutorial, we will need:


We are going to isolate all the Kubernetes objects related to Bitwarden in the namespace bitwarden.

To create a namespace, run the following command:

$ kubectl create namespace bitwarden


The first step consists in setting up a volume to store Bitwarden config files and data. If you followed the previous articles to install and configure a self-hosting platform using RaspberryPi and Kubernetes, you remember we have on each worker a NFS client pointing to a SSD on /mnt/ssd.

1. Deploy the Persistent Volume (PV)

The Persistent Volume specify the name, the size, the location and the access modes of the volume:

Create the following file and apply it to the k8 cluster.

## bitwarden.persistentvolume.yml
apiVersion: v1
kind: PersistentVolume
  name: bitwarden-ssd
    type: local
  storageClassName: manual
    storage: 500Mi
    - ReadWriteOnce
    path: "/mnt/ssd/bitwarden"
$ kubectl apply -f bitwarden.persistentvolume.yml
persistentvolume/bitwarden created

You can verify the PV exists with the following command:

$ kubectl get pv

bitwarden-ssd   500Mi      RWO            Retain           Available                             manual                  7s

2. Create the Persistent Volume Claim (PVC)

The Persistent Volume Claim is used to map a Persistent Volume to a deployment or stateful set. Unlike the PV, the PVC belongs to a namespace.

Create the following file and apply it to the k8 cluster.

## bitwarden.persistentvolumeclaim.yml
apiVersion: v1
kind: PersistentVolumeClaim
  namespace: bitwarden
  name: bitwarden-ssd
  storageClassName: manual
    - ReadWriteOnce
      storage: 500Mi
$ kubectl apply -f bitwarden.persistentvolumeclaim.yml
persistentvolumeclaim/bitwarden created

You can verify the PVC exists with the following command:

$ kubectl get pvc -n bitwarden

bitwarden-ssd   Bound    bitwarden-ssd   500Mi      RWO            manual         8s

Outside access

The next part consist to enable the connections to Bitwarden from outside so you can access your passwords from anywhere.

1. Port Forwarding

First you need to go to your router setup and add a port-forwarding rule to map any incoming requests on port 80 or port 443 to be forwarded to (the LoadBalancer IP of the Nginx).

VirginHub - Port-Forwarding

2. Map the subdomain bitwarden.<domain.com> to your home router

First you need to find out what's your router external IP, run this command or go to whatismyip.com.

$ curl ipecho.net/plain

Then, we need to configure our subdomain to make sure bitwarden.<domain.com> resolves to our external static IP. Go to your domain provider console / DNS management add a record:



1. Clone the repo bitwarden-k8s

Clone the repository bitwarden-k8s with the following command (change ~/workspace/bitwarden-k8s by the target folder of your choice):

$ git clone https://github.com/gjeanmart/bitwarden-k8s.git ~/workspace/bitwarden-k8s

2. Download the Chart values of the chart locally

Run the following command to download the Chart values into the local file pihole.values.yml.

$ helm show values ~/workspace/bitwarden-k8s >> bitwarden.values.yml

If you open the file, you will see the default configuration values to setup Bitwarden. Instead of using the flag --set property=value like before, we will use the file bitwarden.values.yml to make all the changes.

3. Update the values

We now need to update a few properties before installing the Helm chart. Open the file bitwarden.values.yml and change the following properties.

First we need to change to an ARM compatible image

## bitwarden.values.yml

  repository: bitwardenrs/server # Change here
  tag: raspberry  # Change here
  pullPolicy: IfNotPresent

Then we configure the environment variables.

Replace [ADMIN_TOKEN] by the result of the command $ openssl rand -base64 48. This token will be used to connect to the Bitwarden administration interface.

## bitwarden.values.yml

  SIGNUPS_ALLOWED: false  # Disable Sign Up form (invitation only)
  INVITATIONS_ALLOWED: true # Enable invitation
  ADMIN_TOKEN: "[ADMIN_TOKEN]" # Copy/Paste the result of the command `$ openssl rand -base64 48` (admin interface password)
  DOMAIN: "https://bitwarden.<domain.com>" # Domain used to access Bitwarden
  SMTP_HOST: "smtp.gmail.com" # SMTP host (invitation)
  SMTP_FROM: "no-reply@<domain.com>" # From email (invitation)
  SMTP_PORT: 587 # SMTP Port (invitation)
  SMTP_SSL: true # SMTP SSL (invitation)
  SMTP_USERNAME: "[SMTP_USERNAME]"  # SMTP username (invitation)
  SMTP_PASSWORD: "[SMTP_PASSWORD]"  # SMTP password (invitation)

In the next step, we configure an ingress to access Bitwarden and issue a certificate (especially if we want to access from outside).

Replace <domain.com> by your domain (same as the section "Internet access")

## bitwarden.values.yml

  enabled: true # Generate an Ingress while deploying
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod" # Cluster Issuer configured with certmanager
  path: /
    - bitwarden.<domain.com> # Domain for Bitwarden
    - secretName: bitwarden-domain-com-tls 
        - bitwarden.<domain.com> # Domain for Bitwarden

Finally, we want to plug Bitwarden to the persistent volume created at the beginning of the article pointing to /mnt/ssd/bitwarden.

## bitwarden.values.yml

### Persist data to a persistent volume
  enabled: true # Change here
  existingClaim: "bitwarden-ssd" # Change here

4. Install the Chart

In the part, we will install the Helm chart under the namespace bitwarden with bitwarden.values.yml as configuration file.

$ helm install bitwarden ~/workspace/bitwarden-k8s \
  --namespace bitwarden \
  --values bitwarden.values.yml

After a couple of minutes, check if the pod and service is up and running:

$ kubectl get pods -n bitwarden -o wide

NAME                                      READY   STATUS    RESTARTS   AGE     IP            NODE          NOMINATED NODE   READINESS GATES
bitwarden-bitwarden-k8s-58db5c445-7w7wq   1/1     Running   0          4m53s   kube-master   <none>           <none>


Once Bitwarden is up and running, we can start configuring our first user.

1. Access the admin interface

First, access the admin interface which should be available on https://bitwarden.<domain.com>/admin and enter the <ADMIN_PASSWORD> generated previously.

2. Invite your first user

Once connected, you can check and modify the different parameters of Bitwarden and invite a new user. Enter an email address to invite a new user.

After a few seconds, You should received the invitation via email. Click on "Join the Organisation".

3. Create an account and login for the first time

Click on "Create Account".

Configure the details of the user: name, master password (encryption key) and click on "Submit".

Finally, log into with the newly created user using the couple email, master password.


You now have a fully self-hosted password manager accessible via your own domain from anywhere.

You can also install and configure your custom server to easily and safely access your password: