Self-Hosted Vaultwarden Password Manager on Docker: Practical Step-by-Step Guide

self-hosted-vaultwarden-password-manager-docker.md
title Self-Hosted Vaultwarden Password Manager on Docker: Practical Step-by-Step Guide
date
author VahaC
read 7 min read
category Self-Hosting
tags #container #Docker #Homelab
Self-Hosted Vaultwarden Password Manager on Docker: Practical Step-by-Step Guide

Setting up a self-hosted Vaultwarden password manager is one of the simplest and most rewarding things you can do in your homelab. A single Docker container, a few environment variables, and you have a fully functional password vault — compatible with every official Bitwarden app and browser extension. No multi-container orchestration, no broken internal services, no hassle. 🛡️

In this guide I’ll walk you through the complete process:

  • Install — deploy a self-hosted Vaultwarden password manager on Docker with OpenMediaVault 🐳
  • Secure — put it behind Nginx Proxy Manager with HTTPS and lock down signups + admin panel 🔒
  • Maintain — update the container and back up your vault reliably ♻️

Why Vaultwarden? 🤔

Vaultwarden is a community-built, Rust-based server that implements the Bitwarden API. It’s fully compatible with all official Bitwarden clients — browser extensions, mobile apps, desktop apps, and the CLI.

Why many self-hosters prefer it:

  • Extremely lightweight — runs on ~10 MB of RAM at idle. One container, built-in SQLite, built-in web vault 🪶
  • All premium features unlocked — TOTP authenticator, file attachments, emergency access, organizations — without a paid plan ⚡
  • Just works — no Installation ID/Key required, no phone-home to Bitwarden’s cloud, no internal service discovery bugs 🎯
  • Active development — large community, frequent releases, solid wiki documentation 📖

💡 Vaultwarden is not an official Bitwarden product. It’s an independent reimplementation. But in practice, for personal and homelab use, it’s the go-to choice for a self-hosted Vaultwarden password manager setup.


Prerequisites ✅

Here’s what you need to set up a self-hosted Vaultwarden password manager on Docker:

  • A Linux server with Docker Engine and Docker Compose installed. New to Docker? Start with Docker for Beginners: Containers, Images, Volumes, Compose
  • Nginx Proxy Manager (NPM) running and accessible (same or separate machine)
  • A domain name (e.g. vault.example.com) with DNS pointing to your public IP
  • Router port forwarding: TCP 80 and 443 → your NPM host

Quick check:

docker --version
docker compose version

🎯 Reference IPs used in this guide (replace with yours):

  • Docker host (OMV): 10.0.0.20
  • NPM host: 10.0.0.10
  • Domain: vault.example.com

Step 1 — Create the Project Directory 📁

SSH into your Docker host:

sudo mkdir -p /srv/docker/vaultwarden
cd /srv/docker/vaultwarden

Step 2 — Create docker-compose.yml 🐳

sudo nano /srv/docker/vaultwarden/docker-compose.yml

Paste:

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

⚠️ Replace 10.0.0.20 with your actual server IP and vault.example.com with your domain.

What each setting does:

  • DOMAIN — tells Vaultwarden the URL it’s served at (needed for HTTPS links in emails and the web vault)
  • SIGNUPS_ALLOWED: "true" — lets you create your first account. We’ll disable this after signup 🔒
  • ./vw-data:/data — all persistent data (SQLite database, RSA keys, attachments) lives in this folder
  • 10.0.0.20:8085:80 — binds port 8085 on your LAN IP only (not exposed on all interfaces)

Step 3 — Launch Vaultwarden ▶️

cd /srv/docker/vaultwarden
sudo docker compose up -d

Check that it’s running:

sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'

Test from any LAN machine:

curl -I http://10.0.0.20:8085

You should see HTTP/1.1 200 OK. That’s it — Vaultwarden is alive. No cryptic logs, no crashing nginx, no multi-service orchestration. 🎉

If something goes wrong:

sudo docker logs --tail 50 vaultwarden

For real-time container log monitoring, Dozzle is a great lightweight option. 📊


Step 4 — Set Up HTTPS via Nginx Proxy Manager 🌍🔒

Open your NPM dashboard (10.0.0.10) → Hosts → Proxy Hosts → Add Proxy Host.

Details tab:

  • Domain Names: vault.example.com
  • Scheme: http
  • Forward Hostname / IP: 10.0.0.20
  • Forward Port: 8085
  • ✅ Websockets Support
  • ✅ Block Common Exploits

SSL tab:

  • Request a new Let’s Encrypt certificate
  • ✅ Force SSL

Save, wait a few seconds, then open:

https://vault.example.com

You should see the Vaultwarden web vault. Create your account and set a strong master password. Your self-hosted Vaultwarden password manager is now live! 🎉

For extra protection against brute-force attacks, add CrowdSec with Nginx Proxy Manager for real-time intrusion detection. 🛡️


Step 5 — Lock It Down After First Signup 🔒

Once your account is created, disable public registration immediately:

sudo nano /srv/docker/vaultwarden/docker-compose.yml

Change:

SIGNUPS_ALLOWED: "false"

Restart:

cd /srv/docker/vaultwarden
sudo docker compose down
sudo docker compose up -d

Now nobody else can register. If you ever need to invite someone, use the admin panel (next section) or temporarily re-enable signups.


Optional: Enable the Admin Panel 🛠️

The admin panel lets you manage users, view registrations, and change server settings via a web UI at https://vault.example.com/admin.

Generate a secure admin token using Vaultwarden’s built-in hasher:

sudo docker exec -it vaultwarden /vaultwarden hash

It will ask you to enter and confirm a password. The output is an Argon2 hash. Copy it — it looks like:

$argon2id$v=19$m=65540,t=3,p=4$...long-hash...

Add it to your docker-compose.yml under environment:

environment:
  DOMAIN: "https://vault.example.com"
  SIGNUPS_ALLOWED: "false"
  ADMIN_TOKEN: "$argon2id$v=19$m=65540,t=3,p=4$YOUR_HASH_HERE"

⚠️ Important: wrap the hash value in double quotes in the YAML file. If you use a .env file instead, use single quotes and replace every $ with $$.

Restart:

cd /srv/docker/vaultwarden
sudo docker compose down
sudo docker compose up -d

Now go to https://vault.example.com/admin and log in with the password you typed (not the hash). 🔐


Updating Your Self-Hosted Vaultwarden Password Manager ♻️

Keeping your self-hosted Vaultwarden password manager updated is straightforward — and it’s good practice to back up first (see next section):

cd /srv/docker/vaultwarden
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d

Verify:

sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
sudo docker logs --tail 20 vaultwarden

Your vault data in vw-data/ stays intact — only the container image changes. 🔄


Backing Up Your Self-Hosted Vaultwarden Password Manager 🗄️

All your data lives in one folder: vw-data/. It contains the SQLite database (db.sqlite3), RSA encryption keys, and attachments. If you lose this folder, your passwords are unrecoverable. ☠️

Create a Backup

Stop the container first to avoid copying a half-written database:

cd /srv/docker/vaultwarden
sudo docker compose down
sudo tar -czf ~/vaultwarden-backup-$(date +%F).tar.gz vw-data
sudo docker compose up -d

Downtime is typically under 30 seconds. ⏱️

Verify

ls -lh ~/vaultwarden-backup-*.tar.gz
tar -tzf ~/vaultwarden-backup-$(date +%F).tar.gz | head -10

Make sure vw-data/db.sqlite3 is listed in the archive.

Restore from Backup 🧯

⚠️ This replaces your current vault. Only do this if your data is broken or lost.

cd /srv/docker/vaultwarden
sudo docker compose down
sudo mv vw-data vw-data.broken.$(date +%F-%H%M)
sudo tar -xzf ~/vaultwarden-backup-YYYY-MM-DD.tar.gz
sudo docker compose up -d

💡 Pro tip: store backup copies on a different physical disk or sync them offsite. If you run OneDrive or Nextcloud on your homelab, drop backups into a synced folder.


Connecting Bitwarden Clients to Your Self-Hosted Vaultwarden Password Manager 📱

The beauty of Vaultwarden is that it works with every official Bitwarden client. Install any of these:

Before logging in, tap the ⚙️ gear icon on the login screen and set:

  • Server URL: https://vault.example.com

Then log in with the email and master password you created earlier. Your vault will sync across all devices automatically. 🔄


Final Thoughts ✅

You now have a working self-hosted Vaultwarden password manager with HTTPS, locked-down registration, and a clean update/backup workflow. The whole thing runs in one container and barely touches your server’s resources.

A few reminders:

  • Back up before every update — 30 seconds of downtime can save hours of pain 🗄️
  • Keep SIGNUPS_ALLOWED set to false unless you’re actively inviting someone 🔒
  • Keep Docker and your host OS updated — your vault is only as secure as the server it runs on 🛡️
  • Managing multiple Docker services? Portainer gives you a visual dashboard for all of them 📊

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.