$ initializing ...
homelab-vaultwarden

Vaultwarden: your own Bitwarden

HomelabServicesDocker

Introduction

There are countless services we can be signed up to nowadays.

Many of them we need to access daily, and others perhaps not for months, but whatever their use, on many occasions we end up using similar passwords, making our accounts easier to compromise.

Add to that the small oversights we can commit ourselves. Let me give you an example: imagine an important account, one with important data or access to bank accounts. We set a complex password; however, we configure the recovery email with one that has a simple password, reused many times. Well, it's easy for both to have been exposed.

Two-factor authentication or passkeys mitigate this and can be very effective in these cases, but often, to avoid added complexity, we never get around to setting them up, unless the service makes them mandatory.

Either way, using similar passwords or ones that can be deduced from our personal data (dates, names, etc.) is not a good idea at all.

But managing hundreds of different passwords every day, along with TOTP codes, is not convenient either.

The need for a password manager

That's where the need for a password manager that can handle all of this comes from.

At this point there are two kinds: those based on local files, or those based on a service. Both are valid.

Among the local file-based ones, KeePass stands out. What advantages does this type have? Well, the data never leaves our control, since it lives in a local file, which makes backups or replicas simple.

But it has a major drawback because none of those replicas are synchronized, so we would have to build and maintain a system to keep all those files in sync.

I used this for a while, relying on GDrive for synchronization, but at times it stops working and you end up with unsynced files, comparing the differences between one and the other.

Bitwarden Cloud

That's why the solution I bring you is to use an online password management service.

If you don't want complications, Bitwarden Cloud is your solution. It's a very mature SaaS service that lets you store your passwords and TOTP codes for MFA, and it has plugins for the most well-known browsers, plus apps for PC, Mac, iOS and Android, as well as online access.

Because it solves all the drawbacks that other kinds of applications have, in terms of synchronization and cross-platform access.

The drawback is that it's paid.

Vaultwarden: your own Bitwarden

There is open-source, self-hosted software, very easy to manage, that is very easy to deploy if we own a small home lab.

It's called Vaultwarden, and its great advantage is that it implements the same Bitwarden API specifications, so all the software built for Bitwarden is compatible with it, which gives it access to all the plugins and apps.

Is it safe to keep passwords in a home lab?

You might think that having access to passwords is something very critical, that you don't want to leave in the hands of a homegrown home lab that maybe sometimes you haven't had time to update with security patches and is vulnerable, or goes down for some reason.

In the first case, I'd tell you to always use a VPN for your home lab, since it's the safest option and there are plenty of choices where managing the connection from any device is very simple. WireGuard and OpenVPN are usually highly recommended options.

In the second case, there's not much of an issue either, since every app configured to point at your home lab stores a local copy, so you can access it even if the server is off or unreachable.

The only thing to keep in mind is that, in case you're using that local copy, you won't be able to update or create new entries, but you'll be able to look up all your passwords.

Hands on

The easiest way is to install it through Docker and, on top of that, it doesn't depend on any additional database service, since we can use SQLite to store the information.

This docker-compose.yml I've tested running on a Raspberry Pi, so it's a perfectly valid solution for a small home lab.

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      SMTP_HOST: smtp.example.host
      SMTP_FROM: info@example.host
      SMTP_PORT: 465
      SMTP_SECURITY: force_tls
      SMTP_USERNAME: info@example.host
      SMTP_PASSWORD: example-password
      SMTP_TIMEOUT: 15
      WEBSOCKET_ENABLED: "true"
      SIGNUPS_ALLOWED: "false"
      DOMAIN: "https://vaultwarden.example.host"
      ENABLE_ATTACHMENTS: "true"
      ATTACHMENTS_FOLDER: "/data/attachments"
      ATTACHMENTS_MAX_SIZE: "10485760"
    ports:
      - "9445:80"
    volumes:
      - ./data:/data

Image and container

image: vaultwarden/server:latest
container_name: vaultwarden
restart: always

Here we specify the Vaultwarden image we're going to use, the name the container will have, and that Docker should restart it automatically if it stops.

Data persistence

One of the most important points is this one:

volumes:
  - ./data:/data

Vaultwarden stores all its information inside /data. By mounting this volume, we're making that information stay stored outside the container.

This is essential because we can delete, update or recreate the container without losing our data.

Plus, by using SQLite, we don't need to spin up another container with MySQL, PostgreSQL or similar.

Port

ports:
  - "9445:80"

Vaultwarden listens internally on port 80 of the container, while we expose it on port 9445 of the server.

Therefore:

Server → 9445 → Container → 80

If we use a reverse proxy, like Nginx Proxy Manager, we could use this port only inside our network.

Domain

DOMAIN: "https://vaultwarden.example.host"

Here we specify the URL we'll use to reach Vaultwarden.

That URL doesn't necessarily have to be a public Internet address. We can use an internal domain as long as our devices are able to resolve it.

For example, we can make:

vaultwarden.example.host → 192.168.1.30

through a DNS entry in AdGuard Home, or even by modifying the hosts file of the devices.

This allows us to have a URL like:

https://vaultwarden.example.host

even though the service is only reachable from our local network or through a VPN.

That said, if we use HTTPS, we'll also have to have the certificate for that domain properly configured.

WebSockets

WEBSOCKET_ENABLED: "true"

Enables WebSockets, which allow keeping a persistent communication between the Bitwarden/Vaultwarden apps and the server.

It's recommended to keep it enabled, especially if we're going to use the desktop and mobile apps.

User sign-up

SIGNUPS_ALLOWED: "false"

This point is especially important if the server is going to be reachable from the Internet.

With false, nobody can freely create a new account.

The idea would be to initially create our account and then disable sign-ups.

Email

These variables:

SMTP_HOST: smtp.example.host
SMTP_FROM: info@example.host
SMTP_PORT: 465
SMTP_SECURITY: force_tls
SMTP_USERNAME: info@example.host
SMTP_PASSWORD: example-password

allow us to configure the SMTP server that Vaultwarden will use to send emails.

Attachments

ENABLE_ATTACHMENTS: "true"
ATTACHMENTS_FOLDER: "/data/attachments"
ATTACHMENTS_MAX_SIZE: "10485760"

Allows using file attachments in Vaultwarden.

In this case we're setting a limit of approximately 10 MB.

And, of course, the backups

Precisely because we're using:

  • ./data:/data

making a backup is relatively simple.

The data folder is critical, since it contains the database and the rest of Vaultwarden's persistent information.

Therefore, it's not enough to save the docker-compose.yml: we must have a backup strategy for /data.

Back to blog