Self-Hosting·6 min read·

Deploying Vaultwarden: Lightweight Self-Hosted Password Management

Host a secure, private Bitwarden-compatible vault with Vaultwarden on Linux, featuring WebSocket notifications, encrypted backups, and admin lockdown.

NB

Netbay Infrastructure Team

Netbay Engineering

On this page

Password management is the first line of defense against credential stuffing and credential theft. Bitwarden is the gold standard for cross-platform open-source password managers, but its official enterprise server stack is written in C# and Microsoft SQL Server, requiring at least 3GB of RAM.

Vaultwarden is an alternative Bitwarden-compatible server implementation written in Rust. It implements the complete Bitwarden API specification—including organization vaults, two-factor authentication (FIDO2/WebAuthn), and real-time WebSocket push notifications—while consuming less than 40MB of system memory.

Architectural Security and Prerequisites

Vaultwarden adheres to zero-knowledge encryption:

  1. Master passwords never leave the client browser or mobile application.
  2. Cryptographic keys (AES-256 and RSA-2048) are derived on client devices using PBKDF2 or Argon2id.
  3. Vaultwarden stores only encrypted ciphertext; even the server administrator cannot decrypt vault passwords.
  4. Modern WebAuthn and WebCrypto APIs mandate TLS encryption (HTTPS).

By running Vaultwarden behind a TLS reverse proxy like Caddy or Nginx, you ensure that cryptographic payloads and session tokens are transmitted securely across the public internet.

Writing the Docker Compose File

Create the application directory at /srv/vaultwarden:

bash
sudo mkdir -p /srv/vaultwarden/data
sudo chown -R 1000:1000 /srv/vaultwarden
cd /srv/vaultwarden

Generate a cryptographically secure Argon2 administrative token:

bash
# Generate admin token using openssl
openssl rand -base64 32

Create docker-compose.yml:

yaml
# /srv/vaultwarden/docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=false # Disable public signups after setup
      - INVITATIONS_ALLOWED=true
      - ADMIN_TOKEN=YourGeneratedArgon2TokenHere
      - SENDS_ALLOWED=true
      - EMERGENCY_ACCESS_ALLOWED=true
      - DOMAIN=https://vault.example.com
    volumes:
      - /srv/vaultwarden/data:/data
    ports:
      - "127.0.0.1:8000:80"
      - "127.0.0.1:3012:3012" # Dedicated WebSocket notifications port

Notice that ports bind to 127.0.0.1 rather than 0.0.0.0, ensuring that only the local reverse proxy can reach the application.

Expand
Vaultwarden Password Security
Vaultwarden Zero-Knowledge Password Vault

Configuring Caddy with WebSocket Routing

Bitwarden browser extensions rely on WebSockets to synchronize password changes instantly across devices without polling. Configure Caddy to proxy both standard HTTP traffic and WebSocket connections:

caddy
# /etc/caddy/Caddyfile
vault.example.com {
    # Route real-time WebSocket notifications to port 3012
    @websockets {
        header Connection *Upgrade*
        header Upgrade websocket
    }
    reverse_proxy @websockets 127.0.0.1:3012

    # Route standard API traffic to port 8000
    reverse_proxy 127.0.0.1:8000 {
        header_up X-Real-IP {remote_host}
    }

    # Strict security headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }

    encode zstd gzip
}

Reload Caddy:

bash
sudo systemctl reload caddy
Vaultwarden Zero-Knowledge Architecture Client Application - Browser / Mobile App - Argon2id key derivation - AES-256 client encrypt - Master key never leaves Zero-Knowledge trust Caddy TLS Edge - Port 443 HTTPS - Auto Let's Encrypt - WebSocket /notifications - API route to :8000 HSTS preloaded Vaultwarden (Rust) - Memory footprint <40MB - Encrypted SQLite WAL - SIGNUPS_ALLOWED=false - Instant extension sync High-Speed SSD storage Vaultwarden provides complete Bitwarden enterprise compatibility with minimal RAM
Self-Hosted Security, Backups, and Private Server Management
YouTube

Safe Live Backups of SQLite WAL

Never copy a live SQLite database with raw cp, as this risks capturing an inconsistent transaction during WAL flushing. Use sqlite3 .backup:

bash
# Execute an atomic live backup of the SQLite database
sudo sqlite3 /srv/vaultwarden/data/db.sqlite3 ".backup '/srv/vaultwarden/data/db_backup.sqlite3'"

# Archive database and attachments
tar -czf /srv/vaultwarden/vaultwarden-backup-$(date +%F).tar.gz   /srv/vaultwarden/data/db_backup.sqlite3   /srv/vaultwarden/data/attachments   /srv/vaultwarden/data/rsa_key.pem

Vaultwarden guarantees that your organization's sensitive credentials remain entirely under your sovereign control.

Deploy your private Vaultwarden instance on Netbay Linux VPS in under 60 seconds with High-Speed SSD in Lucknow DC01 — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance