What you'll need
- A VPS on Ubuntu 22.04/24.04 with a dedicated IPv4.
- A domain name with an A record pointing at that IP (e.g. vault.example.com).
- Ports 80 and 443 reachable (needed for the TLS challenge).
Step 1: Install Docker
apt update
apt install -y ca-certificates curl
curl -fsSL https://get.docker.com | sh
docker --versionStep 2: Open the firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enableStep 3: Generate an admin token
The admin panel lets you manage users and settings. Vaultwarden expects an Argon2 hash of your token. Generate one with the container itself.
docker run --rm -it vaultwarden/server /vaultwarden hashType a long random password when prompted; copy the printed $argon2 string. You will paste it into the compose file in the next step.
Step 4: Write docker-compose.yml
Create /opt/vaultwarden/docker-compose.yml. Vaultwarden stores its database in a named volume; Caddy terminates TLS and proxies to it. SIGNUPS_ALLOWED is set to false after you create your own account.
services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
environment:
DOMAIN: https://vault.example.com
SIGNUPS_ALLOWED: "true"
ADMIN_TOKEN: "PASTE_ARGON2_HASH_HERE"
volumes:
- vw-data:/data
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
volumes:
vw-data:
caddy-data:Step 5: Write the Caddyfile
Caddy's config is two lines: your domain and where to send traffic. It handles certificate issuance and renewal on its own.
vault.example.com {
reverse_proxy vaultwarden:80
}Step 6: Launch and create your account
cd /opt/vaultwarden
docker compose up -d
docker compose logs -f caddyOnce Caddy reports a certificate was obtained, open https://vault.example.com, create your account, and log in from the Bitwarden app or browser extension using your domain as the server URL.
Then lock the door: set SIGNUPS_ALLOWED to "false" in the compose file and run docker compose up -d again so nobody else can register.
Backups and keeping it safe
Everything lives in the vw-data volume: the SQLite database, attachments, and keys. Back it up regularly. A simple nightly cron that snapshots the database file is enough for a personal vault.
docker run --rm -v vaultwarden_vw-data:/data -v /opt/backups:/backup \
alpine tar czf /backup/vw-$(date +%F).tar.gz -C /data .- Copy those archives off the server (object storage, another machine). A backup on the same box is not a backup.
- Reach the admin panel at https://vault.example.com/admin using the token you hashed in Step 3.
- Update with: docker compose pull && docker compose up -d.
Vaultwarden idles at a few dozen megabytes of RAM, so the cheapest box runs it easily for a few dollars a month. You can deploy a fresh VPS in about 60 seconds, and because billing is hourly you can even test the whole stack for cents before committing your real domain.