Vaultwarden: Self-Hosting a Password Manager You Actually Control

Bitwarden's vault, on hardware you own

A password manager is the single most important piece of software most people never think about. It quietly holds the keys to your email, your bank, your tax account, and the embarrassing forum you joined in 2009 and forgot to delete. Handing that responsibility to a cloud service is perfectly reasonable, and the big providers do a genuinely good job. But if you would rather your encrypted vault lived on a box in your own cupboard than on someone else’s servers, Vaultwarden is the project that makes self-hosting practical without demanding you become a cryptographer first. This guide walks through what it is, how to stand one up safely, and the honest trade-offs you accept when you take the keys back.

The case for self-hosting is partly about control and partly about economics. Hosted Bitwarden is inexpensive, but premium features such as organisations, file attachments, and TOTP storage sit behind a subscription. Vaultwarden unlocks essentially all of those features for the cost of running a small container. That alone tempts plenty of people.

The deeper motivation is custody. Even though a well-designed vault is encrypted client-side, meaning the server only ever sees ciphertext, some people simply prefer that the ciphertext never leaves their control. If you run the server, there is no third party to subpoena, no business model that might change, and no remote outage that locks you out of your own logins. You also get to decide exactly who can create an account, which matters more than it sounds.

None of this is an attack on hosted services. For most households, paid Bitwarden is the sensible choice precisely because someone else handles uptime, patching, and backups. Self-hosting is for people who actively want that work, or who already run a home server and would like one more useful service on it.

Vaultwarden is an unofficial, community-built server that speaks the Bitwarden API. It was originally written under the name “bitwarden_rs” and is implemented in Rust, which is why it is so light: it happily runs in a few tens of megabytes of memory on a Raspberry Pi, where the official Bitwarden server stack is comparatively heavy and assumes a more serious deployment.

The clever part is compatibility. Because Vaultwarden implements the same API the official clients expect, you keep using the real Bitwarden apps, browser extensions, and command-line tools. You simply point them at your own server URL instead of the public one. Your vault, your sync, your autofill, all unchanged from the user’s point of view, but the backend is yours.

It is worth being precise about the relationship: Vaultwarden is not produced or endorsed by Bitwarden the company. It is an independent reimplementation. That brings flexibility and a low resource footprint, but it also means you are trusting a separate project’s code and its security track record, which has been good but is not the same organisation.

The cleanest way to run Vaultwarden is in a container. The example below assumes you already have Docker and the Compose plugin installed, and that you will be putting the service behind a reverse proxy (more on that shortly, because it is mandatory).

Create a directory and a compose.yaml:

mkdir -p ~/vaultwarden && cd ~/vaultwarden
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "false"
      ADMIN_TOKEN: "${ADMIN_TOKEN}"
    volumes:
      - ./data:/data
    ports:
      - "127.0.0.1:8080:80"

Notice the port binding is 127.0.0.1:8080:80. That deliberately exposes the container only on the loopback interface, so nothing reaches it except your reverse proxy. Generate a strong admin token and store it in a .env file beside the compose file:

openssl rand -base64 48
# .env
ADMIN_TOKEN=paste-the-long-random-string-here

Then bring it up:

docker compose up -d
docker compose logs -f

The logs will confirm it has started. At this point the service is running but is not yet reachable from your browser over a proper address, which is exactly how it should be until HTTPS is in front of it.

This deserves its own section in bold letters: never expose Vaultwarden over plain HTTP. The Bitwarden clients use the Web Crypto API, which browsers only permit over a secure context. More fundamentally, your login flow and vault sync traffic must be encrypted in transit. Running a password manager over HTTP is the security equivalent of mailing your house keys on a postcard.

The standard approach is a reverse proxy that terminates TLS and forwards to the loopback port. Caddy is the gentlest option because it obtains and renews certificates automatically. A complete Caddyfile can be as short as this:

vault.example.com {
    reverse_proxy 127.0.0.1:8080
}

Caddy will fetch a certificate from Let’s Encrypt, redirect HTTP to HTTPS, and keep the certificate renewed. If you prefer Nginx or Traefik the principle is identical: terminate TLS at the proxy, proxy to 127.0.0.1:8080, and forward the standard headers. Make sure the DOMAIN environment variable in your compose file matches the public HTTPS URL exactly, because Vaultwarden uses it to construct links and validate requests.

If your server is only ever reached from inside your own network, you still want TLS, but you can use an internal certificate authority or a wildcard certificate for a domain you control rather than exposing the box to the public internet.

Once HTTPS is live, open https://vault.example.com in a browser. Because signups are disabled, you create the first account through the admin page or by temporarily enabling signups, then turning them off again.

In any official Bitwarden client, the trick is the same. Before logging in, open the settings (often a cog icon on the login screen) and set the Server URL to your domain. Then log in with your vault credentials as normal. This works in:

  • The browser extensions for Firefox, Chrome, and the rest
  • The desktop applications on Linux, macOS, and Windows
  • The mobile apps on Android and iOS
  • The bw command-line tool, via bw config server https://vault.example.com

From here, autofill, password generation, TOTP codes, and folders all behave exactly as they would against hosted Bitwarden, because they are the very same apps.

The admin interface lives at https://vault.example.com/admin and is gated by the ADMIN_TOKEN you generated. From here you can invite users, see diagnostics, and tweak settings without editing environment variables by hand.

The most important setting is open registration. By default you should keep SIGNUPS_ALLOWED set to false, because an internet-facing vault server with open signups is an invitation for strangers to create accounts on your hardware. If you want to add family members, either invite them explicitly from the admin page or flip signups on briefly, register the accounts, and flip them straight back off. For tighter control, the SIGNUPS_DOMAINS_WHITELIST option restricts registration to specific email domains.

Treat the admin token like a root password. Anyone who has it can reconfigure your server.

Everything that matters lives in the ./data directory you mounted: the SQLite database, attachments, the RSA keys used to sign tokens, and your configuration. Back that directory up and you can rebuild the entire service anywhere.

Because the database is held open while the container runs, a clean backup is best taken with the service briefly stopped, or via SQLite’s online backup. A simple nightly approach:

cd ~/vaultwarden
docker compose stop
tar czf "/backups/vaultwarden-$(date +%F).tar.gz" data
docker compose start

The stop window is a couple of seconds. Send those archives somewhere off the machine, encrypt them at rest, and actually test a restore once, because an untested backup is just a hopeful rumour. Remember that the vault contents are already encrypted, but the backup archive also contains the signing keys, so guard it carefully.

The reassuring part of the threat model is that your vault is encrypted on the client before it ever reaches the server, derived from your master password. A server compromise exposes ciphertext, not plaintext passwords, provided your master password is strong. The server still sees metadata, login timing, and the structure of your vault, so it is not a magic invisibility cloak.

Now the caveats, stated plainly. You are the operations team now: patching the container, renewing certificates, monitoring for the day it falls over, and keeping backups current. If your server dies and your backups are stale, that is on you. Vaultwarden is excellent software but is a community project, not the official server, so you inherit its update cadence. And exposing any service to the public internet enlarges your attack surface, so keep the host updated, consider restricting access to a VPN, and never reuse the admin token anywhere else.

Self-hosting a password manager is one of the more rewarding home-server projects precisely because the stakes make you careful. Done properly, you end up with a fast, private, fully featured vault that answers only to you, which is exactly the point.