August 23, 2026

Vaultwarden: Bitwarden Compatibility on Your Own Server

Deployment notes for Vaultwarden, a lightweight self-hosted password manager server compatible with official Bitwarden clients: architecture, Docker Compose setup, HTTPS requirements, SQLite WAL backup strategy, and limitations.

Vaultwarden is an alternative implementation of the Bitwarden server written in Rust: a single lightweight binary compatible with official Bitwarden clients. Deployment and evaluation notes, not a claim that it replaces every credential-management need.

Why run your own Bitwarden server

The official Bitwarden cloud is convenient — clients are genuinely good — but three things rankle: data still lives on a third-party server even though the vault is encrypted; TOTP, attachments, and organizations require a premium subscription; and the official server is resource-heavy and .NET-based, expensive to self-host. Vaultwarden addresses all three: compatible with every official client (browser extension, iOS/Android apps, desktop), lightweight — RAM typically below 50 MB — and premium features free. The selling point is compatibility: the clients stay the same, only the server URL changes.

Architecture: a single Rust binary behind the Bitwarden API

Vaultwarden implements the Bitwarden Client API almost completely in one Rust binary, with SQLite as the default database backend; the bundled web vault is an official Bitwarden build with patches, so the browser UI is identical to bitwarden.com. Data is encrypted client-side; the server only stores ciphertext and never receives the master password. All data lives in one directory: db.sqlite3 (plus -wal/-shm), attachments/, sends/, config.json, and rsa_key.* files for auth tokens. WebSocket live-sync for browser/desktop is on by default since v1.29 and runs on the main HTTP port since v1.31 (port 3012 is gone); mobile uses FCM/APNs push requiring credentials from Bitwarden’s cloud.

Deployment with Docker Compose

This is the Compose setup used:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - WEBSOCKET_ENABLED=true
    volumes:
      - ./vw-data:/data
    ports:
      - "8008:80"

The ./vw-data volume holds all persistent data; port 8008 is published from the container’s port 80. Behind a reverse proxy, set the DOMAIN environment variable to the public URL. Note: WEBSOCKET_ENABLED is deprecated since v1.29 — WebSocket is on by default, just ensure the proxy forwards Upgrade/Connection headers. The image runs as root by default; add user: "1000:1000" for least privilege.

HTTPS is mandatory, plus admin panel hardening

HTTPS is not optional: the web vault needs the Web Crypto API, which browsers only expose in secure contexts, and clients refuse plain HTTP except on localhost. The recommended path is a TLS-handling reverse proxy — Caddy, Nginx Proxy Manager, Traefik, Cloudflare Tunnel, or Tailscale HTTPS — with Let’s Encrypt or Cloudflare origin certificates. Built-in TLS via ROCKET_TLS is not recommended: immature, no ECC, no strict SNI. Mobile apps need correct OCSP stapling; self-signed or incomplete chains break login on many devices.

The admin panel at /admin only becomes active once ADMIN_TOKEN is set. Use a long random string (e.g. openssl rand -base64 32), ideally argon2id-hashed via vaultwarden hash, and enable it only after HTTPS is in place. Public registration is on by default: set SIGNUPS_ALLOWED=false for a private instance; consider fail2ban for brute force.

Backing up the SQLite WAL database

Nearly all vault data lives in db.sqlite3 inside /data. WAL mode makes direct copies while the container runs risky; the documented approach is the sqlite3 CLI’s .backup command (Online Backup API) or VACUUM INTO, or the built-in docker exec vaultwarden /vaultwarden backup since v1.32.1. The images ship no sqlite3 binary or cron, so schedule backups on the host.

Do not forget attachments/ (files outside the database), config.json (admin token and SMTP credentials in plaintext), and rsa_key.* (loss forces every user to log in again). Backups should be encrypted — e.g. a Duplicati repository — with at least one copy off-host. When restoring, stop the container first and delete any stale -wal file.

Limitations worth knowing

  • Not an official Bitwarden project. Maintained by volunteers with no release schedule; bugs cannot be reported to Bitwarden support.
  • Feature parity is not 100%. The Public API is only partial (Directory Connector), passkey login is in progress, and New Device Login Protection, custom roles, and some enterprise policies are missing; SSO and directory sync are not a priority.
  • Mobile clients still touch Bitwarden’s cloud. FCM/APNs push needs credentials from Bitwarden’s cloud — a trade-off if going fully Bitwarden-free.
  • Sensitive to TLS configuration. Self-signed or incomplete chains break client connections; mobile requires correct OCSP stapling.
  • Single failure domain. Server down means the vault is unreachable until it recovers; off-host backups remain mandatory, and a lost master password means nobody can open the data.

Conclusion

For a single-machine homelab comfortable with the Bitwarden client ecosystem, Vaultwarden is a rational choice: full client compatibility, small footprint, premium features without a subscription. The trade-offs are clear — an unofficial project with missing features, mobile push tied to Bitwarden’s cloud, and TLS that must be right. With encrypted backups and an off-host copy, it is an honest foundation for credential management.

References