Why Run Your Own Password Vault?
Bitwarden is widely trusted as an open-source password manager, but trusting the software and trusting a third-party server are two different things. Vaultwarden is a lightweight, unofficial Bitwarden-compatible server written in Rust that lets you run the entire stack on your own hardware. Your credentials never leave a machine you control, the sync works with all official Bitwarden apps and browser extensions, and the resource footprint is small enough to run on a Raspberry Pi.
The appeal goes beyond privacy. Self-hosting means no subscription fees for premium features like TOTP authenticator support, encrypted file attachments, and emergency access – all of which Vaultwarden unlocks for free. That alone makes the setup effort worth it for anyone managing more than a handful of accounts.
This guide walks through deploying Vaultwarden using Docker, securing it behind an HTTPS reverse proxy with Nginx and Let’s Encrypt, and connecting your Bitwarden clients to it.

Prerequisites and What You Will Need
Before touching a terminal, confirm you have a Linux server with Docker and Docker Compose installed. This can be a home server, a VPS, or a Raspberry Pi running a 64-bit OS. Vaultwarden requires very little RAM – 256 MB is sufficient under normal load – so an entry-level VPS at a few dollars a month works perfectly. You also need a domain name pointing to your server’s IP address, because Bitwarden clients enforce HTTPS and will refuse to connect over plain HTTP. If you do not have a domain, services like DuckDNS offer free subdomains.
You will need ports 80 and 443 open on your firewall. On most cloud providers that means configuring a security group or firewall rule in the control panel. On a home server you will need to forward those ports on your router. Nginx Proxy Manager is a popular choice for handling the reverse proxy and SSL certificates with a GUI, but this guide uses a direct Nginx config with Certbot for full transparency over what is happening.
Install Docker by following the official Docker documentation for your distribution. Once docker and docker compose commands return version numbers without errors, you are ready to proceed.
Deploying Vaultwarden with Docker Compose
Create a working directory and a docker-compose.yml file inside it. The configuration below is the starting point:
docker-compose.yml contents:
- image: vaultwarden/server:latest
- container_name: vaultwarden
- restart: unless-stopped
- environment:
- DOMAIN=https://vault.yourdomain.com
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=your-secret-admin-token
- volumes: ./vw-data/:/data/
- ports: 127.0.0.1:8080:80
Binding to 127.0.0.1:8080 rather than 0.0.0.0:8080 means Vaultwarden only accepts connections from localhost – Nginx will proxy traffic to it rather than exposing it directly. Set ADMIN_TOKEN to a long random string; you can generate one with openssl rand -base64 48. Once the file is saved, run docker compose up -d to pull the image and start the container. Check that it is running with docker compose ps.
With the container running, configure Nginx to act as the HTTPS front end. Install Nginx and Certbot, then run certbot –nginx -d vault.yourdomain.com to obtain a certificate. In your Nginx server block, proxy traffic to the Vaultwarden container like this: set proxy_pass http://127.0.0.1:8080; and include the standard proxy headers – X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto https. Vaultwarden also needs WebSocket support for live sync, so add a separate location /notifications/hub block that proxies to port 3012 on the container and sets proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection “upgrade”. After reloading Nginx with nginx -s reload, visiting your domain in a browser should show the Vaultwarden login page over HTTPS.

Locking It Down and Disabling Open Registration
Out of the box, Vaultwarden allows anyone who reaches your URL to create an account. That is useful for your initial setup, but once you have created your personal account – or accounts for anyone else who will use this instance – go into the admin panel at https://vault.yourdomain.com/admin and set SIGNUPS_ALLOWED=false in the environment variables, then restart the container. Alternatively, set it directly in the docker-compose.yml and run docker compose up -d again. From that point forward, the registration form will return an error for anyone who is not invited by an admin.
The admin panel also lets you enable email verification, configure SMTP for sending invite links and two-step login notifications, and manage existing users. Setting up SMTP is strongly recommended – without it you cannot send emergency access emails or account recovery links. Most people use a transactional email service like Mailgun or a Gmail app password for this. The relevant environment variables are SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, and SMTP_FROM.
Enable two-factor authentication on your Vaultwarden account immediately after creating it. The Bitwarden app supports TOTP, email codes, and FIDO2 hardware keys. Since Vaultwarden unlocks premium 2FA methods for all users by default, you can use a hardware key like a YubiKey without any additional configuration – something the hosted Bitwarden service gates behind a paid plan.
Connecting Bitwarden Clients and Staying Updated
Every official Bitwarden client – the desktop app, mobile apps, and browser extensions – supports custom server URLs. In the Bitwarden app, tap or click the region selector on the login screen, choose Self-hosted, and enter your domain in the Server URL field. The client will connect to your Vaultwarden instance instead of Bitwarden’s cloud. All features work identically: vault sync, autofill, Send, and organization sharing if you set that up. For teams looking at a more structured multi-user setup with role-based access, Passbolt is worth comparing – it is built specifically for team credential management with a different sharing model.
Keeping Vaultwarden updated is straightforward with Docker. Run docker compose pull to fetch the latest image, then docker compose up -d to restart with the new version. Your data persists in the ./vw-data/ directory, which is mounted as a volume and untouched by container updates. Back that directory up regularly – a simple cron job that tarballs it and copies it to an offsite location is sufficient. Losing your vault data because of a disk failure with no backup is the one scenario that turns self-hosting from a smart choice into a cautionary tale.
One detail that catches people off guard: Vaultwarden’s WebSocket port (3012) does not need to be publicly exposed if Nginx is handling the upgrade headers correctly. If vault sync feels slow or the browser extension shows connection errors, the first thing to check is whether the /notifications/hub location block in Nginx is present and correctly proxying to port 3012. A missing upgrade header in that block is the most common cause of sync failures after an otherwise successful setup.

Vaultwarden sits at an unusual intersection: the security of a well-audited open-source client combined with a server you run yourself on hardware only you can access. Every other self-hosted tool in your stack – your documents, your notes, your code – is only as protected as the credentials guarding it, and those credentials are now stored somewhere you can actually inspect, back up, and shut down on your own terms.





