Vaultwarden is an unofficial, lightweight server that implements the Bitwarden API. You use the official Bitwarden apps and browser extensions, but your encrypted vault lives on your own server. It runs happily in under 100 MB of RAM, which makes it one of the most popular self-hosted apps.

Vaultwarden is a community project, not affiliated with Bitwarden Inc. For organisations that need official support or compliance features, the official Bitwarden self-hosted server is the alternative.

What you need

  • A VPS with Docker and Docker Compose — see installing Docker on Ubuntu.
  • A domain or subdomain, e.g. vault.example.com, pointing to the server.
  • HTTPS is mandatory: the Bitwarden clients and the browser’s Web Crypto API refuse to work over plain HTTP.

1. Compose file

mkdir -p ~/vaultwarden && cd ~/vaultwarden

compose.yaml:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "true"        # set to false after creating your account(s)
      ADMIN_TOKEN: "${ADMIN_TOKEN}"
    volumes:
      - ./data:/data
    ports:
      - "127.0.0.1:8080:80"

Binding to 127.0.0.1 keeps Vaultwarden off the public internet; the reverse proxy on the host handles HTTPS. Pin a version tag instead of latest if you prefer controlled upgrades.

2. Admin token

The /admin page manages users and settings. Protect it with an Argon2-hashed token:

docker run --rm -it vaultwarden/server /vaultwarden hash

Enter a strong password twice; it prints a $argon2id$… string. Put it in .env, escaping each $ as $$ for Compose:

ADMIN_TOKEN='$$argon2id$$v=19$$m=65540,t=3,p=4$$…'

You log in to /admin with the plain password, not the hash.

3. Start

docker compose up -d
docker compose logs -f

4. HTTPS with Nginx

/etc/nginx/sites-available/vaultwarden:

server {
    listen 80;
    server_name vault.example.com;

    client_max_body_size 525M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d vault.example.com

The Upgrade headers enable WebSocket notifications, so changes sync to other devices immediately. Recent Vaultwarden versions serve WebSockets on the main port — no separate port 3012 is needed anymore.

Prefer Caddy? Its two-line config gets certificates automatically — see Caddy as a reverse proxy.

5. Create your account and close signups

Open https://vault.example.com, create your account, and log in from the Bitwarden apps by choosing Self-hosted and entering your server URL.

Then disable open registration — otherwise anyone who finds your server can create an account:

      SIGNUPS_ALLOWED: "false"
docker compose up -d

You can still invite family or team members from /admin (requires SMTP) or allow signups only for your domain with SIGNUPS_DOMAINS_WHITELIST.

SMTP enables invitations, email verification and 2FA via email:

      SMTP_HOST: "smtp.example.com"
      SMTP_FROM: "[email protected]"
      SMTP_PORT: "587"
      SMTP_SECURITY: "starttls"
      SMTP_USERNAME: "[email protected]"
      SMTP_PASSWORD: "${SMTP_PASSWORD}"

Use a transactional email service or your mail provider’s SMTP.

7. Backups — the most important step

If the server dies without a backup, your passwords are gone. The data/ directory contains:

  • db.sqlite3 — the vault database (encrypted entries)
  • attachments/, sends/ — files
  • rsa_key* — keys used to sign login tokens
  • config.json — settings made in the admin panel

Back up the SQLite database safely while running:

sqlite3 ~/vaultwarden/data/db.sqlite3 ".backup '/var/backups/vw-$(date +%F).sqlite3'"
tar czf /var/backups/vw-files-$(date +%F).tar.gz -C ~/vaultwarden/data attachments sends config.json rsa_key.pem

Copy backups off the server and encrypt them — see BorgBackup. Also keep an encrypted export of your vault (Bitwarden app → Export vault) somewhere offline.

8. Hardening

  • Enable two-step login for your account (authenticator app or a FIDO2 key).
  • Keep /admin protected by the Argon2 token, or disable it after setup by removing ADMIN_TOKEN.
  • Add Fail2Ban for failed logins: set LOG_FILE=/data/vaultwarden.log and create a filter matching Username or password is incorrect.
  • Keep the host patched and Docker images updated.

Updating

cd ~/vaultwarden
docker compose pull
docker compose up -d
docker image prune -f

Back up before upgrading.

Why a VPS for this?

A password manager must be reachable from your phone, laptop and work computer at all times. A small VPS with a static IP is more reliable than a home server behind a residential connection. Vaultwarden is tiny — the smallest VPS plan has plenty of headroom, and you can run other apps alongside it. Compare with Passbolt for teams.

  • Vaultwarden
  • Bitwarden
  • Self-Hosting