2026-09-18

How to Self-Host Vaultwarden on a Raspberry Pi 5 with Automatic HTTPS and Backups

Vaultwarden runs comfortably on a Raspberry Pi 5 and gives you a fully functional, self-hosted Bitwarden-compatible password manager in under an hour. This guide covers exactly how I set it up on my own Pi 5 — NVMe boot, Docker, Caddy for automatic HTTPS, and encrypted off-site backups — with the real numbers from my build.

My Hardware

Sequential reads land at 453 MB/s and writes at 438 MB/s; random 4K reads hit 16,433 IOPS. For a SQLite-backed password vault that rarely exceeds a few megabytes, this is wildly more than enough. SoC temperature sat at 49.4 °C idle and actually dropped to 48.8 °C under load during a sustained fio run — the active cooler on my Pi 5 clearly had headroom to spare.

If you want to keep your NVMe drive portable for cloning or offline backups, an external enclosure like M.2 NVMe SSD Enclosure – USB-C 10Gbps with Magnetic Closure makes swapping and imaging painless.

Prerequisites

You need a domain name pointing to your home IP (or a VPS IP). I use a cheap domain from Namecheap. You also need port 443 forwarded on your router to the Pi's local IP, or a reverse tunnel if your ISP uses CGNAT.

Ensure Docker and Docker Compose are installed:

sudo apt update && sudo apt install -y docker.io docker-compose-v2
sudo usermod -aG docker $USER
# Log out and back in

Step 1: Directory Structure

mkdir -p ~/vaultwarden/{data,caddy_data,caddy_config,backups}
cd ~/vaultwarden

Step 2: Docker Compose File

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: "" # set via argon2 hash, see below
    volumes:
      - ./data:/data
    expose:
      - "80"

  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy_data:/data
      - ./caddy_config:/config

Generate the Admin Token

Don't put a plaintext password in the compose file. Generate an Argon2 hash:

docker run --rm vaultwarden/server /vaultwarden hash --preset owasp

Paste your password when prompted, then put the full $argon2id$... output string into the ADMIN_TOKEN field.

Step 3: Caddyfile for Automatic HTTPS

Create Caddyfile in the same directory:

vault.yourdomain.com {
    reverse_proxy vaultwarden:80
}

That's it. Caddy handles Let's Encrypt certificate issuance and renewal automatically. No certbot cron jobs, no nginx config.

Step 4: Start Everything

docker compose up -d

Visit https://vault.yourdomain.com — you should see the Bitwarden web vault. Create your first account, then immediately set SIGNUPS_ALLOWED: "false" (already done in the compose file above) and restart:

docker compose restart vaultwarden

The admin panel lives at https://vault.yourdomain.com/admin.

Step 5: Automatic Encrypted Backups

The Vaultwarden SQLite database lives in ./data/db.sqlite3. It's small — typically under 10 MB even with hundreds of entries. Back it up nightly.

Local Backup Script

Create backup.sh:

#!/bin/bash
BACKUP_DIR="/home/$USER/vaultwarden/backups"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
DB_PATH="/home/$USER/vaultwarden/data"

# Use sqlite3 .backup for a consistent copy
sqlite3 "$DB_PATH/db.sqlite3" ".backup '$BACKUP_DIR/db-$TIMESTAMP.sqlite3'"

# Encrypt with age (or gpg)
age -p -o "$BACKUP_DIR/db-$TIMESTAMP.sqlite3.age" "$BACKUP_DIR/db-$TIMESTAMP.sqlite3"
rm "$BACKUP_DIR/db-$TIMESTAMP.sqlite3"

# Keep only last 30 backups locally
ls -t "$BACKUP_DIR"/*.age | tail -n +31 | xargs -r rm
chmod +x backup.sh
sudo apt install -y age sqlite3

Cron It

crontab -e
# Add:
0 3 * * * /home/$USER/vaultwarden/backup.sh

Off-Site Copy

I push the encrypted .age files to a Backblaze B2 B2 bucket using rclone:

sudo apt install -y rclone
rclone config  # set up a B2 remote called "b2vault"

Append to backup.sh:

rclone copy "$BACKUP_DIR" b2vault:your-bucket-name/vaultwarden --max-age 24h

B2's first 10 GB of storage is free — you'll never hit that with password vault backups.

Alternatively, if you'd rather keep everything on your own infrastructure, a small VPS on Hetzner Cloud running an rsync target works well for a few euros per month.

Step 6: Hardening Checklist

Performance Reality Check

On my Pi 5, the Vaultwarden container uses roughly 25–40 MB of RAM and near-zero CPU at rest. Logins and vault syncs from the Bitwarden app are effectively instant — the 16K random-read IOPS from the NVMe are never the bottleneck; the SQLite database is tiny. With 15 Gi of RAM, you can comfortably run Vaultwarden alongside other services (reverse proxy, monitoring, Home Assistant, etc.) without contention.

Thermals are a non-issue. My SoC sits under 50 °C even under synthetic load. If you're running a fanless passive case, your numbers will be higher — reportedly 65–70 °C under load based on community reports — but still within the Pi 5's thermal throttle threshold of 85 °C. If dust buildup becomes a concern with active cooling, JAKEHOE Fan Cleaner – Dust Removal Tool for Server & NAS Fans is handy for periodic maintenance.

Who Should NOT Do This

🛠️ From the bench shop

Gear from our own store that fits this build — shipped tracked, UK support.

M.2 NVMe SSD Enclosure – USB-C 10Gbps with Magnetic Closure£36.99View →
M.2 SSD Enclosure – NVMe & SATA USB External Aluminium Case£26.99View →
The Homelab Agent Kit — 9 AI Agents, 13-Chapter Build Guide, Python£29.00View →

Free: Raspberry Pi Server Hardening Checklist

Eighteen checks for locking down a Raspberry Pi server — keys-only SSH, mesh VPN instead of port forwarding, scoped firewall rules, and the grep that catches an API key before you push it.

No spam, unsubscribe in one click. I never share or sell your address.

← all articles

Some links are affiliate links — if you buy through them I may earn a small commission at no extra cost to you. Benchmarks are run on my own hardware. · Shop · Contact