Vaultwarden is a lightweight, open-source server that implements the Bitwarden protocol. You use the same polished Bitwarden browser extensions and mobile apps you may already know — but the vault lives on your server, not a company’s cloud. It is genuinely tiny: the process is happy on the cheapest VPS you can find.
Why self-host a password manager?
The appeal is control. When you run Vaultwarden, you own the encrypted vault file. There is no subscription (beyond whatever you pay for the VPS), no policy changes from a vendor, and no third-party breach that includes your data. The official Bitwarden apps are polished and work identically against a self-hosted server — this is not a rough DIY experience.
The trade-offs are real and worth naming. HTTPS is your responsibility. A password manager running over plain HTTP is worse than useless — it actively endangers you. Backups are your responsibility. If the server disappears and you have no copy of the data volume, the vault is gone. Self-hosting a password manager is higher-stakes than self-hosting a blog. Go in with that awareness and it is entirely manageable; go in blind and it is a liability.
Prerequisites
- A small VPS — 1 vCPU / 1 GB RAM is more than enough. See Best VPS for Self-Hosting for current options across providers.
- A domain or subdomain, such as
vault.yourdomain.com. If you have not done this before, follow How to Point a Domain to Your VPS. - Docker and Docker Compose installed on the server.
- A reverse proxy configured to terminate TLS — the next section links to the setup guide.
Step 1 — Write the Compose file
Create a directory for Vaultwarden and add a compose.yml file:
services:
vaultwarden:
image: vaultwarden/server:latest
restart: always
volumes:
- ./vw-data:/data
environment:
DOMAIN: "https://vault.yourdomain.com"
SIGNUPS_ALLOWED: "true"
ports:
- "127.0.0.1:8080:80"
A few notes on this config:
- Bind to
127.0.0.1:8080so the port is not directly exposed to the internet — traffic should arrive through your reverse proxy only. - Set
DOMAINto your actual HTTPS URL. Vaultwarden uses this for WebAuthn and other features that need the origin. - Leave
SIGNUPS_ALLOWED: "true"for now so you can create your account. You will disable it immediately after.
Step 2 — Start the container and create your account
docker compose up -d
Once HTTPS is live (Step 3 below), open https://vault.yourdomain.com in a browser, create your account, and verify it works. Then immediately disable open registration:
SIGNUPS_ALLOWED: "false"
Apply the change:
docker compose up -d
From this point, only existing accounts can log in. No one else can register.
Step 3 — HTTPS is mandatory
This bears repeating: never run a password manager over plain HTTP. All credentials travel in the clear, and most Bitwarden client features require a secure context anyway.
Put a reverse proxy in front of the Vaultwarden container and issue a free Let’s Encrypt certificate. Nginx Proxy Manager makes this straightforward — point vault.yourdomain.com at 127.0.0.1:8080 and let it handle the cert. Full walkthrough: Nginx Proxy Manager Setup.
One important detail: Vaultwarden uses WebSockets for live sync between clients. Your proxy must forward the Upgrade and Connection headers. Nginx Proxy Manager handles this automatically; if you are using raw Nginx or Caddy, ensure you have the WebSocket proxy directives in place.
Step 4 — Connect the Bitwarden apps
In any Bitwarden client — browser extension, iOS, Android, or desktop — look for Self-hosted server URL on the login screen (it is usually behind a settings or region selector). Enter https://vault.yourdomain.com and save. Then log in with the credentials you created in Step 2. Everything else — autofill, sync, collections, password generator — works identically to the hosted Bitwarden service.
Backups — do not skip this
A password vault you cannot restore is a disaster. Back up the vw-data directory regularly and store copies off-server:
- Ship the archive to an object store (S3-compatible, Backblaze B2, etc.) or a separate machine.
- Encrypt the backup before it leaves the server —
gpgsymmetric encryption is sufficient. - Test the restore process at least once. A backup you have never tested is not a backup.
A simple cron job that tars the directory, encrypts it, and uploads it covers the basics. Schedule it nightly at minimum.
Troubleshooting
Can’t register an account. SIGNUPS_ALLOWED is set to false (or you set it to false already). Set it back to true, restart, create the account, then disable it again.
Bitwarden app refuses to connect or shows a certificate error. The server URL is wrong, HTTPS is not configured, or the certificate is not trusted. Confirm the domain resolves to your VPS, the proxy is running, and a valid cert is in place.
Live sync does not work — changes on one device do not appear on another. WebSocket connections are being dropped. Your reverse proxy must forward the Upgrade and Connection headers. In Nginx, add proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection "upgrade"; to the location block.
Lost admin access. Set the ADMIN_TOKEN environment variable in the Compose file to a strong random string, restart the container, and access /admin in the browser. Generate a token with openssl rand -base64 48. Remove or randomize the token again when you are done.
Which VPS to run it on
Vaultwarden is the rare service where the cheapest tier is genuinely fine. You do not need much — something in the 1 GB RAM range from a reliable provider is all it takes. Hetzner offers some of the best value in Europe, and Vultr has a solid global network if location matters. See Best VPS for Self-Hosting for a full comparison.
If you are already running other services on the same box, Vaultwarden coexists happily alongside things like Nextcloud. Once the server is up, also review How to Secure a VPS — SSH hardening and a firewall are especially important when a password manager is involved.