Quick answer

Your vault runs as a single Rust binary in a Debian 12 LXC on Proxmox, bound to 127.0.0.1:8080 with Caddy in front issuing the Let’s Encrypt certificate for vault.yourdomain.com, because Bitwarden clients will not sync over plain HTTP. Back up rsa_key* alongside db.sqlite3, or every session invalidates after a restore. Total container RAM is about 100MB.

By LK Wood IV · 2026-05-29 · ~14 min read · St. Louis County, MO

Architecture diagram of Vaultwarden on Proxmox: a Debian 12 LXC inside a Proxmox VE host runs the Rust Vaultwarden binary on 127.0.0.1:8080 behind a Caddy reverse proxy that terminates Let's Encrypt HTTPS; browser, mobile, and desktop Bitwarden clients sync in over HTTPS, access is via public Let's Encrypt or Tailscale-only, and a daily 2 AM job backs up the SQLite database, attachments, and RSA keys to a NAS — about 100MB total RAM.

Password managers that live in someone else’s cloud have one failure mode that self-hosted doesn’t: the company goes under, gets acquired, or changes pricing. Vaultwarden on Proxmox solves this. Your vault lives on hardware you own, all Bitwarden official clients work against it without modification, and the whole setup runs in a lightweight LXC container that uses maybe 80MB of RAM.

This guide goes from zero to a working Vaultwarden install with HTTPS, automatic backups, and all your devices connected.

What Vaultwarden is

Vaultwarden is an open-source reimplementation of the Bitwarden server written in Rust. It is not affiliated with Bitwarden, Inc., but it is compatible with all official Bitwarden clients — browser extensions, mobile apps, desktop apps — without any modification to those clients.

What you get versus bitwarden.com paid plans: organizations, collections, TOTP authenticator codes, and Bitwarden Send — all for free, running on your own hardware. What you don’t get: Bitwarden’s enterprise compliance features and their guaranteed uptime. For a homelab password manager, the trade is worth it.

(If you haven’t settled that trade yet, Vaultwarden vs Bitwarden breaks down the eleven-container official deployment against this single Rust container, exactly which features you give up, and where Bitwarden’s newer lite option lands. Come back here to build it.)

Prerequisites

  • Proxmox VE 8.x with LXC capability
  • A domain name you control with the ability to add a DNS record (even a subdomain works)
  • Tailscale or port forwarding to reach your homelab from outside (for syncing mobile devices)
  • Basic comfort with SSH and running commands

For the HTTPS setup, this guide uses Caddy as the reverse proxy because its automatic Let’s Encrypt handling requires zero certificate management on your part. If you already have nginx handling reverse proxy, adapt the config blocks to nginx.

Step 1: Create a Debian LXC in Proxmox

In the Proxmox web UI:

  1. Create CT → Debian 12 template (download from Proxmox if not already present)
  2. Hostname: vaultwarden
  3. Storage: 8GB is plenty (Vaultwarden + OS is under 500MB; increase if you’ll store file attachments)
  4. RAM: 256MB minimum, 512MB comfortable
  5. CPU: 1 core is sufficient
  6. Network: DHCP or a static IP on your LAN
  7. Features → Nesting: enable if you want Docker later; not required for this setup

Start the container and SSH in as root, or use the Proxmox console.

Update the system:

apt update && apt upgrade -y
apt install -y curl wget unzip

Step 2: Install Vaultwarden

Vaultwarden ships as a single binary with no external dependencies beyond a SQLite database. The simplest install method is the official Docker image, but since we’re in an LXC and want minimal overhead, we’ll use the pre-built binary distribution.

Option A: Docker Compose (easiest, ~5MB extra overhead)

Install Docker:

curl -fsSL https://get.docker.com | sh

Create a directory and compose file:

mkdir -p /opt/vaultwarden/data
cd /opt/vaultwarden
# /opt/vaultwarden/docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    volumes:
      - ./data:/data
    environment:
      DOMAIN: "https://vault.yourdomain.com"
      SIGNUPS_ALLOWED: "false"
      ADMIN_TOKEN: "generate-a-strong-token-here"
    ports:
      - "127.0.0.1:8080:80"

Generate a strong admin token:

openssl rand -base64 48

Paste the output as ADMIN_TOKEN. Set DOMAIN to the URL you’ll access Vaultwarden at.

Start it:

docker compose up -d
docker compose logs -f

Vaultwarden is now listening on 127.0.0.1:8080. The reverse proxy (next step) exposes it publicly over HTTPS.

Option B: Pre-built binary (no Docker)

Download the latest release from github.com/dani-garcia/vaultwarden/releases. Get the amd64-musl tarball:

wget https://github.com/dani-garcia/vaultwarden/releases/latest/download/vaultwarden-1.32.7-linux-amd64.tar.gz
tar -xzf vaultwarden-*.tar.gz
mv vaultwarden /usr/local/bin/
chmod +x /usr/local/bin/vaultwarden

Create a data directory and .env file:

mkdir -p /opt/vaultwarden/data
# /opt/vaultwarden/.env
DATA_FOLDER=/opt/vaultwarden/data
DOMAIN=https://vault.yourdomain.com
SIGNUPS_ALLOWED=false
ADMIN_TOKEN=your-strong-token-here
ROCKET_ADDRESS=127.0.0.1
ROCKET_PORT=8080

Create a systemd service:

# /etc/systemd/system/vaultwarden.service
[Unit]
Description=Vaultwarden password server
After=network.target

[Service]
User=root
EnvironmentFile=/opt/vaultwarden/.env
ExecStart=/usr/local/bin/vaultwarden
Restart=on-failure
WorkingDirectory=/opt/vaultwarden

[Install]
WantedBy=multi-user.target
systemctl enable --now vaultwarden
systemctl status vaultwarden

Step 3: HTTPS with Caddy

Install Caddy:

apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install -y caddy

Create the Caddyfile:

# /etc/caddy/Caddyfile
vault.yourdomain.com {
    reverse_proxy localhost:8080
}

Replace vault.yourdomain.com with your actual domain. Caddy automatically obtains a Let’s Encrypt certificate for this domain — no certbot, no manual renewal.

For Caddy to get the certificate, port 80 and 443 on your router must forward to this LXC’s LAN IP. If you’re using Tailscale for access only (not exposing to the internet), skip Let’s Encrypt and use Caddy with a self-signed cert or use the Tailscale HTTPS feature instead.

systemctl enable --now caddy
systemctl status caddy

After Caddy starts, wait 30–60 seconds for certificate issuance, then visit https://vault.yourdomain.com. You should see the Bitwarden login screen.

Step 4: Create your account and disable signups

Open https://vault.yourdomain.com and create your account. After your account is created, signups are already disabled in the config (SIGNUPS_ALLOWED=false). New users would need to go through the admin panel at https://vault.yourdomain.com/admin to create accounts.

The admin panel requires the ADMIN_TOKEN you set. Go there now and confirm the settings look right.

Enable TOTP 2FA. In your Vaultwarden account settings → Security → Two-step login → enable Authenticator App. Store the recovery codes somewhere safe — not in Vaultwarden itself (obvious), not in your email (bad idea), somewhere physically separate.

Step 5: Connect all devices

Browser extension: Install the Bitwarden extension for Chrome, Firefox, or Safari. Click the extension → Settings → Self-Hosted Environment. Set Server URL to https://vault.yourdomain.com. Log in with your account.

Mobile (iOS/Android): Open the Bitwarden app → Settings → Self-Hosted → Server URL. Same URL. Log in. On iOS, go to Settings → Passwords → Password Options → enable Bitwarden for AutoFill.

Desktop app: Same flow — Settings → Self-Hosted.

After each client connects and syncs, disable bitwarden.com as an option in the extension settings (under the account menu) so you don’t accidentally log into the cloud version.

Step 6: Automated backups

Vaultwarden stores everything in /opt/vaultwarden/data/ (or /opt/vaultwarden/data for the Docker setup where it’s a volume at ./data). The critical files:

  • db.sqlite3 — your entire vault database
  • attachments/ — any file attachments
  • config.json — server configuration (mostly redundant with your .env, but include it)
  • rsa_key* — RSA keys for JWT signing (back these up or sessions will invalidate after a restore)

Create a backup script:

#!/bin/bash
# /opt/vaultwarden/backup.sh
BACKUP_DIR=/mnt/nas-backups/vaultwarden
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
DEST="$BACKUP_DIR/vw-backup-$TIMESTAMP"

mkdir -p "$DEST"

# Use SQLite's online backup API to avoid corruption during a live backup
sqlite3 /opt/vaultwarden/data/db.sqlite3 ".backup '$DEST/db.sqlite3'"
cp -r /opt/vaultwarden/data/attachments "$DEST/" 2>/dev/null || true
cp /opt/vaultwarden/data/rsa_key* "$DEST/"

# Keep only 30 days of backups
find "$BACKUP_DIR" -name "vw-backup-*" -mtime +30 -exec rm -rf {} +

echo "Backup complete: $DEST"
chmod +x /opt/vaultwarden/backup.sh

# Add to crontab - daily at 2am
echo "0 2 * * * root /opt/vaultwarden/backup.sh >> /var/log/vw-backup.log 2>&1" >> /etc/crontab

Replace /mnt/nas-backups/vaultwarden with your NAS mount point or a path that gets swept by Proxmox Backup Server.

Critical: test the restore before you need it. Stop Vaultwarden, replace db.sqlite3 with a backup copy, start Vaultwarden, verify your passwords are there, then restore the production database. Takes 5 minutes and confirms your backup is valid.

Step 7: Tailscale-only access (no public exposure)

If you don’t want Vaultwarden reachable from the public internet — only accessible while on your tailnet — skip the Let’s Encrypt setup and use Tailscale HTTPS instead.

Tailscale provides valid HTTPS certificates for your tailnet nodes via tailscale cert. On the Vaultwarden container (with Tailscale installed):

tailscale cert vaultwarden.your-tailnet.ts.net

This generates a certificate at /var/lib/tailscale/certs/. Update your Caddyfile to use it:

vaultwarden.your-tailnet.ts.net {
    tls /var/lib/tailscale/certs/vaultwarden.your-tailnet.ts.net.crt \
        /var/lib/tailscale/certs/vaultwarden.your-tailnet.ts.net.key
    reverse_proxy localhost:8080
}

Now Vaultwarden is only reachable when you’re connected to your tailnet. No public port exposure. Mobile Bitwarden clients sync when you’re on tailnet (at home or connected via Tailscale from anywhere). This is the highest-security configuration for a homelab password manager.

Updating Vaultwarden

For Docker Compose:

cd /opt/vaultwarden
docker compose pull
docker compose up -d

For the binary:

systemctl stop vaultwarden
# Download new binary, replace /usr/local/bin/vaultwarden
systemctl start vaultwarden

Vaultwarden runs automatic database migrations on startup. Back up before updating regardless.

Resource usage

On an idle Debian 12 LXC running Vaultwarden (Docker, 3 users, 1200 vault items):

  • RAM: ~85MB for Vaultwarden + ~15MB for Caddy = ~100MB total container RAM
  • CPU: <1% idle, brief spikes on sync
  • Disk: ~45MB for database + OS, excluding attachments
  • Network: negligible except during initial sync

This is a workload that runs comfortably alongside a dozen other services on a mini PC with 16GB RAM. It does not need its own machine. The Power & Cost Calculator shows adding an LXC like this costs essentially nothing in electricity — the container overhead is measured in milliwatts.


Running Vaultwarden and other self-hosted services on Proxmox? The LXC vs VM guide covers when to use each. Tailscale setup handles the remote access piece — sync your Bitwarden clients from anywhere without exposing ports. If you prefer to give Vaultwarden a clean vault.yourdomain.com address without a dedicated Caddy instance, Nginx Proxy Manager centralizes SSL termination across all your services.

Sources

Frequently asked questions

Is Vaultwarden compatible with the Bitwarden apps?
Yes. Vaultwarden is an unofficial, open-source Bitwarden server implementation. You use the official Bitwarden clients (browser extension, iOS, Android, desktop) and just point them at your server URL instead of bitwarden.com. All official apps work without modification.
Does Vaultwarden require a domain name?
Bitwarden clients require HTTPS to enable password autofill — they will not sync over plain HTTP. You need either a real domain with a Let’s Encrypt certificate, or a self-signed certificate added as trusted on each client device. For homelab use, the easiest path is a subdomain of a domain you own with a Let’s Encrypt cert via Caddy or nginx.
How do I back up Vaultwarden?
Vaultwarden stores everything in a single SQLite database at /data/db.sqlite3. Back up this file plus the /data/attachments directory. A simple daily cron that copies these to your NAS or PBS datastore is sufficient. Do not back up the running container while Vaultwarden is writing — either stop the container first, or use SQLite’s built-in online backup API.
Can I migrate from LastPass or 1Password?
Yes. The Bitwarden web vault at your server URL has an import function that accepts CSV exports from LastPass, 1Password, Dashlane, Keeper, and most other major password managers. Export from your old manager, import at your Vaultwarden URL — takes about 5 minutes.
What happens to my passwords if my Proxmox host goes down?
If the server is unreachable, Bitwarden clients fall back to their local encrypted vault cache. You can still read passwords; you just can’t sync changes until the server is back. This is the same behavior as with bitwarden.com. For high availability, run Vaultwarden on a UPS-protected host.

Evidence ledger

Last updated
Methodology
This tutorial was written and edited by Lowell K. Wood IV in St. Louis County, MO. Specs, prices, commands, and version numbers are drawn from the official vendor, reseller, and project documentation current on the date above, and were verified before publishing. First-person hardware claims appear only where the article shows a verifiable artifact — a photo, receipt, or measurement — or links to the TechFuelHQ Open Bench Datasets. Every fact is human-verified against its cited source before publishing; AI assists with first-draft structure and source-gathering, not with the verdict. Full editorial standard: methodology.
Update log
  • 2026-07-25 — Last reviewed and updated.
Corrections
Spotted an error or stale price? Email hello@techfuelhq.com. Confirmed corrections are added to the update log above.

About the author

Written by Lowell K. Wood IV. Lowell builds and runs TechFuelHQ from St. Louis, Missouri, pairing thirteen-plus years of hands-on homelab, PC, server, and networking experience with cited third-party testing and first-party benchmarks on the gear he still runs. He also works ground EMS as a Nationally Registered Paramedic (NREMT).