Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Vaultwarden - Hardened Docker Deployment

Self-hosted Bitwarden-compatible password manager using Vaultwarden with a PostgreSQL backend. This template follows the repository hardening baseline: non-root containers, cap_drop: ALL, no-new-privileges, private IPC, read-only app root filesystem, internal database network, resource limits, and localhost-only web binding.

Vaultwarden is the community Rust implementation of the Bitwarden server API. It is not affiliated with Bitwarden, Inc.

Architecture

Browsers / Bitwarden clients
  |
Reverse proxy with HTTPS
  |
127.0.0.1:8080
  |
[vaultwarden-front] -- Vaultwarden (port 8080)
  |
[vaultwarden-db] -- PostgreSQL 18

Services

Service Image Purpose
vaultwarden vaultwarden/server:1.36.0-alpine Web vault, Bitwarden-compatible API, admin panel
postgres postgres:18.4 PostgreSQL database on an internal-only Docker network

Ports

Port Binding Purpose
${VAULTWARDEN_PORT:-8080} 127.0.0.1 Reverse proxy target for web vault, API, and WebSocket notifications

Vaultwarden 1.31+ serves WebSocket notifications on the main HTTP port, so this template does not expose the old 3012 listener.

Quick Start

cd vaultwarden
cp .env.example .env

Generate secrets:

openssl rand -hex 32  # POSTGRES_PASSWORD
openssl rand -hex 32  # POSTGRES_NON_ROOT_PASSWORD
docker run --rm -it vaultwarden/server:1.36.0-alpine /vaultwarden hash --preset owasp

Paste the generated Argon2 PHC string into ADMIN_TOKEN in .env, keeping single quotes around it:

ADMIN_TOKEN='$argon2id$v=19$m=19456,t=2,p=1$...'

Create networks and data directories:

docker network create vaultwarden-front
docker network create --internal vaultwarden-db
mkdir -p data/app data/db
sudo chown -R "$(id -u):$(id -g)" data

Deploy:

docker compose up -d

Point your reverse proxy at http://127.0.0.1:8080 and set DOMAIN=https://vault.example.com to the exact public URL.

First User

The secure default is SIGNUPS_ALLOWED=false and INVITATIONS_ALLOWED=false.

For a fresh instance, use one of these bootstrap paths:

  1. Temporarily set SIGNUPS_ALLOWED=true, create the owner account, then set it back to false and recreate the container.
  2. Keep public signups disabled and use /admin with ADMIN_TOKEN to manage users. Configure SMTP first if you want email invitations to work cleanly.

Do not leave public signups enabled on an internet-facing password manager.

Reverse Proxy

Caddy example:

vault.example.com {
    reverse_proxy http://127.0.0.1:8080
}

The proxy must preserve WebSocket upgrades for /notifications/hub; Caddy does this automatically. If your proxy writes access logs to disk or forwards them to a log store, redact access_token query parameters under /notifications/*.

Configuration Notes

  • ADMIN_TOKEN should be an Argon2 PHC string generated by vaultwarden hash, not a plain text password.
  • DOMAIN must be HTTPS for Web Crypto, WebAuthn/U2F, attachments, and client links.
  • HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS=true protects internal services from favicon-fetch SSRF-style probes.
  • ORG_CREATION_USERS=none is the locked-down default. Change it to a comma-separated email allowlist or all if users need to create organizations.
  • SMTP is optional, but recommended for invitations, account verification, email 2FA, emergency access, and device emails.

Backup

Back up both PostgreSQL and data/app. The app directory contains attachments, Sends, icon cache, RSA keys, and local config overrides created by the admin panel.

mkdir -p backups
set -a
. ./.env
set +a
docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > "backups/vaultwarden-$(date +%Y%m%d).sql"
tar -czf "backups/vaultwarden-data-$(date +%Y%m%d).tar.gz" data/app .env

Store backups encrypted and test restores before relying on them.

Updates

Images are pinned. Update by changing tags through Renovate or manually, then:

docker compose pull
docker compose up -d
docker compose logs -f vaultwarden

Check upstream release notes before major upgrades. Password-manager updates are worth treating with more suspicion than a casual dashboard bump.