Skip to main content

Self-Host Vaultwarden with Docker Compose

Vaultwarden needs HTTPS. The web vault encrypts and decrypts your passwords in the browser with the Web Crypto API, and browsers only allow that API on a secure origin. Over plain HTTP on anything other than localhost, you cannot create an account or unlock the vault in the web vault. Two more things matter from the first day: DOMAIN, the public https:// address of the server, and a persistent volume at /data.

Vaultwarden is a small server written in Rust that speaks the Bitwarden API. You use the official Bitwarden apps — browser extension, desktop, mobile and CLI — and point them at your own server. It is not affiliated with Bitwarden, Inc.

If you're new to Docker Compose, check out our guide on how to self-host a Docker Compose app. More stacks are in our Docker Compose library.

Self-host Vaultwarden with Docker Compose (minimal)​

services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "true"
volumes:
- ./vw-data:/data
ports:
- "127.0.0.1:8080:80"

This uses the default SQLite database inside /data. Put a reverse proxy with a TLS certificate (Caddy, Traefik, nginx) in front of port 8080. WebSocket live sync runs on the same port, so the proxy needs no extra route for it.

To use PostgreSQL instead of SQLite, add a DATABASE_URL:

DATABASE_URL: "postgresql://vaultwarden:changeme@db:5432/vaultwarden"

Vaultwarden creates its tables on the first start.

Deploy Vaultwarden on Hostim.dev (one click)​

Try it Yourself

Guest project runs for 1 hour. Log in to save and extend to 5 days.

The template gives you HTTPS on a *.hostim.dev subdomain, DOMAIN already set to that address, a managed PostgreSQL database for the vault, and a volume for attachments and keys.

ResourceDetails
Appvaultwarden/server Docker image
DatabaseManaged PostgreSQL (DATABASE_URL set for you)
Volume/data
AdminAdmin panel at /admin, generated ADMIN_TOKEN
DomainFree *.hostim.dev subdomain, DOMAIN set for you
SSLLet's Encrypt (auto-enabled)
Port80

How to deploy​

  1. Go to your Hostim.dev dashboard.
  2. Click Create Project → Use a Template.
  3. Select Vaultwarden.
  4. Choose a resource plan.
  5. Deploy.

Post-deploy notes​

  1. Create your account. Open the app URL and click Create account. Your master password never leaves the browser, so nobody can reset it for you. If you lose it, the vault is lost.
  2. Close signups. Set SIGNUPS_ALLOWED to false on the app. The app restarts with the new value. While it is true, anyone who finds the URL can register on your server. To add people later, invite their email address from the admin panel. Without SMTP no email is sent: tell them to open the app URL and click Create account with that exact address.
  3. Hash the admin token. The admin panel is at /admin. The template generates a plain-text ADMIN_TOKEN, and Vaultwarden logs a notice about it on every start. To replace it with a hash, open a shell into the app (hostim exec vaultwarden), run /vaultwarden hash, and enter the password you want to use. Paste the printed $argon2id$… string into ADMIN_TOKEN as it is. On Hostim no escaping is needed. In a Docker Compose file every $ must be written as $$. From then on, log in to /admin with the password, not the hash.
  4. Connect your clients. In any Bitwarden app, choose Self-hosted on the login screen and enter your app URL as the server URL.

Settings from the admin panel override environment variables​

When you click Save in the /admin panel, Vaultwarden writes every setting on the page to /data/config.json, not only the one you changed. That file wins over environment variables. After one save, changes to SIGNUPS_ALLOWED, DOMAIN, ADMIN_TOKEN or the SMTP settings in the app's environment are ignored. Either manage settings only in the admin panel, or click Reset defaults there. That deletes config.json, and the environment variables apply again.

Email​

Vaultwarden sends no email until you set SMTP_HOST and SMTP_FROM. Most providers also need SMTP_USERNAME and SMTP_PASSWORD (set both or neither). SMTP_SECURITY defaults to starttls, and SMTP_PORT defaults to 587 with it. Without SMTP, signup, login and two-factor login with an authenticator app all work. Features that need email do not: email as a second factor, password hints by email, email verification, and invitation emails.

Where your data is stored​

WhatWhere
Users, vault items, folders, organizationsManaged PostgreSQL
File attachments and Send files/data/attachments, /data/sends
JWT signing key/data/rsa_key.pem
Settings saved in the admin panel/data/config.json
Website icon cache/data/icon_cache

Back up the database and the /data volume together. If you lose rsa_key.pem, Vaultwarden creates a new one and every client has to log in again; the vault itself stays readable, because it is encrypted with your master password, not with this key.


Frequently asked questions

What is the minimal docker-compose.yml for Vaultwarden?

One service: the vaultwarden/server image, a volume at /data, port 80 published to a reverse proxy, and DOMAIN set to the public https:// address. With no DATABASE_URL, it uses SQLite inside /data. The full file is in the section above.

Why does Vaultwarden need HTTPS?

The web vault encrypts and decrypts data in the browser with the Web Crypto API, which browsers only expose on secure origins. On plain HTTP (except localhost) you cannot create an account or unlock the vault in the web vault. Put a reverse proxy with a TLS certificate in front of it, or use a host that terminates HTTPS for you.

Can Vaultwarden use PostgreSQL or MySQL instead of SQLite?

Yes. Set DATABASE_URL to postgresql://user:password@host:5432/dbname or mysql://user:password@host:3306/dbname. Vaultwarden creates the tables on the first start. The Hostim template uses a managed PostgreSQL database. Attachments, Send files and the signing key still live in /data, so keep that volume either way.

How do I stop strangers from signing up on my Vaultwarden server?

Create your own account first, then set SIGNUPS_ALLOWED=false and restart. New users can then join only through an invitation: from the admin panel, or from an organization owner (unless you also set INVITATIONS_ALLOWED=false). If you ever clicked Save in the admin panel, the values in /data/config.json override the environment variables.

How do I secure the Vaultwarden ADMIN_TOKEN?

Run vaultwarden hash inside the container (the binary is /vaultwarden in the official image), enter a password, and set ADMIN_TOKEN to the printed $argon2id$ string. In Docker Compose, write each $ as $$. Log in to /admin with the password, not the hash. If ADMIN_TOKEN is not set at all, the admin panel is disabled.

Do I need a separate WebSocket port for live sync?

No. Since version 1.29, WebSocket notifications run on the main HTTP port. The old port 3012 and the extra reverse-proxy route are no longer needed.

Which Bitwarden apps work with Vaultwarden?

The official Bitwarden browser extensions, desktop apps, mobile apps and CLI. On the login screen choose Self-hosted and enter your server URL.

How do I update Vaultwarden?

Docker: docker compose pull && docker compose up -d. Hostim.dev: redeploy the app. Database migrations run automatically on start. Back up the database and /data first.


Alternatives​

  • Bitwarden (official self-hosted) — the original server; the standard install runs several containers and needs more memory
  • Passbolt — password manager built for teams, with its own clients
  • KeePassXC — local password database file, no server

Source + Docs​


Looking for something else? Browse all templates →


Try it now​

Deploy Vaultwarden Now – in less than 60 seconds