Skip to Content

Vaultwarden Self-Hosting Guide: Deploy Your Own Bitwarden Password Manager in 15 Minutes

Set up a fully functional, self-hosted password manager using Vaultwarden and Docker Compose with zero ongoing subscription costs.

Cloud password managers are convenient until they aren't. Subscription hikes, outages, or the nagging feeling that someone else holds your keys — it adds up. Vaultwarden changes the equation. It's a lightweight, Rust-based reimplementation of the Bitwarden server API that runs happily on a $5 VPS and idles at around 50 MB of RAM. You get full compatibility with all official Bitwarden clients, zero monthly fees, and complete control over your vault data.

This guide covers everything from a bare Docker setup to a hardened, reverse-proxied deployment. If you want production-ready configurations with specific reverse proxies, check our dedicated guides for Caddy, NGINX + PostgreSQL, or Traefik.

What You Need Before Starting

Vaultwarden is not demanding, but it does have one hard requirement: HTTPS. Bitwarden clients refuse to connect over plain HTTP, so you need a domain with a valid TLS certificate. Here's the checklist:

  • A Linux server (Ubuntu 22.04 or 24.04 LTS recommended)
  • Docker Engine 24.x+ and Docker Compose v2 installed
  • At least 256 MB free RAM and 500 MB disk space
  • A domain or subdomain pointing to your server
  • A reverse proxy (Caddy, NGINX, or Traefik) with SSL termination configured
  • Basic familiarity with Docker Compose and Linux file permissions

That's it. No database server required — Vaultwarden uses SQLite by default, which handles thousands of users without breaking a sweat.

Project Structure and Docker Compose Setup

Start by creating a dedicated project directory. Isolating Vaultwarden in its own folder keeps volumes, environment files, and backups organized.

sudo mkdir -p /opt/vaultwarden
sudo chown $USER:$USER /opt/vaultwarden
cd /opt/vaultwarden

Create a docker-compose.yml file with the essential service definition. Bind the container port to 127.0.0.1 so Vaultwarden is only reachable through your reverse proxy, never directly from the internet.

services:
  vaultwarden:
    image: vaultwarden/server:1.35.4
    container_name: vaultwarden
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - vw-data:/data
    env_file:
      - .env

volumes:
  vw-data:

We use a named volume (vw-data) rather than a bind mount for simplicity. If you prefer bind mounts for easier backup access, replace the volume block with - ./data:/data.

Environment Configuration

The .env file controls every important behavior. Create it alongside your Compose file:

# Required: your public domain with https://
DOMAIN=https://vault.example.com

# Disable new signups after you create your account
SIGNUPS_ALLOWED=false

# Optional: admin panel for user management
ADMIN_TOKEN=$(openssl rand -base64 48)

# Optional: SMTP for email verification and invites
SMTP_HOST=smtp.example.com
[email protected]
SMTP_PORT=587
SMTP_SECURITY=starttls
[email protected]
SMTP_PASSWORD=your_app_password

Generate a strong admin token with OpenSSL and store it securely. The admin panel lives at /admin and lets you manage users, organizations, and diagnostics without touching the database.

openssl rand -base64 48

Important: never commit .env to version control. Add it to .gitignore if your project lives in a repository.

Starting the Container and Health Checks

Launch Vaultwarden with a single command:

docker compose up -d

Verify the container is running and healthy:

docker compose ps
docker compose logs --tail 50

Look for the line indicating the server is listening. If you see errors about the database path, check your volume permissions. Vaultwarden runs as UID 1000 inside the container by default.

Reverse Proxy and HTTPS

Vaultwarden requires HTTPS for all client connections. Since the container only exposes port 8080 on localhost, you need a reverse proxy to handle TLS termination and forward traffic. Below is a minimal NGINX configuration. For Traefik or Caddy, see our linked production guides above.

server {
    listen 443 ssl http2;
    server_name vault.example.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_buffering off;
        proxy_request_buffering off;
    }

    location /notifications/hub {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

The /notifications/hub location enables WebSocket connections for live vault syncing across devices. Without it, clients will still work, but changes won't propagate in real time.

Client Configuration and First Login

Once your domain resolves and HTTPS is active, open any official Bitwarden client. On the login screen, select Self-hosted and enter your server URL:

Server URL: https://vault.example.com

Create your master account while SIGNUPS_ALLOWED is still true (or temporarily enable it). After registration, set SIGNUPS_ALLOWED=false, restart the container, and you're closed to new registrations.

docker compose down
# Edit .env: SIGNUPS_ALLOWED=false
docker compose up -d

Invite additional users through the admin panel or by generating direct invite links. Organization support works exactly like hosted Bitwarden, so you can share collections with family or team members.

Backup, Updates, and Maintenance

Automated Backups

Your vault data lives in the SQLite database at /data/db.sqlite3 inside the container. Back it up regularly with a simple cron script:

#!/bin/bash
BACKUP_DIR="/opt/backups/vaultwarden"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

docker exec vaultwarden sqlite3 /data/db.sqlite3 ".backup '/tmp/db-backup.sql'"
docker cp vaultwarden:/tmp/db-backup.sql $BACKUP_DIR/vaultwarden_$TIMESTAMP.sql

# Keep only the last 14 backups
ls -t $BACKUP_DIR/*.sql | tail -n +15 | xargs -r rm

Updating Vaultwarden

Updates are straightforward. Pull the latest image, recreate the container, and verify:

docker compose pull
docker compose up -d
docker compose logs --tail 20

Always review the release notes before major version bumps. Breaking changes are rare, but they happen.

Tips and Troubleshooting

Container won't start

Check permissions on the data directory. If using a bind mount, ensure the host directory is writable by UID 1000:

sudo chown -R 1000:1000 /opt/vaultwarden/data

Clients show connection errors

Verify HTTPS is active and your certificate is valid. Bitwarden clients reject self-signed certs unless explicitly configured to trust them. Use Let's Encrypt or a commercial certificate.

WebSocket sync not working

Ensure your reverse proxy forwards the /notifications/hub path with proper upgrade headers. NGINX users need the separate location block shown earlier. Caddy and Traefik handle this automatically.

Admin panel inaccessible

The admin panel is at https://vault.example.com/admin. If you get a 404, confirm ADMIN_TOKEN is set in your .env and the container was restarted after the change.

Email not sending

Test SMTP credentials independently with a tool like swaks or msmtp. Vaultwarden logs SMTP errors at the warn level — check logs if invites or verification emails fail silently.

Database corruption

SQLite is robust, but power loss during writes can corrupt the database. Use a UPS if running on bare metal, or enable write-ahead logging (WAL) by setting ENABLE_DB_WAL=true in your .env. WAL mode improves concurrency and crash recovery.

Next Steps

You now have a self-hosted password manager that rivals commercial offerings in features and security, without the recurring cost. For hardened production deployments with specific reverse proxies, explore our detailed guides:

Need help hardening your setup, migrating from a cloud provider, or deploying at scale for your organization? Contact our team for enterprise Vaultwarden consulting and managed infrastructure services.

OpenClaw Docker VPS Deploy: Run Your Own AI Agent Gateway in Under 30 Minutes
Deploy OpenClaw on any VPS using Docker Compose — get a production-ready AI agent gateway with automatic HTTPS, persistent storage, and zero local dependencies.