Vaultwarden on a LYLIX VPS — self-hosted Bitwarden-compatible password manager
Vaultwarden is a lightweight Bitwarden-compatible server in Rust — works with all the official Bitwarden clients (browser extension, mobile apps, desktop), but runs on a fraction of the resources. A 1 GB VPS happily serves a family or small team. This article walks the full setup.
Sizing
Single user or small team (under 20 accounts): a 1 GB / 1 vCPU VPS is plenty. Storage need scales with the number of file attachments stored in the vault (which most users don't use heavily) — 5–10 GB disk is usually enough.
The setup, Docker Compose style
Vaultwarden's recommended deployment is Docker. Install Docker on a fresh LYLIX VPS, then drop a compose file:
# /opt/vaultwarden/docker-compose.yml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: https://vault.example.com
SIGNUPS_ALLOWED: "false" # disable after creating your account
ADMIN_TOKEN: "<long-random-token-you-set>"
SMTP_HOST: smtp.example.com
SMTP_PORT: 587
SMTP_SSL: starttls
SMTP_USERNAME: vault@example.com
SMTP_PASSWORD: "<smtp-password>"
SMTP_FROM: vault@example.com
volumes:
- /opt/vaultwarden/data:/data
ports:
- "127.0.0.1:8001:80" # bind to loopback only; reverse-proxy in front
cd /opt/vaultwarden
docker compose up -d
docker compose logs -f vaultwarden
Reverse proxy with TLS
WebSockets are critical for vault sync; configure your reverse proxy carefully. With Caddy (easiest):
# /etc/caddy/Caddyfile
vault.example.com {
reverse_proxy localhost:8001
}
Caddy handles TLS + WebSockets automatically. Reload Caddy and visit https://vault.example.com.
With nginx, you need the WebSocket-aware proxy config from the reverse-proxy-ssl-patterns article (the map $http_upgrade $connection_upgrade stanza). Without it, real-time sync fails silently.
First-run setup
- Hit
https://vault.example.com. Create your account (signups still enabled on first boot). - Edit docker-compose.yml: set
SIGNUPS_ALLOWED: "false". Restart vaultwarden. - Visit
https://vault.example.com/admin, enter your ADMIN_TOKEN. From here you can invite users, configure mail templates, browse the user list, set vault policies. - Install the Bitwarden client (browser extension or mobile app). When asked, set the Server URL to
https://vault.example.com(under Settings → Region: Self-hosted).
Backups
Critical. Lose the vaultwarden data directory and every password your users stored is gone (encrypted, so a leaked backup is fine, but a destroyed backup is a disaster).
# /etc/cron.daily/vaultwarden-backup
#!/bin/bash
cd /opt/vaultwarden
docker compose exec -T vaultwarden sqlite3 /data/db.sqlite3 ".backup /data/backup/db-$(date +%F).sqlite3"
restic backup data/backup --tag vaultwarden
Pair with the off-host backup pattern in the backups-recovery category — restic to Backblaze B2 is the cheap-and-cheerful default.
Mobile-app verification flow
Bitwarden mobile apps require email verification for new logins. SMTP must work — that's why the SMTP_* env vars matter. Test by trying to add a new device; if you don't receive the verification email within a minute, check your VPS's mail logs and the SMTP credentials.
Fail2ban
Vaultwarden logs failed login attempts in a parseable format. Add a fail2ban jail to block brute-force attempts:
# /etc/fail2ban/jail.d/vaultwarden.conf
[vaultwarden]
enabled = true
port = 80,443
filter = vaultwarden
backend = polling
journalmatch = CONTAINER_NAME=vaultwarden
maxretry = 3
bantime = 1h
findtime = 10m
# /etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>.*$
ignoreregex =
Upgrade discipline
Vaultwarden tracks Bitwarden's API; new server releases sometimes require client updates and vice versa. Before upgrading:
- Read the release notes on the GitHub project.
- Back up the data directory.
docker compose pull && docker compose up -d- Sanity-test login on at least one client immediately.
Also Read
Powered by WHMCompleteSolution