Self-Host Vaultwarden on Ubuntu 22.04

Published on — Nov. 29, 2022
#self-host #vaultwarden #tool #oracle-cloud #cloudflare #docker

This article describes how to use docker and cloudflare to deploy Vaultwarden (formerly Bitwarden_RS) on an Oracle Cloud Free-tier account (Ampere A1, AArch64) on Ubuntu 22.04.


I decided to settle for Ubuntu and Docker after struggling for a whole night (literally) to deploy Vaultwarden by Podman on Oracle Linux 8 (ol8).

Why not use ol8 and Docker? To make a long story short, trying to install docker on ol8 is a nightmare.

As a result, in this article, I’ll show you how to install Vaultwarden (formerly Bitwarden_RS) on Ubuntu 22.04. The hosting machine I used is ARM architecture (Ampere A1), but I’m pretty sure this tutorial will work on x86_64 machines as well.

Prerequisites

  • A domain name
  • A Cloudflare account (Optional, can be replaced by Let’s Encrypt, etc.)
  • An Oracle Cloud account (Optional, can be replaced by any other provider)

Setup Cloudflare

I went with cloudflare for my TLS certificate because I use it to manage DNS records and other things. Instead that, you can use another similar service, such as Let’s Encrypt, and follow the official wiki, or you can purchase your own certificates. It should be noted that not configuring HTTPS is strongly discouraged, so please select the appropriate service for your data security.

Create Oracle Cloud Instance

For each account, Oracle Cloud provides two x86 instances (shape: VM.Standard.E2.1.Micro) and up to four AArch64 instances (shape: VM.Standard.A1.Flex). That’s a great bargain for me. However, keep in mind that Oracle Cloud reserves the right to terminate any free-tier account at any time. This is one of the prices of free.

Each tenancy gets the first 3,000 OCPU hours and 18,000 GB hours per month for free to create Ampere A1 Compute instances using the VM.Standard.A1.Flex shape (equivalent to 4 OCPUs and 24 GB of memory). Each tenancy also gets two VM.Standard.E2.1.Micro instances for free. Learn more about Always Free resources

You can use this article to create Oracle Cloud instances, manage ingress rules, and so on.

Setup Your Server

Here are some commands to help you set up your instance. Before you begin, I strongly advise you to create an A record in your DNS manager.

Login Via SSH

On Oracle Cloud, the default username for root is ubuntu. Please remember to replace ubuntu (if you are not using Oracle Cloud) and YOUR_SERVER_IP with the appropriate values.

1
$ ssh ubuntu@YOUR_SERVER_IP

Create a New User

On Linux, it’s not a good idea to use the root account all the time, so creating a new user for the remaining tasks is preferable. Especially if you’re unfamiliar with Linux (like me) and don’t want to mess it up.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ sudo adduser vaultwarden
# Follow the instruction to add a password, you
#   can leave a blank for name etc.

# Granting super user privileges to your new user
$ sudo usermod -aG sudo vaultwarden

# WARNING: Do NOT type `~/.ssh/`
#   because it will only copy the content in
#   the fold instead of the whole folder.
#   If you accidently typied `~/.ssh/`, simply
#   create the folder manually and move the file(s) into it
$ sudo rsync --archive --chown=vaultwarden:vaultwarden ~/.ssh /home/vaultwarden

vaultwarden is the user name, you can choose whatever you want.

Setup the Firewall

Next, use ufw to setup the firewall to allow incoming HTTPS. Feel free to use tools that you are familiar with, such as firewalld.

1
2
3
4
5
6
7
8
9
$ sudo ufw status

# Enable the `ufw` if it is inactive
$ sudo ufw enable

$ sudo ufw allow https

# Or you can use the port
$ sudo ufw allow 443

Possible output:

1
2
Rule added
Rule added (v6)

We check the status again to make sure ufw is running

1
$ sudo ufw status

You could proceed if the output looks like this.

1
2
3
4
5
6
Status: active

To                         Action      From
--                         ------      ----
443                        ALLOW       Anywhere
443 (v6)                   ALLOW       Anywhere (v6)

Install Docker

Installing Docker on Ubuntu is fairly simple. The commands I used were taken from the official documentation. You can go there directly or use the commands I’ve provided below if you don’t want to open an exta website.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ sudo apt-get update

# Install requirements
$ sudo apt-get install \
        ca-certificates \
        curl \
        gnupg \
        lsb-release

# You can create the folder manually
#   if `/etc/apt/keyrings` does not exist
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
   | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

$ echo \
  "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

$ sudo apt-get update

$ sudo apt-get install \
        docker-ce \
        docker-ce-cli \
        containerd.io \
        docker-compose-plugin

# Test
$ sudo docker run hello-world

Add Cloudflare Origin Certificates to Your Server

If you do not want to use Cloudflare or do not want to use Full (strict) mode, simply skip this step.

On your homepage, click SSL/TLS -> Origin Server -> Create Certificate

Generate Step 1

In the next step, you can simply leave everything as is, but make sure the private key type is RSA (2048).

Finally, save the key and certificate to your server. You can, for example, simply copy and paste them into new files like:

1
2
3
4
5
6
7
8
# Create a folder to store ssl certs
$ mkdir ~/vw/ssl -p

$ vim ~/vw/ssl/cert.pem
# Then paste the cert into it

$ vim ~/vw/ssl/key.pem
# Then paste the key into it

Deploy Vaultwarden Via Docker

It is extremely simple to deploy Vaultwarden without a reverse proxy using Docker, though this is not recommended. The only reason I chose to enable HTTPS through Rocket is that I know nothing about reverse proxies. Here’s what I did:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ sudo docker pull vaultwarden/server:latest

# Create a folder to store data
$ mkdir ~/vw/vw-data

# Create the Docker container for Vaultwarden
#   I highly recommand you to read the explanation
#   prior to invoke this line of script
$ sudo docker run -d --name vaultwarden \
    -v /home/vaultwarden/vw/vw-data/:/data/ \
    -v /home/vaultwarden/vw/ssl/:/ssl/ \
    -e ROCKET_TLS='{certs="/ssl/cert.pem", key="/ssl/key.pem"}' \
    -p 443:80 \
    --restart on-failure \
    vaultwarden/server:latest
  • -d make the container run in the background
  • --name vaultwarden give the container a name, change it if you wish
  • -v /PATH_TO_FOLDER_YOU_CREATED/:/data/ tell the container where the data actually located, so the files like database can still exist if the coontainer is stopped or deleted
  • -v /PATH_TO_FOLDER_YOU_CREATED/:/ssl/ same as above, but for ssl certs
  • -e ROCKET_TLS='{certs="/path/to/cert.pem", key="/path/to/key.pem"' set an environment variable called ROCKET_TLS, so the Rocket framework can locate related files
  • --restart on-failure ensure the container remains running when host reboot
  • vaultwarden/server:latest mirror name

If everything goes well, you can visit your website and create an account.

Further Configuration

you may want to disable unwanted registration or enable the admin page.

Disable Registeration

First, stop and delete the currently running container.

Don’t worry, if the container is destroyed, your data will not be erased. Remember what we did in the previous step about storing them outside the container in a custom path? (For those who are unfamiliar with Docker)

1
2
$ sudo docker stop vaultwarden
$ sudo docker rm vaultwarden

Then create a new container:

1
2
3
4
5
6
7
8
9
# Note a new line added
$ sudo docker run -d --name vaultwarden \
    -v /home/vaultwarden/vw/vw-data/:/data/ \
    -v /home/vaultwarden/vw/ssl/:/ssl/ \
    -e ROCKET_TLS='{certs="/ssl/cert.pem", key="/ssl/key.pem"}' \
    -e SIGNUPS_ALLOWED=false \
    -p 443:80 \
    --restart on-failure \
    vaultwarden/server:latest
  • -e SIGNUPS_ALLOWED=false set the environment variable to false

Enable Admin Page

You can enable the admin page for convenience if you don’t want to manually recreate a new container every time you change a setting.

The admin page

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ sudo docker stop vaultwarden
$ sudo docker rm vaultwarden

# Note a new line added
$ sudo docker run -d --name vaultwarden \
    -v /home/vaultwarden/vw/vw-data/:/data/ \
    -v /home/vaultwarden/vw/ssl/:/ssl/ \
    -e ROCKET_TLS='{certs="/ssl/cert.pem", key="/ssl/key.pem"}' \
    -e ADMIN_TOKEN=YOUR_TOKEN \
    -p 443:80 \
    --restart on-failure \
    vaultwarden/server:latest
  • -e ADMIN_TOKEN=YOUR_TOKEN set the environment variable, remember to replace it with your own password. You can generate a strong token by running $ openssl rand -bas e64 48. Please keep it secret

Then you can enable/disable physical secure key support (like Yubico), enable/disable invitation etc.

Reference

  1. Initial Server Setup with Ubuntu 22.04, from DigitalOcean

  2. UFW Essentials: Common Firewall Rules and Commands, from DigitalOcean

  3. Install Docker Engine on Ubuntu, from Docker Documentation

  4. Enabling HTTPS, from dani-garcia/vaultwarden Wiki

Extra Resources

Furthermore, if you want to use firewalld to manage your firewall or podman instead of docker, this article may be useful:

  • How I Setup Bitwarden on Oracle Cloud Free Tier with Cloudflare, from Medium by andtheysay

Linode also offers a detailed tutorial for enabling HTTPS via Caddy (a reverse proxy tool) as well as starting from scratch.

  • Self-Hosting the vaultwarden Password Manager, from Linode

And here’s how to use Let's Encrypt instead of Cloudflare.

Project Homepage: dani-garcia/vaultwarden on GitHub

Docker Documentation: get-started on docker docs