Trusting a third party with your password vault is a calculated risk. Even reputable services can be breached, subpoenaed, or shut down. Self-hosting Bitwarden using Vaultwarden — a lightweight, community-maintained Rust reimplementation of the Bitwarden server — puts your vault entirely under your control. You keep your data, you manage your backups, and no one can lock you out or hand your data to anyone.
This guide walks through deploying Vaultwarden on a VPS (a $5/month Hetzner or DigitalOcean instance works fine) or a home server running Ubuntu or Debian.
What is Vaultwarden?
Vaultwarden (formerly Bitwarden_RS) is a server-side implementation of the Bitwarden API written in Rust. It is compatible with all official Bitwarden clients — browser extensions, mobile apps, and the desktop application — so you get the full Bitwarden experience without running Bitwarden’s official server, which requires significantly more resources. Vaultwarden runs comfortably on a 512 MB RAM VPS.
Important: Vaultwarden is an unofficial, community project. It is not affiliated with Bitwarden, Inc. For personal and family use it is excellent. For enterprise compliance requirements, evaluate accordingly.
Requirements
- A VPS or home server running Ubuntu 22.04 or Debian 12
- A domain name with DNS you control (e.g.,
vault.yourdomain.com) - Docker and Docker Compose installed
- Port 80 and 443 open in your firewall
Step 1: Install Docker and Docker Compose
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Add the Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Add your user to the docker group
sudo usermod -aG docker $USER
newgrp docker
Verify the installation:
docker --version
docker compose version
Step 2: Point Your Domain to the Server
In your DNS provider’s control panel, create an A record for vault.yourdomain.com pointing to your server’s public IP address. Allow a few minutes for DNS propagation before proceeding.
Step 3: Create the Docker Compose File
Create a working directory and compose file:
mkdir -p ~/vaultwarden && cd ~/vaultwarden
Create docker-compose.yml:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.yourdomain.com"
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: "your-strong-random-token-here"
volumes:
- ./vw-data:/data
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- vaultwarden
volumes:
caddy_data:
caddy_config:
A few important notes on the configuration:
SIGNUPS_ALLOWED: "false"disables public registration. Create your account first by temporarily setting this to"true", then flip it back.ADMIN_TOKENshould be a long random string. Generate one withopenssl rand -base64 48.- Vaultwarden data is stored in
./vw-dataon the host, making backups straightforward.
Step 4: Configure Caddy as a Reverse Proxy
Caddy handles HTTPS automatically using Let’s Encrypt. Create a file named Caddyfile:
vault.yourdomain.com {
reverse_proxy vaultwarden:80
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy no-referrer
}
}
Replace vault.yourdomain.com with your actual domain throughout.
Step 5: Start Vaultwarden
Temporarily enable signups to create your account:
Edit the SIGNUPS_ALLOWED line in docker-compose.yml to "true", then run:
docker compose up -d
Visit https://vault.yourdomain.com in your browser. You should see the Bitwarden login page served over HTTPS with a valid certificate. Create your account, then:
- Edit
docker-compose.ymland setSIGNUPS_ALLOWEDback to"false" - Restart the container:
docker compose restart vaultwarden
Step 6: Connect Bitwarden Clients
In any official Bitwarden client (browser extension, iOS, Android, desktop), click the region selector or settings and enter your self-hosted server URL:
https://vault.yourdomain.com
Log in with the credentials you just created. Your vault data will sync to the server you control.
Step 7: Set Up Automatic Backups
The entire Vaultwarden database lives in ./vw-data/db.sqlite3. A simple cron job to back it up:
# Create backup script
cat > ~/vaultwarden/backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/root/vw-backups"
DATE=$(date +%Y-%m-%d_%H-%M)
mkdir -p "$BACKUP_DIR"
# Stop container briefly for a clean SQLite backup
docker stop vaultwarden
cp ~/vaultwarden/vw-data/db.sqlite3 "$BACKUP_DIR/vaultwarden-$DATE.sqlite3"
docker start vaultwarden
# Keep only the last 14 backups
ls -t "$BACKUP_DIR"/vaultwarden-*.sqlite3 | tail -n +15 | xargs -r rm
EOF
chmod +x ~/vaultwarden/backup.sh
Schedule it with cron:
crontab -e
Add:
0 2 * * * /root/vaultwarden/backup.sh
For off-site backups, use rclone to sync the backup directory to Backblaze B2, S3, or any other remote storage.
Step 8: Enable Two-Factor Authentication
In your Bitwarden vault, go to Account Settings > Security > Two-step login and enable TOTP-based 2FA using an app like Aegis (Android) or Raivo OTP (iOS). This protects your vault even if someone obtains your master password.
Vaultwarden also supports FIDO2/WebAuthn hardware keys for 2FA, which is the strongest option available.
Maintenance and Updates
Keep Vaultwarden updated to receive security patches:
cd ~/vaultwarden
docker compose pull
docker compose up -d
docker image prune -f
Run this monthly or subscribe to Vaultwarden’s GitHub releases for notifications.
Security Hardening
- Firewall: Use
ufwto restrict port access. Only 80 and 443 should be publicly reachable. - Fail2ban: Install fail2ban and configure it to parse Vaultwarden logs for brute-force attempts.
- Admin panel: The admin panel at
/adminis protected by theADMIN_TOKEN. Keep this token secret and change it if it is ever exposed. - SMTP for notifications: Configure
SMTP_HOST,SMTP_FROM, and related variables to receive email alerts for new device logins.
Self-hosting your password manager is one of the highest-impact privacy moves you can make. With Vaultwarden running on a $5 VPS, you get a full-featured, encrypted password manager with zero dependence on external companies — and total control over your most sensitive data.