KnowledgebaseSelf-Hosting › Vaultwarden on a LYLIX VPS — self-hosted Bitwarden-compatible password manager

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

  1. Hit https://vault.example.com. Create your account (signups still enabled on first boot).
  2. Edit docker-compose.yml: set SIGNUPS_ALLOWED: "false". Restart vaultwarden.
  3. 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.
  4. 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

« « Back

Powered by WHMCompleteSolution