Blog / Tutorials

Self-hosting Vaultwarden on a VPS, step by step

By the NoctHost TeamMay 20, 20268 min read

Vaultwarden is a lightweight, unofficial server that speaks the Bitwarden protocol. It runs the official Bitwarden apps and browser extensions against your own box, in a single small container, with a fraction of the resource footprint of the official self-hosted stack.

You will run Vaultwarden behind Caddy, which fetches and renews a Let's Encrypt certificate automatically, so your vault is reachable over real HTTPS at your own domain. You will also set the admin token and configure backups, because a password manager you cannot restore is a liability.

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 --version

Step 2: Open the firewall

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Tip — Caddy needs port 80 open to complete the HTTP-01 ACME challenge, even though your vault is served on 443. Do not block it.

Step 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 hash

Type 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.

/opt/vaultwarden/docker-compose.yml
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:
Tip — The ADMIN_TOKEN value must be the full $argon2 hash, wrapped in quotes because it contains $ characters. A plain-text token also works but is far less safe at rest.

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.

/opt/vaultwarden/Caddyfile
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 caddy

Once 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.

Spin one up in about a minute

Email signup, pay with crypto, hourly billing. Trying a box costs cents — destroy it when you are done.

Deploy a server

Frequently asked

Is Vaultwarden compatible with the official Bitwarden apps?
Yes. Vaultwarden implements the Bitwarden API, so the official desktop apps, mobile apps, and browser extensions all work against it. You just point them at your own server URL instead of bitwarden.com.
Do I really need a domain and HTTPS?
Effectively yes. The Bitwarden clients refuse to send your vault over plain HTTP, and your master password protects everything. A domain plus Caddy's automatic certificates is the path of least resistance to a trusted TLS setup.
How do I move my existing Bitwarden vault over?
Export your vault from the official client as a JSON file, create your account on Vaultwarden, then use the client's import feature pointed at your new server. Delete the unencrypted export file afterwards.

Keep reading