DockerHomeLab
A computer server room with stacked rack hardware, where a self-hosted Vaultwarden password manager would run
guides

Self-Host Vaultwarden (Bitwarden) with Docker Compose

Run your own password manager with Vaultwarden, a lightweight Bitwarden-compatible server. A working Docker Compose file, HTTPS setup, the admin panel, and the security settings that matter.

By Editorial · · 8 min read

Vaultwarden is an unofficial, Bitwarden-compatible server written in Rust. It speaks the same API as the official Bitwarden server, which means every official Bitwarden client — browser extensions, mobile apps, desktop apps, the CLI — connects to it without modification. The difference is footprint: Vaultwarden runs in a single small container, comfortably on a Raspberry Pi, and unlocks features (TOTP storage, attachments, organizations) that Bitwarden gates behind a paid plan on their hosted service.

This guide gets Vaultwarden running in Docker Compose, puts it behind HTTPS (which it requires to be fully functional), and locks down the settings that matter for a password manager you’re trusting with your entire digital life.

Why HTTPS Is Non-Negotiable Here

A password manager is the one service you should never run over plain HTTP. Two concrete reasons:

  1. The Bitwarden browser extension and mobile apps refuse to connect to a non-HTTPS server (except localhost). This isn’t optional — the Web Crypto APIs the clients depend on are only available in secure contexts.
  2. Vaultwarden itself needs to know it’s being served over HTTPS for attachments and other features to work correctly. The official docs state plainly that “vaultwarden needs to know it’s https to work properly with attachments.”

So this guide treats a reverse proxy as part of the install, not an afterthought.

Prerequisites

  • Docker and Docker Compose installed
  • A domain name (or subdomain) you can point at your server, e.g. vault.yourdomain.com
  • A reverse proxy for TLS. We’ll use Traefik; Caddy and Nginx Proxy Manager work equally well.

Step 1: Create the Service Directory

mkdir -p ~/services/vaultwarden
cd ~/services/vaultwarden

All of Vaultwarden’s state — the SQLite database, attachments, keys — lives in one data directory, which makes backups trivial.

Step 2: Write the Compose File

Create ~/services/vaultwarden/docker-compose.yml. This is the minimal configuration from the official wiki, adapted with Traefik labels for HTTPS:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - DOMAIN=https://vault.yourdomain.com
      - SIGNUPS_ALLOWED=true
    volumes:
      - ./vw-data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.vaultwarden.rule=Host(`vault.yourdomain.com`)"
      - "traefik.http.routers.vaultwarden.entrypoints=websecure"
      - "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
      - "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
    networks:
      - traefik-proxy

networks:
  traefik-proxy:
    external: true

The important details:

  • The container listens on port 80 internally. That’s why the Traefik label is loadbalancer.server.port=80 — Traefik terminates TLS and forwards to port 80 inside the container. There’s no published port on the host because Traefik handles all inbound traffic.
  • DOMAIN must be the full https:// URL you’ll access Vaultwarden at. Set it correctly from the start; some features misbehave if it’s wrong.
  • SIGNUPS_ALLOWED=true lets you register the first account. You will turn this off in the next step.
  • ./vw-data:/data is the single directory holding everything. Back it up.

Step 3: Start It and Create Your Account

docker compose up -d
docker compose logs -f

Once the logs show Vaultwarden listening, visit https://vault.yourdomain.com. You should see a valid certificate (the padlock in your browser) and the Bitwarden web vault login screen. Click Create account and register your user. This first account is yours.

Step 4: Disable Open Signups

This is the step people forget, and it’s the one that matters most. With SIGNUPS_ALLOWED=true, anyone who finds your server URL can create an account on it. Once your own account exists, turn registration off.

Edit the Compose file:

    environment:
      - DOMAIN=https://vault.yourdomain.com
      - SIGNUPS_ALLOWED=false

Then recreate the container:

docker compose up -d

Now the registration form is closed. If you need to add family members later, you’ll invite them through an organization, or briefly flip the flag back on, register them, and turn it off again.

Step 5: Enable the Admin Panel (Carefully)

Vaultwarden has an admin page at /admin for managing users, organizations, and server settings. It’s disabled by default, and you enable it by setting an ADMIN_TOKEN. Generate a strong token — Vaultwarden recommends an Argon2 PHC hash, which you can generate with the binary itself:

docker exec -it vaultwarden /vaultwarden hash

This prompts for a password and prints an Argon2 hash string. Put that hash in your environment:

    environment:
      - DOMAIN=https://vault.yourdomain.com
      - SIGNUPS_ALLOWED=false
      - ADMIN_TOKEN=$argon2id$v=19$m=...   # the hash from the command above

Recreate the container and visit https://vault.yourdomain.com/admin. You’ll be asked for the password you hashed. Because the stored value is a hash rather than the plaintext token, an attacker who reads your Compose file or environment can’t immediately use it.

If you don’t need the admin panel, leave ADMIN_TOKEN unset and the page stays disabled — one less thing exposed.

Step 6: Hardening the Deployment

A few settings worth applying once the basics work:

Restrict the admin page further. Even with a token, consider IP-allowlisting /admin at the reverse proxy, or only enabling the token when you actively need it. The admin panel can change server-wide settings.

Turn on push notifications (optional). Mobile clients can use Bitwarden’s push relay so changes sync instantly. This requires registering for an installation ID and key at the Bitwarden site and setting PUSH_ENABLED, PUSH_INSTALLATION_ID, and PUSH_INSTALLATION_KEY. It’s optional; without it, clients still sync on a poll.

Disable invitations and password hints you don’t want. Variables like INVITATIONS_ALLOWED and SHOW_PASSWORD_HINT control behaviors you may want off for a single-user instance.

Keep it off the public internet if you can. As with any high-value service, the most robust option is to reach Vaultwarden over a VPN (WireGuard or Tailscale) rather than publishing it. The clients still need HTTPS, but you can serve a valid certificate to a private hostname. If you do publish it, the strong master password and the closed-signups setting are doing the heavy lifting — make sure both are right.

Step 7: Back Up the Vault

Vaultwarden’s entire state is in the vw-data directory. A backup is a copy of that directory. The cleanest approach is to stop the container briefly, copy the data, and start it again so the SQLite database isn’t mid-write:

cd ~/services/vaultwarden
docker compose stop
tar czf vaultwarden-backup-$(date +%F).tar.gz vw-data
docker compose start

For a hands-off setup, the community vaultwarden/server ecosystem includes backup sidecar containers that snapshot the SQLite database safely while it’s running. Whatever you choose, follow a real backup discipline — see our notes on 3-2-1 backups. Losing this database means losing every password it holds.

Step 8: Updating

docker compose pull
docker compose up -d

Vaultwarden releases frequently. Because it tracks the Bitwarden API, keeping it current also keeps it compatible with the latest official clients. The vw-data volume persists across updates, so this is a safe, routine operation — just make sure your backup ran first.

The Payoff

You now have a password manager that you control end to end, compatible with the polished official Bitwarden clients, with the premium features unlocked, running in a container small enough to share a Raspberry Pi with three other services. The most security-sensitive service in your homelab is also one of the simplest to run — provided you get HTTPS and the signup flag right, which you now have.

Sources

  1. Vaultwarden — Using Docker Compose (official wiki)
  2. Vaultwarden — Enabling admin page

Related

Comments