Vaultwarden Complete Self-Hosting Guide 2026: Free Bitwarden Alternative Setup
Published on January 10, 2026
Introduction
Vaultwarden (formerly known as Bitwarden_RS) is an unofficial, open-source, community-driven server implementation of the Bitwarden password manager API. Written in Rust, Vaultwarden is designed to be lightweight, efficient, and easy to self-host—making it an ideal choice for individuals, families, and small organizations who want complete control over their password data.
This comprehensive guide covers every aspect of Vaultwarden deployment, from basic Docker installation to advanced configurations including reverse proxy setup, two-factor authentication, email configuration, and enterprise-grade backup strategies.
What is Vaultwarden?
Vaultwarden is a re-implementation of the Bitwarden server API. This means:
- It works with all official Bitwarden client applications (browser extensions, desktop apps, mobile apps)
- Your passwords are encrypted client-side before reaching the server
- It includes premium features for free that would require a subscription with official Bitwarden
Vaultwarden vs Official Bitwarden: Key Differences
| Aspect | Vaultwarden | Official Bitwarden Self-Hosted |
|---|---|---|
| Technology | Rust (single binary) | .NET + SQL Server |
| RAM Usage | ~30-50 MB | 2-4 GB minimum |
| Docker Containers | 1 container | 6-8 containers |
| Setup Complexity | Simple | Complex |
| Premium Features | ✅ Free (TOTP, 2FA, Organizations) | Requires subscription |
| Official Support | ❌ Community-driven | ✅ Official support |
| Third-Party Audits | ❌ No formal audits | ✅ Regular security audits |
| Database | SQLite (default), MySQL, PostgreSQL | SQL Server |
| Target Audience | Individuals, families, small orgs | Enterprise, large organizations |
⚠️ Important Note: While Vaultwarden is secure (passwords are encrypted client-side), it has not undergone formal third-party security audits like the official Bitwarden server. Evaluate your security requirements before choosing.
Who Is This Guide For?
- Beginners setting up their first self-hosted password manager
- Privacy-conscious users wanting full control over their passwords
- Home lab enthusiasts looking for a lightweight password solution
- Small teams needing shared password management without subscription costs
- Raspberry Pi users seeking resource-efficient applications
Part 1: System Requirements
Hardware Requirements
Vaultwarden is extremely lightweight and can run on minimal hardware:
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
| RAM | 128 MB | 256 MB+ | Vaultwarden uses ~30-50 MB |
| CPU | Any | Any | Rust is highly efficient |
| Storage | 100 MB | 1 GB+ | For database and attachments |
| Architecture | x86_64, ARM64, ARMv7 | Any | Supports Raspberry Pi |
Supported Platforms
| Platform | Support Level | Notes |
|---|---|---|
| Linux (Ubuntu/Debian) | ✅ Excellent | Recommended for production |
| Linux (Other distros) | ✅ Good | Docker works on most distros |
| Windows (WSL2) | ⚠️ Good | Via Docker Desktop |
| macOS | ⚠️ Good | Via Docker Desktop |
| Synology/QNAP NAS | ✅ Good | Container Manager support |
| Raspberry Pi | ✅ Excellent | Perfect for Pi 3/4/5 |
| Unraid | ✅ Good | Community templates available |
Network Requirements
| Port | Protocol | Purpose | Required |
|---|---|---|---|
| 80 | TCP | HTTP (redirects, Let’s Encrypt) | ✅ For SSL |
| 443 | TCP | HTTPS (main access) | ✅ Recommended |
| 3012 | TCP | WebSocket notifications | Optional |
| Custom (e.g., 8080) | TCP | Local-only access | Optional |
Critical Security Requirement: HTTPS
🔒 HTTPS is Required: Bitwarden clients require HTTPS for production use. Running Vaultwarden without HTTPS is only acceptable for:
- Local network access only (e.g.,
192.168.x.x)- Development and testing purposes
This guide covers setting up HTTPS via reverse proxy.
Part 2: Prerequisites
Before installing Vaultwarden, prepare your system with these essential steps. This ensures you have the necessary tools and security basics in place.
Step 1: Update Your System
Updating ensures you have the latest security patches and software versions.
For *nix (Linux - e.g., Ubuntu/Debian):
# Update package lists
sudo apt update
# Upgrade all installed packages
sudo apt upgrade -y Command breakdown:
sudo: Runs the command with administrator (root) privileges - you’ll enter your passwordapt: Package manager for Debian-based systems like Ubuntuupdate: Refreshes the list of available packages from repositoriesupgrade -y: Installs newer versions;-yautomatically confirms prompts
For other Linux distributions:
# Fedora/RHEL/CentOS
sudo dnf update -y
# Arch Linux
sudo pacman -Syu
# openSUSE
sudo zypper update For macOS:
# Update system software
softwareupdate -i -a Command breakdown:
softwareupdate: Apple’s built-in system update tool-i: Install updates-a: All available updates
For Windows (PowerShell as Administrator):
# Update all apps via Windows Package Manager
winget upgrade --all
# Or use Windows Update via Settings
# Settings > Update & Security > Windows Update > Check for updates Step 2: Create a Dedicated User (Security Best Practice)
Running services as root or your main user is a security risk. Create a dedicated user for Vaultwarden.
For *nix (Linux):
# Create a new user named 'vaultuser'
sudo adduser vaultuser What this does: Creates a new system user. You’ll be prompted to set a password and optional user details (press Enter to skip).
# Add the user to the sudo group (for admin tasks)
sudo usermod -aG sudo vaultuser Command breakdown:
usermod: Modifies a user account-aG: Appends to group without removing from other groupssudo: The administrators group
# Switch to the new user
su - vaultuser Command breakdown:
su: Switch user-: Loads the new user’s full environment (home directory, shell settings)
For macOS:
- Go to System Settings → Users & Groups
- Click the lock icon and authenticate
- Click + to add a new user
- Create a Standard user named “vaultuser”
- In Terminal, grant admin access:
sudo dscl . -append /Groups/admin GroupMembership vaultuser For Windows:
# Create a new local user (PowerShell as Administrator)
$Password = Read-Host -AsSecureString "Enter password"
New-LocalUser "vaultuser" -Password $Password -Description "Vaultwarden Service Account"
# Add to Administrators group
Add-LocalGroupMember -Group "Administrators" -Member "vaultuser" Step 3: Install Git (For Repository Cloning)
Git is a version control tool used to download source code. While not strictly required for Docker installation, it’s useful for future updates and native builds.
For *nix (Linux):
sudo apt install git -y For Fedora:
sudo dnf install git -y For macOS:
# Install Xcode Command Line Tools (includes Git)
xcode-select --install
# Or via Homebrew (if installed)
brew install git For Windows:
- Download from git-scm.com
- Run the installer with default options
- Open Git Bash (installed with Git) for Unix-like commands
Verify Installation:
git --version
# Expected: git version 2.x.x Step 4: Install a Text Editor
You’ll need a text editor for editing configuration files.
For *nix (Linux):
# Nano - beginner-friendly editor
sudo apt install nano -y
# Or Vim - more powerful, steeper learning curve
sudo apt install vim -y Nano basics:
- Open file:
nano filename - Save:
Ctrl+O, thenEnter - Exit:
Ctrl+X
For macOS:
Nano is pre-installed. Alternatively:
# Install via Homebrew
brew install nano For Windows:
Download Notepad++ or use built-in Notepad.
Step 5: Configure Firewall
Firewalls block unauthorized access to your server. Configure them to allow only necessary ports.
For *nix (Ubuntu/Debian with UFW):
# Install UFW if not present
sudo apt install ufw -y
# Allow SSH (for remote access - skip if local only)
sudo ufw allow OpenSSH
# Allow HTTP (for Let's Encrypt certificate verification)
sudo ufw allow 80/tcp
# Allow HTTPS (for secure web access)
sudo ufw allow 443/tcp
# Enable the firewall
sudo ufw enable What this does:
allow OpenSSH: Permits SSH connections (port 22)allow 80/tcp: Permits HTTP connectionsallow 443/tcp: Permits HTTPS connectionsenable: Activates the firewall (answerywhen prompted)
# Check firewall status
sudo ufw status For Fedora/RHEL/CentOS (firewalld):
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload For macOS:
- Open System Settings → Network → Firewall
- Turn on the firewall
- Click Options to configure specific app permissions
For Windows:
- Open Windows Security → Firewall & network protection
- Click Allow an app through firewall
- Add entries for ports 80 and 443 when needed
Step 6: Domain Name Setup
For external access with HTTPS, you need a domain name pointing to your server.
Option A: Use a Free Dynamic DNS Service (DuckDNS)
DuckDNS provides free subdomains that update automatically.
- Go to duckdns.org and sign in
- Create a subdomain (e.g.,
yourvault.duckdns.org) - Note your token from the DuckDNS dashboard
- Update it to point to your public IP (visible at whatismyip.com)
Automatic IP Updates (for dynamic IPs):
Create a cron job to update your IP automatically:
# Edit crontab
crontab -e
# Add this line (updates every 5 minutes)
*/5 * * * * curl -s "https://www.duckdns.org/update?domains=yourvault&token=YOUR_TOKEN_HERE&ip=" >/dev/null 2>&1 Command breakdown:
*/5 * * * *: Run every 5 minutescurl -s: Silently calls the DuckDNS update URL>/dev/null 2>&1: Suppresses output
Option B: Use a Purchased Domain
- Purchase a domain from a registrar (Namecheap, Cloudflare, GoDaddy, etc.)
- In your registrar’s DNS settings, create an A record:
- Name:
vault(or@for root domain) - Type:
A - Value: Your server’s public IP address
- TTL: 300 (or Auto)
- Name:
💡 Security Tip: Avoid using “bitwarden” or “password” in your domain name - obscurity adds a small layer of protection.
Step 7: Port Forwarding (For Home Networks)
If hosting at home behind a router, forward ports 80 and 443 to your server:
- Find your server’s local IP:
ip a(Linux) oripconfig(Windows) - Log into your router (usually
192.168.1.1or192.168.0.1) - Find Port Forwarding settings (varies by router)
- Add rules:
- External Port 80 → Internal IP, Port 80
- External Port 443 → Internal IP, Port 443
- Save and apply
⚠️ Security Warning: Exposing ports to the internet increases attack surface. Ensure Vaultwarden and your server are properly secured.
Part 3: Docker Installation
Docker is the recommended method for running Vaultwarden as it provides isolation, easy updates, and consistent behavior across platforms.
Option A: Linux (Ubuntu/Debian) - Recommended
This is the preferred setup for Vaultwarden in production environments.
Step 1: Update System Packages
# Update package index
sudo apt update
# Upgrade existing packages
sudo apt upgrade -y What this does: Ensures your system has the latest security patches and package information before installing new software.
Step 2: Remove Conflicting Docker Versions
# Remove old Docker packages that might conflict
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove -y $pkg 2>/dev/null
done What this does: Removes outdated Docker packages from default repositories that might conflict with the official Docker installation.
Step 3: Install Docker Prerequisites
# Install required packages
sudo apt-get install -y
ca-certificates
curl
gnupg
lsb-release Package breakdown:
ca-certificates: Enables HTTPS communicationcurl: Tool for downloading files from URLsgnupg: GNU Privacy Guard for verifying package signatureslsb-release: Identifies the Linux distribution
Step 4: Add Docker’s Official GPG Key
# Create directory for keyrings
sudo install -m 0755 -d /etc/apt/keyrings
# Download and install Docker's GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg |
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Ensure key is readable
sudo chmod a+r /etc/apt/keyrings/docker.gpg What this does: Downloads Docker’s official signing key, which verifies that Docker packages are authentic and haven’t been tampered with.
Step 5: Add Docker Repository
# Add Docker repository to apt sources
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null What this does: Adds Docker’s official package repository, ensuring you get the latest Docker version with all features and security updates.
💡 Note for Debian: Replace
ubuntuwithdebianin the URL above if using Debian.
Step 6: Install Docker Engine
# Update package index with new repository
sudo apt-get update
# Install Docker Engine and plugins
sudo apt-get install -y
docker-ce
docker-ce-cli
containerd.io
docker-buildx-plugin
docker-compose-plugin Package breakdown:
docker-ce: Docker Community Edition (the main engine)docker-ce-cli: Command-line interface for Dockercontainerd.io: Container runtimedocker-buildx-plugin: Enhanced image building capabilitiesdocker-compose-plugin: Docker Compose V2 (usesdocker composeinstead ofdocker-compose)
Step 7: Configure Non-Root Docker Access (Recommended)
# Add current user to docker group
sudo usermod -aG docker $USER
# Apply group changes immediately (or log out and back in)
newgrp docker What this does: Allows running Docker commands without sudo. You must log out and log back in for changes to take effect permanently.
⚠️ Security Note: Adding a user to the
dockergroup grants them root-equivalent access on the system. Only add trusted users.
Step 8: Enable Docker to Start on Boot
# Enable Docker service
sudo systemctl enable docker
# Start Docker service
sudo systemctl start docker What this does: Ensures Docker starts automatically when your server boots up.
Step 9: Verify Installation
# Check Docker version
docker --version
# Expected output: Docker version 25.x.x, build xxxxxxx
# Check Docker Compose version
docker compose version
# Expected output: Docker Compose version v2.x.x
# Test Docker with hello-world
docker run hello-world If you see the “Hello from Docker!” message, your installation is successful.
Option B: Windows (Docker Desktop + WSL2)
Docker Desktop provides an easy way to run Docker on Windows using WSL2 (Windows Subsystem for Linux 2).
Prerequisites
- Windows 10 version 21H2 or higher, or Windows 11
- 64-bit processor with Second Level Address Translation (SLAT)
- 4 GB RAM minimum (8 GB recommended)
- Virtualization enabled in BIOS
Step 1: Enable WSL2
Open PowerShell as Administrator and run:
# Install WSL with the default Ubuntu distribution
wsl --install
# This will:
# - Enable Windows Subsystem for Linux feature
# - Enable Virtual Machine Platform feature
# - Install the Linux kernel update package
# - Set WSL 2 as the default version
# - Install Ubuntu distribution Restart your computer when prompted.
Step 2: Verify WSL2 Installation
After restart, open PowerShell:
# Check WSL status
wsl --status
# List installed distributions
wsl --list --verbose Ensure the VERSION column shows “2” for your distribution.
Step 3: Download and Install Docker Desktop
- Visit Docker Desktop for Windows
- Download the installer (
Docker Desktop Installer.exe) - Run the installer with these options:
- ✅ Use WSL 2 instead of Hyper-V (Critical!)
- ✅ Add shortcut to desktop (Optional)
- Click OK to proceed with installation
- Restart your computer when prompted
Step 4: Configure Docker Desktop
- Launch Docker Desktop from Start Menu
- Accept the Docker Subscription Service Agreement
- When Docker Desktop opens, go to Settings (gear icon)
- Navigate to Resources → WSL Integration
- Toggle ON for your default WSL distro (Ubuntu)
- Click Apply & Restart
Step 5: Verify Docker Installation
Open PowerShell or Windows Terminal:
# Check Docker version
docker --version
# Check Docker Compose version
docker compose version
# Test Docker
docker run hello-world You should see the “Hello from Docker!” message.
💡 Tip: For best performance, store your Vaultwarden data inside WSL2 (e.g.,
/home/yourusername/vaultwarden) rather than on Windows drives.
Option C: macOS (Docker Desktop)
Prerequisites
- macOS 12 (Monterey) or newer
- Apple Silicon (M1/M2/M3/M4) or Intel processor
- 4 GB RAM minimum (8 GB recommended)
Step 1: Download Docker Desktop
- Visit Docker Desktop for Mac
- Download the appropriate version:
- Apple Silicon (M1/M2/M3/M4): Download “Apple Chip” version
- Intel Macs: Download “Intel Chip” version
Step 2: Install Docker Desktop
- Open the downloaded
.dmgfile - Drag the Docker icon to the Applications folder
- Open Docker from the Applications folder
- Accept the Docker Subscription Service Agreement
Step 3: Configure Resources (Optional)
- Click the Docker icon in the menu bar
- Go to Settings → Resources
- Adjust memory allocation if needed (default is usually sufficient)
- For Apple Silicon, enable Use Virtualization framework (faster)
Step 4: Verify Installation
Open Terminal:
# Check Docker version
docker --version
# Check Docker Compose version
docker compose version
# Test Docker
docker run hello-world Option D: Alternative Method Using Homebrew (macOS)
# Install Docker via Homebrew
brew install --cask docker
# Launch Docker (first time setup)
open /Applications/Docker.app
# Verify installation after Docker starts
docker --version Part 4: Vaultwarden Installation
This section covers two methods for installing Vaultwarden with Docker: the simple CLI method and the recommended Docker Compose method.
Method 1: Simple Docker CLI (Quick Start)
For a quick installation without a configuration file, use the Docker CLI directly.
For All Platforms:
# Create data directory for persistence
mkdir -p ~/vaultwarden/data Basic Run Command:
# Pull the latest Vaultwarden image
docker pull vaultwarden/server:latest
# Run Vaultwarden container
docker run -d
--name vaultwarden
-e DOMAIN="https://vault.yourdomain.com"
-e SIGNUPS_ALLOWED=true
-e WEBSOCKET_ENABLED=true
-v ~/vaultwarden/data:/data
-p 8080:80
-p 3012:3012
--restart unless-stopped
vaultwarden/server:latest Command breakdown:
-d: Run in detached mode (background)--name vaultwarden: Name the container for easy reference-e DOMAIN=...: Set environment variable for your server URL-e SIGNUPS_ALLOWED=true: Allow user registrations-e WEBSOCKET_ENABLED=true: Enable real-time sync-v ~/vaultwarden/data:/data: Mount persistent data volume-p 8080:80: Map container port 80 to host port 8080-p 3012:3012: Map WebSocket port--restart unless-stopped: Auto-restart unless manually stoppedvaultwarden/server:latest: The official Vaultwarden image
Managing the Container:
# Check if container is running
docker ps
# View logs
docker logs vaultwarden
# Follow logs in real-time
docker logs -f vaultwarden
# Stop the container
docker stop vaultwarden
# Start the container
docker start vaultwarden
# Remove the container (data is preserved in volume)
docker rm vaultwarden
# Update to latest version
docker pull vaultwarden/server:latest
docker stop vaultwarden
docker rm vaultwarden
# Re-run the docker run command above Windows (PowerShell):
# Create data directory
New-Item -ItemType Directory -Force -Path "$HOMEaultwardendata"
# Run Vaultwarden
docker run -d `
--name vaultwarden `
-e DOMAIN="https://vault.yourdomain.com" `
-e SIGNUPS_ALLOWED=true `
-v "${HOME}aultwardendata:/data" `
-p 8080:80 `
--restart unless-stopped `
vaultwarden/server:latest 💡 When to use CLI vs Compose: Use CLI for testing or simple setups. Use Docker Compose (below) for production, as it’s easier to manage configuration changes.
Method 2: Docker Compose (Recommended)
Docker Compose is the recommended method for running Vaultwarden as it provides easy configuration management and container orchestration.
Step 1: Create Project Directory
Linux/macOS:
# Create directory for Vaultwarden
mkdir -p ~/vaultwarden
cd ~/vaultwarden
# Create data directory
mkdir -p data Windows (PowerShell):
# Create directory for Vaultwarden
New-Item -ItemType Directory -Force -Path "$HOMEaultwardendata"
Set-Location "$HOMEaultwarden" Step 2: Create Docker Compose File
Create a file named docker-compose.yml:
Linux/macOS:
nano docker-compose.yml Windows (PowerShell):
notepad docker-compose.yml Add the following content:
# Vaultwarden Docker Compose Configuration
# https://github.com/dani-garcia/vaultwarden
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
# Environment variables for configuration
environment:
# ==========================================
# DOMAIN CONFIGURATION (Required for HTTPS)
# ==========================================
# Your Vaultwarden domain with https://
- DOMAIN=https://vault.yourdomain.com
# ==========================================
# SIGNUP SETTINGS
# ==========================================
# Allow new user registrations (set to false after initial setup)
- SIGNUPS_ALLOWED=true
# Only allow signups from specific email domain(s)
# - SIGNUPS_DOMAINS_WHITELIST=yourdomain.com,otherdomain.org
# Require email verification for new signups
- SIGNUPS_VERIFY=true
# ==========================================
# ADMIN PANEL (Highly Recommended)
# ==========================================
# Generate a secure token with: openssl rand -base64 48
# Or use: docker exec -it vaultwarden /vaultwarden hash
- ADMIN_TOKEN=YOUR_SECURE_ADMIN_TOKEN_HERE
# ==========================================
# WEBSOCKET NOTIFICATIONS
# ==========================================
# Enable for real-time sync across devices
- WEBSOCKET_ENABLED=true
# ==========================================
# LOGGING
# ==========================================
- LOG_LEVEL=warn
# Options: trace, debug, info, warn, error, off
# ==========================================
# TWO-FACTOR AUTHENTICATION
# ==========================================
# Set organization name for Authenticator apps
- AUTHENTICATOR_DISABLE_TIME_DRIFT=false
# ==========================================
# INVITATIONS
# ==========================================
- INVITATIONS_ALLOWED=true
# Volume mapping for persistent data
volumes:
# Map host data directory to container
# Linux/macOS: ./data:/data
# Windows: Adjust path as needed
- ./data:/data
# Port mapping
ports:
# Main web interface (change left side to use different port)
- "8080:80"
# WebSocket port for notifications
- "3012:3012" Important: Replace YOUR_SECURE_ADMIN_TOKEN_HERE with a secure token (see next section).
Step 3: Generate a Secure Admin Token
The ADMIN_TOKEN protects your admin panel. Generate a secure token:
Option 1: Using OpenSSL (Recommended)
# Generate a random 48-character token
openssl rand -base64 48 Copy the output and replace YOUR_SECURE_ADMIN_TOKEN_HERE in your docker-compose.yml.
Option 2: Using Argon2 Hash (Most Secure)
For enhanced security, use an Argon2 hash instead of a plain token:
# Start Vaultwarden temporarily
docker run --rm -it vaultwarden/server /vaultwarden hash
# Enter your desired admin password when prompted
# Copy the entire hash output (starts with $argon2id$...) The hash will look like:
$argon2id$v=19$m=65540,t=3,p=4$bXl... Use this entire string as your ADMIN_TOKEN value.
Step 4: Understanding Environment Variables
Here’s a comprehensive list of all important Vaultwarden environment variables:
Core Settings
| Variable | Description | Default |
|---|---|---|
DOMAIN | Your Vaultwarden URL (e.g., https://vault.example.com) | None |
SIGNUPS_ALLOWED | Allow new user registrations | true |
INVITATIONS_ALLOWED | Allow user invitations | true |
ADMIN_TOKEN | Password/hash for admin panel | None (admin disabled) |
WEBSOCKET_ENABLED | Enable WebSocket notifications | false |
LOG_LEVEL | Logging verbosity | Info |
User Registration Controls
| Variable | Description | Default |
|---|---|---|
SIGNUPS_VERIFY | Require email verification | false |
SIGNUPS_DOMAINS_WHITELIST | Restrict signups to email domains | None |
DISABLE_ICON_DOWNLOAD | Disable downloading website icons | false |
Security Settings
| Variable | Description | Default |
|---|---|---|
PASSWORD_HINTS_ALLOWED | Allow password hints | true |
SHOW_PASSWORD_HINT | Show hints on login page | false |
DISABLE_2FA_REMEMBER | Disable “remember 2FA” option | false |
SMTP/Email Configuration (For Verification)
| Variable | Description | Example |
|---|---|---|
SMTP_HOST | SMTP server address | smtp.gmail.com |
SMTP_PORT | SMTP port | 587 |
SMTP_SECURITY | Connection security | starttls |
SMTP_USERNAME | SMTP username | your@email.com |
SMTP_PASSWORD | SMTP password or app password | your-app-password |
SMTP_FROM | From email address | vault@yourdomain.com |
SMTP_FROM_NAME | From display name | Vaultwarden |
Step 5: Start Vaultwarden
# Navigate to your Vaultwarden directory
cd ~/vaultwarden
# Pull the image and start the container
docker compose up -d
# -d flag runs in detached (background) mode What this command does:
- Pulls the latest Vaultwarden image from Docker Hub
- Creates the container with your configuration
- Starts the container in the background
Step 6: Verify Vaultwarden is Running
# Check container status
docker compose ps
# Expected output:
# NAME STATUS PORTS
# vaultwarden Up (healthy) 0.0.0.0:8080->80/tcp, 0.0.0.0:3012->3012/tcp
# View container logs
docker compose logs -f
# Press Ctrl+C to exit log view Step 7: Access Vaultwarden
- Open your web browser
- Navigate to
http://YOUR_SERVER_IP:8080- Or
http://localhost:8080if running locally
- Or
- You should see the Vaultwarden web interface
⚠️ Warning: Until you set up HTTPS, only access Vaultwarden from your local network!
Part 5: Reverse Proxy Setup (HTTPS)
For secure external access, you need to set up a reverse proxy with SSL/TLS certificates. This section covers two popular options: Caddy and Nginx Proxy Manager.
Understanding Reverse Proxies
A reverse proxy:
- Receives HTTPS requests from the internet
- Terminates SSL/TLS encryption
- Forwards requests to Vaultwarden (via HTTP internally)
- Returns encrypted responses to clients
┌────────────────────┐
Internet ──► Reverse Proxy (HTTPS:443) ──► │ Vaultwarden │
│ SSL Termination │ (HTTP:8080) │
│ Let's Encrypt Certs └────────────────────┘
└────────────────────────────────────────────────── Prerequisites for All Methods
Before setting up a reverse proxy:
- Domain Name: Own a domain (e.g.,
yourdomain.com) or subdomain (e.g.,vault.yourdomain.com) - DNS Record: Create an A record pointing your domain to your server’s public IP
- Port Forwarding: Forward ports 80 and 443 from your router to your server
- Firewall: Allow incoming connections on ports 80 and 443
Option A: Caddy Reverse Proxy (Simplest)
Caddy is an excellent choice for Vaultwarden because:
- Automatic HTTPS: Obtains and renews Let’s Encrypt certificates automatically
- Simple configuration: Minimal setup required
- Built-in HTTP/2 and HTTP/3 support
Step 1: Update Docker Compose
Create a new docker-compose.yml with Caddy included:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.yourdomain.com
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=YOUR_SECURE_ADMIN_TOKEN
- WEBSOCKET_ENABLED=true
volumes:
- ./vw-data:/data
# Note: No ports exposed - Caddy will handle external access
networks:
- vaultwarden-network
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80" # Required for Let's Encrypt HTTP challenge
- "443:443" # HTTPS
- "443:443/udp" # HTTP/3 (QUIC)
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy-data:/data
- ./caddy-config:/config
networks:
- vaultwarden-network
networks:
vaultwarden-network:
driver: bridge Step 2: Create Caddyfile
Create a file named Caddyfile in the same directory:
nano Caddyfile Add the following content:
# Vaultwarden Caddy Configuration
# Replace vault.yourdomain.com with your actual domain
vault.yourdomain.com {
# Enable logging
log {
level INFO
output file /data/access.log {
roll_size 10mb
roll_keep 10
}
}
# Security headers
header {
# Enable strict HTTPS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Prevent XSS attacks
X-XSS-Protection "1; mode=block"
# Prevent MIME type sniffing
X-Content-Type-Options "nosniff"
# Control iframe embedding
X-Frame-Options "SAMEORIGIN"
# Referrer policy
Referrer-Policy "strict-origin-when-cross-origin"
# Remove server header
-Server
}
# Proxy all requests to Vaultwarden
reverse_proxy vaultwarden:80 {
# WebSocket support
header_up X-Real-IP {remote_host}
}
# Handle WebSocket notifications (optional, for real-time sync)
reverse_proxy /notifications/hub vaultwarden:3012
} What each section does:
vault.yourdomain.com: Your domain - Caddy automatically gets SSL certificateslog: Access logging with rotationheader: Security headers to protect against common attacksreverse_proxy: Forwards requests to the Vaultwarden container
Step 3: Start the Stack
# Create required directories
mkdir -p vw-data caddy-data caddy-config
# Start all containers
docker compose up -d
# Check logs for SSL certificate acquisition
docker compose logs caddy -f Caddy will automatically:
- Detect the domain in your Caddyfile
- Request an SSL certificate from Let’s Encrypt
- Configure HTTPS redirects
- Renew certificates automatically
Step 4: Verify HTTPS
Open https://vault.yourdomain.com in your browser. You should see:
- A valid SSL certificate (padlock icon)
- The Vaultwarden login page
Option B: Nginx Proxy Manager (GUI-Based)
Nginx Proxy Manager (NPM) provides a user-friendly web interface for managing reverse proxies.
Step 1: Create Docker Compose with NPM
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.yourdomain.com
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=YOUR_SECURE_ADMIN_TOKEN
- WEBSOCKET_ENABLED=true
volumes:
- ./vw-data:/data
networks:
- proxy-network
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "81:81" # NPM Admin Panel
volumes:
- ./npm-data:/data
- ./npm-letsencrypt:/etc/letsencrypt
networks:
- proxy-network
networks:
proxy-network:
driver: bridge Step 2: Start the Containers
mkdir -p vw-data npm-data npm-letsencrypt
docker compose up -d Step 3: Access NPM Admin Panel
- Open
http://YOUR_SERVER_IP:81 - Log in with default credentials:
- Email:
admin@example.com - Password:
changeme
- Email:
- Immediately change these credentials when prompted
Step 4: Configure Proxy Host for Vaultwarden
In NPM, go to Hosts → Proxy Hosts
Click Add Proxy Host
Fill in the Details tab:
- Domain Names:
vault.yourdomain.com - Scheme:
http - Forward Hostname/IP:
vaultwarden - Forward Port:
80 - Block Common Exploits: ✅ Enable
- Websockets Support: ✅ Enable
- Domain Names:
Go to the SSL tab:
- SSL Certificate: Request a new SSL Certificate
- Force SSL: ✅ Enable
- HTTP/2 Support: ✅ Enable
- HSTS Enabled: ✅ Enable
- Click Save
NPM will automatically obtain a Let’s Encrypt certificate
Step 5: Verify the Setup
Navigate to https://vault.yourdomain.com and verify:
- Valid SSL certificate
- Vaultwarden web interface loads correctly
Option C: Existing Nginx Server
If you already have Nginx installed, add this configuration:
Create Nginx Site Configuration
sudo nano /etc/nginx/sites-available/vaultwarden # Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name vault.yourdomain.com;
# Let's Encrypt verification
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# Redirect all other requests to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS Server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name vault.yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/vault.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.yourdomain.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Allow large file uploads (for attachments)
client_max_body_size 525M;
# Security headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
# Main location - proxy to Vaultwarden
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket support for notifications
location /notifications/hub {
proxy_pass http://127.0.0.1:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /notifications/hub/negotiate {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
} Enable the Site and Get SSL Certificate
# Enable the site
sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# If test passes, reload Nginx
sudo systemctl reload nginx
# Obtain SSL certificate
sudo certbot --nginx -d vault.yourdomain.com Part 6: Initial Configuration
Step 1: Create Your Admin Account
- Navigate to
https://vault.yourdomain.com(your Vaultwarden URL) - Click Create Account
- Enter:
- Email: Your email address
- Name: Your display name
- Master Password: A strong, unique password
- Master Password Hint: (Optional, not recommended)
- Click Submit
🔒 Master Password Tips:
- Use at least 16 characters
- Mix uppercase, lowercase, numbers, and symbols
- Consider using a passphrase (e.g., “correct-horse-battery-staple”)
- Never reuse passwords - this should be unique
- Store your master password securely (consider writing it down and keeping it in a safe)
Step 2: Access the Admin Panel
The admin panel provides server-wide configuration options:
- Navigate to
https://vault.yourdomain.com/admin - Enter your
ADMIN_TOKEN(from your docker-compose.yml) - You’ll see the admin dashboard with various settings
Key Admin Panel Sections
| Section | Purpose |
|---|---|
| General Settings | Domain, icons, attachments |
| Users | Manage registered users |
| Organizations | View/manage organizations |
| Diagnostics | System information and health |
| SMTP Settings | Configure email delivery |
Step 3: Configure SMTP (For Email Verification)
Email is required for:
- Account verification
- Password reset
- Organization invitations
- Two-step login email codes
Option A: Configure via Admin Panel
- Go to Admin Panel → SMTP Email Settings
- Enter your SMTP details:
- Host: Your SMTP server (e.g.,
smtp.gmail.com) - Port: Usually
587(STARTTLS) or465(SSL) - From Address:
noreply@yourdomain.com - From Name:
Vaultwarden - Username: Your email/SMTP username
- Password: Your email password or app-specific password
- Security:
starttlsorforce_tls
- Host: Your SMTP server (e.g.,
- Click Save and then Send Test Email
Option B: Configure via Environment Variables
Add to your docker-compose.yml:
environment:
# ... other variables ...
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=your.email@gmail.com
- SMTP_PASSWORD=your-app-password
- SMTP_FROM=vault@yourdomain.com
- SMTP_FROM_NAME=Vaultwarden 💡 Gmail Users: You must use an App Password, not your regular Gmail password.
Step 4: Disable Open Signups (Recommended)
After creating accounts for yourself and any family/team members:
Method 1: Via Admin Panel
- Go to Admin Panel → General Settings
- Set Allow New Signups to No
- Click Save
Method 2: Via Environment Variable Update docker-compose.yml:
environment:
- SIGNUPS_ALLOWED=false Then restart:
docker compose down
docker compose up -d Step 5: Invite New Users (When Signups Disabled)
With signups disabled, invite users via email:
- Go to Admin Panel → Users
- Click Invite User
- Enter the email address
- The user receives an invitation email to create their account
Part 7: Two-Factor Authentication (2FA)
Vaultwarden supports multiple 2FA methods to protect your vault.
Available 2FA Methods
| Method | Description | Security Level |
|---|---|---|
| Authenticator App (TOTP) | Time-based codes from apps like Authy/Google Authenticator | ⭐⭐⭐ Good |
| WebAuthn/FIDO2 | Hardware security keys (YubiKey, etc.) | ⭐⭐⭐⭐⭐ Excellent |
| Email Codes | One-time codes sent via email | ⭐⭐ Basic |
| Duo Security | Duo Mobile push notifications | ⭐⭐⭐⭐ Very Good |
Setting Up Authenticator App (TOTP)
- Log in to your Vaultwarden web vault
- Go to Settings → Security → Two-step Login
- Click Manage next to Authenticator App
- Enter your master password when prompted
- Scan the QR code with your authenticator app:
- Recommended: Authy, Aegis, Google Authenticator, Microsoft Authenticator
- Enter the 6-digit code from your app to verify
- Save your recovery code somewhere secure (not in your vault!)
Setting Up WebAuthn/FIDO2 (Hardware Keys)
Hardware security keys like YubiKey provide the strongest protection:
- Go to Settings → Security → Two-step Login
- Click Manage next to FIDO2 WebAuthn
- Enter your master password
- Give your key a name (e.g., “Primary YubiKey”)
- Insert your security key when prompted
- Touch the key to confirm
- Save your recovery code
💡 Recommendation: Register at least 2 security keys - one for regular use and one as backup.
Recovery Codes
⚠️ Critical: Always save your recovery code when enabling 2FA!
The recovery code is your emergency access method if you lose your 2FA device. Store it:
- In a physical safe
- With a trusted family member
- On an encrypted USB drive in a secure location
- NOT in your password vault (you can’t access it without 2FA!)
Part 8: Client Applications Setup
Browser Extensions
Installing the Extension
Install the Bitwarden extension for your browser:
Click the Bitwarden icon → Click the Gear icon (Settings)
Go to Settings → scroll to Self-Hosted Environment
Enter your server URL:
- Server URL:
https://vault.yourdomain.com
- Server URL:
Click Save
Log in with your Vaultwarden credentials
Desktop Applications
Download Bitwarden Desktop:
- Windows: Microsoft Store or Direct Download
- macOS: App Store or Direct Download
- Linux: Snap, Flatpak, or AppImage
Open the app → Click Gear icon (before logging in)
Enter your Self-Hosted Server URL:
https://vault.yourdomain.comClick Save and log in
Mobile Applications
iOS
- Download Bitwarden from App Store
- Open the app
- Tap Log in
- Tap Self-hosted (or gear icon before logging in)
- Enter Server URL:
https://vault.yourdomain.com - Tap Save and log in
- Enable Auto-fill:
- Settings → Passwords → AutoFill Passwords → Bitwarden
Android
- Download Bitwarden from Play Store or F-Droid
- Open the app
- Tap Log in
- Tap the Gear icon
- Enter Server URL:
https://vault.yourdomain.com - Tap Save and log in
- Enable Auto-fill:
- Settings → Passwords & accounts → Autofill service → Bitwarden
Part 9: Backup and Restore
Regular backups are essential for your password vault. Vaultwarden uses a SQLite database that can be easily backed up.
What to Back Up
| File/Folder | Description | Priority |
|---|---|---|
db.sqlite3 | Main database with all vault data | Critical |
rsa_key.pem | RSA private key | Critical |
rsa_key.pub.pem | RSA public key | Important |
attachments/ | Attachment files | Important |
config.json | Configuration | Low (can rebuild) |
Method 1: Manual Backup
Step 1: Stop Vaultwarden (Recommended for Consistency)
# Stop the container temporarily
docker compose stop vaultwarden Step 2: Create Backup
# Navigate to your Vaultwarden directory
cd ~/vaultwarden
# Create backup directory with timestamp
backup_dir="backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$backup_dir"
# Copy data directory
cp -r data/* "$backup_dir/"
# Create compressed archive
tar -czvf "vaultwarden_backup_$(date +%Y%m%d_%H%M%S).tar.gz" "$backup_dir"
# Clean up temporary directory
rm -rf "$backup_dir" Step 3: Restart Vaultwarden
docker compose start vaultwarden Method 2: Using Built-in Backup Command
Vaultwarden includes a built-in backup command:
# Create database backup without stopping the container
docker exec vaultwarden /vaultwarden backup
# This creates a timestamped backup file in the data directory
# e.g., db_20250110_120000.sqlite3 Method 3: Automated Daily Backups
Create an automated backup script:
nano ~/vaultwarden/backup.sh #!/bin/bash
# Vaultwarden Automated Backup Script
# Configuration
VAULTWARDEN_DIR="$HOME/vaultwarden"
BACKUP_DIR="$HOME/vaultwarden-backups"
RETENTION_DAYS=30
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Create timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Create backup using built-in command
docker exec vaultwarden /vaultwarden backup
# Compress entire data directory
tar -czvf "$BACKUP_DIR/vaultwarden_$TIMESTAMP.tar.gz"
-C "$VAULTWARDEN_DIR" data
# Remove backups older than retention period
find "$BACKUP_DIR" -name "vaultwarden_*.tar.gz" -mtime +$RETENTION_DAYS -delete
# Log backup completion
echo "[$(date)] Backup completed: vaultwarden_$TIMESTAMP.tar.gz" >> "$BACKUP_DIR/backup.log" Make it executable and schedule with cron:
# Make script executable
chmod +x ~/vaultwarden/backup.sh
# Open crontab
crontab -e
# Add daily backup at 2:00 AM
0 2 * * * /home/yourusername/vaultwarden/backup.sh Restoring from Backup
Step 1: Stop Vaultwarden
cd ~/vaultwarden
docker compose down Step 2: Extract Backup
# Remove existing data (make sure you have a backup!)
rm -rf data/*
# Extract backup
tar -xzvf vaultwarden_backup_YYYYMMDD_HHMMSS.tar.gz
# Move extracted files to data directory
mv backup_YYYYMMDD_HHMMSS/* data/ If restoring only the database file:
# Remove WAL file if exists (prevents corruption)
rm -f data/db.sqlite3-wal
# Copy backup database
cp db_backup.sqlite3 data/db.sqlite3 Step 3: Restart Vaultwarden
docker compose up -d
# Check logs for any issues
docker compose logs -f Backup Best Practices
- 3-2-1 Rule: 3 copies, 2 different media types, 1 offsite
- Encrypt backups before storing in cloud (use
gpgorage) - Test restores periodically
- Document your backup procedure
- Store encryption keys separately from backups
Method 4: Incremental Backups with rsync/robocopy
For efficient incremental backups that only copy changed files:
For Linux/macOS (rsync):
# Basic incremental backup
rsync -av ~/vaultwarden/data/ /backup/path/vaultwarden/
# Command breakdown:
# -a: Archive mode (preserves permissions, timestamps, etc.)
# -v: Verbose output
# With deletion of removed files (mirror backup)
rsync -av --delete ~/vaultwarden/data/ /backup/path/vaultwarden/
# To a remote server via SSH
rsync -avz -e ssh ~/vaultwarden/data/ user@backup-server:/backup/vaultwarden/
# -z: Compress during transfer for faster remote backups Automate with cron:
# Edit crontab
crontab -e
# Add daily rsync backup at 2:30 AM
30 2 * * * rsync -av --delete ~/vaultwarden/data/ /backup/vaultwarden/ >> /var/log/vaultwarden-backup.log 2>&1 For Windows (Robocopy):
# Basic incremental backup
robocopy C:aultwardendata D:ackupaultwarden /MIR /R:3 /W:10
# Command breakdown:
# /MIR: Mirror mode (deletes files in destination not in source)
# /R:3: Retry 3 times on failure
# /W:10: Wait 10 seconds between retries
# With logging
robocopy C:aultwardendata D:ackupaultwarden /MIR /R:3 /W:10 /LOG:C:ackupaultwarden-backup.log Automate with Task Scheduler:
- Open Task Scheduler
- Create Basic Task → Name: “Vaultwarden Backup”
- Trigger: Daily at 2:00 AM
- Action: Start a program →
robocopy - Arguments:
C:\vaultwarden\data D:\backup\vaultwarden /MIR /R:3 /W:10
Part 10: Updating Vaultwarden
Keeping Vaultwarden updated ensures you have the latest security patches and features.
Standard Update Procedure
# Navigate to your Vaultwarden directory
cd ~/vaultwarden
# Pull the latest image
docker compose pull
# Restart with new image
docker compose up -d
# Verify the update
docker compose logs -f Update to Specific Version
If you want to pin to a specific version:
# In docker-compose.yml, change:
image: vaultwarden/server:latest
# To a specific version:
image: vaultwarden/server:1.30.5 Then run:
docker compose up -d Automatic Updates with Watchtower
Watchtower can automatically update your containers:
# Add to docker-compose.yml
services:
watchtower:
image: containrrr/watchtower
container_name: watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# Update at 4 AM daily
- WATCHTOWER_SCHEDULE=0 0 4 * * *
# Only update labeled containers (optional)
# - WATCHTOWER_LABEL_ENABLE=true ⚠️ Caution: While convenient, automatic updates can cause issues if an update introduces breaking changes. Consider using monitored updates or setting up notifications.
Part 11: Troubleshooting
Common Issues and Solutions
Issue: Cannot Access Vaultwarden at All
Symptoms: Browser says “Unable to connect” or times out
Solutions:
# Check if container is running
docker compose ps
# If not running, check logs
docker compose logs vaultwarden
# Verify port is listening
sudo netstat -tlnp | grep 8080 # Linux
# or
lsof -i :8080 # macOS Issue: SSL Certificate Errors
Symptoms: Browser shows “Not Secure” or certificate warnings
Solutions:
- Verify DNS is correctly pointing to your server:
dig vault.yourdomain.com - Check Caddy/Nginx logs for certificate issues:
docker compose logs caddy - Ensure ports 80 and 443 are open in your firewall
Issue: WebSocket Connection Failed
Symptoms: Changes don’t sync in real-time across devices
Solutions:
- Verify
WEBSOCKET_ENABLED=truein environment - Check if port 3012 is accessible
- Ensure reverse proxy is configured for WebSocket upgrades
Issue: Email Not Sending
Symptoms: Can’t verify email or send invitations
Solutions:
- Test SMTP settings in Admin Panel
- Check SMTP credentials and allow less secure apps (for Gmail)
- Verify
SIGNUPS_VERIFY=trueif using email verification
Issue: Admin Panel Not Accessible
Symptoms: /admin shows “Admin Panel not enabled”
Solutions:
- Verify
ADMIN_TOKENis set in docker-compose.yml - Restart the container after adding token
- Check for syntax errors in ADMIN_TOKEN value
Viewing Logs
# View all logs
docker compose logs
# View Vaultwarden logs only
docker compose logs vaultwarden
# Follow logs in real-time
docker compose logs -f
# View last 100 lines
docker compose logs --tail 100 Debug Mode
For troubleshooting, enable debug logging:
environment:
- LOG_LEVEL=debug
# or for very detailed output:
- LOG_LEVEL=trace Restart and check logs for detailed information.
Part 12: Security Best Practices
Server-Level Security
Keep everything updated
- Host operating system
- Docker
- Vaultwarden container
Use a firewall
# Allow only necessary ports (Linux UFW) sudo ufw allow 22/tcp # SSH sudo ufw allow 80/tcp # HTTP (for SSL) sudo ufw allow 443/tcp # HTTPS sudo ufw enableDisable root SSH login
# In /etc/ssh/sshd_config: PermitRootLogin noEnable Fail2Ban for brute-force protection
Fail2Ban monitors logs and bans IPs with too many failed login attempts.
Installation and Configuration:
# Install Fail2Ban sudo apt install fail2ban -y # Create Vaultwarden jail configuration sudo nano /etc/fail2ban/jail.d/vaultwarden.localAdd this configuration:
[vaultwarden] enabled = true port = 80,443 filter = vaultwarden action = iptables-allports[name=vaultwarden] logpath = /path/to/vaultwarden/data/vaultwarden.log maxretry = 5 bantime = 3600 findtime = 600Create the filter:
sudo nano /etc/fail2ban/filter.d/vaultwarden.confAdd:
[Definition] failregex = ^.*Username or password is incorrect. Try again. IP: <ADDR>.$ ignoreregex =Enable Vaultwarden logging (add to docker-compose.yml):
environment: - LOG_FILE=/data/vaultwarden.log - LOG_LEVEL=warnStart Fail2Ban:
sudo systemctl enable fail2ban sudo systemctl restart fail2ban # Check status sudo fail2ban-client status vaultwardenConsider VPN Access for extra security
Instead of exposing Vaultwarden directly to the internet, access it only through a VPN:
- WireGuard: Modern, fast VPN (recommended)
- OpenVPN: Established, widely supported
- Tailscale: Easy mesh VPN with zero configuration
Benefits:
- No public exposure of your Vaultwarden server
- Encrypted tunnel for all traffic
- Access from anywhere securely
Vaultwarden-Specific Security
Use a strong ADMIN_TOKEN (hash, not plaintext)
Disable signups after setup
- SIGNUPS_ALLOWED=falseEnable email verification
- SIGNUPS_VERIFY=trueEnforce 2FA for all users (through policy)
Regular backups stored securely offsite
Use HTTPS only (never expose HTTP)
Hide password hints
- SHOW_PASSWORD_HINT=falseDisable icon downloads (prevents potential security issues)
- DISABLE_ICON_DOWNLOAD=true
Personal Security
- Use a strong, unique master password
- Enable 2FA on your Vaultwarden account
- Save recovery codes in a secure physical location
- Regularly audit vault entries and active sessions
- Log out sessions on devices you no longer use
- Use hardware security keys (YubiKey, etc.) for maximum protection
Part 13: Advanced Configuration
Custom Icons
You can mount a custom icons directory:
volumes:
- ./data:/data
- ./icons:/icons
environment:
- ICON_CACHE_FOLDER=/icons Database Options
Vaultwarden supports multiple databases:
SQLite (Default)
# No additional configuration needed
# Uses data/db.sqlite3 automatically MySQL/MariaDB
environment:
- DATABASE_URL=mysql://user:password@mysql:3306/vaultwarden PostgreSQL
environment:
- DATABASE_URL=postgresql://user:password@postgres:5432/vaultwarden Memory Limits
Limit container resources:
services:
vaultwarden:
deploy:
resources:
limits:
memory: 256M Quick Reference
Essential Commands
| Command | Description |
|---|---|
docker compose up -d | Start containers |
docker compose down | Stop containers |
docker compose logs -f | View live logs |
docker compose pull | Update images |
docker compose restart | Restart containers |
docker exec -it vaultwarden /bin/sh | Shell into container |
Important URLs
| URL | Purpose |
|---|---|
https://vault.yourdomain.com | Main web vault |
https://vault.yourdomain.com/admin | Admin panel |
https://vault.yourdomain.com/api | API endpoint (for clients) |
Environment Variable Quick Reference
| Variable | Example | Description |
|---|---|---|
DOMAIN | https://vault.example.com | Server URL |
SIGNUPS_ALLOWED | true/false | Allow registrations |
ADMIN_TOKEN | secure-hash-or-token | Admin panel password |
WEBSOCKET_ENABLED | true | Real-time sync |
SMTP_HOST | smtp.gmail.com | Email server |
Conclusion
You now have a fully functional, secure Vaultwarden installation! This self-hosted password manager gives you:
- ✅ Complete control over your password data
- ✅ HTTPS encrypted access
- ✅ Two-factor authentication
- ✅ Multi-device synchronization
- ✅ Premium Bitwarden features at no cost
- ✅ Automated backups
Next Steps
- Import existing passwords from your current password manager
- Install browser extensions on all devices
- Set up family/team members with their own accounts
- Review and organize your vault with folders and collections
- Set up organizations for shared passwords
Additional Resources
- Vaultwarden GitHub
- Vaultwarden Wiki
- Bitwarden Help Center (client configuration)
- Bitwarden Community Forums
Last updated: January 2026
Comments
Sign in to join the discussion!
Your comments help others in the community.